From 5a3a260e707ccfce7ec3c1f779f23fe8b0468175 Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 14:25:46 +0200 Subject: [PATCH 01/11] CI: revive workflows for Julia 1.12 (Ubuntu + Windows) - checkout@v4 with recursive submodules; julia-actions v2 stack - Julia 1.12 (matches [compat]/[sources]); drop macOS and stale 1.7 - non-blocking Codecov v4 - add opt-in julia-nightly.yml forward-guard (manual + weekly, non-gating) Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/CI.yml | 73 ++++++++++++++--------------- .github/workflows/julia-nightly.yml | 45 ++++++++++++++++++ 2 files changed, 80 insertions(+), 38 deletions(-) create mode 100644 .github/workflows/julia-nightly.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index fb8467f..f58ae77 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,56 +2,53 @@ name: CI on: pull_request: push: - branches: - - master - tags: '*' + branches: [master] + tags: ['*'] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + jobs: test: - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + name: Julia ${{ matrix.version }} - ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: - fail-fast: true + fail-fast: false matrix: - include: - - os: windows-latest - arch: 'x64' - version: '1.7' - - os: ubuntu-latest - arch: 'x64' - version: '1.7' - - os: macos-latest - arch: 'x64' - version: '1.7' + version: ['1.12'] + os: [ubuntu-latest, windows-latest] + arch: [x64] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + submodules: recursive - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: actions/cache@v1 - env: - cache-name: cache-artifacts - with: - path: ~/.julia/artifacts - key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} - restore-keys: | - ${{ runner.os }}-test-${{ env.cache-name }}- - ${{ runner.os }}-test- - ${{ runner.os }}- - - name: Build - # Use bash always to avoid having to escape quotes for Windows - shell: bash - run: julia --compiled-modules=no --color=yes --project -e 'import Pkg; Pkg.Registry.add("General"); Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")); Pkg.build(;verbose = true);Pkg.instantiate()' + - uses: julia-actions/cache@v2 - - name: Test - uses: julia-actions/julia-runtest@v1 + - name: Add registries + instantiate + shell: bash + run: | + julia --color=yes --project -e ' + import Pkg + Pkg.Registry.add("General") + Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) + Pkg.instantiate() + Pkg.build(; verbose=true)' - - name: Calculate process coverage - uses: julia-actions/julia-processcoverage@v1 + - uses: julia-actions/julia-runtest@v1 - - name: Coverage report - uses: codecov/codecov-action@v1 + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v4 with: - file: lcov.info + files: lcov.info + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/julia-nightly.yml b/.github/workflows/julia-nightly.yml new file mode 100644 index 0000000..abb72ac --- /dev/null +++ b/.github/workflows/julia-nightly.yml @@ -0,0 +1,45 @@ +name: Julia nightly +# Forward-guard against the next Julia. Not part of PR gating: runs on a +# weekly schedule and manual dispatch only, so a break here never blocks a +# merge. +on: + workflow_dispatch: + schedule: + - cron: '11 7 * * 1' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + test-nightly: + name: Julia ${{ matrix.version }} - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + version: ['nightly'] + os: [ubuntu-latest, windows-latest] + arch: [x64] + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: julia-actions/setup-julia@v2 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: julia-actions/cache@v2 + - name: Add registries + instantiate + shell: bash + run: | + julia --color=yes --project -e ' + import Pkg + Pkg.Registry.add("General") + Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) + Pkg.instantiate() + Pkg.build(; verbose=true)' + - uses: julia-actions/julia-runtest@v1 From 424a2c99eff8e00f621f2c07998078f0e6f5389e Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 14:38:55 +0200 Subject: [PATCH 02/11] docs: add Documenter site (install + API) with Pages deploy - docs/ scaffold: index, installation, examples, API reference - API page pulls existing docstrings for OM.simulate/translate/flatten, library loaders, and result export - docs.yml: build on PR, deploy to gh-pages on master/tags via GITHUB_TOKEN - warnonly=true for initial deploys; tighten once API pages are complete Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/docs.yml | 45 ++++++++++++++++++++++++++++ docs/Project.toml | 9 ++++++ docs/make.jl | 27 +++++++++++++++++ docs/src/api.md | 32 ++++++++++++++++++++ docs/src/examples.md | 32 ++++++++++++++++++++ docs/src/index.md | 22 ++++++++++++++ docs/src/installation.md | 61 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 228 insertions(+) create mode 100644 .github/workflows/docs.yml create mode 100644 docs/Project.toml create mode 100644 docs/make.jl create mode 100644 docs/src/api.md create mode 100644 docs/src/examples.md create mode 100644 docs/src/index.md create mode 100644 docs/src/installation.md diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..557ec19 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,45 @@ +name: Documentation +on: + push: + branches: [master] + tags: ['*'] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write # deploydocs pushes the built site to the gh-pages branch + statuses: write + +jobs: + docs: + name: Build and deploy docs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: julia-actions/setup-julia@v2 + with: + version: '1.12' + + - uses: julia-actions/cache@v2 + + - name: Instantiate docs environment + shell: bash + run: | + julia --project=docs --color=yes -e ' + import Pkg + Pkg.Registry.add("General") + Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) + Pkg.instantiate()' + + - name: Build and deploy + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} + run: julia --project=docs --color=yes docs/make.jl diff --git a/docs/Project.toml b/docs/Project.toml new file mode 100644 index 0000000..a8b459b --- /dev/null +++ b/docs/Project.toml @@ -0,0 +1,9 @@ +[deps] +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +OM = "2f925a0b-2436-437b-858e-49aee461894b" + +[sources] +OM = {path = ".."} + +[compat] +Documenter = "1" diff --git a/docs/make.jl b/docs/make.jl new file mode 100644 index 0000000..3bd870b --- /dev/null +++ b/docs/make.jl @@ -0,0 +1,27 @@ +using Documenter +using OM + +makedocs( + sitename = "OM.jl", + authors = "John Tinnerholm and contributors", + modules = [OM], + format = Documenter.HTML( + prettyurls = get(ENV, "CI", "false") == "true", + canonical = "https://JKRT.github.io/OM.jl", + ), + pages = [ + "Home" => "index.md", + "Installation" => "installation.md", + "Examples" => "examples.md", + "API reference" => "api.md", + ], + # Keep the first deploys from hard-failing on as-yet-undocumented bindings + # or cross-reference gaps; tighten to `false` once the API pages are filled. + warnonly = true, +) + +deploydocs( + repo = "github.com/JKRT/OM.jl.git", + devbranch = "master", + push_preview = true, +) diff --git a/docs/src/api.md b/docs/src/api.md new file mode 100644 index 0000000..e1b3be3 --- /dev/null +++ b/docs/src/api.md @@ -0,0 +1,32 @@ +# API reference + +The public API is called through the `OM` module (functions are qualified, +e.g. `OM.simulate`). + +## Simulation and translation + +```@docs +OM.simulate +OM.translate +OM.flatten +OM.getMTKProblem +OM.resimulate +``` + +## Libraries + +```@docs +OM.loadLibrary +OM.loadPackage +OM.loadInstalledLibrary +OM.installLibrary +OM.libraries +``` + +## Output and inspection + +```@docs +OM.exportCSV +OM.writeModelToFile +OM.exportModelica +``` diff --git a/docs/src/examples.md b/docs/src/examples.md new file mode 100644 index 0000000..11fbd15 --- /dev/null +++ b/docs/src/examples.md @@ -0,0 +1,32 @@ +# Examples + +## A simple pendulum + +```julia +using OM +sol = OM.simulate("Modelica.Mechanics.MultiBody.Examples.Elementary.Pendulum"; + MSL_Version = "MSL:3.2.3", stopTime = 1.0) +``` + +## Translate without simulating + +Build the in-memory model (frontend + backend) and inspect or solve it later: + +```julia +OM.translate("Modelica.Electrical.Analog.Examples.DifferenceAmplifier"; + MSL_Version = "MSL:3.2.3") +prob = OM.getMTKProblem("Modelica.Electrical.Analog.Examples.DifferenceAmplifier") +``` + +## Flatten only (frontend) + +```julia +(flatModel, functions) = OM.flatten("Modelica.Mechanics.MultiBody.Examples.Elementary.Pendulum") +``` + +## Export results + +```julia +sol = OM.simulate("Modelica....SomeModel"; MSL_Version = "MSL:3.2.3", stopTime = 1.0) +OM.exportCSV(sol, "result.csv") +``` diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..c749815 --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,22 @@ +# OM.jl + +OM.jl is a Modelica compiler written in Julia. It takes Modelica models +(including the Modelica Standard Library), flattens and lowers them through a +Julia frontend and backend, and simulates them via the +[SciML](https://sciml.ai) / ModelingToolkit ecosystem. + +The typical user flow is a single call: + +```julia +using OM +sol = OM.simulate("Modelica.Mechanics.MultiBody.Examples.Elementary.Pendulum"; + MSL_Version = "MSL:3.2.3", stopTime = 1.0) +``` + +- **[Installation](installation.md)** — how to get OM.jl and its submodules set up. +- **[Examples](examples.md)** — worked simulations. +- **[API reference](api.md)** — the public functions (`simulate`, `translate`, + `flatten`, library loading, result export). + +The pipeline is FRONTEND (parse → SCode → instantiate → type → flatten) → +BACKEND (BDAE → SimCode → code generation) → SIMULATE. diff --git a/docs/src/installation.md b/docs/src/installation.md new file mode 100644 index 0000000..afc59c1 --- /dev/null +++ b/docs/src/installation.md @@ -0,0 +1,61 @@ +# Installation + +OM.jl is a multi-package project: the compiler stages live in sibling +sub-packages (`OMFrontend.jl`, `OMBackend.jl`, `OMParser.jl`, …) that the +top-level `OM` package references through `Project.toml` `[sources]` paths. +Those sub-packages are git **submodules**, so they must be checked out. + +## Requirements + +- **Julia ≥ 1.12** (the project's `[compat]` pins `julia = "1.12"`, and the + `[sources]` table requires Julia ≥ 1.11). +- Git. + +## Clone with submodules + +```bash +git clone --recurse-submodules https://github.com/JKRT/OM.jl.git +cd OM.jl +``` + +If you already cloned without `--recurse-submodules`: + +```bash +git submodule update --init --recursive +``` + +## Instantiate + +OM.jl depends on packages registered in the General registry **and** in the +OpenModelica registry, so add both before instantiating: + +```julia +julia --project -e ' + import Pkg + Pkg.Registry.add("General") + Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) + Pkg.instantiate() + Pkg.build(; verbose = true)' +``` + +## First run + +```julia +using OM +sol = OM.simulate("Modelica.Mechanics.MultiBody.Examples.Elementary.Pendulum"; + MSL_Version = "MSL:3.2.3", stopTime = 1.0) +``` + +The first call compiles a large dependency tree (ModelingToolkit, +DifferentialEquations); subsequent runs in the same session are fast. + +## Other MSL versions and third-party libraries + +`MSL_Version` selects the bundled serialized MSL (3.2.3 or 4.0.0). To use an +installed-but-unbundled version or a third-party library, load it through the +general loader and pass the returned key: + +```julia +key = OM.loadInstalledLibrary("Modelica"; version = "4.1.0") +OM.simulate("Modelica....SomeModel"; libraries = [key]) +``` From 7d2aac672c39c2a4f7dc8cf7da206bae1bdc3291 Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 15:34:25 +0200 Subject: [PATCH 03/11] CI: build native libs before precompile (fixes OMParser load) instantiate auto-precompiles, but OMBackend's precompile workload loads OMParser whose native .so is produced by the build step. Disable auto-precompile during instantiate, run Pkg.build, then Pkg.precompile so the downloaded parser libraries exist first. Applied to CI, nightly, docs. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/CI.yml | 11 +++++++++-- .github/workflows/docs.yml | 8 ++++++-- .github/workflows/julia-nightly.yml | 7 +++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f58ae77..e05c8ca 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -34,15 +34,22 @@ jobs: - uses: julia-actions/cache@v2 - - name: Add registries + instantiate + - name: Add registries, build native libs, precompile shell: bash + # Build BEFORE precompile: OMParser downloads its native shared + # libraries in the build step, and OMBackend's precompile workload + # loads OMParser. Disable auto-precompile during instantiate, build, + # then precompile so the native libs exist first. + env: + JULIA_PKG_PRECOMPILE_AUTO: '0' run: | julia --color=yes --project -e ' import Pkg Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) Pkg.instantiate() - Pkg.build(; verbose=true)' + Pkg.build(; verbose=true) + Pkg.precompile()' - uses: julia-actions/julia-runtest@v1 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 557ec19..c121ad6 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -10,7 +10,7 @@ concurrency: cancel-in-progress: true permissions: - contents: write # deploydocs pushes the built site to the gh-pages branch + contents: write statuses: write jobs: @@ -30,12 +30,16 @@ jobs: - name: Instantiate docs environment shell: bash + env: + JULIA_PKG_PRECOMPILE_AUTO: '0' run: | julia --project=docs --color=yes -e ' import Pkg Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) - Pkg.instantiate()' + Pkg.instantiate() + Pkg.build(; verbose=true) + Pkg.precompile()' - name: Build and deploy shell: bash diff --git a/.github/workflows/julia-nightly.yml b/.github/workflows/julia-nightly.yml index abb72ac..9b3ea2b 100644 --- a/.github/workflows/julia-nightly.yml +++ b/.github/workflows/julia-nightly.yml @@ -33,13 +33,16 @@ jobs: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - uses: julia-actions/cache@v2 - - name: Add registries + instantiate + - name: Add registries, build native libs, precompile shell: bash + env: + JULIA_PKG_PRECOMPILE_AUTO: '0' run: | julia --color=yes --project -e ' import Pkg Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) Pkg.instantiate() - Pkg.build(; verbose=true)' + Pkg.build(; verbose=true) + Pkg.precompile()' - uses: julia-actions/julia-runtest@v1 From 469ed6dec8e2085dc3d112a4b46a30bed8a221bc Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 15:38:32 +0200 Subject: [PATCH 04/11] CI: build only native-artifact packages, skip OMBackend build.jl OMBackend's deps/build.jl is a standalone-dev script (Pkg.add of registry deps + rebuild of OMParser/OMFrontend). In the OM umbrella it is redundant and its build sandbox resolves relative ../DAE.jl sources to a nonexistent sibling path. OMBackend has no native artifact, so build only OMParser, OMRuntimeExternalC, OMFrontend; OMBackend is still precompiled normally. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/CI.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/julia-nightly.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e05c8ca..0e4d977 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -48,7 +48,7 @@ jobs: Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) Pkg.instantiate() - Pkg.build(; verbose=true) + Pkg.build(["OMParser", "OMRuntimeExternalC", "OMFrontend"]; verbose=true) Pkg.precompile()' - uses: julia-actions/julia-runtest@v1 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c121ad6..5afac46 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -38,7 +38,7 @@ jobs: Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) Pkg.instantiate() - Pkg.build(; verbose=true) + Pkg.build(["OMParser", "OMRuntimeExternalC", "OMFrontend"]; verbose=true) Pkg.precompile()' - name: Build and deploy diff --git a/.github/workflows/julia-nightly.yml b/.github/workflows/julia-nightly.yml index 9b3ea2b..c8e8a8f 100644 --- a/.github/workflows/julia-nightly.yml +++ b/.github/workflows/julia-nightly.yml @@ -43,6 +43,6 @@ jobs: Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) Pkg.instantiate() - Pkg.build(; verbose=true) + Pkg.build(["OMParser", "OMRuntimeExternalC", "OMFrontend"]; verbose=true) Pkg.precompile()' - uses: julia-actions/julia-runtest@v1 From cb7bef7c5868f99d95cec22816decc2ba58e41d7 Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 15:46:35 +0200 Subject: [PATCH 05/11] CI: build only OMParser + OMRuntimeExternalC (native artifacts) OMFrontend's build.jl (like OMBackend's) is a standalone-dev script that Pkg.add's deps from git master, clobbering the umbrella's path sources - it re-resolved OMParser to git#master, dropping the just-built native lib and breaking precompile. Build only the two packages that download genuine native artifacts and whose builds don't clobber sources; OMFrontend/OMBackend are precompiled normally. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/CI.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/julia-nightly.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0e4d977..e03ea27 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -48,7 +48,7 @@ jobs: Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) Pkg.instantiate() - Pkg.build(["OMParser", "OMRuntimeExternalC", "OMFrontend"]; verbose=true) + Pkg.build(["OMParser", "OMRuntimeExternalC"]; verbose=true) Pkg.precompile()' - uses: julia-actions/julia-runtest@v1 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 5afac46..c654c03 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -38,7 +38,7 @@ jobs: Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) Pkg.instantiate() - Pkg.build(["OMParser", "OMRuntimeExternalC", "OMFrontend"]; verbose=true) + Pkg.build(["OMParser", "OMRuntimeExternalC"]; verbose=true) Pkg.precompile()' - name: Build and deploy diff --git a/.github/workflows/julia-nightly.yml b/.github/workflows/julia-nightly.yml index c8e8a8f..ba9b00a 100644 --- a/.github/workflows/julia-nightly.yml +++ b/.github/workflows/julia-nightly.yml @@ -43,6 +43,6 @@ jobs: Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) Pkg.instantiate() - Pkg.build(["OMParser", "OMRuntimeExternalC", "OMFrontend"]; verbose=true) + Pkg.build(["OMParser", "OMRuntimeExternalC"]; verbose=true) Pkg.precompile()' - uses: julia-actions/julia-runtest@v1 From b70e18b159ddad4be0cc9e9f066e1d8ebb4ca390 Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 16:35:17 +0200 Subject: [PATCH 06/11] CI: sibling-checkout + Pkg.develop layout (mirror OMFrontend CI) Submodule-recursive + committed-Manifest fought the project's design: OMParser's native lib (git-ignored, downloaded at build) wasn't found at precompile, and submodule pointers are unreliable. Adopt OMFrontend.jl's proven pattern: check out OM and every sub-package as siblings, Pkg.develop them via ../.jl, build only the native-artifact packages (OMParser/OMRuntimeExternalC), resolve, precompile, then run tests. No submodules used, so submodule-pointer drift is irrelevant. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/CI.yml | 56 +++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e03ea27..3849675 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -12,10 +12,16 @@ concurrency: permissions: contents: read +env: + # OM's Project.toml lives in the OM.jl subdir of the workspace; pin it so the + # cache action and inline julia calls key off the same project. + JULIA_PROJECT: OM.jl + jobs: test: name: Julia ${{ matrix.version }} - ${{ matrix.os }} runs-on: ${{ matrix.os }} + timeout-minutes: 120 strategy: fail-fast: false matrix: @@ -23,9 +29,26 @@ jobs: os: [ubuntu-latest, windows-latest] arch: [x64] steps: - - uses: actions/checkout@v4 + # OM and every sub-package are checked out as SIBLINGS in the workspace. + # The packages' [sources] reference ../.jl, and we Pkg.develop them + # explicitly below. This mirrors OMFrontend.jl's working CI and avoids the + # submodule-pointer + nested-path issues entirely. + - name: Checkout OM.jl + uses: actions/checkout@v4 with: - submodules: recursive + path: OM.jl + - { name: Checkout Absyn.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/Absyn.jl, ref: master, path: Absyn.jl } } + - { name: Checkout ArrayUtil.jl, uses: actions/checkout@v4, with: { repository: JKRT/ArrayUtil.jl, ref: master, path: ArrayUtil.jl } } + - { name: Checkout DAE.jl, uses: actions/checkout@v4, with: { repository: JKRT/DAE.jl, ref: master, path: DAE.jl } } + - { name: Checkout DoubleEnded.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/DoubleEnded.jl, ref: master, path: DoubleEnded.jl } } + - { name: Checkout ImmutableList.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/ImmutableList.jl, ref: master, path: ImmutableList.jl } } + - { name: Checkout ListUtil.jl, uses: actions/checkout@v4, with: { repository: JKRT/ListUtil.jl, ref: master, path: ListUtil.jl } } + - { name: Checkout MetaModelica.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/MetaModelica.jl, ref: master, path: MetaModelica.jl } } + - { name: Checkout OMBackend.jl, uses: actions/checkout@v4, with: { repository: JKRT/OMBackend.jl, ref: master, path: OMBackend.jl } } + - { name: Checkout OMFrontend.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMFrontend.jl, ref: master, path: OMFrontend.jl } } + - { name: Checkout OMParser.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMParser.jl, ref: master, path: OMParser.jl } } + - { name: Checkout OMRuntimeExternalC.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMRuntimeExternalC.jl, ref: master, path: OMRuntimeExternalC.jl } } + - { name: Checkout SCode.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/SCode.jl, ref: master, path: SCode.jl } } - uses: julia-actions/setup-julia@v2 with: @@ -33,13 +56,16 @@ jobs: arch: ${{ matrix.arch }} - uses: julia-actions/cache@v2 + with: + cache-name: om-ci - - name: Add registries, build native libs, precompile + - name: Develop siblings, build native libs, precompile shell: bash - # Build BEFORE precompile: OMParser downloads its native shared - # libraries in the build step, and OMBackend's precompile workload - # loads OMParser. Disable auto-precompile during instantiate, build, - # then precompile so the native libs exist first. + working-directory: OM.jl + # Disable auto-precompile so the native-lib build runs before precompile + # (OMParser/OMRuntimeExternalC download shared libs in their build step). + # Build only those two: OMBackend/OMFrontend build.jl are standalone-dev + # scripts that Pkg.add deps from git and clobber the dev'd path sources. env: JULIA_PKG_PRECOMPILE_AUTO: '0' run: | @@ -47,13 +73,25 @@ jobs: import Pkg Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) - Pkg.instantiate() + siblings = [ + "../Absyn.jl", "../ArrayUtil.jl", "../DAE.jl", "../DoubleEnded.jl", + "../ImmutableList.jl", "../ListUtil.jl", "../MetaModelica.jl", + "../OMBackend.jl", "../OMFrontend.jl", "../OMParser.jl", + "../OMRuntimeExternalC.jl", "../SCode.jl", + ] + Pkg.develop([Pkg.PackageSpec(path = p) for p in siblings]) Pkg.build(["OMParser", "OMRuntimeExternalC"]; verbose=true) + Pkg.resolve() Pkg.precompile()' - - uses: julia-actions/julia-runtest@v1 + - name: Test + shell: bash + working-directory: OM.jl + run: julia --color=yes --code-coverage=user --project=. -e 'include("test/runtests.jl")' - uses: julia-actions/julia-processcoverage@v1 + with: + directories: OM.jl/src - uses: codecov/codecov-action@v4 with: files: lcov.info From 3a4ce2138beeceff23263deacd35abf2ff70fc4f Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 17:10:12 +0200 Subject: [PATCH 07/11] CI: run tests from OM.jl/test (runtests.jl guards pwd==@__DIR__) Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3849675..513ceb2 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -86,8 +86,8 @@ jobs: - name: Test shell: bash - working-directory: OM.jl - run: julia --color=yes --code-coverage=user --project=. -e 'include("test/runtests.jl")' + working-directory: OM.jl/test # runtests.jl guards pwd() == @__DIR__ + run: julia --color=yes --code-coverage=user --project=.. -e 'include("runtests.jl")' - uses: julia-actions/julia-processcoverage@v1 with: From d5178fc96ae4012a32b07f0236307766b195435e Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 17:13:44 +0200 Subject: [PATCH 08/11] CI: add test-only deps (ADTypes, Sundials, Logging, Test) to env runtests.jl/testUtils.jl 'using' these but OM declares only Test in [extras]; include(runtests.jl) on the main project does not merge [targets]. Promote them to direct deps in the CI env (already resolved transitively). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/CI.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 513ceb2..ecae7a3 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -80,6 +80,9 @@ jobs: "../OMRuntimeExternalC.jl", "../SCode.jl", ] Pkg.develop([Pkg.PackageSpec(path = p) for p in siblings]) + # Test-only deps used by test/testUtils.jl but absent from OM [deps] + # (already in the resolved manifest transitively; promote to direct). + Pkg.add(["ADTypes", "Sundials", "Logging", "Test"]) Pkg.build(["OMParser", "OMRuntimeExternalC"]; verbose=true) Pkg.resolve() Pkg.precompile()' From 724b21862cade82bf4773488d6f24bac9b38ad8c Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 17:17:08 +0200 Subject: [PATCH 09/11] CI: drop coverage steps for now (not relevant while reviving CI) Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/CI.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ecae7a3..f05779f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -90,13 +90,4 @@ jobs: - name: Test shell: bash working-directory: OM.jl/test # runtests.jl guards pwd() == @__DIR__ - run: julia --color=yes --code-coverage=user --project=.. -e 'include("runtests.jl")' - - - uses: julia-actions/julia-processcoverage@v1 - with: - directories: OM.jl/src - - uses: codecov/codecov-action@v4 - with: - files: lcov.info - fail_ci_if_error: false - token: ${{ secrets.CODECOV_TOKEN }} + run: julia --color=yes --project=.. -e 'include("runtests.jl")' From 2e4c6257223062024df0709f0ee2d8a6e2ddf6e7 Mon Sep 17 00:00:00 2001 From: JKRT Date: Sat, 13 Jun 2026 18:11:02 +0200 Subject: [PATCH 10/11] CI: propagate sibling-checkout pattern to nightly + docs workflows Same proven recipe as CI.yml (sibling checkouts, Pkg.develop, native-only build, no coverage). nightly: weekly/dispatch on Julia nightly. docs: builds the Documenter site against the dev'd OM. (nightly/docs not act-validated; CI.yml is the act-proven one.) Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/docs.yml | 34 ++++++++++++++-- .github/workflows/julia-nightly.yml | 62 +++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 12 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c654c03..70ae5c2 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,19 +17,36 @@ jobs: docs: name: Build and deploy docs runs-on: ubuntu-latest + timeout-minutes: 120 steps: - - uses: actions/checkout@v4 + - name: Checkout OM.jl + uses: actions/checkout@v4 with: - submodules: recursive + path: OM.jl + - { name: Checkout Absyn.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/Absyn.jl, ref: master, path: Absyn.jl } } + - { name: Checkout ArrayUtil.jl, uses: actions/checkout@v4, with: { repository: JKRT/ArrayUtil.jl, ref: master, path: ArrayUtil.jl } } + - { name: Checkout DAE.jl, uses: actions/checkout@v4, with: { repository: JKRT/DAE.jl, ref: master, path: DAE.jl } } + - { name: Checkout DoubleEnded.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/DoubleEnded.jl, ref: master, path: DoubleEnded.jl } } + - { name: Checkout ImmutableList.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/ImmutableList.jl, ref: master, path: ImmutableList.jl } } + - { name: Checkout ListUtil.jl, uses: actions/checkout@v4, with: { repository: JKRT/ListUtil.jl, ref: master, path: ListUtil.jl } } + - { name: Checkout MetaModelica.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/MetaModelica.jl, ref: master, path: MetaModelica.jl } } + - { name: Checkout OMBackend.jl, uses: actions/checkout@v4, with: { repository: JKRT/OMBackend.jl, ref: master, path: OMBackend.jl } } + - { name: Checkout OMFrontend.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMFrontend.jl, ref: master, path: OMFrontend.jl } } + - { name: Checkout OMParser.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMParser.jl, ref: master, path: OMParser.jl } } + - { name: Checkout OMRuntimeExternalC.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMRuntimeExternalC.jl, ref: master, path: OMRuntimeExternalC.jl } } + - { name: Checkout SCode.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/SCode.jl, ref: master, path: SCode.jl } } - uses: julia-actions/setup-julia@v2 with: version: '1.12' - uses: julia-actions/cache@v2 + with: + cache-name: om-docs - - name: Instantiate docs environment + - name: Instantiate docs env (sibling develop + native build) shell: bash + working-directory: OM.jl env: JULIA_PKG_PRECOMPILE_AUTO: '0' run: | @@ -37,12 +54,21 @@ jobs: import Pkg Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) - Pkg.instantiate() + siblings = [ + "../Absyn.jl", "../ArrayUtil.jl", "../DAE.jl", "../DoubleEnded.jl", + "../ImmutableList.jl", "../ListUtil.jl", "../MetaModelica.jl", + "../OMBackend.jl", "../OMFrontend.jl", "../OMParser.jl", + "../OMRuntimeExternalC.jl", "../SCode.jl", + ] + Pkg.develop([Pkg.PackageSpec(path = p) for p in siblings]) + Pkg.develop(Pkg.PackageSpec(path = ".")) Pkg.build(["OMParser", "OMRuntimeExternalC"]; verbose=true) + Pkg.resolve() Pkg.precompile()' - name: Build and deploy shell: bash + working-directory: OM.jl env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} diff --git a/.github/workflows/julia-nightly.yml b/.github/workflows/julia-nightly.yml index ba9b00a..5903282 100644 --- a/.github/workflows/julia-nightly.yml +++ b/.github/workflows/julia-nightly.yml @@ -1,7 +1,6 @@ name: Julia nightly -# Forward-guard against the next Julia. Not part of PR gating: runs on a -# weekly schedule and manual dispatch only, so a break here never blocks a -# merge. +# Forward-guard against the next Julia. Not part of PR gating: weekly + +# manual dispatch only, so a break here never blocks a merge. on: workflow_dispatch: schedule: @@ -14,10 +13,16 @@ concurrency: permissions: contents: read +env: + # OM's Project.toml lives in the OM.jl subdir of the workspace; pin it so the + # cache action and inline julia calls key off the same project. + JULIA_PROJECT: OM.jl + jobs: test-nightly: name: Julia ${{ matrix.version }} - ${{ matrix.os }} runs-on: ${{ matrix.os }} + timeout-minutes: 120 strategy: fail-fast: false matrix: @@ -25,16 +30,43 @@ jobs: os: [ubuntu-latest, windows-latest] arch: [x64] steps: - - uses: actions/checkout@v4 + # OM and every sub-package are checked out as SIBLINGS in the workspace. + # The packages' [sources] reference ../.jl, and we Pkg.develop them + # explicitly below. This mirrors OMFrontend.jl's working CI and avoids the + # submodule-pointer + nested-path issues entirely. + - name: Checkout OM.jl + uses: actions/checkout@v4 with: - submodules: recursive + path: OM.jl + - { name: Checkout Absyn.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/Absyn.jl, ref: master, path: Absyn.jl } } + - { name: Checkout ArrayUtil.jl, uses: actions/checkout@v4, with: { repository: JKRT/ArrayUtil.jl, ref: master, path: ArrayUtil.jl } } + - { name: Checkout DAE.jl, uses: actions/checkout@v4, with: { repository: JKRT/DAE.jl, ref: master, path: DAE.jl } } + - { name: Checkout DoubleEnded.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/DoubleEnded.jl, ref: master, path: DoubleEnded.jl } } + - { name: Checkout ImmutableList.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/ImmutableList.jl, ref: master, path: ImmutableList.jl } } + - { name: Checkout ListUtil.jl, uses: actions/checkout@v4, with: { repository: JKRT/ListUtil.jl, ref: master, path: ListUtil.jl } } + - { name: Checkout MetaModelica.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/MetaModelica.jl, ref: master, path: MetaModelica.jl } } + - { name: Checkout OMBackend.jl, uses: actions/checkout@v4, with: { repository: JKRT/OMBackend.jl, ref: master, path: OMBackend.jl } } + - { name: Checkout OMFrontend.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMFrontend.jl, ref: master, path: OMFrontend.jl } } + - { name: Checkout OMParser.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMParser.jl, ref: master, path: OMParser.jl } } + - { name: Checkout OMRuntimeExternalC.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMRuntimeExternalC.jl, ref: master, path: OMRuntimeExternalC.jl } } + - { name: Checkout SCode.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/SCode.jl, ref: master, path: SCode.jl } } + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} + - uses: julia-actions/cache@v2 - - name: Add registries, build native libs, precompile + with: + cache-name: om-nightly + + - name: Develop siblings, build native libs, precompile shell: bash + working-directory: OM.jl + # Disable auto-precompile so the native-lib build runs before precompile + # (OMParser/OMRuntimeExternalC download shared libs in their build step). + # Build only those two: OMBackend/OMFrontend build.jl are standalone-dev + # scripts that Pkg.add deps from git and clobber the dev'd path sources. env: JULIA_PKG_PRECOMPILE_AUTO: '0' run: | @@ -42,7 +74,21 @@ jobs: import Pkg Pkg.Registry.add("General") Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/OpenModelica/OpenModelicaRegistry.git")) - Pkg.instantiate() + siblings = [ + "../Absyn.jl", "../ArrayUtil.jl", "../DAE.jl", "../DoubleEnded.jl", + "../ImmutableList.jl", "../ListUtil.jl", "../MetaModelica.jl", + "../OMBackend.jl", "../OMFrontend.jl", "../OMParser.jl", + "../OMRuntimeExternalC.jl", "../SCode.jl", + ] + Pkg.develop([Pkg.PackageSpec(path = p) for p in siblings]) + # Test-only deps used by test/testUtils.jl but absent from OM [deps] + # (already in the resolved manifest transitively; promote to direct). + Pkg.add(["ADTypes", "Sundials", "Logging", "Test"]) Pkg.build(["OMParser", "OMRuntimeExternalC"]; verbose=true) + Pkg.resolve() Pkg.precompile()' - - uses: julia-actions/julia-runtest@v1 + + - name: Test + shell: bash + working-directory: OM.jl/test # runtests.jl guards pwd() == @__DIR__ + run: julia --color=yes --project=.. -e 'include("runtests.jl")' From f040c5f3eff6d1caf4879d4d0f93503c385883c4 Mon Sep 17 00:00:00 2001 From: JKRT_CLAUDE_ACCOUNT Date: Mon, 15 Jun 2026 09:04:38 +0200 Subject: [PATCH 11/11] CI: install BLAS / LAPACK / gfortran runtime on Linux (#45) --- .github/workflows/CI.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f05779f..4cdc283 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -50,6 +50,17 @@ jobs: - { name: Checkout OMRuntimeExternalC.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/OMRuntimeExternalC.jl, ref: master, path: OMRuntimeExternalC.jl } } - { name: Checkout SCode.jl, uses: actions/checkout@v4, with: { repository: OpenModelica/SCode.jl, ref: master, path: SCode.jl } } + # libSimulationRuntimeC.so in the OMRuntimeExternalC.jl libs-v0.1.0 + # Linux zip has DT_NEEDED entries for liblapack.so.3, libblas.so.3 and + # libgfortran.so.5. ubuntu-24.04 does not ship those by default, so + # dlopen fails and every MSL / Spice3 / external-builtin test that goes + # through structural_simplify chains down to it. The Windows + # x86_64-mingw32 zip ships its own MinGW DLLs (libgfortran-5.dll, + # libopenblas.dll, ...) so no install step is needed there. + - name: Install OMC runtime system deps (Linux) + if: runner.os == 'Linux' + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends liblapack3 libblas3 libgfortran5 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }}