From 0182ae092885b0f8960ee3a944f5fabe6d3f4bb8 Mon Sep 17 00:00:00 2001 From: Hofer-Julian Date: Mon, 22 Apr 2024 17:26:51 +0200 Subject: [PATCH] Use a Rust binary to expose Ribasim CLI - libribasim and ribasim_cli can share the same libraries - we get `ribasim.exe` instead of `ribasim.cmd` --- build/cli_wrapper/Cargo.lock | 7 + build/cli_wrapper/Cargo.toml | 7 + build/cli_wrapper/src/main.rs | 29 +++++ build/src/create_app.jl | 45 +++---- pixi.lock | 235 ++++++++++++++++++++++++++++++++++ pixi.toml | 1 + 6 files changed, 297 insertions(+), 27 deletions(-) create mode 100644 build/cli_wrapper/Cargo.lock create mode 100644 build/cli_wrapper/Cargo.toml create mode 100644 build/cli_wrapper/src/main.rs diff --git a/build/cli_wrapper/Cargo.lock b/build/cli_wrapper/Cargo.lock new file mode 100644 index 000000000..9dd21010d --- /dev/null +++ b/build/cli_wrapper/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ribasim" +version = "0.0.0" diff --git a/build/cli_wrapper/Cargo.toml b/build/cli_wrapper/Cargo.toml new file mode 100644 index 000000000..c7a6ed1cb --- /dev/null +++ b/build/cli_wrapper/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ribasim" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/build/cli_wrapper/src/main.rs b/build/cli_wrapper/src/main.rs new file mode 100644 index 000000000..e8a33325b --- /dev/null +++ b/build/cli_wrapper/src/main.rs @@ -0,0 +1,29 @@ +use std::env; + +fn main() { + // 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 std::env::consts::OS == "windows" { + env::set_var( + "PATH", + format!( + "{};{}", + exe_dir.join("bin").display(), + env::var("PATH").unwrap_or_default() + ), + ); + } + + // TODO: Do I need to set LD_LIBRARY_PATH on linux? + + // Get the command line arguments + let args: Vec = std::env::args().skip(1).collect(); + + // Parse command line arguments + todo!(); + + // Call ribasim shared library and check for errors + todo!() +} diff --git a/build/src/create_app.jl b/build/src/create_app.jl index 2f49c394f..54e04165e 100644 --- a/build/src/create_app.jl +++ b/build/src/create_app.jl @@ -29,31 +29,22 @@ function build_app() 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 + # 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) + + run(Cmd(`cargo build --release`; dir = "cli_wrapper")) + ribasim = Sys.iswindows() ? "ribasim.exe" : "ribasim" + cp("cli_wrapper/target/release/$ribasim", "libribasim/$ribasim"; force = true) 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..14f5cdbf3 100644 --- a/pixi.toml +++ b/pixi.toml @@ -207,6 +207,7 @@ qgis-plugin-manager = "*" quarto = "*" quartodoc = "*" ruff = "*" +rust = "*" twine = "*" [feature.py312.dependencies]