Skip to content

Use -lfmilib_shared instead of -lfmilib - #15864

Merged
adrpo merged 6 commits into
OpenModelica:masterfrom
adeas31:fmilib-linking
Jun 19, 2026
Merged

adrpo merged 6 commits into
OpenModelica:masterfrom
adeas31:fmilib-linking

Conversation

@adeas31

@adeas31 adeas31 commented Jun 18, 2026

Copy link
Copy Markdown
Member

Since OpenModelicaFMIRuntimeC is linked with fmilib_shared Restored several FMI import tests. Some of them are still failing.

Since `OpenModelicaFMIRuntimeC` is linked with `fmilib_shared`
Restored several FMI import tests. Some of them are still failing.
@adeas31
adeas31 requested a review from adrpo June 18, 2026 12:48
@adeas31 adeas31 self-assigned this Jun 18, 2026
The FMIL CMake build only produces libfmilib.a (static) and
libfmilib_shared.dll (+ import lib). The extra libfmilib.dll seen in
build/lib/omc came from the `fmil` install rule in Makefile.common,
which aliases libfmilib$(SHREXT) -> libfmilib_shared$(SHREXT) so that
`-lfmilib` resolves to the shared lib on Linux/macOS. On Windows
SHREXT=.dll and MSYS `ln -sf` copies the file, producing a real
libfmilib.dll next to libfmilib.a and making `-lfmilib` ambiguous.

Guard the alias so it is skipped when SHREXT==.dll (Windows). With the
stray DLL gone, `-lfmilib` links the static libfmilib.a again, so revert
the SimCodeFunctionUtil.mo workaround back to `-lfmilib`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@adrpo adrpo added CI/Build MSYS2-UCRT64 Build pull request with Windows MSYS2 UCRT64 CI/CMake/Enable/MSYS2-UCRT64 labels Jun 18, 2026
adrpo and others added 3 commits June 18, 2026 19:47
The Windows-only "Sanity check - testsuite" stage runs a few quick
testsuite models via rtest. Add the FMI ME 2.0 HelloFMIWorld roundtrip
(buildModelFMU -> importFMU -> simulate). The simulate step compiles and
links the generated FMU-import code with -lfmilib, so this guards against
a regression where a stray libfmilib.dll makes -lfmilib ambiguous on
Windows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>
The 6 re-enabled FMI ModelExchange/2.0 import tests still failed on CI
with "Output mismatch" because their // Result: blocks were stale:
- buildModelFMU now names the FMU by the short class name
  (e.g. initial_equation1.fmu, not initializationTestsFMI.initial_equation1.fmu)
- the assert/simulation log format changed
- numeric results drifted within solver tolerance

Regenerate the reference output with rtest -b and upgrade the MSL
dependency to 4.1.0 for the library-based ones (ChuaCircuit, Pendulum,
DoublePendulum, testChangeParam). All six now pass locally; verified
stable across repeated runs. omc-diff normalises numeric tokens, so the
1e-6/1e-06 tolerance formatting is platform-independent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>
The generated FMU-import executable links -lOpenModelicaFMIRuntimeC -lfmilib
(static). But libOpenModelicaFMIRuntimeC.a was compiled with fmilib.h
declaring the FMI functions as __declspec(dllimport): since fmilib_shared
is also built, fmilib_config.h leaves FMILIB_STATIC_LIB_ONLY undefined and
a plain consumer gets dllimport. The objects then reference __imp_fmi2_*
symbols that the static libfmilib.a does not provide, so linking with
-lfmilib fails with "undefined reference to __imp_fmi2_*".

Compile the FMI runtime objects with -DFMILIB_STATIC_LIB_ONLY on MinGW so
fmilib.h emits plain (non-dllimport) symbols that resolve against the
static libfmilib.a. Follows the existing CMINPACK_NO_DLL pattern; the omc
compiler side already side-steps this in FMIImpl.c via FMILIB_BUILDING_LIBRARY.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@adrpo
adrpo enabled auto-merge (squash) June 18, 2026 20:37

@adrpo adrpo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it a bit

…lum ME 2.0 tests

The DoublePendulum and Pendulum Modelica.Mechanics.MultiBody examples
exceed the default limit of 20 event iterations when run as imported
ModelExchange 2.0 FMUs, aborting with LOG_ASSERT. Pass simflags="-mei=50"
to the FMU simulate calls and update the reference output accordingly
(adds the 'Maximum number of event iterations changed to 50' message and
drops the stale LOG_ASSERT lines from the Pendulum reference).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@adrpo
adrpo merged commit 7c5c63b into OpenModelica:master Jun 19, 2026
5 checks passed
adrpo added a commit that referenced this pull request Jun 19, 2026
* Use `-lfmilib_shared` instead of `-lfmilib` (#15864)

* Use `-lfmilib_shared` instead of `-lfmilib`

Since `OpenModelicaFMIRuntimeC` is linked with `fmilib_shared`
Restored several FMI import tests. Some of them are still failing.

* [FMI] Fix Windows build: stop generating stray libfmilib.dll

The FMIL CMake build only produces libfmilib.a (static) and
libfmilib_shared.dll (+ import lib). The extra libfmilib.dll seen in
build/lib/omc came from the `fmil` install rule in Makefile.common,
which aliases libfmilib$(SHREXT) -> libfmilib_shared$(SHREXT) so that
`-lfmilib` resolves to the shared lib on Linux/macOS. On Windows
SHREXT=.dll and MSYS `ln -sf` copies the file, producing a real
libfmilib.dll next to libfmilib.a and making `-lfmilib` ambiguous.

Guard the alias so it is skipped when SHREXT==.dll (Windows). With the
stray DLL gone, `-lfmilib` links the static libfmilib.a again, so revert
the SimCodeFunctionUtil.mo workaround back to `-lfmilib`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [CI] Add FMI import test to Windows sanity check

The Windows-only "Sanity check - testsuite" stage runs a few quick
testsuite models via rtest. Add the FMI ME 2.0 HelloFMIWorld roundtrip
(buildModelFMU -> importFMU -> simulate). The simulate step compiles and
links the generated FMU-import code with -lfmilib, so this guards against
a regression where a stray libfmilib.dll makes -lfmilib ambiguous on
Windows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>

* [FMI] Resolve references for re-enabled FMI 2.0 import tests

The 6 re-enabled FMI ModelExchange/2.0 import tests still failed on CI
with "Output mismatch" because their // Result: blocks were stale:
- buildModelFMU now names the FMU by the short class name
  (e.g. initial_equation1.fmu, not initializationTestsFMI.initial_equation1.fmu)
- the assert/simulation log format changed
- numeric results drifted within solver tolerance

Regenerate the reference output with rtest -b and upgrade the MSL
dependency to 4.1.0 for the library-based ones (ChuaCircuit, Pendulum,
DoublePendulum, testChangeParam). All six now pass locally; verified
stable across repeated runs. omc-diff normalises numeric tokens, so the
1e-6/1e-06 tolerance formatting is platform-independent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>

* [FMI] Build FMI runtime against static fmilib on MinGW

The generated FMU-import executable links -lOpenModelicaFMIRuntimeC -lfmilib
(static). But libOpenModelicaFMIRuntimeC.a was compiled with fmilib.h
declaring the FMI functions as __declspec(dllimport): since fmilib_shared
is also built, fmilib_config.h leaves FMILIB_STATIC_LIB_ONLY undefined and
a plain consumer gets dllimport. The objects then reference __imp_fmi2_*
symbols that the static libfmilib.a does not provide, so linking with
-lfmilib fails with "undefined reference to __imp_fmi2_*".

Compile the FMI runtime objects with -DFMILIB_STATIC_LIB_ONLY on MinGW so
fmilib.h emits plain (non-dllimport) symbols that resolve against the
static libfmilib.a. Follows the existing CMINPACK_NO_DLL pattern; the omc
compiler side already side-steps this in FMIImpl.c via FMILIB_BUILDING_LIBRARY.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: Adrian Pop <adrian.pop@liu.se>
Co-authored-by: Adrian Pop <adrian.pop@liu.se>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [FMI] Fix broken FMI 1.0 model-exchange export (#15838) (#15845)

* [FMI] Fix broken FMI 1.0 model-exchange export (#15838)

FMI 1.0 ME export (fmuType="me", version="1.0") was completely broken
while FMI 2.0 worked: the legacy FMI 1.0 runtime had drifted from the
maintained FMI 2.0 path. Fixed across 4 source files:

- SimCode/SimCodeMain.mo: guard the fmu2_model_interface.c model-defines
  patch with FMUVersion <> "1.0" (that file does not exist for FMI 1.0).
- Template/CodegenFMU.tpl: FMI 1.0 <Model>_FMU.h now includes
  fmu1_model_interface.h (types + ModelInstance) before the .c.inc
  implementation, drops the bogus fmi2Functions.h include, and emits the
  .c.inc after the forward declarations it calls.
- fmi/export/buildproject/CMakeLists.txt.in: exclude *_info.c from the
  compiled-source glob (it is an include-only string literal #included
  into <Model>_init_fmu.c).
- fmi/export/openmodelica/fmu1_model_interface.c.inc: add missing
  includes; switch fmiInstantiateModel from Boehm GC (not linked) to the
  memory pool; add read_simulation_info / allocModelDataVars /
  scalarAllocArrayAttributes / calculateAllScalarLength before
  initializeDataStruc; fix 1-arg read_input_fmu; LOG_EVENTS ->
  OMC_LOG_EVENTS; fix inverted getNextSampleTimeFMU upcomingTimeEvent
  logic; use updateDiscreteSystem; report iterationConverged=false when
  discrete changes; re-evaluate functionDAE after deactivating samples
  so when(sample()) clauses fire (fmpy does not call
  fmiCompletedIntegratorStep for FMI 1.0).

Adds a testsuite test (FMI1MEfmpy.mos) that exports a few FMI 1.0 ME
FMUs (continuous, time/sample event, and state event models) and
validates each one with an independent FMI importer (FMPy): the model is
simulated both in OpenModelica and as an exported FMU, and the two result
sets are compared with diffSimulationResults(). Uses the shared
testsuite/openmodelica/fmi/simulate_fmu_fmpy.py helper. Also updates the
ModelExchange/1.0 testsuite test lists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>

* [testsuite] partest: link python helper scripts into the sandbox

FMI1MEfmpy.mos invokes system("python3 ../../simulate_fmu_fmpy.py ...").
That path is correct for an in-place run but partest runs each test in a
_temp subdirectory one level deeper, so ../../ no longer reaches the helper
and the test failed with "No such file or directory".

Handle this generally in runtest.pl: detect python invocations during
sandbox setup and recreate the referenced script at the exact path the test
uses, pointing at the real file with an absolute target so it resolves
regardless of how many '../' the path contains. The link is created outside
the sandbox and removed again in exit_sandbox() so it does not pollute the
testsuite tree.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>

---------

Signed-off-by: Adrian Pop <adrian.pop@liu.se>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [FMI] Fix FMI 1.0 model-exchange CVODE build + direct-feedthrough outputs (#15862) (#15863)

Two follow-up fixes to #15838 for the FMI 1.0 model-exchange export.

1. Don't pull CVODE into FMI 1.0 exports.
   Exporting with --fmiFlags=s:cvode copied the sundials sources
   (cvode_solver.c/sundials_error.c) into the FMU and compiled them, but
   cvode_solver.h includes the FMI 2.0 header fmi-export/fmu2_model_interface.h,
   which does not exist in an FMI 1.0 export (it only ships
   fmu1_model_interface.h):

     cvode_solver.h:34:12: fatal error:
     'fmi-export/fmu2_model_interface.h' file not found

   The in-FMU CVODE integrator drives the fmi2 ModelInstance / fmi2DoStep API,
   i.e. it is a Co-Simulation feature, and OpenModelica only exports FMI 1.0 as
   Model Exchange (CS export requires FMI 2.0, see FMI.canExportFMU). A
   model-exchange FMU is integrated by the importer, so an in-FMU integrator
   does not apply.

   SimCode/SimCodeMain.mo: for FMUVersion == "1.0" skip copying the sundials
   sources, keep NEED_CVODE=OFF in the generated FMU CMakeLists, and warn that
   the 's:cvode' flag is ignored.

2. Re-evaluate direct-feedthrough outputs on fmiGetReal.
   A stateless algebraic model (e.g. y = 2*u) exported as FMI 1.0 ME always
   reported y = 0: with no continuous states an importer never calls
   fmiGetDerivatives, and fmiGetReal returned the stored value without
   re-evaluating the model after fmiSetReal/fmiSetTime. Ported the
   _need_update dirty-flag mechanism from fmu2_model_interface.c to the FMI 1.0
   interface: the fmiSet* functions mark the model dirty and fmiGet*
   re-evaluate it (functionODE/algebraics/output) before reading, clearing the
   flag in fmiInitialize/fmiEventUpdate/fmiCompletedIntegratorStep/
   fmiGetDerivatives. Verified with FMPy: the gain model now returns y = 2*u.

Tests (testsuite ModelExchange/1.0):
- FMI1MEcvodeFlag.mos: exports an FMI 1.0 ME FMU with --fmiFlags=s:cvode,
  checks it builds, the warning is emitted, and NEED_CVODE is OFF.
- FMI1MEInputOutput.mos: exports the issue's reproducer (a Modelica.Blocks
  gain with a Real input and output) as FMI 1.0 ME.
- FMI1MEfmpy.mos: adds a stateless DirectFeedthrough (y = 2*time) model and
  validates it through FMPy; without fix 2 FMPy reads y = 0.

Follow-up to #15838.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Enable OMOptim build and bump submodule to resurrected version (#15839)

* Enable OMOptim build and bump submodule to resurrected version

Bump the OMOptim submodule to bb7164b, which replaces the dead
CORBA/OmcCommunicator link with in-process libOpenModelicaCompiler,
drives simulations via -overrideFile, and adds a CMake build.

Add the OM_OMOPTIM_ENABLE option (OFF by default) and, under
OM_ENABLE_GUI_CLIENTS, gate omc_add_subdirectory(OMOptim) behind it.

Refs #14506

* Bump OMOptim submodule to fixed unix build (c84b399)

Picks up OMOptim #29, which removes the dead CORBA omc_communication
step from Makefile.unix.in and bumps the bundled ParadisEO CMake minimum
to 3.5, fixing the OMOptim configure/build failures on the CI.

Refs #14506

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: Adrian Pop <adrian.pop@liu.se>
Co-authored-by: Adeel Asghar <adeel.asghar@liu.se>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@adeas31
adeas31 deleted the fmilib-linking branch June 22, 2026 12:38
adrpo added a commit to SVAGEN26/OpenModelica that referenced this pull request Jun 22, 2026
* Use `-lfmilib_shared` instead of `-lfmilib`

Since `OpenModelicaFMIRuntimeC` is linked with `fmilib_shared`
Restored several FMI import tests. Some of them are still failing.

* [FMI] Fix Windows build: stop generating stray libfmilib.dll

The FMIL CMake build only produces libfmilib.a (static) and
libfmilib_shared.dll (+ import lib). The extra libfmilib.dll seen in
build/lib/omc came from the `fmil` install rule in Makefile.common,
which aliases libfmilib$(SHREXT) -> libfmilib_shared$(SHREXT) so that
`-lfmilib` resolves to the shared lib on Linux/macOS. On Windows
SHREXT=.dll and MSYS `ln -sf` copies the file, producing a real
libfmilib.dll next to libfmilib.a and making `-lfmilib` ambiguous.

Guard the alias so it is skipped when SHREXT==.dll (Windows). With the
stray DLL gone, `-lfmilib` links the static libfmilib.a again, so revert
the SimCodeFunctionUtil.mo workaround back to `-lfmilib`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [CI] Add FMI import test to Windows sanity check

The Windows-only "Sanity check - testsuite" stage runs a few quick
testsuite models via rtest. Add the FMI ME 2.0 HelloFMIWorld roundtrip
(buildModelFMU -> importFMU -> simulate). The simulate step compiles and
links the generated FMU-import code with -lfmilib, so this guards against
a regression where a stray libfmilib.dll makes -lfmilib ambiguous on
Windows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>

* [FMI] Resolve references for re-enabled FMI 2.0 import tests

The 6 re-enabled FMI ModelExchange/2.0 import tests still failed on CI
with "Output mismatch" because their // Result: blocks were stale:
- buildModelFMU now names the FMU by the short class name
  (e.g. initial_equation1.fmu, not initializationTestsFMI.initial_equation1.fmu)
- the assert/simulation log format changed
- numeric results drifted within solver tolerance

Regenerate the reference output with rtest -b and upgrade the MSL
dependency to 4.1.0 for the library-based ones (ChuaCircuit, Pendulum,
DoublePendulum, testChangeParam). All six now pass locally; verified
stable across repeated runs. omc-diff normalises numeric tokens, so the
1e-6/1e-06 tolerance formatting is platform-independent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>

* [FMI] Build FMI runtime against static fmilib on MinGW

The generated FMU-import executable links -lOpenModelicaFMIRuntimeC -lfmilib
(static). But libOpenModelicaFMIRuntimeC.a was compiled with fmilib.h
declaring the FMI functions as __declspec(dllimport): since fmilib_shared
is also built, fmilib_config.h leaves FMILIB_STATIC_LIB_ONLY undefined and
a plain consumer gets dllimport. The objects then reference __imp_fmi2_*
symbols that the static libfmilib.a does not provide, so linking with
-lfmilib fails with "undefined reference to __imp_fmi2_*".

Compile the FMI runtime objects with -DFMILIB_STATIC_LIB_ONLY on MinGW so
fmilib.h emits plain (non-dllimport) symbols that resolve against the
static libfmilib.a. Follows the existing CMINPACK_NO_DLL pattern; the omc
compiler side already side-steps this in FMIImpl.c via FMILIB_BUILDING_LIBRARY.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: Adrian Pop <adrian.pop@liu.se>
Co-authored-by: Adrian Pop <adrian.pop@liu.se>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrian Pop <adrian.pop@liu.se>
adrpo added a commit to adrpo/OpenModelica that referenced this pull request Aug 3, 2026
A Modelica Boolean is an int (modelica_boolean), and that is what the code
generated for an external "C" function passes:

  int* _booleanValues_c89 = data_of_boolean_c89_array(_booleanValues);
  fmi2GetBoolean_OMC(..., _booleanValues_c89);

fmi2GetBoolean_OMC declared the parameter as signed char* and filled it through
an int_to_signedchar conversion, so it wrote one byte of every four and the
caller read the other three from whatever happened to be on the heap. An
imported FMU read its booleans as values like -787477503, differing from run to
run. An external "C" declaration has no prototype at the call site, so nothing
diagnosed the mismatch.

Take int*, as the FMI 1.0 wrapper always has, and drop the two conversion
helpers, which existed only for the byte assumption. There is no FMI 3.0 import
runtime yet; when there is, its booleans are int as well.

This is why the FMI import tests disabled in OpenModelica#8728 still failed after OpenModelica#15864
restored the rest: BooleanNetwork1 and Modelica.Blocks.Sources.BooleanPulse read
garbage instead of their boolean outputs, and FMIExercise reads
newStatesAvailable through the same path, which made its event handling
non-deterministic.

Part of OpenModelica#15913.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0194DfNv58DKpeCd52ZdnK7J
Signed-off-by: Adrian Pop <adrian.pop@liu.se>
adrpo added a commit to adrpo/OpenModelica that referenced this pull request Aug 3, 2026
OpenModelica#8728 moved 15 FMI import tests into FAILING_FMI_IMPORT, a list no make target
references, in March 2022. OpenModelica#15864 fixed the linking problem behind most of them
and restored 11. The remaining four are fixed by the two preceding commits:
BooleanNetwork1, Modelica.Blocks.Sources.BooleanPulse and FMIExercise by the
boolean type in the import runtime, BouncingBall by the FMU reporting an event
that changed its continuous states. FAILING_FMI_IMPORT is now empty and gone.

Each of the four reproduces the values it asserted before it was disabled; the
references were not simply regenerated from whatever the current build produces.
BooleanNetwork1 and FMIExercise compare the imported FMU against the native
simulation of the same model, and they now agree.

The tests are also brought up to date, which is what OpenModelica#15864 did for the other
11 and is needed for them to run at all:

- buildModelFMU names the FMU after the last identifier of the class, so a model
  inside a package is written as BooleanPulse.fmu rather than
  Modelica.Blocks.Sources.BooleanPulse.fmu; importFMU, the generated wrapper and
  the teardown follow.
- Modelica 3.2.1 is not installed any more; BooleanPulse uses 4.1.0.
- The imported wrapper needs --allowNonStandardModelica=reinitInAlgorithms.
- -d=-newInst is dropped: they run on the new frontend.

testExperimentalFMU stays in FAILINGTESTFILES, now with a note on what actually
fails. It passes version="2" where buildModelFMU wants "2.0", and once that is
corrected the FMU builds but the generated sources no longer contain
advection_functionODE_Partial, which is what the test greps for -- the
fmuExperimental codegen it covers is gone, so regenerating its reference would
leave a test that asserts nothing.

Part of OpenModelica#15913.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0194DfNv58DKpeCd52ZdnK7J
Signed-off-by: Adrian Pop <adrian.pop@liu.se>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI/Build MSYS2-UCRT64 Build pull request with Windows MSYS2 UCRT64

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants