diff --git a/.gitignore b/.gitignore
index 8ee64eb35..e0c6cc05a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,8 +10,8 @@ docs/build/
docs/site/
/generated_testmodels
-build/ribasim_cli/
-build/libribasim/
+build/ribasim/
+build/cli_wrapper/target
JuliaSysimage.dll
LocalPreferences.toml
diff --git a/.teamcity/Ribasim/buildTypes/Ribasim_Ribasim_MakeGitHubRelease.xml b/.teamcity/Ribasim/buildTypes/Ribasim_Ribasim_MakeGitHubRelease.xml
index dc38105e1..752161053 100644
--- a/.teamcity/Ribasim/buildTypes/Ribasim_Ribasim_MakeGitHubRelease.xml
+++ b/.teamcity/Ribasim/buildTypes/Ribasim_Ribasim_MakeGitHubRelease.xml
@@ -56,17 +56,17 @@ pixi run github-release]]>
-
+
-
+
-
+
-
+
-
+
@@ -90,7 +90,7 @@ pixi run github-release]]>
-
+
@@ -110,4 +110,3 @@ pixi run github-release]]>
-
diff --git a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildLibribasim.xml b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildRibasim.xml
similarity index 93%
rename from .teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildLibribasim.xml
rename to .teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildRibasim.xml
index c3bfb6fdc..d47affbe6 100644
--- a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildLibribasim.xml
+++ b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildRibasim.xml
@@ -1,10 +1,10 @@
- Build libribasim
+ Build Ribasim
-
+
@@ -32,7 +32,7 @@ source /usr/share/Modules/init/bash
module load pixi
module load gcc/11.3.0
pixi run remove-artifacts
-pixi run build-libribasim]]>
+pixi run build]]>
@@ -59,4 +59,3 @@ pixi run build-libribasim]]>
-
diff --git a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildRibasimCli.xml b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildRibasimCli.xml
deleted file mode 100644
index 60a02eca6..000000000
--- a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_BuildRibasimCli.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
- Build ribasim_cli
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimApi.xml b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimApi.xml
index 57421a5a8..7d43eae23 100644
--- a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimApi.xml
+++ b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimApi.xml
@@ -7,9 +7,6 @@
-
-
-
@@ -90,13 +87,13 @@ pixi run test-ribasim-api]]>
-
+
-
+
-
+
@@ -107,4 +104,3 @@ pixi run test-ribasim-api]]>
-
diff --git a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimCli.xml b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimCli.xml
index 395cb5bab..49ec570ff 100644
--- a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimCli.xml
+++ b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimCli.xml
@@ -90,13 +90,13 @@ pixi run test-ribasim-cli]]>
-
+
-
+
-
+
@@ -107,4 +107,3 @@ pixi run test-ribasim-cli]]>
-
diff --git a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildLibribasim.xml b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildRibasim.xml
similarity index 93%
rename from .teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildLibribasim.xml
rename to .teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildRibasim.xml
index 5ab8cce3f..9bdb69beb 100644
--- a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildLibribasim.xml
+++ b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildRibasim.xml
@@ -1,10 +1,9 @@
- Build libribasim
+ Build Ribasim
-
@@ -25,7 +24,7 @@ pixi run --environment=dev install-ci]]>
+pixi run build]]>
@@ -54,4 +53,3 @@ pixi run build-libribasim]]>
-
diff --git a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildRibasimCli.xml b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildRibasimCli.xml
deleted file mode 100644
index 9ff25e3d1..000000000
--- a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_BuildRibasimCli.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
- Build ribasim_cli
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimApi.xml b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimApi.xml
index 5683f3182..a7cbbf33b 100644
--- a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimApi.xml
+++ b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimApi.xml
@@ -6,9 +6,6 @@
-
-
-
@@ -78,13 +75,13 @@
-
+
-
+
-
+
@@ -95,4 +92,3 @@
-
diff --git a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimCli.xml b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimCli.xml
index 035f583e2..2801b668e 100644
--- a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimCli.xml
+++ b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimCli.xml
@@ -78,13 +78,13 @@
-
+
-
+
-
+
@@ -95,4 +95,3 @@
-
diff --git a/README.md b/README.md
index df35fc317..8bf297918 100644
--- a/README.md
+++ b/README.md
@@ -24,11 +24,6 @@ For most users the [latest release](https://github.com/Deltares/Ribasim/releases
- QGIS plugin: [ribasim_qgis.zip](https://github.com/Deltares/Ribasim/releases/latest/download/ribasim_qgis.zip).
- Generated testmodels: [generated_testmodels.zip](https://github.com/Deltares/Ribasim/releases/latest/download/generated_testmodels.zip)
-The nightly builds contain the latest developments and can be found below. It is important to either use the release or nightly for all components.
-
-- Ribasim executable: [ribasim_cli.zip](https://ribasim.s3.eu-west-3.amazonaws.com/teamcity/Ribasim_Ribasim/BuildRibasimCliWindows/latest/ribasim_cli.zip).
-- QGIS plugin: [ribasim_qgis.zip](https://ribasim.s3.eu-west-3.amazonaws.com/teamcity/Ribasim_Ribasim/BuildRibasimCliWindows/latest/ribasim_qgis.zip).
-

diff --git a/build/build.jl b/build/build.jl
index f19181825..0c459ce21 100644
--- a/build/build.jl
+++ b/build/build.jl
@@ -4,24 +4,71 @@ using TOML
using LibGit2
include("src/add_metadata.jl")
-include("src/create_app.jl")
-include("src/create_lib.jl")
"""
-Build the Ribasim CLI, libribasim, or both, using PackageCompiler.
-Run from the command line with:
+# Ribasim CLI
- julia --project build.jl --app --lib
+In order to find out about it's usage call `ribasim --help`
+
+# Libribasim
+
+Libribasim is a shared library that exposes Ribasim functionality to external (non-Julian)
+programs. It can be compiled using [PackageCompiler's
+create_lib](https://julialang.github.io/PackageCompiler.jl/stable/libs.html), which is set
+up in this directory. The C API that is offered to control Ribasim is the C API of the
+[Basic Model Interface](https://bmi.readthedocs.io/en/latest/), also known as BMI.
+
+Not all BMI functions are implemented yet, this has been set up as a proof of concept to
+demonstrate that we can use other software such as
+[`imod_coupler`](https://github.com/Deltares/imod_coupler) to control Ribasim and couple it to
+other models.
+
+Here is an example of using libribasim from Python:
+
+```python
+In [1]: from ctypes import CDLL, c_int, c_char_p, create_string_buffer, byref
+
+In [2]: c_dll = CDLL("libribasim", winmode=0x08) # winmode for Windows
+
+In [3]: argument = create_string_buffer(0)
+ ...: c_dll.init_julia(c_int(0), byref(argument))
+Out[3]: 1
+
+In [4]: config_path = "ribasim.toml"
+
+In [5]: c_dll.initialize(c_char_p(config_path.encode()))
+Out[5]: 0
+
+In [6]: c_dll.update()
+Out[6]: 0
+```
"""
-function main(ARGS)
+function main()
+ project_dir = "../core"
+ license_file = "../LICENSE"
+ output_dir = "ribasim"
+ git_repo = ".."
+
# change directory to this script's location
cd(@__DIR__)
- if "--app" in ARGS
- build_app()
- elseif "--lib" in ARGS
- build_lib()
- end
+ create_library(
+ project_dir,
+ output_dir;
+ lib_name = "libribasim",
+ precompile_execution_file = "precompile.jl",
+ include_lazy_artifacts = false,
+ include_transitive_dependencies = false,
+ include_preferences = true,
+ force = true,
+ )
+
+ readme = @doc(build_app)
+ add_metadata(project_dir, license_file, output_dir, git_repo, readme)
+ run(Cmd(`cargo build --release`; dir = "cli_wrapper"))
+ ribasim = Sys.iswindows() ? "ribasim.exe" : "ribasim"
+ cp("cli_wrapper/target/release/$ribasim", "ribasim/$ribasim"; force = true)
end
-main(ARGS)
+
+main()
diff --git a/build/cli_wrapper/Cargo.lock b/build/cli_wrapper/Cargo.lock
new file mode 100644
index 000000000..0fe889c8f
--- /dev/null
+++ b/build/cli_wrapper/Cargo.lock
@@ -0,0 +1,254 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "anstream"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "libc"
+version = "0.2.153"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+
+[[package]]
+name = "libloading"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
+dependencies = [
+ "cfg-if",
+ "windows-targets",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "ribasim"
+version = "2024.7.0"
+dependencies = [
+ "clap",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
diff --git a/build/cli_wrapper/Cargo.toml b/build/cli_wrapper/Cargo.toml
new file mode 100644
index 000000000..82b19f5ba
--- /dev/null
+++ b/build/cli_wrapper/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "ribasim"
+version = "2024.7.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clap = { version = "4.5.4", features = ["derive"] }
+libc = "0.2.153"
+libloading = "0.8.3"
diff --git a/build/cli_wrapper/src/main.rs b/build/cli_wrapper/src/main.rs
new file mode 100644
index 000000000..3aa394c3f
--- /dev/null
+++ b/build/cli_wrapper/src/main.rs
@@ -0,0 +1,67 @@
+use std::{
+ env::{self, consts::OS},
+ ffi::CString,
+ path::PathBuf,
+};
+
+use clap::Parser;
+use libloading::{Library, Symbol};
+use std::process::ExitCode;
+
+#[derive(Parser)]
+#[command(version)]
+struct Cli {
+ /// Path to the TOML file
+ toml_path: PathBuf,
+}
+
+fn main() -> ExitCode {
+ // Get the path to the directory containing the current executable
+ let exe_dir = env::current_exe().unwrap().parent().unwrap().to_owned();
+
+ // Set the appropriate environment variable for the current platform
+ if OS == "windows" {
+ env::set_var(
+ "PATH",
+ format!(
+ "{};{}",
+ exe_dir.join("bin").display(),
+ env::var("PATH").unwrap_or_default()
+ ),
+ );
+ }
+
+ // TODO: Do we need to set LD_LIBRARY_PATH on linux?
+
+ // Parse command line arguments
+ let cli = Cli::parse();
+
+ if !cli.toml_path.is_file() {
+ eprintln!("File not found {:?}", cli.toml_path);
+ return ExitCode::FAILURE;
+ }
+
+ let shared_lib_path = match OS {
+ "windows" => exe_dir.join("bin/libribasim.dll"),
+ "linux" => exe_dir.join("lib/libribasim.so"),
+ _ => unimplemented!(),
+ };
+ unsafe {
+ // Load the library
+ let lib = Library::new(shared_lib_path).unwrap();
+
+ // Init Julia
+ let init_julia: Symbol i32> =
+ lib.get(b"init_julia").unwrap();
+ init_julia(0, CString::default().as_ptr());
+
+ // Execute
+ let execute: Symbol i32> =
+ lib.get(b"execute").unwrap();
+ let toml_path_c = CString::new(cli.toml_path.to_str().unwrap()).unwrap();
+ let exit_code = execute(toml_path_c.as_ptr());
+
+ // Return with same exit code as `execute` did
+ ExitCode::from(exit_code as u8)
+ }
+}
diff --git a/build/src/create_app.jl b/build/src/create_app.jl
deleted file mode 100644
index 2f49c394f..000000000
--- a/build/src/create_app.jl
+++ /dev/null
@@ -1,59 +0,0 @@
-"""
-# Ribasim CLI
-
-This is a [Julia](https://julialang.org/) project that uses the
-[Ribasim](https://github.com/Deltares/Ribasim) Julia package, puts a simple command line
-interface (cli) on top, and packages this into a standalone application using
-[PackageCompiler.jl](https://github.com/JuliaLang/PackageCompiler.jl).
-
-This enables using Ribasim without having to install Julia, and thus makes it more
-convenient to use in certain settings where installation must be simple and no interactive
-Julia session is needed.
-
-If you have installed Julia and Ribasim, a simulation can also be started from the command
-line as follows:
-
-```
-julia --eval 'using Ribasim; Ribasim.main("path/to/model/ribasim.toml")'
-```
-
-With a Ribasim CLI build this becomes:
-
-```
-ribasim path/to/model/ribasim.toml
-```
-"""
-function build_app()
- project_dir = "../core"
- license_file = "../LICENSE"
- output_dir = "ribasim_cli"
- git_repo = ".."
-
- create_app(
- project_dir,
- output_dir;
- # map from binary name to julia function name
- executables = ["ribasim" => "main"],
- precompile_execution_file = "precompile.jl",
- include_lazy_artifacts = false,
- include_transitive_dependencies = false,
- include_preferences = true,
- force = true,
- )
-
- readme = @doc(build_app)
- add_metadata(project_dir, license_file, output_dir, git_repo, readme)
-
- # On Windows, write ribasim.cmd in the output_dir, that starts ribasim.exe.
- # Since the bin dir contains a julia.exe and many DLLs that you may not want in your path,
- # with this script you can put output_dir in your path instead.
- if Sys.iswindows()
- cmd = raw"""
- @echo off
- "%~dp0bin\ribasim.exe" %*
- """
- open(normpath(output_dir, "ribasim.cmd"); write = true) do io
- print(io, cmd)
- end
- end
-end
diff --git a/build/src/create_lib.jl b/build/src/create_lib.jl
deleted file mode 100644
index 87381dded..000000000
--- a/build/src/create_lib.jl
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-# Libribasim
-
-Libribasim is a shared library that exposes Ribasim functionality to external (non-Julian)
-programs. It can be compiled using [PackageCompiler's
-create_lib](https://julialang.github.io/PackageCompiler.jl/stable/libs.html), which is set
-up in this directory. The C API that is offered to control Ribasim is the C API of the
-[Basic Model Interface](https://bmi.readthedocs.io/en/latest/), also known as BMI.
-
-Not all BMI functions are implemented yet, this has been set up as a proof of concept to
-demonstrate that we can use other software such as
-[`imod_coupler`](https://github.com/Deltares/imod_coupler) to control Ribasim and couple it to
-other models.
-
-Here is an example of using libribasim from Python:
-
-```python
-In [1]: from ctypes import CDLL, c_int, c_char_p, create_string_buffer, byref
-
-In [2]: c_dll = CDLL("libribasim", winmode=0x08) # winmode for Windows
-
-In [3]: argument = create_string_buffer(0)
- ...: c_dll.init_julia(c_int(0), byref(argument))
-Out[3]: 1
-
-In [4]: config_path = "ribasim.toml"
-
-In [5]: c_dll.initialize(c_char_p(config_path.encode()))
-Out[5]: 0
-
-In [6]: c_dll.update()
-Out[6]: 0
-```
-"""
-function build_lib()
- project_dir = "../core"
- license_file = "../LICENSE"
- output_dir = "libribasim"
- git_repo = ".."
-
- create_library(
- project_dir,
- output_dir;
- lib_name = "libribasim",
- precompile_execution_file = "precompile.jl",
- include_lazy_artifacts = false,
- include_transitive_dependencies = false,
- include_preferences = true,
- force = true,
- )
-
- readme = @doc(build_app)
- add_metadata(project_dir, license_file, output_dir, git_repo, readme)
-end
diff --git a/build/tests/test_models.py b/build/tests/test_cli.py
similarity index 52%
rename from build/tests/test_models.py
rename to build/tests/test_cli.py
index 61a1aa804..06b1ce83f 100644
--- a/build/tests/test_models.py
+++ b/build/tests/test_cli.py
@@ -5,20 +5,38 @@
import ribasim
import ribasim_testmodels
+executable = Path(__file__).parents[1] / "ribasim" / "ribasim"
+
@pytest.mark.parametrize(
"model_constructor",
ribasim_testmodels.constructors.values(),
)
-def test_ribasim_cli(model_constructor, tmp_path):
+def test_models(model_constructor, tmp_path):
model = model_constructor()
assert isinstance(model, ribasim.Model)
model.write(tmp_path / "ribasim.toml")
- executable = Path(__file__).parents[1] / "ribasim_cli" / "bin" / "ribasim"
result = subprocess.run([executable, tmp_path / "ribasim.toml"])
if model_constructor.__name__.startswith("invalid_"):
assert result.returncode != 0
else:
assert result.returncode == 0
+
+
+def test_version():
+ result = subprocess.run(
+ [executable, "--version"], check=True, capture_output=True, text=True
+ )
+
+ assert ribasim.__version__ in result.stdout
+
+
+def test_help():
+ subprocess.run([executable, "--help"], check=True)
+
+
+def test_missing_toml():
+ result = subprocess.run([executable, "/there/is/no/toml"])
+ assert result.returncode != 0
diff --git a/core/src/libribasim.jl b/core/src/libribasim.jl
index e8af88f50..73069973d 100644
--- a/core/src/libribasim.jl
+++ b/core/src/libribasim.jl
@@ -186,6 +186,10 @@ Base.@ccallable function get_last_bmi_error(error_message::Cstring)::Cint
end
end
+Base.@ccallable function execute(toml_path::Cstring)::Cint
+ Ribasim.main(unsafe_string(toml_path))
+end
+
Base.@ccallable function get_value_ptr_double(
name::Cstring,
value_ptr::Ptr{Ptr{Cvoid}},
diff --git a/core/src/main.jl b/core/src/main.jl
index 1e75e721f..1818d1394 100644
--- a/core/src/main.jl
+++ b/core/src/main.jl
@@ -14,15 +14,6 @@ function run(config::Config)::Model
return model
end
-function help(x::AbstractString)::Cint
- println(x)
- println("Usage: ribasim path/to/model/ribasim.toml")
- return 1
-end
-
-main(toml_path::AbstractString)::Cint = main([toml_path])
-main()::Cint = main(ARGS)
-
"""
main(toml_path::AbstractString)::Cint
main(ARGS::Vector{String})::Cint
@@ -32,26 +23,10 @@ This is the main entry point of the application.
Performs argument parsing and sets up logging for both terminal and file.
Calls Ribasim.run() and handles exceptions to convert to exit codes.
"""
-function main(ARGS::Vector{String})::Cint
- n = length(ARGS)
- if n != 1
- return help("Exactly 1 argument expected, got $n")
- end
- arg = only(ARGS)
-
- if arg == "--version"
- version = pkgversion(Ribasim)
- print(version)
- return 0
- end
-
- if !isfile(arg)
- return help("File not found: $arg")
- end
-
+function main(toml_path::AbstractString)::Cint
try
# show progress bar in terminal
- config = Config(arg)
+ config = Config(toml_path)
mkpath(results_path(config, "."))
open(results_path(config, "ribasim.log"), "w") do io
logger = setup_logger(; verbosity = config.logging.verbosity, stream = io)
diff --git a/core/test/main_test.jl b/core/test/main_test.jl
index 042751719..b94336808 100644
--- a/core/test/main_test.jl
+++ b/core/test/main_test.jl
@@ -1,12 +1,3 @@
-@testitem "version" begin
- using IOCapture: capture
-
- (; value, output) = capture() do
- Ribasim.main(["--version"])
- end
- @test value == 0
- @test output == string(pkgversion(Ribasim))
-end
@testitem "toml_path" begin
using IOCapture: capture
@@ -24,7 +15,7 @@ end
@test ispath(toml_path)
(; value, output, error, backtrace) = capture() do
- Ribasim.main([toml_path])
+ Ribasim.main(toml_path)
end
@test value == 0
if value != 0
@@ -34,23 +25,3 @@ end
end
@test occursin("version in the TOML config file does not match", output)
end
-
-@testitem "too many arguments for main" begin
- using IOCapture: capture
-
- (; value, output) = capture() do
- Ribasim.main(["too", "many"])
- end
- @test value == 1
- @test occursin("Exactly 1 argument expected, got 2", output)
-end
-
-@testitem "non-existing file for main" begin
- using IOCapture: capture
-
- (; value, output) = capture() do
- Ribasim.main(["non-existing-file.toml"])
- end
- @test value == 1
- @test occursin("File not found: non-existing-file.toml", output)
-end
diff --git a/pixi.lock b/pixi.lock
index ed4501dbe..18e8a36e1 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -1151,6 +1151,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.14.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/beartype-0.18.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.12.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-hf600244_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.3.0-py312h7900ff3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.1.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/blosc-1.21.5-h0f2a231_0.conda
@@ -1228,6 +1229,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/freexl-2.0.0-h743c826_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2024.3.1-pyhca7485f_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/future-1.0.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-13.2.0-h1d3d475_6.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/gdal-3.8.4-py312h257dd4b_5.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/geopandas-0.14.3-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/geopandas-base-0.14.3-pyha770c72_0.conda
@@ -1292,6 +1294,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.25.4-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/kealib-1.5.3-h2f55d51_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_17.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/keyring-25.1.0-pyha804496_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.4.5-py312h8572e83_1.conda
@@ -1330,6 +1333,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.4.3-h59595ed_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-13.2.0-h95c4c6d_106.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-1.10.3-hd590300_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgdal-3.8.4-h7c88fdf_5.conda
@@ -1364,6 +1368,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.25.3-h08a7969_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libre2-11-2023.09.01-h5a48ba9_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/librttopo-1.1.0-h8917695_15.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-13.2.0-h95c4c6d_6.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsecret-0.18.8-h329b89f_2.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsndfile-1.2.2-hc60ed4a_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.18-h36c2ea0_1.tar.bz2
@@ -1528,6 +1533,8 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.18.0-py312h4b3b743_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/rtree-1.2.0-py312hb0aae1a_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py312h9118e91_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.77.2-h70c747d_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.77.2-h2c6d0dc_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.8-h06160fa_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.4.1.post1-py312h394d371_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.12.0-py312heda63a1_2.conda
@@ -1546,6 +1553,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.45.2-h2c6b66d_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.2-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/suitesparse-5.10.1-h5a4f163_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_17.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tabulate-0.9.0-pyhd8ed1ab_1.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2021.11.0-h00ab1b0_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tblib-3.0.0-pyhd8ed1ab_0.conda
@@ -2000,6 +2008,8 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-64/rpds-py-0.18.0-py312h1b0e595_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/rtree-1.2.0-py312h8974cf7_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py312h1bc86af_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/rust-1.77.2-h7e1429e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.77.2-h38e4360_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/scikit-learn-1.4.1.post1-py312h7167a34_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.12.0-py312h8adb940_2.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-1.8.2-pyhd1c38e8_0.conda
@@ -2453,6 +2463,8 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.18.0-py312h77200ec_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rtree-1.2.0-py312h22f7183_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py312h1ae9fbf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.77.2-h4ff7c5d_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.77.2-hf6ec828_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.4.1.post1-py312hd4306f4_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.12.0-py312h9d7df2b_2.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-1.8.2-pyhd1c38e8_0.conda
@@ -2895,6 +2907,8 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.18.0-py312hfccd98a_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/rtree-1.2.0-py312h72b5f30_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py312h60fbdae_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/win-64/rust-1.77.2-hf8d6059_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.77.2-h17fc481_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/scikit-learn-1.4.1.post1-py312hcacafb1_0.conda
- conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.12.0-py312h8753938_2.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-1.8.2-pyh08f2357_0.conda
@@ -7814,6 +7828,21 @@ packages:
license_family: MIT
size: 118200
timestamp: 1705564819537
+- kind: conda
+ name: binutils_impl_linux-64
+ version: '2.40'
+ build: hf600244_0
+ subdir: linux-64
+ url: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-hf600244_0.conda
+ sha256: a7e0ea2b71a5b03d82e5a58fb6b612ab1c44d72ce161f9aa441f7ba467cd4c8d
+ md5: 33084421a8c0af6aef1b439707f7662a
+ depends:
+ - ld_impl_linux-64 2.40 h41732ed_0
+ - sysroot_linux-64
+ license: GPL-3.0-only
+ license_family: GPL
+ size: 5414922
+ timestamp: 1674833958334
- kind: conda
name: black
version: 24.3.0
@@ -12204,6 +12233,26 @@ packages:
license_family: MIT
size: 364081
timestamp: 1708610254418
+- kind: conda
+ name: gcc_impl_linux-64
+ version: 13.2.0
+ build: h1d3d475_6
+ build_number: 6
+ subdir: linux-64
+ url: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-13.2.0-h1d3d475_6.conda
+ sha256: 9c0651484a777f524c32196b826b89e09fc5dc8ca4f8b86839f8f7d7d48850ae
+ md5: fb523fa3954d16178f7df937af68544f
+ depends:
+ - binutils_impl_linux-64 >=2.40
+ - libgcc-devel_linux-64 13.2.0 h95c4c6d_106
+ - libgcc-ng >=13.2.0
+ - libgomp >=13.2.0
+ - libsanitizer 13.2.0 h95c4c6d_6
+ - libstdcxx-ng >=13.2.0
+ - sysroot_linux-64
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ size: 53768088
+ timestamp: 1713755155489
- kind: conda
name: gdal
version: 3.8.4
@@ -14707,6 +14756,22 @@ packages:
license_family: MIT
size: 133421
timestamp: 1703116732437
+- kind: conda
+ name: kernel-headers_linux-64
+ version: 2.6.32
+ build: he073ed8_17
+ build_number: 17
+ subdir: noarch
+ noarch: generic
+ url: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_17.conda
+ sha256: fb39d64b48f3d9d1acc3df208911a41f25b6a00bd54935d5973b4739a9edd5b6
+ md5: d731b543793afc0433c4fd593e693fce
+ constrains:
+ - sysroot_linux-64 ==2.12
+ license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0
+ license_family: GPL
+ size: 710627
+ timestamp: 1708000830116
- kind: conda
name: keyring
version: 25.1.0
@@ -17297,6 +17362,19 @@ packages:
license: Apache 2.0
size: 531143
timestamp: 1527899216421
+- kind: conda
+ name: libgcc-devel_linux-64
+ version: 13.2.0
+ build: h95c4c6d_106
+ build_number: 106
+ subdir: noarch
+ noarch: generic
+ url: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-13.2.0-h95c4c6d_106.conda
+ sha256: b0bf49439d146275a0ad5cb5e6bf15da0f1257cdc7299589da820fd55d19588a
+ md5: 960fa4aaa5c6a4733ac71954d835ce99
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ size: 2581282
+ timestamp: 1713754805427
- kind: conda
name: libgcc-ng
version: 13.2.0
@@ -19639,6 +19717,20 @@ packages:
license_family: GPL
size: 213839
timestamp: 1700766697471
+- kind: conda
+ name: libsanitizer
+ version: 13.2.0
+ build: h95c4c6d_6
+ build_number: 6
+ subdir: linux-64
+ url: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-13.2.0-h95c4c6d_6.conda
+ sha256: 7dfe018f816e424692a322aef993096061e28e13ad7e1c19b35c9e16f69c6bb0
+ md5: be66a394ae0eb4bbeba5bba54e83ce53
+ depends:
+ - libgcc-ng >=13.2.0
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ size: 4139988
+ timestamp: 1713755043582
- kind: conda
name: libsecret
version: 0.18.8
@@ -31066,6 +31158,133 @@ packages:
license_family: MIT
size: 6285718
timestamp: 1711999610306
+- kind: conda
+ name: rust
+ version: 1.77.2
+ build: h4ff7c5d_0
+ subdir: osx-arm64
+ url: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.77.2-h4ff7c5d_0.conda
+ sha256: 048ffabbbbd1b5109d59ec15610cf0e489c39b4f6f380953816bcb26dad8da17
+ md5: 4083c1a9d7f5c9591273f578530d6388
+ depends:
+ - rust-std-aarch64-apple-darwin 1.77.2 hf6ec828_0
+ license: MIT
+ license_family: MIT
+ size: 145759919
+ timestamp: 1712743398771
+- kind: conda
+ name: rust
+ version: 1.77.2
+ build: h70c747d_0
+ subdir: linux-64
+ url: https://conda.anaconda.org/conda-forge/linux-64/rust-1.77.2-h70c747d_0.conda
+ sha256: 3b8cf09335d23c52d6e7150e4cc6d999ed4e2b3dc2307652f20e1a4669ff0846
+ md5: ba764892e80fe0380bb7fa99751b186d
+ depends:
+ - gcc_impl_linux-64
+ - libgcc-ng >=12
+ - libzlib >=1.2.13,<1.3.0a0
+ - rust-std-x86_64-unknown-linux-gnu 1.77.2 h2c6d0dc_0
+ license: MIT
+ license_family: MIT
+ size: 186765686
+ timestamp: 1712741423714
+- kind: conda
+ name: rust
+ version: 1.77.2
+ build: h7e1429e_0
+ subdir: osx-64
+ url: https://conda.anaconda.org/conda-forge/osx-64/rust-1.77.2-h7e1429e_0.conda
+ sha256: d12cde3691eb50148b49460ac2bff0c0716204099a38d36132762ffb0c6c79fd
+ md5: 13c8a97dd157999cdd23adaac7919047
+ depends:
+ - rust-std-x86_64-apple-darwin 1.77.2 h38e4360_0
+ license: MIT
+ license_family: MIT
+ size: 192493395
+ timestamp: 1712743664947
+- kind: conda
+ name: rust
+ version: 1.77.2
+ build: hf8d6059_0
+ subdir: win-64
+ url: https://conda.anaconda.org/conda-forge/win-64/rust-1.77.2-hf8d6059_0.conda
+ sha256: 978228c14a3d2af2d9d52230443f232d7a22cbbe98d359a306b1a761773d4589
+ md5: ba05fee8761e5bd25ae642a4b77d2ed7
+ depends:
+ - rust-std-x86_64-pc-windows-msvc 1.77.2 h17fc481_0
+ license: MIT
+ license_family: MIT
+ size: 187565499
+ timestamp: 1712743189902
+- kind: conda
+ name: rust-std-aarch64-apple-darwin
+ version: 1.77.2
+ build: hf6ec828_0
+ subdir: noarch
+ noarch: generic
+ url: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.77.2-hf6ec828_0.conda
+ sha256: 19b17ddca3896f12a640858b45a7ba5e8495ca07286b622535ca5a4bf8217906
+ md5: 729f181cdeb249ff2da37f434b548633
+ depends:
+ - __unix
+ constrains:
+ - rust >=1.77.2,<1.77.3.0a0
+ license: MIT
+ license_family: MIT
+ size: 30933811
+ timestamp: 1712740743456
+- kind: conda
+ name: rust-std-x86_64-apple-darwin
+ version: 1.77.2
+ build: h38e4360_0
+ subdir: noarch
+ noarch: generic
+ url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.77.2-h38e4360_0.conda
+ sha256: 1d0a99136ab0a2b05d9df4d5a7a8d665595c2e72ee1d19fcad0c6f1b402f37d1
+ md5: 67db6d59468a8145fb076d75d156b69c
+ depends:
+ - __unix
+ constrains:
+ - rust >=1.77.2,<1.77.3.0a0
+ license: MIT
+ license_family: MIT
+ size: 31857486
+ timestamp: 1712740749097
+- kind: conda
+ name: rust-std-x86_64-pc-windows-msvc
+ version: 1.77.2
+ build: h17fc481_0
+ subdir: noarch
+ noarch: generic
+ url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.77.2-h17fc481_0.conda
+ sha256: 0c290c52a3cf1ac43a316d6caf0e073614351ccae31c681d6953dec7a2ff21e3
+ md5: 2149767f1c882154246a9a569991e3c3
+ depends:
+ - __win
+ constrains:
+ - rust >=1.77.2,<1.77.3.0a0
+ license: MIT
+ license_family: MIT
+ size: 25276039
+ timestamp: 1712742986757
+- kind: conda
+ name: rust-std-x86_64-unknown-linux-gnu
+ version: 1.77.2
+ build: h2c6d0dc_0
+ subdir: noarch
+ noarch: generic
+ url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.77.2-h2c6d0dc_0.conda
+ sha256: 73f7537db6bc0471135a85a261798abe77e7e83794f945a0355c4068973f31f6
+ md5: db8b81b3806faafe2f6f7bd431f72e37
+ depends:
+ - __unix
+ constrains:
+ - rust >=1.77.2,<1.77.3.0a0
+ license: MIT
+ license_family: MIT
+ size: 33827015
+ timestamp: 1712741238767
- kind: conda
name: s2n
version: 1.4.8
@@ -32485,6 +32704,22 @@ packages:
license: LGPL-2.1-or-later AND BSD-3-Clause AND GPL-2.0-or-later AND Apache-2.0
size: 1125223
timestamp: 1705677285644
+- kind: conda
+ name: sysroot_linux-64
+ version: '2.12'
+ build: he073ed8_17
+ build_number: 17
+ subdir: noarch
+ noarch: generic
+ url: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_17.conda
+ sha256: b4e4d685e41cb36cfb16f0cb15d2c61f8f94f56fab38987a44eff95d8a673fb5
+ md5: 595db67e32b276298ff3d94d07d47fbf
+ depends:
+ - kernel-headers_linux-64 2.6.32 he073ed8_17
+ license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0
+ license_family: GPL
+ size: 15127123
+ timestamp: 1708000843849
- kind: conda
name: tabulate
version: 0.9.0
diff --git a/pixi.toml b/pixi.toml
index 837fb5402..3b5de6041 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -88,15 +88,7 @@ lint = { depends_on = [
"mypy-ribasim-qgis",
] }
# Build
-build-ribasim-cli = { cmd = "julia --project build.jl --app", cwd = "build", depends_on = [
- "generate-testmodels",
- "initialize-julia",
-] }
-build-libribasim = { cmd = "julia --project build.jl --lib", cwd = "build", depends_on = [
- "generate-testmodels",
- "initialize-julia",
-] }
-build = { "cmd" = "julia --project build.jl --app --lib", cwd = "build", depends_on = [
+build = { "cmd" = "julia --project build.jl", cwd = "build", depends_on = [
"generate-testmodels",
"initialize-julia",
] }
@@ -207,6 +199,7 @@ qgis-plugin-manager = "*"
quarto = "*"
quartodoc = "*"
ruff = "*"
+rust = "*"
twine = "*"
[feature.py312.dependencies]
diff --git a/python/ribasim_api/ribasim_api/ribasim_api.py b/python/ribasim_api/ribasim_api/ribasim_api.py
index 341f1e7c4..74544e6f9 100644
--- a/python/ribasim_api/ribasim_api/ribasim_api.py
+++ b/python/ribasim_api/ribasim_api/ribasim_api.py
@@ -30,3 +30,6 @@ def shutdown_julia(self) -> None:
def update_subgrid_level(self) -> None:
self.lib.update_subgrid_level()
+
+ def execute(self, config_file: str) -> None:
+ self._execute_function(self.lib.execute, config_file.encode())
diff --git a/python/ribasim_api/tests/conftest.py b/python/ribasim_api/tests/conftest.py
index b69fe8167..7c57ed6bc 100644
--- a/python/ribasim_api/tests/conftest.py
+++ b/python/ribasim_api/tests/conftest.py
@@ -12,7 +12,7 @@ def libribasim_paths() -> tuple[Path, Path]:
repo_root = Path(__file__).parents[3].resolve()
lib_or_bin = "bin" if platform.system() == "Windows" else "lib"
extension = ".dll" if platform.system() == "Windows" else ".so"
- lib_folder = repo_root / "build" / "libribasim" / lib_or_bin
+ lib_folder = repo_root / "build" / "ribasim" / lib_or_bin
lib_path = lib_folder / f"libribasim{extension}"
return lib_path, lib_folder
diff --git a/python/ribasim_api/tests/test_bmi.py b/python/ribasim_api/tests/test_bmi.py
index 101bf7ed5..be1c9e340 100644
--- a/python/ribasim_api/tests/test_bmi.py
+++ b/python/ribasim_api/tests/test_bmi.py
@@ -132,3 +132,9 @@ def test_get_version(libribasim):
config = tomli.load(fp)
assert libribasim.get_version() == config["version"]
+
+
+def test_execute(libribasim, basic, tmp_path):
+ basic.write(tmp_path / "ribasim.toml")
+ config_file = str(tmp_path / "ribasim.toml")
+ libribasim.execute(config_file)