Skip to content

Commit 6a0e852

Browse files
authored
use Makefile to build FMU's for Cpp runtime in OMEdit (#13142)
1 parent dfdcd7a commit 6a0e852

File tree

4 files changed

+97
-36
lines changed

4 files changed

+97
-36
lines changed

OMCompiler/Compiler/Template/CodegenFMUCpp.tpl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,8 @@ case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__), simula
772772

773773
# simulations use -O0 by default; can be changed to e.g. -O2 or -Ofast
774774
SIM_OPT_LEVEL=-O0
775-
775+
# the default is ON by default, override the var from commandLine to skip the zipping of fmu e.g. make -f ZIP_FMU=OFF
776+
ZIP_FMU = ON
776777
# native build or cross compilation
777778
ifeq ($(TARGET_TRIPLET),)
778779
TRIPLET=<%Autoconf.triple%>
@@ -857,12 +858,18 @@ case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__), simula
857858
<%\t%>cp "$(OMHOME)/share/omc/runtime/cpp/licenses/sundials.license" "documentation/"
858859
endif
859860
<%\t%>rm -f <%fmuTargetName%>.fmu
861+
ifeq ($(ZIP_FMU),ON)
860862
ifeq ($(USE_FMU_SUNDIALS),ON)
861863
<%\t%>zip -r "<%fmuTargetName%>.fmu" modelDescription.xml binaries sources documentation
862864
<%\t%>rm -rf documentation
863865
else
864866
<%\t%>zip -r "<%fmuTargetName%>.fmu" modelDescription.xml binaries sources
865867
endif
868+
endif
869+
870+
ifeq ($(ZIP_FMU),OFF)
871+
<%\t%>rm -f OMCpp<%fileNamePrefix%>* <%fileNamePrefix%>_FMU.* <%fileNamePrefix%>.def <%fileNamePrefix%>.sh <%fileNamePrefix%>.bat <%fileNamePrefix%>.makefile <%fileNamePrefix%>_init.xml
872+
endif
866873

867874
clean:
868875
<%\t%>rm -f OMCpp<%fileNamePrefix%>* <%fileNamePrefix%>_FMU.* <%fileNamePrefix%>.def <%fileNamePrefix%>.sh <%fileNamePrefix%>.bat <%fileNamePrefix%>.makefile <%fileNamePrefix%>_init.xml

OMEdit/OMEditLIB/FMI/FMUExportOutputWidget.cpp

Lines changed: 67 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,25 +50,23 @@
5050
FmuExportOutputWidget::FmuExportOutputWidget(LibraryTreeItem* pLibraryTreeItem, QWidget *pParent)
5151
: QWidget(pParent)
5252
{
53+
mTargetLanguage = OptionsDialog::instance()->getSimulationPage()->getTargetLanguageComboBox()->currentText();
5354
mpLibraryTreeItem = pLibraryTreeItem;
5455

55-
// set the FMU Name and the fmuTmpPath
56-
if (!OptionsDialog::instance()->getFMIPage()->getFMUNameTextBox()->text().isEmpty()) {
57-
/*
58-
* fix issue https://github.com/OpenModelica/OpenModelica/issues/12916,
59-
* use hashed string for fmu tmp directory
60-
*/
61-
QString hashedString = QString::number(stringHashDjb2(mmc_mk_scon(OptionsDialog::instance()->getFMIPage()->getFMUNameTextBox()->text().toUtf8().constData())));
56+
// set the FMU name
57+
const QString fmuNameText = OptionsDialog::instance()->getFMIPage()->getFMUNameTextBox()->text();
58+
mFMUName = fmuNameText.isEmpty() ? mpLibraryTreeItem->getName() : fmuNameText;
59+
60+
/*
61+
* set the fmuTmpPath
62+
* fix issue https://github.com/OpenModelica/OpenModelica/issues/12916,
63+
* use hashed string for fmu tmp directory
64+
*/
65+
if (mTargetLanguage.compare("C") == 0) {
66+
QString hashedString = QString::number(stringHashDjb2(mmc_mk_scon(mFMUName.toUtf8().constData())));
6267
mFmuTmpPath = QDir::currentPath().append("/").append(hashedString.left(3)+".fmutmp");
63-
mFMUName = OptionsDialog::instance()->getFMIPage()->getFMUNameTextBox()->text();
6468
} else {
65-
/*
66-
* fix issue https://github.com/OpenModelica/OpenModelica/issues/12916,
67-
* use hashed string for fmu tmp directory
68-
*/
69-
QString hashedString = QString::number(stringHashDjb2(mmc_mk_scon(mpLibraryTreeItem->getName().toUtf8().constData())));
70-
mFmuTmpPath = QDir::currentPath().append("/").append(hashedString.left(3)+".fmutmp");
71-
mFMUName = mpLibraryTreeItem->getName();
69+
mFmuTmpPath = QDir::currentPath();
7270
}
7371

7472
// progress label
@@ -88,7 +86,7 @@ FmuExportOutputWidget::FmuExportOutputWidget(LibraryTreeItem* pLibraryTreeItem,
8886
// Compilation Output TextBox
8987
mpCompilationOutputTextBox = new OutputPlainTextEdit;
9088
mpCompilationOutputTextBox->setFont(QFont(Helper::monospacedFontInfo.family()));
91-
mpGeneratedFilesTabWidget->addTab(mpCompilationOutputTextBox, tr("Generate Target Files"));
89+
mpGeneratedFilesTabWidget->addTab(mpCompilationOutputTextBox, tr("Configure"));
9290

9391
mpPostCompilationOutputTextBox = new OutputPlainTextEdit;
9492
mpPostCompilationOutputTextBox->setFont(QFont(Helper::monospacedFontInfo.family()));
@@ -157,7 +155,7 @@ void FmuExportOutputWidget::cancelCompilation()
157155
setPostCompilationProcessKilled(true);
158156
mpPostCompilationProcess->kill();
159157
mIsPostCompilationProcessRunning = false;
160-
progressStr = tr("Building cmake of %1 is cancelled.").arg(mpLibraryTreeItem->getName());
158+
progressStr = tr("Building of %1 is cancelled.").arg(mpLibraryTreeItem->getName());
161159
mpCancelButton->setEnabled(false);
162160
} else if (isZipCompilationProcessRunning()) {
163161
setZipCompilationProcessKilled(true);
@@ -186,7 +184,7 @@ void FmuExportOutputWidget::updateMessageTab(const QString &text)
186184
* \brief FmuExportOutputWidget::compileModel
187185
* generates cmake target files for the compiled model
188186
*/
189-
void FmuExportOutputWidget::compileModel()
187+
void FmuExportOutputWidget::compileModelCRuntime()
190188
{
191189
mpCompilationProcess = new QProcess;
192190
connect(mpCompilationProcess, SIGNAL(started()), SLOT(compilationProcessStarted()));
@@ -383,6 +381,37 @@ void FmuExportOutputWidget::runPostCompilation()
383381
mpGeneratedFilesTabWidget->setCurrentIndex(1);
384382
}
385383

384+
/*!
385+
* \brief FmuExportOutputWidget::compileModelCppRuntime
386+
* Runs the post compilation command after the compilation of the model.
387+
*/
388+
void FmuExportOutputWidget::compileModelCppRuntime()
389+
{
390+
mpPostCompilationProcess = new QProcess;
391+
connect(mpPostCompilationProcess, SIGNAL(started()), SLOT(postCompilationProcessStarted()));
392+
connect(mpPostCompilationProcess, SIGNAL(readyReadStandardOutput()), SLOT(readPostCompilationStandardOutput()));
393+
connect(mpPostCompilationProcess, SIGNAL(readyReadStandardError()), SLOT(readPostCompilationStandardError()));
394+
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
395+
connect(mpPostCompilationProcess, SIGNAL(errorOccurred(QProcess::ProcessError)), SLOT(postCompilationProcessError(QProcess::ProcessError)));
396+
#else
397+
connect(mpPostCompilationProcess, SIGNAL(error(QProcess::ProcessError)), SLOT(postCompilationProcessError(QProcess::ProcessError)));
398+
#endif
399+
connect(mpPostCompilationProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(postCompilationProcessFinished(int, QProcess::ExitStatus)));
400+
401+
// set the current directory to makefile directory
402+
MainWindow::instance()->getOMCProxy()->changeDirectory(mFmuTmpPath);
403+
404+
QString program = "make";
405+
QStringList arguments;
406+
arguments << "-f" << mFMUName + "_FMU.makefile" << "ZIP_FMU=OFF";
407+
408+
writePostCompilationOutput(QString("%1 %2\n").arg(program, arguments.join(" ")), Qt::blue);
409+
mpPostCompilationProcess->start(program, arguments);
410+
mpGeneratedFilesTabWidget->setTabEnabled(1, true);
411+
mpGeneratedFilesTabWidget->setTabEnabled(0, false);
412+
mpGeneratedFilesTabWidget->setCurrentIndex(1);
413+
}
414+
386415
/*!
387416
* \brief FmuExportOutputWidget::postCompilationProcessStarted
388417
* Slot activated when mpPostCompilationProcess started signal is raised.\n
@@ -391,10 +420,14 @@ void FmuExportOutputWidget::runPostCompilation()
391420
void FmuExportOutputWidget::postCompilationProcessStarted()
392421
{
393422
mIsPostCompilationProcessRunning = true;
394-
const QString progressStr = tr("Building cmake of %1.").arg(mpLibraryTreeItem->getName());
423+
const QString progressStr = tr("Building %1").arg(mpLibraryTreeItem->getName());
395424
mpProgressLabel->setText(progressStr);
396425
mpProgressBar->setTextVisible(true);
397-
mpProgressBar->setMaximum(100);
426+
if (mTargetLanguage.compare("C")==0) {
427+
mpProgressBar->setMaximum(100);
428+
} else {
429+
mpProgressBar->setRange(0, 0);
430+
}
398431
updateMessageTab(progressStr);
399432
mpCancelButton->setText(tr("Cancel Compilation"));
400433
mpCancelButton->setEnabled(true);
@@ -407,13 +440,16 @@ void FmuExportOutputWidget::postCompilationProcessStarted()
407440
void FmuExportOutputWidget::readPostCompilationStandardOutput()
408441
{
409442
QString output = mpPostCompilationProcess->readAllStandardOutput();
410-
// Regular expression to capture progress percentage (e.g., "[ 12%]")
411-
QRegularExpression regex("\\[\\s*(\\d+)%\\]");
412-
QRegularExpressionMatch match = regex.match(output);
413-
if (match.hasMatch()) {
414-
int currentStep = match.captured(1).toInt();
415-
// Update the progress bar
416-
mpProgressBar->setValue(currentStep);
443+
444+
if (mTargetLanguage.compare("C")==0) {
445+
// Regular expression to capture progress percentage (e.g., "[ 12%]")
446+
QRegularExpression regex("\\[\\s*(\\d+)%\\]");
447+
QRegularExpressionMatch match = regex.match(output);
448+
if (match.hasMatch()) {
449+
int currentStep = match.captured(1).toInt();
450+
// Update the progress bar
451+
mpProgressBar->setValue(currentStep);
452+
}
417453
}
418454
writePostCompilationOutput(output, Qt::black);
419455
}
@@ -455,7 +491,7 @@ void FmuExportOutputWidget::postCompilationProcessFinished(int exitCode, QProces
455491
mIsPostCompilationProcessRunning = false;
456492
QString exitCodeStr = tr("Post compilation process failed. Exited with code %1.").arg(Utilities::formatExitCode(exitCode));
457493
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
458-
writePostCompilationOutput(tr("Build cmake finished successfully.\n"), Qt::blue);
494+
writePostCompilationOutput(tr("Build finished successfully.\n"), Qt::blue);
459495
postCompilationProcessFinishedHelper(exitCode, exitStatus);
460496
zipFMU();
461497
} else if (mpCompilationProcess->error() == QProcess::UnknownError) {
@@ -479,9 +515,9 @@ void FmuExportOutputWidget::postCompilationProcessFinishedHelper(int exitCode, Q
479515
mpCancelButton->setEnabled(false);
480516
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
481517
mpProgressBar->setValue(mpProgressBar->maximum());
482-
progressStr = tr("Build cmake of %1 finished.").arg(mpLibraryTreeItem->getName());
518+
progressStr = tr("Build of %1 finished.").arg(mpLibraryTreeItem->getName());
483519
} else {
484-
progressStr = tr("Build cmake of %1 failed.").arg(mpLibraryTreeItem->getName());
520+
progressStr = tr("Build of %1 failed.").arg(mpLibraryTreeItem->getName());
485521
}
486522
mpProgressLabel->setText(progressStr);
487523
updateMessageTab(progressStr);
@@ -554,7 +590,7 @@ void FmuExportOutputWidget::zipFMU()
554590
void FmuExportOutputWidget::ZipCompilationProcessStarted()
555591
{
556592
mIsZipCompilationProcessRunning = true;
557-
const QString progressStr = tr("Zipping of %1.").arg(mpLibraryTreeItem->getName());
593+
const QString progressStr = tr("Zipping of %1").arg(mpLibraryTreeItem->getName());
558594
mpProgressLabel->setText(progressStr);
559595
mpProgressBar->setRange(0, 0);
560596
mpProgressBar->setTextVisible(false);

OMEdit/OMEditLIB/FMI/FMUExportOutputWidget.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,12 @@ class FmuExportOutputWidget : public QWidget
6565
QString getFMUPath() {return mFmuLocationPath;}
6666
void updateMessageTab(const QString &text);
6767
void updateMessageTabProgress();
68-
void compileModel();
68+
void compileModelCRuntime();
69+
void compileModelCppRuntime();
6970
private:
7071
QString mFmuTmpPath;
7172
QString mFMUName;
73+
QString mTargetLanguage;
7274
QString mFmuLocationPath;
7375
LibraryTreeItem *mpLibraryTreeItem;
7476
Label *mpProgressLabel;

OMEdit/OMEditLIB/MainWindow.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,14 @@ void MainWindow::checkAllModels(LibraryTreeItem *pLibraryTreeItem)
11701170

11711171
void MainWindow::exportModelFMU(LibraryTreeItem *pLibraryTreeItem)
11721172
{
1173+
// check for supported targetLanguage C or Cpp
1174+
QString targetLanguage = OptionsDialog::instance()->getSimulationPage()->getTargetLanguageComboBox()->currentText();
1175+
if (targetLanguage.compare("C") != 0 && targetLanguage.compare("Cpp") != 0) {
1176+
MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, tr("Target Language <b>%1</b> is not supported for FMU Export. Only <b>C</b> and <b>Cpp</b> are supported").arg(targetLanguage),
1177+
tr("FMU_EXPORT Failed"), Helper::errorLevel));
1178+
return;
1179+
}
1180+
11731181
/* if Modelica text is changed manually by user then validate it before saving. */
11741182
if (pLibraryTreeItem->getModelWidget()) {
11751183
if (!pLibraryTreeItem->getModelWidget()->validateText(&pLibraryTreeItem)) {
@@ -1186,9 +1194,13 @@ void MainWindow::exportModelFMU(LibraryTreeItem *pLibraryTreeItem)
11861194
* see https://github.com/OpenModelica/OpenModelica/issues/12171, to have short temp directory path and dump the files in it.
11871195
*/
11881196
QString modelDirectoryPath = QString("%1/%2%3").arg(OptionsDialog::instance()->getGeneralSettingsPage()->getWorkingDirectory(), pLibraryTreeItem->getName(), Utilities::generateHash(pLibraryTreeItem->getNameStructure()));
1189-
if (!QDir().exists(modelDirectoryPath)) {
1190-
QDir().mkpath(modelDirectoryPath);
1197+
1198+
QDir dir(modelDirectoryPath);
1199+
if (dir.exists()) {
1200+
dir.removeRecursively();
11911201
}
1202+
dir.mkpath(modelDirectoryPath);
1203+
11921204
// set the folder as working directory
11931205
MainWindow::instance()->getOMCProxy()->changeDirectory(modelDirectoryPath);
11941206
// buildModelFMU parameters
@@ -1227,7 +1239,11 @@ void MainWindow::exportModelFMU(LibraryTreeItem *pLibraryTreeItem)
12271239
// create a FMU compilation window similar to simulation process
12281240
FmuExportOutputWidget * pFmuExportOutputWidget = new FmuExportOutputWidget(pLibraryTreeItem, this);
12291241
MessagesWidget::instance()->addSimulationOutputTab(pFmuExportOutputWidget, pLibraryTreeItem->getName() + "_fmuExport");
1230-
pFmuExportOutputWidget->compileModel();
1242+
if (targetLanguage.compare("C") == 0) {
1243+
pFmuExportOutputWidget->compileModelCRuntime();
1244+
} else {
1245+
pFmuExportOutputWidget->compileModelCppRuntime();
1246+
}
12311247
} else {
12321248
MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, QString("Translation of FMU: <b>%1</b> Failed").arg(pLibraryTreeItem->getName()),
12331249
"Translation Error", Helper::errorLevel));

0 commit comments

Comments
 (0)