diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..cc843b9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,5 @@ +BasedOnStyle: Google +IndentWidth: 4 +IndentAccessModifiers: false +AccessModifierOffset: -4 +ColumnLimit: 100 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..16ef5c5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# GitHub syntax highlighting +pixi.lock linguist-language=YAML + diff --git a/.github/workflows/cpp-test.yml b/.github/workflows/cpp-test.yml new file mode 100644 index 0000000..23e1643 --- /dev/null +++ b/.github/workflows/cpp-test.yml @@ -0,0 +1,77 @@ +on: + push: + branches: + - "main" + pull_request: + +name: C++ + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + format: + name: Format and Lint + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - uses: prefix-dev/setup-pixi@v0.8.1 + with: + environments: format-cpp + + - name: Ensure code is properly formatted + run: | + pixi run format-cpp + git diff --exit-code + + test: + name: Test + strategy: + fail-fast: false + matrix: + os: [ubuntu-20.04, macOS-latest, macOS-14, windows-latest ] + runs-on: ${{ matrix.os }} + needs: [ format ] + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - uses: prefix-dev/setup-pixi@v0.8.1 + with: + environments: test-cpp + + - name: Run the tests + run: | + pixi run test-cpp + + package: + name: Create conda packages + strategy: + matrix: + include: + - os: ubuntu-latest + target-platform: linux-64 + - os: ubuntu-latest + target-platform: linux-aarch64 + - os: windows-latest + target-platform: win-64 + - os: macos-latest + target-platform: osx-64 + - os: macos-14 + target-platform: osx-arm64 + runs-on: ${{ matrix.os }} + needs: [ format ] + steps: + - name: Checkout source code + uses: actions/checkout@v4 + - name: Build conda package + uses: prefix-dev/rattler-build-action@v0.2.11 + with: + recipe-path: recipe/recipe.yaml + # needs to be unique for each matrix entry + artifact-name: package-${{ matrix.target-platform }} + build-args: --target-platform ${{ matrix.target-platform }}${{ matrix.target-platform == 'linux-aarch64' && ' --no-test' || '' }} + diff --git a/.github/workflows/rust-compile.yml b/.github/workflows/rust-compile.yml index f784556..b4d04e1 100644 --- a/.github/workflows/rust-compile.yml +++ b/.github/workflows/rust-compile.yml @@ -42,8 +42,8 @@ jobs: - name: Run clippy run: cargo clippy - build: - name: ubuntu-latest + test: + name: Test runs-on: ubuntu-latest needs: [ format_and_lint ] steps: diff --git a/.gitignore b/.gitignore index fa43deb..45f2537 100644 --- a/.gitignore +++ b/.gitignore @@ -7,10 +7,6 @@ debug/ target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk @@ -18,3 +14,14 @@ Cargo.lock *.pdb **/.DS_Store + +build/ +# pixi environments +.pixi +*.egg-info + +# Ignore rattler-build output directory +output/ + +# Any resolvo snapshots in the root +snapshot-*.json diff --git a/CHANGELOG.md b/CHANGELOG.md index cbef3eb..96694b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.6.2](https://github.com/mamba-org/resolvo/compare/resolvo-v0.6.1...resolvo-v0.6.2) - 2024-06-11 + +### Added +- release-plz resolvo_cpp +- add rattler-build recipe ([#47](https://github.com/mamba-org/resolvo/pull/47)) +- c++ bindings ([#41](https://github.com/mamba-org/resolvo/pull/41)) + +## [0.6.1](https://github.com/mamba-org/resolvo/compare/resolvo-v0.6.0...resolvo-v0.6.1) - 2024-06-10 + +### Added +- add `DependencySnapshot` ([#44](https://github.com/mamba-org/resolvo/pull/44)) + +### Fixed +- publish state of tool + ## [0.6.0](https://github.com/mamba-org/resolvo/compare/v0.5.0...v0.6.0) - 2024-06-07 ### Other diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..21e1ffe --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.21) + +project(resolvo LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(FeatureSummary) + +option(RESOLVO_BUILD_TESTING "Build tests" OFF) +add_feature_info(RESOLVO_BUILD_TESTING RESOLVO_BUILD_TESTING + "configure whether to build the test suite") +include(CTest) + +set(RESOLVO_IS_TOPLEVEL_BUILD TRUE) + +# Place all compiled examples into the same bin directory on Windows, where +# we'll also put the dll +if(WIN32) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/debug) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/release) +elseif(APPLE) + # On macOS, the resolvo_cpp.dylib's install_name uses @rpath. CMake doesn't + # set BUILD_RPATH for imported targets though, so include the directory here + # by hand in the rpath used to build binaries in the build tree (such as our + # examples or tests). + set(CMAKE_BUILD_RPATH ${CMAKE_BINARY_DIR}/cpp) +endif() + +add_subdirectory(cpp/) + +feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:") +feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:") diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a42f4cd --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1833 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand 2.1.0", + "futures-lite 2.3.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.3.1", + "async-executor", + "async-io 2.3.3", + "async-lock 3.4.0", + "blocking", + "futures-lite 2.3.0", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +dependencies = [ + "async-lock 3.4.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.7.1", + "rustix 0.38.34", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel 2.3.1", + "async-task", + "futures-io", + "futures-lite 2.3.0", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cbindgen" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da6bc11b07529f16944307272d5bd9b22530bc7d05751717c9d416586cedab49" +dependencies = [ + "clap 3.2.25", + "heck 0.4.1", + "indexmap 1.9.3", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 1.0.109", + "tempfile", + "toml", +] + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags 1.3.2", + "clap_lex 0.2.4", + "indexmap 1.9.3", + "strsim 0.10.0", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex 0.7.1", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "elsa" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.1.0", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "insta" +version = "1.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "810ae6042d48e2c9e9215043563a58a80b877bc863228a74cf10c49d4620a6f5" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "similar", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +dependencies = [ + "value-bag", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.2.6", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +dependencies = [ + "atomic-waker", + "fastrand 2.1.0", + "futures-io", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.3.9", + "pin-project-lite", + "rustix 0.38.34", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.5.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax 0.8.4", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "resolvo" +version = "0.6.2" +dependencies = [ + "ahash", + "async-std", + "bitvec", + "elsa", + "event-listener 5.3.1", + "futures", + "indexmap 2.2.6", + "insta", + "itertools", + "petgraph", + "proptest", + "resolvo", + "serde", + "serde_json", + "tokio", + "tracing", + "tracing-test", +] + +[[package]] +name = "resolvo_cpp" +version = "0.1.0" +dependencies = [ + "anyhow", + "cbindgen", + "resolvo", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys 0.4.14", + "windows-sys 0.52.0", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "similar" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "solve-snapshot" +version = "0.1.0" +dependencies = [ + "clap 4.5.7", + "csv", + "resolvo", + "serde", + "serde_json", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand 2.1.0", + "rustix 0.38.34", + "windows-sys 0.52.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "pin-project-lite", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing-test" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracing-test-macro", +] + +[[package]] +name = "tracing-test-macro" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" +dependencies = [ + "quote", + "syn 2.0.66", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] diff --git a/Cargo.toml b/Cargo.toml index 124701f..4375bea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,16 +1,30 @@ -[package] -name = "resolvo" -version = "0.6.0" +[workspace] +members = ["cpp", "tools/*"] +resolver = "2" + +[workspace.package] +version = "0.6.2" authors = ["Adolfo Ochagavía ", "Bas Zalmstra ", "Tim de Jager "] -description = "Fast package resolver written in Rust (CDCL based SAT solving)" -keywords = ["dependency", "solver", "version"] -categories = ["algorithms"] homepage = "https://github.com/mamba-org/resolvo" repository = "https://github.com/mamba-org/resolvo" license = "BSD-3-Clause" edition = "2021" readme = "README.md" -resolver = "2" +keywords = ["dependency", "solver", "version"] +categories= ["algorithms"] + +[package] +name = "resolvo" +version.workspace = true +authors.workspace = true +description= "Fast package resolver written in Rust (CDCL based SAT solving)" +keywords.workspace = true +categories.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +edition.workspace = true +readme.workspace = true [dependencies] ahash = "0.8.11" @@ -33,3 +47,4 @@ proptest = "1.2" tracing-test = { version = "0.2.4", features = ["no-env-filter"] } tokio = { version = "1.35.1", features = ["time", "rt"] } resolvo = { path = ".", features = ["tokio"] } +serde_json = "1.0" diff --git a/cpp/CHANGELOG.md b/cpp/CHANGELOG.md new file mode 100644 index 0000000..739d039 --- /dev/null +++ b/cpp/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0](https://github.com/mamba-org/resolvo/releases/tag/resolvo_cpp-v0.1.0) - 2024-06-11 + +### Added +- c++ bindings ([#41](https://github.com/mamba-org/resolvo/pull/41)) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt new file mode 100644 index 0000000..b7c6d13 --- /dev/null +++ b/cpp/CMakeLists.txt @@ -0,0 +1,182 @@ +cmake_minimum_required(VERSION 3.21) + +# Select C++ and C as languages, as Corrosion needs ${CMAKE_C_COMPILER} for +# linking +project(Resolvo LANGUAGES C CXX) + +# Add the Corrosion dependency (used to build Rust code) +include(FetchContent) +FetchContent_Declare( + Corrosion + GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git + GIT_TAG v0.4.9) +FetchContent_MakeAvailable(Corrosion) + +# Extract the version from the rust crate +corrosion_parse_package_version("${CMAKE_CURRENT_SOURCE_DIR}/Cargo.toml" + resolvo_cpp_version) +string(REPLACE "." ";" VERSION_LIST ${resolvo_cpp_version}) +list(GET VERSION_LIST 0 resolvo_cpp_version_major) +list(GET VERSION_LIST 1 resolvo_cpp_version_minor) +list(GET VERSION_LIST 2 resolvo_cpp_version_patch) + +# Add the Corrosion CMake module path to the list of paths to search for modules +list(PREPEND CMAKE_MODULE_PATH ${Corrosion_SOURCE_DIR}/cmake) +find_package(Rust 1.75 REQUIRED MODULE) + +option(BUILD_SHARED_LIBS "Build Resolvo as shared library" ON) + +set(RESOLVO_LIBRARY_CARGO_FLAGS + "" + CACHE STRING + "Flags to pass to cargo when building the Resolvo runtime library") + +if(BUILD_SHARED_LIBS) + set(rustc_lib_type "cdylib") + set(resolvo_cpp_impl "resolvo_cpp-shared") + set(cmake_lib_type "SHARED") +else() + set(rustc_lib_type "staticlib") + set(resolvo_cpp_impl "resolvo_cpp-static") + set(cmake_lib_type "STATIC") +endif() + +corrosion_import_crate( + MANIFEST_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/Cargo.toml" + CRATES + resolvo_cpp + CRATE_TYPES + bin + ${rustc_lib_type}) + +# See +# https://corrosion-rs.github.io/corrosion/common_issues.html#missing-install_name-on-macos-for-ccdylibs--hardcoded-references-to-the-build-directory +if(APPLE + AND RESOLVO_IS_TOPLEVEL_BUILD + AND BUILD_SHARED_LIBS) + corrosion_add_target_local_rustflags( + resolvo_cpp + -Clink-arg=-Wl,-install_name,@rpath/libresolvo_cpp.dylib,-current_version,${resolvo_cpp_version_major}.${resolvo_cpp_version_minor}.${resolvo_cpp_version_patch},-compatibility_version,${resolvo_cpp_version_major}.${resolvo_cpp_version_minor}.0 + ) + set_target_properties(resolvo_cpp-shared PROPERTIES IMPORTED_NO_SONAME 0) + set_target_properties(resolvo_cpp-shared PROPERTIES IMPORTED_SONAME + libresolvo_cpp.dylib) +endif() + +add_library(Resolvo INTERFACE) +add_library(Resolvo::Resolvo ALIAS Resolvo) +target_link_libraries(Resolvo INTERFACE resolvo_cpp) + +set_property( + TARGET resolvo_cpp + APPEND + PROPERTY + CORROSION_ENVIRONMENT_VARIABLES + "RESOLVO_GENERATED_INCLUDE_DIR=${CMAKE_CURRENT_BINARY_DIR}/generated_include/" +) + +file( + GLOB api_headers + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include/" + "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h") + +foreach(header IN LISTS api_headers) + set_property( + TARGET Resolvo + APPEND + PROPERTY PUBLIC_HEADER include/${header}) +endforeach() + +set(generated_headers + ${CMAKE_CURRENT_BINARY_DIR}/generated_include/resolvo_vector_internal.h + ${CMAKE_CURRENT_BINARY_DIR}/generated_include/resolvo_string_internal.h + ${CMAKE_CURRENT_BINARY_DIR}/generated_include/resolvo_internal.h) + +foreach(header IN LISTS generated_headers) + set_property( + TARGET Resolvo + APPEND + PROPERTY PUBLIC_HEADER ${header}) +endforeach() + +target_include_directories( + Resolvo + INTERFACE $ + $ + $) + +export( + TARGETS Resolvo resolvo_cpp + NAMESPACE Resolvo:: + FILE "${CMAKE_BINARY_DIR}/lib/cmake/Resolvo/ResolvoTargets.cmake") +install( + EXPORT ResolvoTargets + NAMESPACE Resolvo:: + DESTINATION lib/cmake/Resolvo) +install( + TARGETS Resolvo resolvo_cpp + EXPORT ResolvoTargets + LIBRARY DESTINATION lib + PUBLIC_HEADER DESTINATION include/resolvo) + +install(FILES $ TYPE LIB) + +if(WIN32) + install(FILES $ TYPE LIB) +endif() + +include(CMakePackageConfigHelpers) + +function(_resolvo_write_configure_file) + foreach( + prop + IMPORTED_LOCATION + IMPORTED_LOCATION_DEBUG + IMPORTED_LOCATION_RELEASE + IMPORTED_LOCATION_RELWITHDEBINFO + IMPORTED_LOCATION_MINSIZEREL + IMPORTED_IMPLIB + IMPORTED_IMPLIB_DEBUG + IMPORTED_IMPLIB_RELEASE + IMPORTED_IMPLIB_RELWITHDEBINFO + IMPORTED_IMPLIB_MINSIZEREL) + get_target_property(value ${resolvo_cpp_impl} ${prop}) + + if(value) + get_filename_component(value ${value} NAME) + list(APPEND RESOLVO_LIB_PROPERTIES ${prop} + "\${_IMPORT_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${value}") + endif() + endforeach() + + foreach(prop IMPORTED_NO_SONAME IMPORTED_SONAME) + get_target_property(value ${resolvo_cpp_impl} ${prop}) + if(value) + list(APPEND RESOLVO_LIB_PROPERTIES ${prop} ${value}) + endif() + endforeach() + + configure_package_config_file( + "cmake/ResolvoConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/Resolvo/ResolvoConfig.cmake" + INSTALL_DESTINATION lib/cmake/resolvo) +endfunction() + +cmake_language(DEFER CALL _resolvo_write_configure_file) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/Resolvo/ResolvoConfigVersion.cmake + VERSION + ${resolvo_cpp_version_major}.${resolvo_cpp_version_minor}.${resolvo_cpp_version_patch} + COMPATIBILITY SameMinorVersion) + +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/Resolvo/ResolvoConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/Resolvo/ResolvoConfigVersion.cmake" + DESTINATION lib/cmake/Resolvo) + +if(RESOLVO_BUILD_TESTING) + add_subdirectory(tests) +endif() diff --git a/cpp/Cargo.toml b/cpp/Cargo.toml new file mode 100644 index 0000000..7357387 --- /dev/null +++ b/cpp/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "resolvo_cpp" +description = "Resolvo C++ integration" +version = "0.1.0" +authors.workspace = true +keywords.workspace = true +categories.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +edition.workspace = true +readme.workspace = true +publish = false + +[lib] +crate-type = ["lib", "cdylib", "staticlib"] + +[dependencies] +resolvo = { version = "0.6.2", path = "../" } + +[build-dependencies] +anyhow = "1" +cbindgen = "0.26.0" + diff --git a/cpp/build.rs b/cpp/build.rs new file mode 100644 index 0000000..452c5fd --- /dev/null +++ b/cpp/build.rs @@ -0,0 +1,92 @@ +use std::path::{Path, PathBuf}; + +use anyhow::Context; + +fn main() -> anyhow::Result<()> { + let manifest_dir = PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").unwrap()); + + println!("cargo:rerun-if-env-changed=RESOLVO_GENERATED_INCLUDE_DIR"); + let output_dir = std::env::var_os("RESOLVO_GENERATED_INCLUDE_DIR").unwrap_or_else(|| { + Path::new(&std::env::var_os("OUT_DIR").unwrap()) + .join("generated_include") + .into() + }); + let output_dir = Path::new(&output_dir); + + println!("cargo:GENERATED_INCLUDE_DIR={}", output_dir.display()); + + std::fs::create_dir_all(output_dir).context("Could not create the include directory")?; + + let mut default_config = cbindgen::Config::default(); + default_config.macro_expansion.bitflags = true; + default_config.pragma_once = true; + default_config.include_version = true; + default_config.namespaces = Some(vec!["resolvo".into(), "cbindgen_private".into()]); + default_config.line_length = 100; + default_config.tab_width = 4; + default_config.language = cbindgen::Language::Cxx; + default_config.cpp_compat = true; + default_config.documentation = true; + default_config.documentation_style = cbindgen::DocumentationStyle::Doxy; + default_config.structure.associated_constants_in_body = true; + default_config.constant.allow_constexpr = true; + default_config.export.exclude = vec!["Slice".into()]; + + cbindgen::Builder::new() + .with_config(default_config.clone()) + .with_src(manifest_dir.join("src/vector.rs")) + .generate() + .context("Unable to generate bindings for resolvo_vector_internal.h")? + .write_to_file(output_dir.join("resolvo_vector_internal.h")); + + let mut string_config = default_config.clone(); + string_config.export.exclude = vec!["String".into()]; + + cbindgen::Builder::new() + .with_config(string_config.clone()) + .with_src(manifest_dir.join("src/string.rs")) + .with_after_include("namespace resolvo { struct String; }") + .generate() + .context("Unable to generate bindings for resolvo_string_internal.h")? + .write_to_file(output_dir.join("resolvo_string_internal.h")); + + let mut config = default_config.clone(); + config.export.exclude.extend(vec![ + "Vector".into(), + "resolvo_vector_free".into(), + "resolvo_vector_allocate".into(), + "resolvo_vector_empty".into(), + "String".into(), + "resolvo_string_bytes".into(), + "resolvo_string_drop".into(), + "resolvo_string_clone".into(), + "resolvo_string_from_bytes".into(), + ]); + config.export.body.insert( + "Slice".to_owned(), + r" + const T &operator[](int i) const { return ptr[i]; } + /// Note: this doesn't initialize Slice properly, but we need to keep the struct as compatible with C + constexpr Slice() = default; + /// Rust uses a NonNull, so even empty slices shouldn't use nullptr + constexpr Slice(const T *ptr, uintptr_t len) : ptr(ptr ? const_cast(ptr) : reinterpret_cast(sizeof(T))), len(len) {}" + .to_owned(), + ); + + cbindgen::Builder::new() + .with_config(config.clone()) + .with_src(manifest_dir.join("src/lib.rs")) + .with_include("resolvo_slice.h") + .with_include("resolvo_vector.h") + .with_include("resolvo_string.h") + .generate() + .context("Unable to generate bindings for resolvo_internal.h")? + .write_to_file(output_dir.join("resolvo_internal.h")); + + println!("cargo:rerun-if-changed=src/lib.rs"); + println!("cargo:rerun-if-changed=src/slice.rs"); + println!("cargo:rerun-if-changed=src/string.rs"); + println!("cargo:rerun-if-changed=src/vector.rs"); + + Ok(()) +} diff --git a/cpp/cmake/ResolvoConfig.cmake.in b/cpp/cmake/ResolvoConfig.cmake.in new file mode 100644 index 0000000..45119ba --- /dev/null +++ b/cpp/cmake/ResolvoConfig.cmake.in @@ -0,0 +1,16 @@ +@PACKAGE_INIT@ + +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +add_library(@resolvo_cpp_impl@ @cmake_lib_type@ IMPORTED) +set_target_properties(@resolvo_cpp_impl@ PROPERTIES @RESOLVO_LIB_PROPERTIES@) + +set(_IMPORT_PREFIX) + +include("${CMAKE_CURRENT_LIST_DIR}/ResolvoTargets.cmake") diff --git a/cpp/include/resolvo.h b/cpp/include/resolvo.h new file mode 100644 index 0000000..6a41aa3 --- /dev/null +++ b/cpp/include/resolvo.h @@ -0,0 +1,37 @@ +#pragma once + +#include "resolvo_dependency_provider.h" +#include "resolvo_internal.h" + +namespace resolvo { + +/** + * Called to solve a package problem. + * + * If the solve was successful, an empty string is returned and selected solvable ids will be + * stored in `result`. If the solve was unsuccesfull an error describing the reason is returned and + * the result vector will be empty. + */ +inline String solve(DependencyProvider &provider, Slice requirements, + Slice constraints, Vector &result) { + cbindgen_private::DependencyProvider bridge{ + static_cast(&provider), + private_api::bridge_display_solvable, + private_api::bridge_display_solvable_name, + private_api::bridge_display_merged_solvables, + private_api::bridge_display_name, + private_api::bridge_display_version_set, + private_api::bridge_display_string, + private_api::bridge_version_set_name, + private_api::bridge_solvable_name, + private_api::bridge_get_candidates, + private_api::bridge_sort_candidates, + private_api::bridge_filter_candidates, + private_api::bridge_get_dependencies, + }; + + String error; + cbindgen_private::resolvo_solve(&bridge, requirements, constraints, &error, &result); + return error; +} +} // namespace resolvo diff --git a/cpp/include/resolvo_dependency_provider.h b/cpp/include/resolvo_dependency_provider.h new file mode 100644 index 0000000..8cd9258 --- /dev/null +++ b/cpp/include/resolvo_dependency_provider.h @@ -0,0 +1,154 @@ +#pragma once + +#include "resolvo_internal.h" +#include "resolvo_slice.h" +#include "resolvo_string.h" +#include "resolvo_vector.h" + +namespace resolvo { +using cbindgen_private::Candidates; +using cbindgen_private::Dependencies; +using cbindgen_private::ExcludedSolvable; +using cbindgen_private::NameId; +using cbindgen_private::SolvableId; +using cbindgen_private::StringId; +using cbindgen_private::VersionSetId; + +/** + * An interface that implements ecosystem specific logic. + */ +struct DependencyProvider { + virtual ~DependencyProvider() = default; + + /** + * Returns a user-friendly string representation of the specified solvable. + * + * When formatting the solvable, it should it include both the name of + * the package and any other identifying properties. + */ + virtual String display_solvable(SolvableId solvable) = 0; + + /** + * Returns a user-friendly string representation of the name of the + * specified solvable. + */ + virtual String display_solvable_name(SolvableId solvable) { + return display_name(solvable_name(solvable)); + } + + /** + * Returns a string representation of multiple solvables merged together. + * + * When formatting the solvables, both the name of the packages and any + * other identifying properties should be included. + */ + virtual String display_merged_solvables(Slice solvable) = 0; + + /** + * Returns an object that can be used to display the given name in a + * user-friendly way. + */ + virtual String display_name(NameId name) = 0; + + /** + * Returns a user-friendly string representation of the specified version + * set. + * + * The name of the package should *not* be included in the display. Where + * appropriate, this information is added. + */ + virtual String display_version_set(VersionSetId version_set) = 0; + + /** + * Returns the string representation of the specified string. + */ + virtual String display_string(StringId string) = 0; + + /** + * Returns the name of the package that the specified version set is + * associated with. + */ + virtual NameId version_set_name(VersionSetId version_set_id) = 0; + + /** + * Returns the name of the package for the given solvable. + */ + virtual NameId solvable_name(SolvableId solvable_id) = 0; + + /** + * Obtains a list of solvables that should be considered when a package + * with the given name is requested. + */ + virtual Candidates get_candidates(NameId package) = 0; + + /** + * Sort the specified solvables based on which solvable to try first. The + * solver will iteratively try to select the highest version. If a + * conflict is found with the highest version the next version is + * tried. This continues until a solution is found. + */ + virtual void sort_candidates(Slice solvables) = 0; + + /** + * Given a set of solvables, return the candidates that match the given + * version set or if `inverse` is true, the candidates that do *not* match + * the version set. + */ + virtual Vector filter_candidates(Slice candidates, + VersionSetId version_set_id, bool inverse) = 0; + + /** + * Returns the dependencies for the specified solvable. + */ + virtual Dependencies get_dependencies(SolvableId solvable) = 0; +}; + +namespace private_api { +extern "C" inline void bridge_display_solvable(void *data, SolvableId solvable, String *result) { + *result = reinterpret_cast(data)->display_solvable(solvable); +} +extern "C" inline void bridge_display_solvable_name(void *data, SolvableId solvable, + String *result) { + *result = reinterpret_cast(data)->display_solvable_name(solvable); +} +extern "C" inline void bridge_display_merged_solvables(void *data, Slice solvable, + String *result) { + *result = reinterpret_cast(data)->display_merged_solvables(solvable); +} +extern "C" inline void bridge_display_name(void *data, NameId name, String *result) { + *result = reinterpret_cast(data)->display_name(name); +} +extern "C" inline void bridge_display_version_set(void *data, VersionSetId version_set, + String *result) { + *result = reinterpret_cast(data)->display_version_set(version_set); +} +extern "C" inline void bridge_display_string(void *data, StringId string, String *result) { + *result = reinterpret_cast(data)->display_string(string); +} + +extern "C" inline NameId bridge_version_set_name(void *data, VersionSetId version_set_id) { + return reinterpret_cast(data)->version_set_name(version_set_id); +} +extern "C" inline NameId bridge_solvable_name(void *data, SolvableId solvable_id) { + return reinterpret_cast(data)->solvable_name(solvable_id); +} + +extern "C" inline void bridge_get_candidates(void *data, NameId package, Candidates *result) { + *result = reinterpret_cast(data)->get_candidates(package); +} +extern "C" inline void bridge_sort_candidates(void *data, Slice solvables) { + return reinterpret_cast(data)->sort_candidates(solvables); +} +extern "C" inline void bridge_filter_candidates(void *data, Slice candidates, + VersionSetId version_set_id, bool inverse, + Vector *result) { + *result = reinterpret_cast(data)->filter_candidates( + candidates, version_set_id, inverse); +} +extern "C" inline void bridge_get_dependencies(void *data, SolvableId solvable, + Dependencies *result) { + *result = reinterpret_cast(data)->get_dependencies(solvable); +} + +} // namespace private_api +} // namespace resolvo diff --git a/cpp/include/resolvo_pool.h b/cpp/include/resolvo_pool.h new file mode 100644 index 0000000..1f6452a --- /dev/null +++ b/cpp/include/resolvo_pool.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +namespace resolvo { +/** + * A Pool is an append only datastructure that associates a unique id with + * every element added. + * + * Id's are allocated in a monotonically increasing fashion, starting from 0. + */ +template +struct Pool { + Pool() = default; + ~Pool() = default; + + /** + * Adds the value to the pool and returns its associated id. If the + * value is already in the pool, returns the id associated with it. + */ + ID alloc(T value) { + if (auto element = value_to_id.find(value); element != value_to_id.end()) { + return element->second; + } + auto id = ID{static_cast(values.size())}; + values.push_back(value); + value_to_id.emplace(std::move(value), id); + return id; + } + + /** + * Returns the value associated with the given id. + */ + const T& operator[](ID id) const { return values[static_cast(id.id)]; } + +private: + std::deque values; + std::unordered_map value_to_id; +}; +} // namespace resolvo diff --git a/cpp/include/resolvo_slice.h b/cpp/include/resolvo_slice.h new file mode 100644 index 0000000..525bd59 --- /dev/null +++ b/cpp/include/resolvo_slice.h @@ -0,0 +1,45 @@ +#pragma once + +namespace resolvo { +template +struct Slice { + /// Note: this doesn't initialize Slice properly, but we need to keep the struct as compatible + /// with C + constexpr Slice() = default; + /// Rust uses a NonNull, so even empty slices shouldn't use nullptr + constexpr Slice(const T *ptr, uintptr_t len) + : ptr(ptr ? const_cast(ptr) : reinterpret_cast(sizeof(T))), len(len) {} + + /// Returns a const pointer to the first element of this slice. + const T *cbegin() const { return reinterpret_cast(ptr); } + + /// Returns a const pointer that points past the last element of this slice. + const T *cend() const { return ptr + len; } + + /// Returns a const pointer to the first element of this slice. + const T *begin() const { return cbegin(); } + + /// Returns a const pointer that points past the last element of this slice. + const T *end() const { return cend(); } + + /// Returns a pointer to the first element of this vector. + T *begin() { return reinterpret_cast(ptr); } + + /// Returns a pointer that points past the last element of this vector. The + /// pointer cannot be dereferenced, it can only be used for comparison. + T *end() { return ptr + len; } + + /// Returns the number of elements in this vector. + std::size_t size() const { return len; } + + /// Returns true if there are no elements on this vector; false otherwise. + bool empty() const { return len == 0; } + + /// This indexing operator returns a reference to the `index`th element of this vector. + T &operator[](std::size_t index) { return begin()[index]; } + +private: + T *ptr; + uintptr_t len; +}; +} // namespace resolvo diff --git a/cpp/include/resolvo_string.h b/cpp/include/resolvo_string.h new file mode 100644 index 0000000..9f2e53f --- /dev/null +++ b/cpp/include/resolvo_string.h @@ -0,0 +1,99 @@ +#pragma once + +#include + +#include "resolvo_string_internal.h" + +namespace resolvo { + +/// A string type that is used on both the Rust and C++ side. +/// +/// This type uses implicit data sharing to make it efficient to pass around +/// copied. When cloning, a reference to the data is cloned, not the data +/// itself. The data uses Copy-on-Write semantics, so the data is only cloned +/// when it is modified. +/// +/// The string data is stored as UTF8-encoded bytes, and it is always terminated +/// with a null character. +struct String { + /// Creates an empty default constructed string. + String() { cbindgen_private::resolvo_string_from_bytes(this, "", 0); } + + /// Creates a new String from a string view. The underlying string data is copied. + String(std::string_view s) { + cbindgen_private::resolvo_string_from_bytes(this, s.data(), s.size()); + } + + /// Creates a new String from the null-terminated string pointer `s`. The underlying + /// string data is copied. It is assumed that the string is UTF-8 encoded. + String(const char *s) : String(std::string_view(s)) {} + + /// Creates a new String from \a other. + String(const String &other) { cbindgen_private::resolvo_string_clone(this, &other); } + + /// Destroys this String and frees the memory if this is the last instance + /// referencing it. + ~String() { cbindgen_private::resolvo_string_drop(this); } + + /// Provides a view to the string data. The returned view is only valid as long as at + /// least this String exists. + operator std::string_view() const { return cbindgen_private::resolvo_string_bytes(this); } + /// Provides a raw pointer to the string data. The returned pointer is only valid as long as at + /// least this String exists. + auto data() const -> const char * { return cbindgen_private::resolvo_string_bytes(this); } + + /// Assigns \a other to this string and returns a reference to this string. + String &operator=(const String &other) { + cbindgen_private::resolvo_string_drop(this); + cbindgen_private::resolvo_string_clone(this, &other); + return *this; + } + + /// Assigns the string view \a s to this string and returns a reference to this string. + /// The underlying string data is copied. It is assumed that the string is UTF-8 encoded. + String &operator=(std::string_view s) { + cbindgen_private::resolvo_string_drop(this); + cbindgen_private::resolvo_string_from_bytes(this, s.data(), s.size()); + return *this; + } + + /// Assigns null-terminated string pointer s to this string and returns a reference + /// to this string. The underlying string data is copied. It is assumed that the string + /// is UTF-8 encoded. + String &operator=(const char *s) { return *this = std::string_view(s); } + + /// Move-assigns `other` to this String instance. + String &operator=(String &&other) { + std::swap(inner, other.inner); + return *this; + } + + /// Writes the string to the specified stream and returns a reference to the stream. + friend std::ostream &operator<<(std::ostream &stream, const String &string) { + return stream << std::string_view(string); + } + + /// Returns true if a is equal to b; otherwise returns false. + friend bool operator==(const String &a, const String &b) { + return std::string_view(a) == std::string_view(b); + } + /// Returns true if a is not equal to b; otherwise returns false. + friend bool operator!=(const String &a, const String &b) { + return std::string_view(a) != std::string_view(b); + } + +private: + void *inner; +}; + +} // namespace resolvo + +namespace std { +template <> +struct hash { + std::uint64_t operator()(const resolvo::String &str) const { + std::hash hash_fn; + return hash_fn(str); + } +}; +} // namespace std diff --git a/cpp/include/resolvo_vector.h b/cpp/include/resolvo_vector.h new file mode 100644 index 0000000..459e178 --- /dev/null +++ b/cpp/include/resolvo_vector.h @@ -0,0 +1,221 @@ +#pragma once + +#include +#include +#include +#include + +#include "resolvo_slice.h" +#include "resolvo_vector_internal.h" + +namespace resolvo { + +/// A simple vector implementation that uses reference counting to share data +/// between multiple instances. The vector is implemented as a contiguous array +/// of elements. The vector is copy-on-write, meaning that when a vector is +/// copied, the data is not copied. +template +struct Vector { + /// Constucts a new empty vector. + Vector() + : inner(const_cast
( + reinterpret_cast(cbindgen_private::resolvo_vector_empty()))) {} + + /// Creates a new vector that holds all the elements of the given std::initializer_list. + Vector(std::initializer_list args) : Vector(Vector::with_capacity(args.size())) { + auto new_data = reinterpret_cast(inner + 1); + auto input_it = args.begin(); + for (std::size_t i = 0; i < args.size(); ++i, ++input_it) { + new (new_data + i) T(*input_it); + inner->size++; + } + } + + /// Creates a vector of a given size, with default-constructed data. + explicit Vector(size_t size) : Vector(Vector::with_capacity(size)) { + auto new_data = reinterpret_cast(inner + 1); + for (std::size_t i = 0; i < size; ++i) { + new (new_data + i) T(); + inner->size++; + } + } + + /// Creates a vector of a given size, initialized with copies of `value`. + explicit Vector(size_t size, const T &value) : Vector(Vector::with_capacity(size)) { + auto new_data = reinterpret_cast(inner + 1); + for (std::size_t i = 0; i < size; ++i) { + new (new_data + i) T(value); + inner->size++; + } + } + + /// Constructs the container with the contents of the range `[first, last)`. + template + Vector(InputIt first, InputIt last) + : Vector(Vector::with_capacity(std::distance(first, last))) { + std::uninitialized_copy(first, last, begin()); + inner->size = inner->capacity; + } + + /// Creates a new vector by copying the contents of another vector. + /// Internally this function simplify increments the reference count of the + /// other vector. Therefore no actual data is copied. + Vector(const Vector &other) : inner(other.inner) { + if (inner->refcount > 0) { + ++inner->refcount; + } + } + + /// Destroys this vector. The underlying data is destroyed if no other + /// vector references it. + ~Vector() { drop(); } + + /// Provides a slice to the internal data. The returned Slice is only valid as long as at + /// least this Vector exists. + operator Slice() const { return Slice(begin(), size()); } + + /// Provides a slice to the internal data. The returned Slice is only valid as long as at + /// least this Vector exists. + operator Slice() { return Slice(begin(), size()); } + + /// Assigns the data of \a other to this vector and returns a reference to this vector. + Vector &operator=(const Vector &other) { + if (other.inner == inner) { + return *this; + } + drop(); + inner = other.inner; + if (inner->refcount > 0) { + ++inner->refcount; + } + return *this; + } + /// Move-assign's `other` to this vector and returns a reference to this vector. + Vector &operator=(Vector &&other) { + std::swap(inner, other.inner); + return *this; + } + + /// Returns a const pointer to the first element of this vector. + const T *cbegin() const { return reinterpret_cast(inner + 1); } + + /// Returns a const pointer that points past the last element of this vector. The + /// pointer cannot be dereferenced, it can only be used for comparison. + const T *cend() const { return cbegin() + inner->size; } + + /// Returns a const pointer to the first element of this vector. + const T *begin() const { return cbegin(); } + /// Returns a const pointer that points past the last element of this vector. The + /// pointer cannot be dereferenced, it can only be used for comparison. + const T *end() const { return cend(); } + + /// Returns a pointer to the first element of this vector. + T *begin() { + detach(inner->size); + return reinterpret_cast(inner + 1); + } + + /// Returns a pointer that points past the last element of this vector. The + /// pointer cannot be dereferenced, it can only be used for comparison. + T *end() { + detach(inner->size); + return begin() + inner->size; + } + + /// Returns the number of elements in this vector. + std::size_t size() const { return inner->size; } + + /// Returns true if there are no elements on this vector; false otherwise. + bool empty() const { return inner->size == 0; } + + /// This indexing operator returns a reference to the `index`th element of this vector. + T &operator[](std::size_t index) { return begin()[index]; } + + /// This indexing operator returns a const reference to the `index`th element of this vector. + const T &operator[](std::size_t index) const { return begin()[index]; } + + /// Returns a reference to the `index`th element of this vector. + const T &at(std::size_t index) const { return begin()[index]; } + + /// Appends the `value` as a new element to the end of this vector. + void push_back(const T &value) { + detach(inner->size + 1); + new (end()) T(value); + inner->size++; + } + + /// Moves the `value` as a new element to the end of this vector. + void push_back(T &&value) { + detach(inner->size + 1); + new (end()) T(std::move(value)); + inner->size++; + } + + /// Clears the vector and removes all elements. The capacity remains unaffected. + void clear() { + if (inner->refcount != 1) { + *this = Vector(); + } else { + auto b = cbegin(), e = cend(); + inner->size = 0; + for (auto it = b; it < e; ++it) { + it->~T(); + } + } + } + + /// Returns true if the vector `a` has the same number of elements as `b` + /// and all the elements also compare equal; false otherwise. + friend bool operator==(const Vector &a, const Vector &b) { + if (a.size() != b.size()) return false; + return std::equal(a.cbegin(), a.cend(), b.cbegin()); + } + + /// Returns the current allocated capacity of this vector. + std::size_t capacity() const { return inner->capacity; } + +private: + void detach(std::size_t expected_capacity) { + if (inner->refcount == 1 && expected_capacity <= inner->capacity) { + return; + } + auto new_array = Vector::with_capacity(expected_capacity); + auto old_data = reinterpret_cast(inner + 1); + auto new_data = reinterpret_cast(new_array.inner + 1); + for (std::size_t i = 0; i < inner->size; ++i) { + new (new_data + i) T(old_data[i]); + new_array.inner->size++; + } + *this = std::move(new_array); + } + + void drop() { + if (inner->refcount > 0 && (--inner->refcount) == 0) { + auto b = cbegin(), e = cend(); + for (auto it = b; it < e; ++it) { + it->~T(); + } + cbindgen_private::resolvo_vector_free(reinterpret_cast(inner), + sizeof(Header) + inner->capacity * sizeof(T), + alignof(Header)); + } + } + + static Vector with_capacity(std::size_t capacity) { + auto mem = cbindgen_private::resolvo_vector_allocate(sizeof(Header) + capacity * sizeof(T), + alignof(Header)); + return Vector(new (mem) Header{{1}, 0, capacity}); + } + + struct Header { + std::atomic refcount; + std::size_t size; + std::size_t capacity; + }; + static_assert(alignof(T) <= alignof(Header), + "Not yet supported because we would need to add padding"); + Header *inner; + explicit Vector(Header *inner) : inner(inner) {} +}; + +} // namespace resolvo diff --git a/cpp/src/lib.rs b/cpp/src/lib.rs new file mode 100644 index 0000000..f8bd5c6 --- /dev/null +++ b/cpp/src/lib.rs @@ -0,0 +1,476 @@ +mod slice; +mod string; +mod vector; + +use std::{ffi::c_void, fmt::Display, ptr::NonNull}; + +use resolvo::{KnownDependencies, SolverCache}; + +use crate::{slice::Slice, string::String, vector::Vector}; + +/// A unique identifier for a single solvable or candidate of a package. These ids should not be +/// random but rather monotonic increasing. Although it is fine to have gaps, resolvo will +/// allocate some memory based on the maximum id. +/// cbindgen:derive-eq +/// cbindgen:derive-neq +#[repr(C)] +#[derive(Copy, Clone)] +pub struct SolvableId { + id: u32, +} + +impl From for SolvableId { + fn from(id: resolvo::SolvableId) -> Self { + Self { id: id.0 } + } +} + +impl From for resolvo::SolvableId { + fn from(id: SolvableId) -> Self { + Self(id.id) + } +} + +/// A unique identifier for a single version set. A version set describes a +/// set of versions. +/// cbindgen:derive-eq +/// cbindgen:derive-neq +#[repr(C)] +#[derive(Copy, Clone)] +pub struct VersionSetId { + id: u32, +} + +impl From for VersionSetId { + fn from(id: resolvo::VersionSetId) -> Self { + Self { id: id.0 } + } +} + +impl From for resolvo::VersionSetId { + fn from(id: VersionSetId) -> Self { + Self(id.id) + } +} + +/// A unique identifier for a single package name. Resolvo will only select +/// one candidate for each unique name. +/// cbindgen:derive-eq +/// cbindgen:derive-neq +#[repr(C)] +#[derive(Copy, Clone)] +pub struct NameId { + id: u32, +} + +impl From for NameId { + fn from(id: resolvo::NameId) -> Self { + Self { id: id.0 } + } +} + +impl From for resolvo::NameId { + fn from(id: NameId) -> Self { + Self(id.id) + } +} + +/// The string id is a unique identifier for a string. +/// cbindgen:derive-eq +/// cbindgen:derive-neq +#[repr(C)] +#[derive(Copy, Clone)] +pub struct StringId { + id: u32, +} + +impl From for StringId { + fn from(id: resolvo::StringId) -> Self { + Self { id: id.0 } + } +} + +impl From for resolvo::StringId { + fn from(id: StringId) -> Self { + Self(id.id) + } +} + +#[derive(Default)] +#[repr(C)] +pub struct Dependencies { + /// A pointer to the first element of a list of requirements. Requirements + /// defines which packages should be installed alongside the depending + /// package and the constraints applied to the package. + pub requirements: Vector, + + /// Defines additional constraints on packages that may or may not be part + /// of the solution. Different from `requirements`, packages in this set + /// are not necessarily included in the solution. Only when one or more + /// packages list the package in their `requirements` is the + /// package also added to the solution. + /// + /// This is often useful to use for optional dependencies. + pub constrains: Vector, +} + +#[repr(C)] +pub struct ExcludedSolvable { + /// The id of the solvable that is excluded from the solver. + pub solvable: SolvableId, + + /// A string that provides more information about why the solvable is + /// excluded (e.g. an error message). + pub reason: StringId, +} + +#[repr(C)] +pub struct Candidates { + /// A list of all solvables for the package. + pub candidates: Vector, + + /// Optionally a pointer to the id of the solvable that is favored over + /// other solvables. The solver will first attempt to solve for the + /// specified solvable but will fall back to other candidates if no solution + /// could be found otherwise. + /// + /// The same behavior can be achieved by sorting this candidate to the top + /// using the [`resolvo::DependencyProvider::sort_candidates`] function but + /// using this method provides better error messages to the user. + pub favored: *const SolvableId, + + /// If specified this is the Id of the only solvable that can be selected. + /// Although it would also be possible to simply return a single + /// candidate using this field provides better error messages to the + /// user. + pub locked: *const SolvableId, + + /// A hint to the solver that the dependencies of some of the solvables are + /// also directly available. This allows the solver to request the + /// dependencies of these solvables immediately. Having the dependency + /// information available might make the solver much faster because it + /// has more information available up-front which provides the solver with a + /// more complete picture of the entire problem space. However, it might + /// also be the case that the solver doesnt actually need this + /// information to form a solution. In general though, if the + /// dependencies can easily be provided one should provide them up-front. + pub hint_dependencies_available: Vector, + + /// A list of solvables that are available but have been excluded from the + /// solver. For example, a package might be excluded from the solver + /// because it is not compatible with the runtime. The solver will not + /// consider these solvables when forming a solution but will use + /// them in the error message if no solution could be found. + pub excluded: Vector, +} + +impl Default for Candidates { + fn default() -> Self { + Self { + candidates: Vector::default(), + favored: std::ptr::null(), + locked: std::ptr::null(), + hint_dependencies_available: Vector::default(), + excluded: Vector::default(), + } + } +} + +/// The dependency provider is a struct that is passed to the solver which +/// implements the ecosystem specific logic to resolve dependencies. +#[repr(C)] +pub struct DependencyProvider { + /// The data pointer is a pointer that is passed to each of the functions. + pub data: *mut c_void, + + /// Returns a user-friendly string representation of the specified solvable. + /// + /// When formatting the solvable, it should it include both the name of + /// the package and any other identifying properties. + pub display_solvable: + unsafe extern "C" fn(data: *mut c_void, solvable: SolvableId, result: NonNull), + + /// Returns a user-friendly string representation of the name of the + /// specified solvable. + pub display_solvable_name: + unsafe extern "C" fn(data: *mut c_void, solvable: SolvableId, result: NonNull), + + /// Returns a string representation of multiple solvables merged together. + /// + /// When formatting the solvables, both the name of the packages and any + /// other identifying properties should be included. + pub display_merged_solvables: unsafe extern "C" fn( + data: *mut c_void, + solvable: Slice, + result: NonNull, + ), + + /// Returns an object that can be used to display the given name in a + /// user-friendly way. + pub display_name: + unsafe extern "C" fn(data: *mut c_void, name: NameId, result: NonNull), + + /// Returns a user-friendly string representation of the specified version + /// set. + /// + /// The name of the package should *not* be included in the display. Where + /// appropriate, this information is added. + pub display_version_set: + unsafe extern "C" fn(data: *mut c_void, version_set: VersionSetId, result: NonNull), + + /// Returns the string representation of the specified string. + pub display_string: + unsafe extern "C" fn(data: *mut c_void, string: StringId, result: NonNull), + + /// Returns the name of the package that the specified version set is + /// associated with. + pub version_set_name: + unsafe extern "C" fn(data: *mut c_void, version_set_id: VersionSetId) -> NameId, + + /// Returns the name of the package for the given solvable. + pub solvable_name: unsafe extern "C" fn(data: *mut c_void, solvable_id: SolvableId) -> NameId, + + /// Obtains a list of solvables that should be considered when a package + /// with the given name is requested. + pub get_candidates: + unsafe extern "C" fn(data: *mut c_void, package: NameId, candidates: NonNull), + + /// Sort the specified solvables based on which solvable to try first. The + /// solver will iteratively try to select the highest version. If a + /// conflict is found with the highest version the next version is + /// tried. This continues until a solution is found. + pub sort_candidates: unsafe extern "C" fn(data: *mut c_void, solvables: Slice), + + /// Given a set of solvables, return the candidates that match the given + /// version set or if `inverse` is true, the candidates that do *not* match + /// the version set. + pub filter_candidates: unsafe extern "C" fn( + data: *mut c_void, + candidates: Slice, + version_set_id: VersionSetId, + inverse: bool, + filtered: NonNull>, + ), + + /// Returns the dependencies for the specified solvable. + pub get_dependencies: unsafe extern "C" fn( + data: *mut c_void, + solvable: SolvableId, + dependencies: NonNull, + ), +} + +impl<'d> resolvo::Interner for &'d DependencyProvider { + fn display_solvable(&self, solvable: resolvo::SolvableId) -> impl Display + '_ { + let mut result = String::default(); + unsafe { (self.display_solvable)(self.data, solvable.into(), NonNull::from(&mut result)) } + result + } + + fn display_solvable_name(&self, solvable: resolvo::SolvableId) -> impl Display + '_ { + let mut result = String::default(); + unsafe { + (self.display_solvable_name)(self.data, solvable.into(), NonNull::from(&mut result)) + } + result + } + + fn display_merged_solvables(&self, solvables: &[resolvo::SolvableId]) -> impl Display + '_ { + let mut result = String::default(); + unsafe { + (self.display_merged_solvables)( + self.data, + Slice::from_slice(std::mem::transmute(solvables)), + NonNull::from(&mut result), + ) + } + result + } + + fn display_name(&self, name: resolvo::NameId) -> impl Display + '_ { + let mut result = String::default(); + unsafe { (self.display_name)(self.data, name.into(), NonNull::from(&mut result)) } + result + } + + fn display_version_set(&self, version_set: resolvo::VersionSetId) -> impl Display + '_ { + let mut result = String::default(); + unsafe { + (self.display_version_set)(self.data, version_set.into(), NonNull::from(&mut result)) + } + result + } + + fn display_string(&self, string_id: resolvo::StringId) -> impl Display + '_ { + let mut result = String::default(); + unsafe { (self.display_string)(self.data, string_id.into(), NonNull::from(&mut result)) } + result + } + + fn version_set_name(&self, version_set: resolvo::VersionSetId) -> resolvo::NameId { + unsafe { (self.version_set_name)(self.data, version_set.into()) }.into() + } + + fn solvable_name(&self, solvable: resolvo::SolvableId) -> resolvo::NameId { + unsafe { (self.solvable_name)(self.data, solvable.into()) }.into() + } +} + +impl<'d> resolvo::DependencyProvider for &'d DependencyProvider { + async fn filter_candidates( + &self, + candidates: &[resolvo::SolvableId], + version_set: resolvo::VersionSetId, + inverse: bool, + ) -> Vec { + let mut result = Vector::default(); + unsafe { + (self.filter_candidates)( + self.data, + Slice::from_slice(std::mem::transmute(candidates)), + version_set.into(), + inverse, + NonNull::from(&mut result), + ) + }; + result.into_iter().map(Into::into).collect() + } + + async fn get_candidates(&self, name: resolvo::NameId) -> Option { + let mut candidates = Candidates { + candidates: Vector::default(), + favored: std::ptr::null(), + locked: std::ptr::null(), + hint_dependencies_available: Vector::default(), + excluded: Vector::default(), + }; + unsafe { (self.get_candidates)(self.data, name.into(), NonNull::from(&mut candidates)) }; + + unsafe { + Some(resolvo::Candidates { + candidates: candidates.candidates.into_iter().map(Into::into).collect(), + favored: candidates.favored.as_ref().copied().map(Into::into), + locked: candidates.locked.as_ref().copied().map(Into::into), + hint_dependencies_available: candidates + .hint_dependencies_available + .into_iter() + .map(Into::into) + .collect(), + excluded: candidates + .excluded + .into_iter() + .map(|excluded| (excluded.solvable.into(), excluded.reason.into())) + .collect(), + }) + } + } + + async fn sort_candidates( + &self, + _solver: &SolverCache, + solvables: &mut [resolvo::SolvableId], + ) { + unsafe { + (self.sort_candidates)(self.data, Slice::from_slice(std::mem::transmute(solvables))) + } + } + + async fn get_dependencies(&self, solvable: resolvo::SolvableId) -> resolvo::Dependencies { + let mut dependencies = Dependencies::default(); + unsafe { + (self.get_dependencies)(self.data, solvable.into(), NonNull::from(&mut dependencies)) + }; + + resolvo::Dependencies::Known(KnownDependencies { + requirements: dependencies + .requirements + .into_iter() + .map(Into::into) + .collect(), + constrains: dependencies + .constrains + .into_iter() + .map(Into::into) + .collect(), + }) + } +} + +#[no_mangle] +#[allow(unused)] +pub extern "C" fn resolvo_solve( + provider: &DependencyProvider, + requirements: Slice, + constraints: Slice, + error: &mut String, + result: &mut Vector, +) -> bool { + let requirements = requirements + .into_iter() + .copied() + .map(Into::into) + .collect::>(); + let constraints = constraints + .into_iter() + .copied() + .map(Into::into) + .collect::>(); + + let mut solver = resolvo::Solver::new(provider); + match solver.solve(requirements, constraints) { + Ok(solution) => { + *result = solution.into_iter().map(Into::into).collect(); + true + } + Err(resolvo::UnsolvableOrCancelled::Unsolvable(problem)) => { + *error = problem.display_user_friendly(&solver).to_string().into(); + false + } + Err(resolvo::UnsolvableOrCancelled::Cancelled(cancelled)) => { + *error = String::from("cancelled"); + false + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_memory_layout_compatiblity() { + assert_eq!( + std::mem::size_of::(), + std::mem::size_of::() + ); + assert_eq!( + std::mem::size_of::(), + std::mem::size_of::() + ); + assert_eq!( + std::mem::size_of::(), + std::mem::size_of::() + ); + assert_eq!( + std::mem::size_of::(), + std::mem::size_of::() + ); + + assert_eq!( + std::mem::align_of::(), + std::mem::align_of::() + ); + assert_eq!( + std::mem::align_of::(), + std::mem::align_of::() + ); + assert_eq!( + std::mem::align_of::(), + std::mem::align_of::() + ); + assert_eq!( + std::mem::align_of::(), + std::mem::align_of::() + ); + } +} diff --git a/cpp/src/slice.rs b/cpp/src/slice.rs new file mode 100644 index 0000000..0662a75 --- /dev/null +++ b/cpp/src/slice.rs @@ -0,0 +1,68 @@ +use std::{fmt::Debug, marker::PhantomData, ptr::NonNull}; + +#[repr(C)] +#[derive(PartialEq)] +pub struct Slice<'a, T> { + /// Invariant, this is a valid slice of len `len` + ptr: NonNull, + len: usize, + phantom: PhantomData<&'a [T]>, +} + +impl<'a, T: Debug> Debug for Slice<'a, T> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.as_slice().fmt(f) + } +} + +// Need to implement manually otherwise it is not implemented if T do not +// implement Copy / Clone +impl<'a, T> Copy for Slice<'a, T> {} + +impl<'a, T> Clone for Slice<'a, T> { + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Slice<'a, T> { + /// Return a slice + pub fn as_slice(self) -> &'a [T] { + // Safety: it ptr is supposed to be a valid slice of given length + unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len) } + } + + /// Create from a native slice + pub const fn from_slice(slice: &'a [T]) -> Self { + Slice { + // Safety: a slice is never null + ptr: unsafe { NonNull::new_unchecked(slice.as_ptr() as *mut T) }, + len: slice.len(), + phantom: PhantomData, + } + } +} + +impl<'a, T> From<&'a [T]> for Slice<'a, T> { + fn from(slice: &'a [T]) -> Self { + Self::from_slice(slice) + } +} + +impl<'a, T> core::ops::Deref for Slice<'a, T> { + type Target = [T]; + fn deref(&self) -> &[T] { + self.as_slice() + } +} + +impl<'a, T> Default for Slice<'a, T> { + fn default() -> Self { + Self::from_slice(&[]) + } +} + +/// Safety: Slice is the same as a rust slice, and a slice of Sync T is Sync +unsafe impl Sync for Slice<'_, T> {} +/// Safety: Slice is the same as a rust slice, and a slice of Send T is Sync +unsafe impl Send for Slice<'_, T> {} diff --git a/cpp/src/string.rs b/cpp/src/string.rs new file mode 100644 index 0000000..2d452f1 --- /dev/null +++ b/cpp/src/string.rs @@ -0,0 +1,134 @@ +use std::{ + fmt::{Debug, Display}, + ops::Deref, +}; + +use crate::vector::Vector; + +/// A string type that is used on both the Rust and C++ side. +/// +/// This type uses implicit data sharing to make it efficient to pass around +/// copied. When cloning, a reference to the data is cloned, not the data +/// itself. The data uses Copy-on-Write semantics, so the data is only cloned +/// when it is modified. +/// +/// The string data is stored as UTF8-encoded bytes, and it is always terminated +/// with a null character. +#[derive(Clone, Default)] +#[repr(C)] +pub struct String { + inner: Vector, +} + +impl String { + /// Returns a pointer to the underlying data. + pub fn as_ptr(&self) -> *const u8 { + self.inner.as_ptr() + } + + /// Returns the size of the string, in bytes. This excludes the terminating + /// null character. + pub fn len(&self) -> usize { + self.inner.len().saturating_sub(1) + } + + /// Returns true if the String is empty + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns a slice to the string + pub fn as_str(&self) -> &str { + // Safety: self.as_ptr is a pointer from the inner which has utf-8 + unsafe { + core::str::from_utf8_unchecked(core::slice::from_raw_parts(self.as_ptr(), self.len())) + } + } +} + +impl Deref for String { + type Target = str; + fn deref(&self) -> &Self::Target { + self.as_str() + } +} + +impl From<&str> for String { + fn from(value: &str) -> Self { + String { + inner: Vector::from_iter(value.as_bytes().iter().cloned().chain(core::iter::once(0))), + } + } +} + +impl From for String { + fn from(s: std::string::String) -> Self { + s.as_str().into() + } +} + +impl From<&std::string::String> for String { + fn from(s: &std::string::String) -> Self { + s.as_str().into() + } +} + +impl Debug for String { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self.as_str()) + } +} + +impl Display for String { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl AsRef for String { + #[inline] + fn as_ref(&self) -> &str { + self.as_str() + } +} + +/// for cbindgen. +#[allow(non_camel_case_types)] +type c_char = u8; + +#[no_mangle] +/// Returns a nul-terminated pointer for this string. +/// The returned value is owned by the string, and should not be used after any +/// mutable function have been called on the string, and must not be freed. +pub extern "C" fn resolvo_string_bytes(ss: &String) -> *const c_char { + if ss.is_empty() { + "\0".as_ptr() + } else { + ss.as_ptr() + } +} + +#[no_mangle] +/// Destroy the shared string +pub unsafe extern "C" fn resolvo_string_drop(ss: *const String) { + core::ptr::read(ss); +} + +#[no_mangle] +/// Increment the reference count of the string. +/// The resulting structure must be passed to resolvo_string_drop +pub unsafe extern "C" fn resolvo_string_clone(out: *mut String, ss: &String) { + core::ptr::write(out, ss.clone()) +} + +#[no_mangle] +/// Safety: bytes must be a valid utf-8 string of size len without null inside. +/// The resulting structure must be passed to resolvo_string_drop +pub unsafe extern "C" fn resolvo_string_from_bytes( + out: *mut String, + bytes: *const c_char, + len: usize, +) { + let str = core::str::from_utf8(core::slice::from_raw_parts(bytes, len)).unwrap(); + core::ptr::write(out, String::from(str)); +} diff --git a/cpp/src/vector.rs b/cpp/src/vector.rs new file mode 100644 index 0000000..e7f4cc3 --- /dev/null +++ b/cpp/src/vector.rs @@ -0,0 +1,439 @@ +use std::{fmt::Debug, mem::MaybeUninit, ops::Deref, ptr::NonNull, sync::atomic}; + +#[repr(C)] +struct VectorHeader { + refcount: atomic::AtomicIsize, + size: usize, + capacity: usize, +} + +#[repr(C)] +struct VectorInner { + header: VectorHeader, + data: MaybeUninit, +} + +#[repr(C)] +pub struct Vector { + inner: NonNull>, +} + +// Safety: We use atomic reference counting, and if T is Send, we can send the +// vector to another thread +unsafe impl Send for Vector {} + +impl Drop for Vector { + fn drop(&mut self) { + unsafe { + if self + .inner + .cast::() + .as_ref() + .refcount + .load(atomic::Ordering::Relaxed) + < 0 + { + return; + } + + if self + .inner + .as_ref() + .header + .refcount + .fetch_sub(1, atomic::Ordering::SeqCst) + == 1 + { + drop_inner(self.inner) + } + } + } +} + +impl Clone for Vector { + fn clone(&self) -> Self { + unsafe { + if self + .inner + .cast::() + .as_ref() + .refcount + .load(atomic::Ordering::Relaxed) + > 0 + { + self.inner + .as_ref() + .header + .refcount + .fetch_add(1, atomic::Ordering::SeqCst); + } + Vector { inner: self.inner } + } + } +} + +impl Vector { + /// Create a new empty array with a pre-allocated capacity in number of + /// items + pub fn with_capacity(capacity: usize) -> Self { + Self { + inner: alloc_with_capacity(capacity), + } + } + + /// Returns a pointer to the first element of the array. + pub fn as_ptr(&self) -> *const T { + unsafe { self.inner.as_ref().data.as_ptr() } + } + + /// Returns the number of elements in the array + pub fn len(&self) -> usize { + unsafe { self.inner.cast::().as_ref().size } + } + + /// Returns true if the Vector is empty + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Return a slice to the array + pub fn as_slice(&self) -> &[T] { + if self.is_empty() { + &[] + } else { + // Safety: When len > 0, we know that the pointer holds an array of + // the size of len + unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len()) } + } + } + + /// Returns the number of elements the vector can hold without reallocating, + /// when not shared + fn capacity(&self) -> usize { + unsafe { self.inner.cast::().as_ref().capacity } + } +} + +impl Vector { + /// Ensure that the reference count is 1 so the array can be changed. + /// If that's not the case, the array will be cloned + fn detach(&mut self, new_capacity: usize) { + let is_shared = unsafe { + self.inner + .as_ref() + .header + .refcount + .load(atomic::Ordering::Relaxed) + } != 1; + if !is_shared && new_capacity <= self.capacity() { + return; + } + let mut new_array = Vector::with_capacity(new_capacity); + core::mem::swap(&mut self.inner, &mut new_array.inner); + let mut size = 0; + for x in new_array.into_iter() { + assert_ne!(size, new_capacity); + unsafe { + core::ptr::write(self.inner.as_mut().data.as_mut_ptr().add(size), x); + size += 1; + self.inner.as_mut().header.size = size; + } + if size == new_capacity { + break; + } + } + } + + /// Adds an element to the array. If the array was shared, this will make a + /// copy of the array. + pub fn push(&mut self, value: T) { + self.detach(determine_capacity_for_growth( + self.capacity(), + self.len() + 1, + core::mem::size_of::(), + )); + unsafe { + core::ptr::write( + self.inner + .as_mut() + .data + .as_mut_ptr() + .add(self.inner.as_mut().header.size), + value, + ); + self.inner.as_mut().header.size += 1; + } + } +} + +impl Deref for Vector { + type Target = [T]; + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl FromIterator for Vector { + fn from_iter>(iter: I) -> Self { + let mut iter = iter.into_iter(); + let mut capacity = iter.size_hint().0; + let mut result = Self::with_capacity(capacity); + let mut size = 0; + while let Some(x) = iter.next() { + if size >= capacity { + capacity = determine_capacity_for_growth( + capacity, + size + 1 + iter.size_hint().0, + core::mem::size_of::(), + ); + unsafe { + result + .inner + .as_ref() + .header + .refcount + .store(0, atomic::Ordering::Relaxed) + }; + let mut iter = IntoIter(IntoIterInner::UnShared(result.inner, 0)); + result.inner = alloc_with_capacity::(capacity); + match &mut iter.0 { + IntoIterInner::UnShared(old_inner, begin) => { + while *begin < size { + unsafe { + core::ptr::write( + result.inner.as_mut().data.as_mut_ptr().add(*begin), + core::ptr::read(old_inner.as_ref().data.as_ptr().add(*begin)), + ); + *begin += 1; + result.inner.as_mut().header.size = *begin; + } + } + } + _ => unreachable!(), + } + } + debug_assert_eq!(result.len(), size); + debug_assert!(result.capacity() > size); + unsafe { + core::ptr::write(result.inner.as_mut().data.as_mut_ptr().add(size), x); + size += 1; + result.inner.as_mut().header.size = size; + } + } + result + } +} + +static SHARED_EMPTY_VEC: VectorHeader = VectorHeader { + refcount: atomic::AtomicIsize::new(-1), + size: 0, + capacity: 0, +}; + +impl Default for Vector { + fn default() -> Self { + Vector { + inner: NonNull::from(&SHARED_EMPTY_VEC).cast(), + } + } +} + +impl Debug for Vector { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.as_slice().fmt(f) + } +} + +impl AsRef<[T]> for Vector { + #[inline] + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +/// Drops the inner vector and deallocates the memory. This is only really a +/// valid operation if the reference count is 0, otherwise there might be other +/// users. +unsafe fn drop_inner(mut inner: NonNull>) { + debug_assert_eq!( + inner + .as_ref() + .header + .refcount + .load(atomic::Ordering::Relaxed), + 0 + ); + let data_ptr = inner.as_mut().data.as_mut_ptr(); + for x in 0..inner.as_ref().header.size { + core::ptr::drop_in_place(data_ptr.add(x)); + } + std::alloc::dealloc( + inner.as_ptr() as *mut u8, + compute_inner_layout::(inner.as_ref().header.capacity), + ) +} + +impl IntoIterator for Vector { + type Item = T; + type IntoIter = IntoIter; + fn into_iter(self) -> Self::IntoIter { + IntoIter(unsafe { + if self + .inner + .as_ref() + .header + .refcount + .load(atomic::Ordering::Relaxed) + == 1 + { + let inner = self.inner; + core::mem::forget(self); + inner + .as_ref() + .header + .refcount + .store(0, atomic::Ordering::Relaxed); + IntoIterInner::UnShared(inner, 0) + } else { + IntoIterInner::Shared(self, 0) + } + }) + } +} + +enum IntoIterInner { + Shared(Vector, usize), + // Elements up to the usize member are already moved out + UnShared(NonNull>, usize), +} + +impl Drop for IntoIterInner { + fn drop(&mut self) { + match self { + IntoIterInner::Shared(..) => { /* drop of Vector takes care of it */ } + IntoIterInner::UnShared(mut inner, begin) => unsafe { + debug_assert_eq!( + inner + .as_ref() + .header + .refcount + .load(atomic::Ordering::Relaxed), + 0 + ); + let data_ptr = inner.as_mut().data.as_mut_ptr(); + for x in (*begin)..inner.as_ref().header.size { + core::ptr::drop_in_place(data_ptr.add(x)); + } + std::alloc::dealloc( + inner.as_ptr() as *mut u8, + compute_inner_layout::(inner.as_ref().header.capacity), + ) + }, + } + } +} + +/// An iterator that moves out of a Vector. +/// +/// This `struct` is created by the `into_iter` method on [`Vector`] +/// (provided by the [`IntoIterator`] trait). +pub struct IntoIter(IntoIterInner); + +impl Iterator for IntoIter { + type Item = T; + + fn next(&mut self) -> Option { + match &mut self.0 { + IntoIterInner::Shared(array, moved) => { + let result = array.as_slice().get(*moved).cloned(); + *moved += 1; + result + } + IntoIterInner::UnShared(inner, begin) => unsafe { + if *begin < inner.as_ref().header.size { + let r = core::ptr::read(inner.as_ref().data.as_ptr().add(*begin)); + *begin += 1; + Some(r) + } else { + None + } + }, + } + } +} + +/// Determine the memory layout to allocate when a specific capacity of T is +/// requested. +fn compute_inner_layout(capacity: usize) -> core::alloc::Layout { + core::alloc::Layout::new::() + .extend(core::alloc::Layout::array::(capacity).unwrap()) + .unwrap() + .0 +} + +/// Allocate the memory for a Vector with the given capacity. Returns an +/// `inner` with size and refcount set to 1 +fn alloc_with_capacity(capacity: usize) -> NonNull> { + let ptr = unsafe { std::alloc::alloc(compute_inner_layout::(capacity)) }; + assert!(!ptr.is_null(), "allocation of {:?} bytes failed", capacity); + unsafe { + core::ptr::write( + ptr as *mut VectorHeader, + VectorHeader { + refcount: 1.into(), + size: 0, + capacity, + }, + ); + } + NonNull::new(ptr).unwrap().cast() +} + +/// Returns a new capacity suitable to store `required_cap` elements. +/// Loosely based on alloc::raw_vec::RawVec::grow_amortized. +fn determine_capacity_for_growth( + current_cap: usize, + required_cap: usize, + elem_size: usize, +) -> usize { + if current_cap >= required_cap { + return current_cap; + } + let cap = core::cmp::max(current_cap * 2, required_cap); + let min_non_zero_cap = if elem_size == 1 { + 8 + } else if elem_size <= 1024 { + 4 + } else { + 1 + }; + core::cmp::max(min_non_zero_cap, cap) +} + +pub(crate) mod ffi { + use super::*; + + #[no_mangle] + /// This function is used for the low-level C++ interface to allocate the + /// backing vector of a Vector. + pub unsafe extern "C" fn resolvo_vector_allocate(size: usize, align: usize) -> *mut u8 { + std::alloc::alloc(std::alloc::Layout::from_size_align(size, align).unwrap()) + } + + #[no_mangle] + /// This function is used for the low-level C++ interface to deallocate the + /// backing vector of a Vector + pub unsafe extern "C" fn resolvo_vector_free(ptr: *mut u8, size: usize, align: usize) { + std::alloc::dealloc( + ptr, + std::alloc::Layout::from_size_align(size, align).unwrap(), + ) + } + + #[no_mangle] + /// This function is used for the low-level C++ interface to initialize the + /// empty Vector. + pub unsafe extern "C" fn resolvo_vector_empty() -> *const u8 { + &SHARED_EMPTY_VEC as *const _ as *const u8 + } +} diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt new file mode 100644 index 0000000..c5de61d --- /dev/null +++ b/cpp/tests/CMakeLists.txt @@ -0,0 +1,34 @@ +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v2.13.8) + +FetchContent_MakeAvailable(Catch2) + +include(CTest) + +macro(resolvo_test NAME) + add_executable(test_${NAME} ${NAME}.cpp) + target_link_libraries(test_${NAME} PRIVATE Resolvo Catch2::Catch2) + target_compile_definitions( + test_${NAME} PRIVATE SOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/\") + # Use debug version of run-time library to enable MSVC iterator debugging + set_property(TARGET test_${NAME} PROPERTY MSVC_RUNTIME_LIBRARY + MultiThreadedDebugDLL) + add_test(NAME test_${NAME} COMMAND test_${NAME}) + + if(MSVC) + target_compile_options(test_${NAME} PRIVATE /W3) + else() + target_compile_options(test_${NAME} PRIVATE -Wall -Wextra -Werror) + endif() + + if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) + # that warning has false positives + target_compile_options(test_${NAME} PRIVATE -Wno-maybe-uninitialized) + endif() +endmacro(resolvo_test) + +resolvo_test(vector) +resolvo_test(string) +resolvo_test(solve) diff --git a/cpp/tests/solve.cpp b/cpp/tests/solve.cpp new file mode 100644 index 0000000..ffb8c66 --- /dev/null +++ b/cpp/tests/solve.cpp @@ -0,0 +1,198 @@ +#define CATCH_CONFIG_MAIN +#include +#include + +#include + +#include "catch2/catch.hpp" + +/** + * A single candidate for a package. + */ +struct Candidate { + resolvo::NameId name; + uint32_t version; + resolvo::Dependencies dependencies; +}; + +/** + * A requirement for a package. + */ +struct Requirement { + resolvo::NameId name; + uint32_t version_start; + uint32_t version_end; +}; + +/** + * A simple database of packages that also implements resolvos DependencyProvider interface. + */ +struct PackageDatabase : public resolvo::DependencyProvider { + resolvo::Pool names; + resolvo::Pool strings; + std::vector candidates; + std::vector requirements; + + /** + * Allocates a new requirement and return the id of the requirement. + */ + resolvo::VersionSetId alloc_requirement(std::string_view package, uint32_t version_start, + uint32_t version_end) { + auto name_id = names.alloc(std::move(package)); + auto id = resolvo::VersionSetId{static_cast(requirements.size())}; + requirements.push_back(Requirement{name_id, version_start, version_end}); + return id; + } + + /** + * Allocates a new candidate and return the id of the candidate. + */ + resolvo::SolvableId alloc_candidate(std::string_view name, uint32_t version, + resolvo::Dependencies dependencies) { + auto name_id = names.alloc(std::move(name)); + auto id = resolvo::SolvableId{static_cast(candidates.size())}; + candidates.push_back(Candidate{name_id, version, dependencies}); + return id; + } + + resolvo::String display_name(resolvo::NameId name) override { + return resolvo::String(names[name]); + } + + resolvo::String display_solvable(resolvo::SolvableId solvable) override { + const auto& candidate = candidates[solvable.id]; + std::stringstream ss; + ss << names[candidate.name] << "=" << candidate.version; + return resolvo::String(ss.str()); + } + + resolvo::String display_merged_solvables( + resolvo::Slice solvables) override { + if (solvables.empty()) { + return resolvo::String(); + } + + std::stringstream ss; + ss << names[candidates[solvables[0].id].name] << " "; + + bool first = true; + for (const auto& solvable : solvables) { + if (!first) { + ss << " | "; + } else { + first = false; + } + + ss << candidates[solvable.id].version; + } + + return resolvo::String(ss.str()); + } + + resolvo::String display_version_set(resolvo::VersionSetId version_set) override { + const auto& req = requirements[version_set.id]; + std::stringstream ss; + ss << req.version_start << ".." << req.version_end; + return resolvo::String(ss.str()); + } + + resolvo::String display_string(resolvo::StringId string_id) override { + return strings[string_id]; + } + + resolvo::NameId version_set_name(resolvo::VersionSetId version_set_id) override { + return requirements[version_set_id.id].name; + } + + resolvo::NameId solvable_name(resolvo::SolvableId solvable_id) override { + return candidates[solvable_id.id].name; + } + + resolvo::Candidates get_candidates(resolvo::NameId package) override { + resolvo::Candidates result; + + for (uint32_t i = 0; i < static_cast(candidates.size()); ++i) { + const auto& candidate = candidates[i]; + if (candidate.name != package) { + continue; + } + result.candidates.push_back(resolvo::SolvableId{i}); + result.hint_dependencies_available.push_back(resolvo::SolvableId{i}); + } + + result.favored = nullptr; + result.locked = nullptr; + + return result; + } + + void sort_candidates(resolvo::Slice solvables) override { + std::sort(solvables.begin(), solvables.end(), + [&](resolvo::SolvableId a, resolvo::SolvableId b) { + return candidates[a.id].version > candidates[b.id].version; + }); + } + + resolvo::Vector filter_candidates( + resolvo::Slice solvables, resolvo::VersionSetId version_set_id, + bool inverse) override { + resolvo::Vector result; + const auto& requirement = requirements[version_set_id.id]; + for (auto solvable : solvables) { + const auto& candidate = candidates[solvable.id]; + bool matches = candidate.version >= requirement.version_start && + candidate.version < requirement.version_end; + if (matches != inverse) { + result.push_back(solvable); + } + } + return result; + } + + resolvo::Dependencies get_dependencies(resolvo::SolvableId solvable) override { + const auto& candidate = candidates[solvable.id]; + return candidate.dependencies; + } +}; + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#elif defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#endif + +SCENARIO("Solve") { + /// Construct a database with packages a, b, and c. + PackageDatabase db; + + // Check that PackageDatabase correctly implements the DependencyProvider interface + static_assert(std::has_virtual_destructor_v); + static_assert(std::is_polymorphic_v); + static_assert(std::is_base_of_v); + + auto a_1 = db.alloc_candidate("a", 1, {{db.alloc_requirement("b", 1, 4)}, {}}); + auto a_2 = db.alloc_candidate("a", 2, {{db.alloc_requirement("b", 1, 4)}, {}}); + auto a_3 = db.alloc_candidate("a", 3, {{db.alloc_requirement("b", 4, 7)}, {}}); + + auto b_1 = db.alloc_candidate("b", 1, {}); + auto b_2 = db.alloc_candidate("b", 2, {}); + auto b_3 = db.alloc_candidate("b", 3, {}); + + auto c_1 = db.alloc_candidate("c", 1, {}); + + // Construct a problem to be solved by the solver + resolvo::Vector requirements = {db.alloc_requirement("a", 1, 3)}; + resolvo::Vector constraints = {db.alloc_requirement("b", 1, 3), + db.alloc_requirement("c", 1, 3)}; + + // Solve the problem + resolvo::Vector result; + resolvo::solve(db, requirements, constraints, result); + + // Check the result + REQUIRE(result.size() == 2); + REQUIRE(result[0] == a_2); + REQUIRE(result[1] == b_2); +} diff --git a/cpp/tests/string.cpp b/cpp/tests/string.cpp new file mode 100644 index 0000000..d1a95d7 --- /dev/null +++ b/cpp/tests/string.cpp @@ -0,0 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include + +#include "catch2/catch.hpp" + +SCENARIO("String") { resolvo::String a("Hello, world!"); } diff --git a/cpp/tests/vector.cpp b/cpp/tests/vector.cpp new file mode 100644 index 0000000..91092f6 --- /dev/null +++ b/cpp/tests/vector.cpp @@ -0,0 +1,20 @@ +#define CATCH_CONFIG_MAIN +#include + +#include "catch2/catch.hpp" + +SCENARIO("Vector") { + resolvo::Vector a{1, 2, 3, 4}; + REQUIRE(a.capacity() >= 4); + REQUIRE(a.size() == 4); + + resolvo::Vector b = a; + REQUIRE(b.capacity() >= 4); + REQUIRE(b.size() == 4); + + REQUIRE(a == b); + + b.push_back(4); + REQUIRE(b.size() == 5); + REQUIRE(a.size() == 4); +} diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 0000000..2afecb6 --- /dev/null +++ b/pixi.lock @@ -0,0 +1,3848 @@ +version: 5 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: {} + format-cpp: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.6.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-18-18.1.6-default_h127d8a8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-18.1.6-default_h127d8a8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cmake-format-0.6.13-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp18.1-18.1.6-default_h127d8a8_0.conda + - 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/libgcc-ng-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.6-hb77312f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.0-hde9e2c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-hc0a3c3a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.7-hc051c1a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h98912ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4ab18f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.1-py312h98912ed_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.6.2-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-18-18.1.6-default_ha3b9224_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-18.1.6-default_ha3b9224_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cmake-format-0.6.13-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp18.1-18.1.6-default_ha3b9224_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-17.0.6-h88467a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.6-hd5e122f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.46.0-h1b8f9f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.7-h3e169fe_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-h87427d6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-2.1.5-py312h41838bb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.1-h87427d6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.3-h1411813_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py312h104f124_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.6-h915ae27_0.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.6.2-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-18-18.1.6-default_h7c89ad4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-18.1.6-default_h7c89ad4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cmake-format-0.6.13-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp18.1-18.1.6-default_h7c89ad4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-17.0.6-h5f092b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.6-hdac5640_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.46.0-hfb93653_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.7-ha661575_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-hfb2fe0b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py312he37b823_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.1-hfb2fe0b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.3-h4a7b5fc_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py312h02f2b3b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.6.2-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-18.1.6-default_h3a3e6c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cmake-format-0.6.13-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.46.0-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py312he70551f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.3.1-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.3-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.1-py312he70551f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-ha32ba9b_20.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33135-h835141b_20.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33135-h22015db_20.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h8ffe710_2.tar.bz2 + test-cpp: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.40-h4852527_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-ha1999f0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.40-hdade7a5_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.28.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.7.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.6.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.29.4-h91dbaaa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.7.0-h00ab1b0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-12.3.0-h915e2ae_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-12.3.0-h58ffeeb_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-12.3.0-h6477408_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-12.3.0-h915e2ae_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-12.3.0-h2a574ab_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-12.3.0-h4a1b8e8_3.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/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.8.0-hca28451_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h0223996_107.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-12.3.0-hb8811af_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h0223996_107.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-hc0a3c3a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.48.0-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.12.1-h297d8ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4ab18f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.75.0-h70c747d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.75.0-h2c6d0dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_17.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.7.0-h282daa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.6.2-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-986-h40f6528_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-986-ha1c5b94_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-16-16.0.6-default_h4c8afb6_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-16.0.6-hd4457cd_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-16.0.6-h8787910_15.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_osx-64-16.0.6-hb91bd55_15.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-16.0.6-default_ha3b9224_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-16.0.6-h6d92fbe_15.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-16.0.6-hb91bd55_15.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.29.4-h1304840_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-16.0.6-ha38d28d_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-16.0.6-ha38d28d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.7.0-h7728843_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-711-ha02d983_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-711-ha20a434_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp16-16.0.6-default_h4c8afb6_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.8.0-hf9fcc65_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-17.0.6-h88467a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm16-16.0.6-hbedff68_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.48.0-h67532ce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.7-h3e169fe_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-h87427d6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.6-h15ab845_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-16.0.6-hbedff68_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.12.1-h3c5361c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.1-h87427d6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rust-1.75.0-h7e1429e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.75.0-h38e4360_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.6-h915ae27_0.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.7.0-h6aa9301_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.6.2-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-986-h4faf515_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-986-h62378fb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-16-16.0.6-default_hb63da90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-16.0.6-h7bc9447_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-16.0.6-hc421ffc_15.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_osx-arm64-16.0.6-h54d7cd3_15.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-16.0.6-default_h095aff0_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-16.0.6-hcd7bac0_15.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-16.0.6-h54d7cd3_15.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.29.4-h2cf84f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-16.0.6-h3808999_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-16.0.6-h3808999_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.7.0-h2ffa867_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-711-h634c8be_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-711-ha4bd21c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp16-16.0.6-default_hb63da90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.8.0-h7b6f9a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-17.0.6-h5f092b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm16-16.0.6-haab561b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.48.0-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.7-ha661575_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-hfb2fe0b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.6-hde57baf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-16.0.6-haab561b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.12.1-h420ef59_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.1-hfb2fe0b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.75.0-h4ff7c5d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.75.0-hf6ec828_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.6.2-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.29.4-h75d51d9_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-1.7.0-h91493d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.8.0-hd5e4a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.12.1-hc790b64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.3.1-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rust-1.75.0-hf8d6059_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.75.0-h17fc481_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-ha32ba9b_20.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33135-h835141b_20.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33135-h22015db_20.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2019_win-64-19.29.30139-he1865b1_20.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vswhere-3.1.4-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.6-h0ea2cb4_0.conda + test-rust: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-ha1999f0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-12.3.0-h58ffeeb_7.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/linux-64/ld_impl_linux-64-2.40-hf3520f5_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h0223996_107.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-12.3.0-hb8811af_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-hc0a3c3a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.75.0-h70c747d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.75.0-h2c6d0dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_17.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/rust-1.75.0-h7e1429e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.75.0-h38e4360_0.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.75.0-h4ff7c5d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.75.0-hf6ec828_0.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/rust-1.75.0-hf8d6059_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.75.0-h17fc481_0.conda +packages: +- kind: conda + name: _libgcc_mutex + version: '0.1' + build: conda_forge + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 + md5: d7c89558ba9fa0495403155b64376d81 + license: None + size: 2562 + timestamp: 1578324546067 +- kind: conda + name: _openmp_mutex + version: '4.5' + build: 2_gnu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 + md5: 73aaf86a425cc6e73fcf236a5a46396d + depends: + - _libgcc_mutex 0.1 conda_forge + - libgomp >=7.5.0 + constrains: + - openmp_impl 9999 + license: BSD-3-Clause + license_family: BSD + size: 23621 + timestamp: 1650670423406 +- kind: conda + name: binutils + version: '2.40' + build: h4852527_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.40-h4852527_2.conda + sha256: 89f06321896092d2d931fc40cd6753f11dfe90ebb9d180c9512b614a7b623423 + md5: 0ea11d9433ec00000e96e82d6381671d + depends: + - binutils_impl_linux-64 >=2.40,<2.41.0a0 + license: GPL-3.0-only + license_family: GPL + size: 31105 + timestamp: 1717523048004 +- kind: conda + name: binutils_impl_linux-64 + version: '2.40' + build: ha1999f0_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-ha1999f0_2.conda + sha256: 93965e6d95da53fa2ead26298eeb8ab53b8e9da0732c4baee2f4ce7d9c16aec1 + md5: 861a9d0b9ad43dcebe5a76f38a7d2527 + depends: + - ld_impl_linux-64 2.40 hf3520f5_2 + - sysroot_linux-64 + license: GPL-3.0-only + license_family: GPL + size: 5584502 + timestamp: 1717523025003 +- kind: conda + name: binutils_linux-64 + version: '2.40' + build: hdade7a5_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.40-hdade7a5_3.conda + sha256: d114b825acef51c1d065ca0a17f97e0e856c48765aecf2f8f164935635013dd2 + md5: 2d9a60578bc28469d9aeef9aea5520c3 + depends: + - binutils_impl_linux-64 2.40.* + - sysroot_linux-64 + license: BSD-3-Clause + license_family: BSD + size: 28868 + timestamp: 1710259805994 +- kind: conda + name: bzip2 + version: 1.0.8 + build: h10d778d_5 + build_number: 5 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + sha256: 61fb2b488928a54d9472113e1280b468a309561caa54f33825a3593da390b242 + md5: 6097a6ca9ada32699b5fc4312dd6ef18 + license: bzip2-1.0.6 + license_family: BSD + size: 127885 + timestamp: 1699280178474 +- kind: conda + name: bzip2 + version: 1.0.8 + build: h93a5062_5 + build_number: 5 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + sha256: bfa84296a638bea78a8bb29abc493ee95f2a0218775642474a840411b950fe5f + md5: 1bbc659ca658bfd49a481b5ef7a0f40f + license: bzip2-1.0.6 + license_family: BSD + size: 122325 + timestamp: 1699280294368 +- kind: conda + name: bzip2 + version: 1.0.8 + build: hcfcfb64_5 + build_number: 5 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda + sha256: ae5f47a5c86fd6db822931255dcf017eb12f60c77f07dc782ccb477f7808aab2 + md5: 26eb8ca6ea332b675e11704cce84a3be + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: bzip2-1.0.6 + license_family: BSD + size: 124580 + timestamp: 1699280668742 +- kind: conda + name: bzip2 + version: 1.0.8 + build: hd590300_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda + sha256: 242c0c324507ee172c0e0dd2045814e746bb303d1eb78870d182ceb0abc726a8 + md5: 69b8b6202a07720f448be700e300ccf4 + depends: + - libgcc-ng >=12 + license: bzip2-1.0.6 + license_family: BSD + size: 254228 + timestamp: 1699279927352 +- kind: conda + name: c-ares + version: 1.28.1 + build: h10d778d_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda + sha256: fccd7ad7e3dfa6b19352705b33eb738c4c55f79f398e106e6cf03bab9415595a + md5: d5eb7992227254c0e9a0ce71151f0079 + license: MIT + license_family: MIT + size: 152607 + timestamp: 1711819681694 +- kind: conda + name: c-ares + version: 1.28.1 + build: h93a5062_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda + sha256: 2fc553d7a75e912efbdd6b82cd7916cc9cb2773e6cd873b77e02d631dd7be698 + md5: 04f776a6139f7eafc2f38668570eb7db + license: MIT + license_family: MIT + size: 150488 + timestamp: 1711819630164 +- kind: conda + name: c-ares + version: 1.28.1 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.28.1-hd590300_0.conda + sha256: cb25063f3342149c7924b21544109696197a9d774f1407567477d4f3026bf38a + md5: dcde58ff9a1f30b0037a2315d1846d1f + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 168875 + timestamp: 1711819445938 +- kind: conda + name: c-compiler + version: 1.7.0 + build: h282daa2_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.7.0-h282daa2_1.conda + sha256: a8e2e2b121e61e3d6a67aa618602815211573e96477ab048176a831ae622bfaf + md5: d27411cb82bc1b76b9f487da6ae97f1d + depends: + - cctools >=949.0.1 + - clang_osx-64 16.* + - ld64 >=530 + - llvm-openmp + license: BSD-3-Clause + license_family: BSD + size: 6396 + timestamp: 1714575615177 +- kind: conda + name: c-compiler + version: 1.7.0 + build: h6aa9301_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.7.0-h6aa9301_1.conda + sha256: dcff26a7e70681945955b6267306e6436b77bf83b34fa0fc81e3c96960c7a1db + md5: c12b8656251acd221948e4970e8539d1 + depends: + - cctools >=949.0.1 + - clang_osx-arm64 16.* + - ld64 >=530 + - llvm-openmp + license: BSD-3-Clause + license_family: BSD + size: 6411 + timestamp: 1714575604618 +- kind: conda + name: c-compiler + version: 1.7.0 + build: hd590300_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.7.0-hd590300_1.conda + sha256: 4213b6cbaed673c07f8b79c089f3487afdd56de944f21c4861ead862b7657eb4 + md5: e9dffe1056994133616378309f932d77 + depends: + - binutils + - gcc + - gcc_linux-64 12.* + license: BSD-3-Clause + license_family: BSD + size: 6324 + timestamp: 1714575511013 +- kind: conda + name: ca-certificates + version: 2024.6.2 + build: h56e8100_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.6.2-h56e8100_0.conda + sha256: d872d11558ebeaeb87bcf9086e97c075a1a2dfffed2d0e97570cf197ab29e3d8 + md5: 12a3a2b3a00a21bbb390d4de5ad8dd0f + license: ISC + size: 156530 + timestamp: 1717311907623 +- kind: conda + name: ca-certificates + version: 2024.6.2 + build: h8857fd0_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.6.2-h8857fd0_0.conda + sha256: ba0614477229fcb0f0666356f2c4686caa66f0ed1446e7c9666ce234abe2bacf + md5: 3c23a8cab15ae51ebc9efdc229fccecf + license: ISC + size: 156145 + timestamp: 1717311781754 +- kind: conda + name: ca-certificates + version: 2024.6.2 + build: hbcca054_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.6.2-hbcca054_0.conda + sha256: 979af0932b2a5a26112044891a2d79e402e5ae8166f50fa48b8ebae47c0a2d65 + md5: 847c3c2905cc467cea52c24f9cfa8080 + license: ISC + size: 156035 + timestamp: 1717311767102 +- kind: conda + name: ca-certificates + version: 2024.6.2 + build: hf0a4a13_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.6.2-hf0a4a13_0.conda + sha256: f5fd189d48965df396d060eb48628cbd9f083f1a1ea79c5236f60d655c7b9633 + md5: b534f104f102479402f88f73adf750f5 + license: ISC + size: 156299 + timestamp: 1717311742040 +- kind: conda + name: cctools + version: '986' + build: h40f6528_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/cctools-986-h40f6528_0.conda + sha256: 4eac1d10ddafb1dc277ddff304a7d314607c7dc99d7a77d69ed75f8fcbdf93d4 + md5: b7a2ca0062a6ee8bc4e83ec887bef942 + depends: + - cctools_osx-64 986 ha1c5b94_0 + - ld64 711 ha02d983_0 + - libllvm16 >=16.0.6,<16.1.0a0 + license: APSL-2.0 + license_family: Other + size: 21663 + timestamp: 1710466476542 +- kind: conda + name: cctools + version: '986' + build: h4faf515_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-986-h4faf515_0.conda + sha256: 505471dfa37dc42ba1a2c4cf65d4c4abe4c36164c8fcb0a375e3c4f3550ab3ee + md5: d81c4480e8445b13129024191231e6c5 + depends: + - cctools_osx-arm64 986 h62378fb_0 + - ld64 711 h634c8be_0 + - libllvm16 >=16.0.6,<16.1.0a0 + license: APSL-2.0 + license_family: Other + size: 21683 + timestamp: 1710466813384 +- kind: conda + name: cctools_osx-64 + version: '986' + build: ha1c5b94_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-986-ha1c5b94_0.conda + sha256: 16ef6a8dd367d7d4d7b3446f73ed95b07603d6b5b3256c3acab9b3a9006ef7eb + md5: a8951de2506df5649f5a3295fdfd9f2c + depends: + - ld64_osx-64 >=711,<712.0a0 + - libcxx + - libllvm16 >=16.0.6,<16.1.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - sigtool + constrains: + - ld64 711.* + - cctools 986.* + - clang 16.0.* + license: APSL-2.0 + license_family: Other + size: 1118961 + timestamp: 1710466421642 +- kind: conda + name: cctools_osx-arm64 + version: '986' + build: h62378fb_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-986-h62378fb_0.conda + sha256: 35907653456fdd854b426060980025689670784c677e2bbecd2fcaf983cfa37c + md5: cb85035a5eceb3a0d3becc1026dbb31d + depends: + - ld64_osx-arm64 >=711,<712.0a0 + - libcxx + - libllvm16 >=16.0.6,<16.1.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - sigtool + constrains: + - clang 16.0.* + - ld64 711.* + - cctools 986.* + license: APSL-2.0 + license_family: Other + size: 1127544 + timestamp: 1710466751857 +- kind: conda + name: clang + version: 16.0.6 + build: h7bc9447_7 + build_number: 7 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang-16.0.6-h7bc9447_7.conda + sha256: 5f04b3a7e576861db61a04aa4824b8196e4cafe92c79a9290fc5eafd4531f010 + md5: 172328871c92aea74ff3b71064f66cb7 + depends: + - clang-16 16.0.6 default_hb63da90_7 + constrains: + - clang-tools 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 81852 + timestamp: 1716981232520 +- kind: conda + name: clang + version: 16.0.6 + build: hd4457cd_7 + build_number: 7 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang-16.0.6-hd4457cd_7.conda + sha256: 2efeb86a87ded2ae4021fb968a15d403619df2ce571713d7e281268208f72fd7 + md5: 0f91e4c1d9d85887db66ddbc185d65d4 + depends: + - clang-16 16.0.6 default_h4c8afb6_7 + constrains: + - clang-tools 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 81750 + timestamp: 1716980780083 +- kind: conda + name: clang-16 + version: 16.0.6 + build: default_h4c8afb6_7 + build_number: 7 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang-16-16.0.6-default_h4c8afb6_7.conda + sha256: 3bf8f0f55fb5eaed9e7f9b647ececb941a1342d14f20d7772fd4328d58912e4f + md5: c9da6a62b571cac3707db69610ed7bd3 + depends: + - __osx >=10.13 + - libclang-cpp16 16.0.6 default_h4c8afb6_7 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + constrains: + - clangxx 16.0.6 + - clangdev 16.0.6 + - clang-tools 16.0.6 + - llvm-tools 16.0.6 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 758914 + timestamp: 1716980696120 +- kind: conda + name: clang-16 + version: 16.0.6 + build: default_hb63da90_7 + build_number: 7 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang-16-16.0.6-default_hb63da90_7.conda + sha256: 51358152f76a4d363459f68fa6cd8f5c88edf6bd09ec8de10970754fb1dc9c91 + md5: 73fa4ed0b361a6882bc3893f16ce0f07 + depends: + - __osx >=11.0 + - libclang-cpp16 16.0.6 default_hb63da90_7 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + constrains: + - clangxx 16.0.6 + - clang-tools 16.0.6 + - clangdev 16.0.6 + - llvm-tools 16.0.6 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 751242 + timestamp: 1716981084563 +- kind: conda + name: clang-format + version: 18.1.6 + build: default_h127d8a8_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/clang-format-18.1.6-default_h127d8a8_0.conda + sha256: 7d111926d120b755b186ae204e5601be7bd8d535a65c20e20ec77c59b4ec8210 + md5: 5793db63d12fb3861fbc0757dfa72ba6 + depends: + - clang-format-18 18.1.6 default_h127d8a8_0 + - libclang-cpp18.1 >=18.1.6,<18.2.0a0 + - libgcc-ng >=12 + - libllvm18 >=18.1.6,<18.2.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22619 + timestamp: 1716714975627 +- kind: conda + name: clang-format + version: 18.1.6 + build: default_h3a3e6c3_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/clang-format-18.1.6-default_h3a3e6c3_0.conda + sha256: fe1f3b18dd52b929db7a407c5725af2330365f4fabbbf8445fd5c765e4a822b0 + md5: 5f500e8080af1e06be3290e1fb5e209a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 1182092 + timestamp: 1716718626420 +- kind: conda + name: clang-format + version: 18.1.6 + build: default_h7c89ad4_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-18.1.6-default_h7c89ad4_0.conda + sha256: 020ed5064bd855cff660721523983117eb90140d456121fda8e92b623cfaccb1 + md5: de593d77089cc395d7f1c7d62cb57d0c + depends: + - clang-format-18 18.1.6 default_h7c89ad4_0 + - libclang-cpp18.1 >=18.1.6,<18.2.0a0 + - libcxx >=16.0.6 + - libllvm18 >=18.1.6,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22938 + timestamp: 1716713640664 +- kind: conda + name: clang-format + version: 18.1.6 + build: default_ha3b9224_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang-format-18.1.6-default_ha3b9224_0.conda + sha256: a0c828ade3b1fa54fb0eaff9a17a77ec65ac61ab50bf5c4bc9313daa8ff1d463 + md5: d4c49cec403dd710e67dbf5fd1072f86 + depends: + - clang-format-18 18.1.6 default_ha3b9224_0 + - libclang-cpp18.1 >=18.1.6,<18.2.0a0 + - libcxx >=16.0.6 + - libllvm18 >=18.1.6,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22775 + timestamp: 1716713290315 +- kind: conda + name: clang-format-18 + version: 18.1.6 + build: default_h127d8a8_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/clang-format-18-18.1.6-default_h127d8a8_0.conda + sha256: b4732ca96df23fd07f0a8dad0a46ec5a6d9e5f3e28e1a63c10e592ee6e518cc4 + md5: d8a9e4d1ae88258ef17e06200953807c + depends: + - libclang-cpp18.1 >=18.1.6,<18.2.0a0 + - libgcc-ng >=12 + - libllvm18 >=18.1.6,<18.2.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 65852 + timestamp: 1716714930189 +- kind: conda + name: clang-format-18 + version: 18.1.6 + build: default_h7c89ad4_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-18-18.1.6-default_h7c89ad4_0.conda + sha256: 30f4793b436d71a89a429b6973414a9974944192adfe2c21c5ebd7845d53fded + md5: 71014e29c45321f3c4bdf013db236177 + depends: + - libclang-cpp18.1 >=18.1.6,<18.2.0a0 + - libcxx >=16.0.6 + - libllvm18 >=18.1.6,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 60494 + timestamp: 1716713570984 +- kind: conda + name: clang-format-18 + version: 18.1.6 + build: default_ha3b9224_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang-format-18-18.1.6-default_ha3b9224_0.conda + sha256: 49bb8ed6fe218e96eed4d5ae045a77aa6cb3e73e4cffa020c93602b0463220c6 + md5: 2938075fa3c2f96d07036e0bbce69153 + depends: + - libclang-cpp18.1 >=18.1.6,<18.2.0a0 + - libcxx >=16.0.6 + - libllvm18 >=18.1.6,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 62081 + timestamp: 1716713224334 +- kind: conda + name: clang_impl_osx-64 + version: 16.0.6 + build: h8787910_15 + build_number: 15 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-16.0.6-h8787910_15.conda + sha256: 2bf8acbe3590ffc25398b4c9dac85d5937b39f2ea51c8347a02836848783e260 + md5: 4604a48f32935cd5d6e6a48e818b7eb0 + depends: + - cctools_osx-64 + - clang 16.0.6.* + - compiler-rt 16.0.6.* + - ld64_osx-64 + - llvm-tools 16.0.6.* + license: BSD-3-Clause + license_family: BSD + size: 17500 + timestamp: 1716758662891 +- kind: conda + name: clang_impl_osx-arm64 + version: 16.0.6 + build: hc421ffc_15 + build_number: 15 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-16.0.6-hc421ffc_15.conda + sha256: 7a6f213f73bae398a66dcde42375e0b13173ab005b292a9539bf978e4f86d808 + md5: 327e0c0022c1db7c390622c247483652 + depends: + - cctools_osx-arm64 + - clang 16.0.6.* + - compiler-rt 16.0.6.* + - ld64_osx-arm64 + - llvm-tools 16.0.6.* + license: BSD-3-Clause + license_family: BSD + size: 17562 + timestamp: 1716758701036 +- kind: conda + name: clang_osx-64 + version: 16.0.6 + build: hb91bd55_15 + build_number: 15 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang_osx-64-16.0.6-hb91bd55_15.conda + sha256: fa671e245773815a8fd16a1f27f046ea159277ca63343ac438c29ad34dbf2ba8 + md5: dc667dff0fefcb19ab8318e9518011f3 + depends: + - clang_impl_osx-64 16.0.6 h8787910_15 + license: BSD-3-Clause + license_family: BSD + size: 20534 + timestamp: 1716758669450 +- kind: conda + name: clang_osx-arm64 + version: 16.0.6 + build: h54d7cd3_15 + build_number: 15 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang_osx-arm64-16.0.6-h54d7cd3_15.conda + sha256: d45e3077906bab088b0b9a5ced9bba306189fddb229a975090594ca6bb9b71bf + md5: d9f7d9cd0d0f6650864edbb70da2bac4 + depends: + - clang_impl_osx-arm64 16.0.6 hc421ffc_15 + license: BSD-3-Clause + license_family: BSD + size: 20499 + timestamp: 1716758707804 +- kind: conda + name: clangxx + version: 16.0.6 + build: default_h095aff0_7 + build_number: 7 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-16.0.6-default_h095aff0_7.conda + sha256: 0daea36dfbd5fc8f86ef987b04a684c7eb492fbf2d74c6329e856e029a786dcd + md5: 3605798690eee4fa8f82ac6519caba2a + depends: + - clang 16.0.6 h7bc9447_7 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 82005 + timestamp: 1716981247780 +- kind: conda + name: clangxx + version: 16.0.6 + build: default_ha3b9224_7 + build_number: 7 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clangxx-16.0.6-default_ha3b9224_7.conda + sha256: 9e3492ddc9fe706d88795b70fd662a7703d9157f94d3e5cd062f70f731c691ff + md5: 00c8a212cbbd427dcbcc4231b23ddc5e + depends: + - clang 16.0.6 hd4457cd_7 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 81879 + timestamp: 1716980792681 +- kind: conda + name: clangxx_impl_osx-64 + version: 16.0.6 + build: h6d92fbe_15 + build_number: 15 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-16.0.6-h6d92fbe_15.conda + sha256: e0b9f2436514ac5e79a66dcd4fc3f61ebb79e2f025647c87963c58587340853b + md5: 0e9dfa5ea554d23a3ad1f373470f84a2 + depends: + - clang_osx-64 16.0.6 hb91bd55_15 + - clangxx 16.0.6.* + - libcxx >=16 + - libllvm16 >=16.0.6,<16.1.0a0 + license: BSD-3-Clause + license_family: BSD + size: 17585 + timestamp: 1716758703238 +- kind: conda + name: clangxx_impl_osx-arm64 + version: 16.0.6 + build: hcd7bac0_15 + build_number: 15 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-16.0.6-hcd7bac0_15.conda + sha256: b6734a6857412a4e84e11ccfed6ae69df141d77eaa4400a3fbe1c01863608275 + md5: 6a1fb927362d036f4964ef9ad74e8df0 + depends: + - clang_osx-arm64 16.0.6 h54d7cd3_15 + - clangxx 16.0.6.* + - libcxx >=16 + - libllvm16 >=16.0.6,<16.1.0a0 + license: BSD-3-Clause + license_family: BSD + size: 17661 + timestamp: 1716758733558 +- kind: conda + name: clangxx_osx-64 + version: 16.0.6 + build: hb91bd55_15 + build_number: 15 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-16.0.6-hb91bd55_15.conda + sha256: 1e16d2133f04a5bac0b35809a0fd65db7e6a4634db313591cf31101d7477a904 + md5: 3d3b8b7b99770601759ef8bc23264df2 + depends: + - clang_osx-64 16.0.6 hb91bd55_15 + - clangxx_impl_osx-64 16.0.6 h6d92fbe_15 + license: BSD-3-Clause + license_family: BSD + size: 19275 + timestamp: 1716758709686 +- kind: conda + name: clangxx_osx-arm64 + version: 16.0.6 + build: h54d7cd3_15 + build_number: 15 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-16.0.6-h54d7cd3_15.conda + sha256: 889f26a0db11f5aa142fdd3aff07dc2ecb815d15dd5193d13366aa74c87c5110 + md5: 1a54f30253dbc52aef6b06304982d089 + depends: + - clang_osx-arm64 16.0.6 h54d7cd3_15 + - clangxx_impl_osx-arm64 16.0.6 hcd7bac0_15 + license: BSD-3-Clause + license_family: BSD + size: 19221 + timestamp: 1716758740702 +- kind: conda + name: cmake + version: 3.29.4 + build: h1304840_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.29.4-h1304840_0.conda + sha256: 56b61469b3fb2a3275a5eb599a9caf366fc0ef3e886d8e547e25fbdd1f3b2b1b + md5: 106e091802d2a8fac3b93eb82d35908a + depends: + - __osx >=10.13 + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.8.0,<9.0a0 + - libcxx >=16 + - libexpat >=2.6.2,<3.0a0 + - libuv >=1.48.0,<2.0a0 + - libzlib >=1.2.13,<2.0a0 + - ncurses >=6.5,<7.0a0 + - rhash >=1.4.4,<2.0a0 + - xz >=5.2.6,<6.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 17387529 + timestamp: 1717458067632 +- kind: conda + name: cmake + version: 3.29.4 + build: h2cf84f3_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.29.4-h2cf84f3_0.conda + sha256: 3ac81b2a3ad594ed426e3e8f1951f687defe561c8331de2dfa2602ab525af11a + md5: 1a308493d30d9ebb147e72fbd59c831d + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.8.0,<9.0a0 + - libcxx >=16 + - libexpat >=2.6.2,<3.0a0 + - libuv >=1.48.0,<2.0a0 + - libzlib >=1.2.13,<2.0a0 + - ncurses >=6.5,<7.0a0 + - rhash >=1.4.4,<2.0a0 + - xz >=5.2.6,<6.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 16240005 + timestamp: 1717457707074 +- kind: conda + name: cmake + version: 3.29.4 + build: h75d51d9_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/cmake-3.29.4-h75d51d9_0.conda + sha256: da67ba2cf6d5b87ebdd219ccb0b0a89376b6be26d30abc1e83e473a91d02ea0e + md5: 4a6005b5f6ed640dce98af55cef38e95 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.8.0,<9.0a0 + - libexpat >=2.6.2,<3.0a0 + - libuv >=1.48.0,<2.0a0 + - libzlib >=1.2.13,<2.0a0 + - ucrt >=10.0.20348.0 + - vc14_runtime >=14.29.30139 + - xz >=5.2.6,<6.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 13894184 + timestamp: 1717458034374 +- kind: conda + name: cmake + version: 3.29.4 + build: h91dbaaa_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.29.4-h91dbaaa_0.conda + sha256: 80c39e10ace7733829220bb382acddd42cf0d698dc7541bfaf9c5fb325cab6b0 + md5: d07b4431d37186cf69ef63a2aba6f47a + depends: + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.8.0,<9.0a0 + - libexpat >=2.6.2,<3.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libuv >=1.48.0,<2.0a0 + - libzlib >=1.2.13,<2.0a0 + - ncurses >=6.5,<7.0a0 + - rhash >=1.4.4,<2.0a0 + - xz >=5.2.6,<6.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 19024763 + timestamp: 1717457328163 +- kind: conda + name: cmake-format + version: 0.6.13 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/cmake-format-0.6.13-pyhd8ed1ab_0.conda + sha256: a916122754ff244143e5fff02362d2efd2b44228e56aee682acdf6960d8a49e8 + md5: 0d8dbd5e9d09c51b4e23ce5c07941c22 + depends: + - jinja2 >=2.10.3 + - python >=3.6 + - pyyaml >=5.3 + - six >=1.13.0 + license: GPL-3.0-only + license_family: GPL + size: 134110 + timestamp: 1697815674808 +- kind: conda + name: compiler-rt + version: 16.0.6 + build: h3808999_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-16.0.6-h3808999_2.conda + sha256: 67f6883f37ea720f97d016c3384962d86ec8853e5f4b0065aa77e335ca80193e + md5: 517f18b3260bb7a508d1f54a96e6285b + depends: + - clang 16.0.6.* + - clangxx 16.0.6.* + - compiler-rt_osx-arm64 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 93724 + timestamp: 1701467327657 +- kind: conda + name: compiler-rt + version: 16.0.6 + build: ha38d28d_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-16.0.6-ha38d28d_2.conda + sha256: de0e2c94d9a04f60ec9aedde863d6c1fad3f261bdb63ec8adc70e2d9ecdb07bb + md5: 3b9e8c5c63b8e86234f499490acd85c2 + depends: + - clang 16.0.6.* + - clangxx 16.0.6.* + - compiler-rt_osx-64 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 94198 + timestamp: 1701467261175 +- kind: conda + name: compiler-rt_osx-64 + version: 16.0.6 + build: ha38d28d_2 + build_number: 2 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-16.0.6-ha38d28d_2.conda + sha256: 75270bd8e306967f6e1a8c17d14f2dfe76602a5c162088f3ea98034fe3d71e0c + md5: 7a46507edc35c6c8818db0adaf8d787f + depends: + - clang 16.0.6.* + - clangxx 16.0.6.* + constrains: + - compiler-rt 16.0.6 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 9895261 + timestamp: 1701467223753 +- kind: conda + name: compiler-rt_osx-arm64 + version: 16.0.6 + build: h3808999_2 + build_number: 2 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-16.0.6-h3808999_2.conda + sha256: 61f1a10e6e8ec147f17c5e36cf1c2fe77ac6d1907b05443fa319fd59be20fa33 + md5: 8c7d77d888e1a218cccd9e82b1458ec6 + depends: + - clang 16.0.6.* + - clangxx 16.0.6.* + constrains: + - compiler-rt 16.0.6 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 9829914 + timestamp: 1701467293179 +- kind: conda + name: cxx-compiler + version: 1.7.0 + build: h00ab1b0_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.7.0-h00ab1b0_1.conda + sha256: cf895938292cfd4cfa2a06c6d57aa25c33cc974d4ffe52e704ffb67f5577b93f + md5: 28de2e073db9ca9b72858bee9fb6f571 + depends: + - c-compiler 1.7.0 hd590300_1 + - gxx + - gxx_linux-64 12.* + license: BSD-3-Clause + license_family: BSD + size: 6283 + timestamp: 1714575513327 +- kind: conda + name: cxx-compiler + version: 1.7.0 + build: h2ffa867_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.7.0-h2ffa867_1.conda + sha256: c07de4bdfcae8e0a589d360b79ae50f8f183fe698bc400b609c5e5d1f26e8b0f + md5: f75f0313233f50a6a58f7444a1c725a9 + depends: + - c-compiler 1.7.0 h6aa9301_1 + - clangxx_osx-arm64 16.* + license: BSD-3-Clause + license_family: BSD + size: 6442 + timestamp: 1714575634473 +- kind: conda + name: cxx-compiler + version: 1.7.0 + build: h7728843_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.7.0-h7728843_1.conda + sha256: 844b0894552468685c6a9f7eaab3837461e1ebea5c3880d8de616c83b618f044 + md5: e04cb15a20553b973dd068c2dc81d682 + depends: + - c-compiler 1.7.0 h282daa2_1 + - clangxx_osx-64 16.* + license: BSD-3-Clause + license_family: BSD + size: 6394 + timestamp: 1714575621870 +- kind: conda + name: cxx-compiler + version: 1.7.0 + build: h91493d7_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-1.7.0-h91493d7_1.conda + sha256: 2ad395bb14a26f69977b90617f344d4d4406625e839738c3f0418ee500121d96 + md5: 3ad688e50a39f7697a17783a1f42ffdd + depends: + - vs2019_win-64 + license: BSD-3-Clause + license_family: BSD + size: 6554 + timestamp: 1714575655901 +- kind: conda + name: gcc + version: 12.3.0 + build: h915e2ae_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/gcc-12.3.0-h915e2ae_7.conda + sha256: 7358118791ddb5e1fb58fb0c52bf4b8b993817bae50f5bbf66677ce4df783fda + md5: 84b1c5cebd0a0443f3d7f90a4be93fc6 + depends: + - gcc_impl_linux-64 12.3.0.* + license: BSD-3-Clause + license_family: BSD + size: 25966 + timestamp: 1715016817964 +- kind: conda + name: gcc_impl_linux-64 + version: 12.3.0 + build: h58ffeeb_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-12.3.0-h58ffeeb_7.conda + sha256: a86af41f4b240ce86f05bc81cac1d10d272bc57e63ebab779aedc887e329e0c1 + md5: 95f78565a09852783d3e90e0389cfa5f + depends: + - binutils_impl_linux-64 >=2.40 + - libgcc-devel_linux-64 12.3.0 h0223996_107 + - libgcc-ng >=12.3.0 + - libgomp >=12.3.0 + - libsanitizer 12.3.0 hb8811af_7 + - libstdcxx-ng >=12.3.0 + - sysroot_linux-64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 51128234 + timestamp: 1715016710479 +- kind: conda + name: gcc_linux-64 + version: 12.3.0 + build: h6477408_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-12.3.0-h6477408_3.conda + sha256: 836692c3d4948f25a19f9071db40f7788edcb342d771786a206a6a122f92365d + md5: 7a53f84c45bdf4656ba27b9e9ed68b3d + depends: + - binutils_linux-64 2.40 hdade7a5_3 + - gcc_impl_linux-64 12.3.0.* + - sysroot_linux-64 + license: BSD-3-Clause + license_family: BSD + size: 30977 + timestamp: 1710260096918 +- kind: conda + name: gxx + version: 12.3.0 + build: h915e2ae_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/gxx-12.3.0-h915e2ae_7.conda + sha256: 81bba3a4a27cf8c8f29c31da2ebd2ec49899974d066ba20ce110ac1d067bfb78 + md5: 721c5433122a02bf3a081db10a2e68e2 + depends: + - gcc 12.3.0.* + - gxx_impl_linux-64 12.3.0.* + license: BSD-3-Clause + license_family: BSD + size: 25402 + timestamp: 1715017020869 +- kind: conda + name: gxx_impl_linux-64 + version: 12.3.0 + build: h2a574ab_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-12.3.0-h2a574ab_7.conda + sha256: c7a577846ae46dade05b7faa8956a7d4187b747bbc9be5c38a2b4ca8f7c108cc + md5: 265caa78b979f112fc241cecd0015c91 + depends: + - gcc_impl_linux-64 12.3.0 h58ffeeb_7 + - libstdcxx-devel_linux-64 12.3.0 h0223996_107 + - sysroot_linux-64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 13036959 + timestamp: 1715016975232 +- kind: conda + name: gxx_linux-64 + version: 12.3.0 + build: h4a1b8e8_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-12.3.0-h4a1b8e8_3.conda + sha256: 5a842fc69c03ac513a2c021f3f21afd9d9ca50b10b95c0dcd236aa77d6d42373 + md5: 9ec22c7c544f4a4f6d660f0a3b0fd15c + depends: + - binutils_linux-64 2.40 hdade7a5_3 + - gcc_linux-64 12.3.0 h6477408_3 + - gxx_impl_linux-64 12.3.0.* + - sysroot_linux-64 + license: BSD-3-Clause + license_family: BSD + size: 29304 + timestamp: 1710260169322 +- kind: conda + name: icu + version: '73.2' + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + sha256: e12fd90ef6601da2875ebc432452590bc82a893041473bc1c13ef29001a73ea8 + md5: cc47e1facc155f91abd89b11e48e72ff + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: MIT + license_family: MIT + size: 12089150 + timestamp: 1692900650789 +- kind: conda + name: icu + version: '73.2' + build: hc8870d7_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + sha256: ff9cd0c6cd1349954c801fb443c94192b637e1b414514539f3c49c56a39f51b1 + md5: 8521bd47c0e11c5902535bb1a17c565f + license: MIT + license_family: MIT + size: 11997841 + timestamp: 1692902104771 +- kind: conda + name: icu + version: '73.2' + build: hf5e326d_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + sha256: f66362dc36178ac9b7c7a9b012948a9d2d050b3debec24bbd94aadbc44854185 + md5: 5cc301d759ec03f28328428e28f65591 + license: MIT + license_family: MIT + size: 11787527 + timestamp: 1692901622519 +- kind: conda + name: jinja2 + version: 3.1.4 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.4-pyhd8ed1ab_0.conda + sha256: 27380d870d42d00350d2d52598cddaf02f9505fb24be09488da0c9b8d1428f2d + md5: 7b86ecb7d3557821c649b3c31e3eb9f2 + depends: + - markupsafe >=2.0 + - python >=3.7 + license: BSD-3-Clause + license_family: BSD + size: 111565 + timestamp: 1715127275924 +- 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: keyutils + version: 1.6.1 + build: h166bdaf_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 + sha256: 150c05a6e538610ca7c43beb3a40d65c90537497a4f6a5f4d15ec0451b6f5ebb + md5: 30186d27e2c9fa62b45fb1476b7200e3 + depends: + - libgcc-ng >=10.3.0 + license: LGPL-2.1-or-later + size: 117831 + timestamp: 1646151697040 +- kind: conda + name: krb5 + version: 1.21.2 + build: h659d440_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda + sha256: 259bfaae731989b252b7d2228c1330ef91b641c9d68ff87dae02cbae682cb3e4 + md5: cd95826dbd331ed1be26bdf401432844 + depends: + - keyutils >=1.6.1,<2.0a0 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - openssl >=3.1.2,<4.0a0 + license: MIT + license_family: MIT + size: 1371181 + timestamp: 1692097755782 +- kind: conda + name: krb5 + version: 1.21.2 + build: h92f50d5_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda + sha256: 70bdb9b4589ec7c7d440e485ae22b5a352335ffeb91a771d4c162996c3070875 + md5: 92f1cff174a538e0722bf2efb16fc0b2 + depends: + - libcxx >=15.0.7 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - openssl >=3.1.2,<4.0a0 + license: MIT + license_family: MIT + size: 1195575 + timestamp: 1692098070699 +- kind: conda + name: krb5 + version: 1.21.2 + build: hb884880_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda + sha256: 081ae2008a21edf57c048f331a17c65d1ccb52d6ca2f87ee031a73eff4dc0fc6 + md5: 80505a68783f01dc8d7308c075261b2f + depends: + - libcxx >=15.0.7 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - openssl >=3.1.2,<4.0a0 + license: MIT + license_family: MIT + size: 1183568 + timestamp: 1692098004387 +- kind: conda + name: krb5 + version: 1.21.2 + build: heb0366b_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda + sha256: 6002adff9e3dcfc9732b861730cb9e33d45fd76b2035b2cdb4e6daacb8262c0b + md5: 6e8b0f22b4eef3b3cb3849bb4c3d47f9 + depends: + - openssl >=3.1.2,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + size: 710894 + timestamp: 1692098129546 +- kind: conda + name: ld64 + version: '711' + build: h634c8be_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-711-h634c8be_0.conda + sha256: bf1fa905f08aa2044d5ca9a387c4d626c1b92a81773665268e87cf03a4db1159 + md5: 5fb1c87739bf8f52d36cb001248e29b6 + depends: + - ld64_osx-arm64 711 ha4bd21c_0 + - libllvm16 >=16.0.6,<16.1.0a0 + constrains: + - cctools 986.* + - cctools_osx-arm64 986.* + license: APSL-2.0 + license_family: Other + size: 18884 + timestamp: 1710466784602 +- kind: conda + name: ld64 + version: '711' + build: ha02d983_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ld64-711-ha02d983_0.conda + sha256: 189f5a0f9f923ee7f165fd9f18633ffa5680c24118d731c0a9956ac21dd42720 + md5: 3ae4930ec076735cce481e906f5192e0 + depends: + - ld64_osx-64 711 ha20a434_0 + - libllvm16 >=16.0.6,<16.1.0a0 + constrains: + - cctools 986.* + - cctools_osx-64 986.* + license: APSL-2.0 + license_family: Other + size: 18819 + timestamp: 1710466446391 +- kind: conda + name: ld64_osx-64 + version: '711' + build: ha20a434_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-711-ha20a434_0.conda + sha256: 8c4cdd119ff4d8c83f6ae044c76560be302e4986ec1d5f278943ed9319f1171c + md5: a8b41eb97c8a9d618243a79ba78fdc3c + depends: + - libcxx + - libllvm16 >=16.0.6,<16.1.0a0 + - sigtool + - tapi >=1100.0.11,<1101.0a0 + constrains: + - clang >=16.0.6,<17.0a0 + - cctools 986.* + - ld 711.* + - cctools_osx-64 986.* + license: APSL-2.0 + license_family: Other + size: 1075550 + timestamp: 1710466354788 +- kind: conda + name: ld64_osx-arm64 + version: '711' + build: ha4bd21c_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-711-ha4bd21c_0.conda + sha256: f27b661fa4cac5b351ed4ee0ec8c8baf27c2f982309a453968418438c8197450 + md5: 38abda2ba1128fdde7b7108cc36a9d99 + depends: + - libcxx + - libllvm16 >=16.0.6,<16.1.0a0 + - sigtool + - tapi >=1100.0.11,<1101.0a0 + constrains: + - ld 711.* + - clang >=16.0.6,<17.0a0 + - cctools 986.* + - cctools_osx-arm64 986.* + license: APSL-2.0 + license_family: Other + size: 1066358 + timestamp: 1710466668466 +- kind: conda + name: ld_impl_linux-64 + version: '2.40' + build: hf3520f5_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_2.conda + sha256: 5ed96807b26bc32d2d180e38e7340388ddfdb642950f888f7da78d274846afea + md5: 61b0bd5219ce7192b4e3633521a78975 + constrains: + - binutils_impl_linux-64 2.40 + license: GPL-3.0-only + license_family: GPL + size: 708179 + timestamp: 1717523002366 +- kind: conda + name: libclang-cpp16 + version: 16.0.6 + build: default_h4c8afb6_7 + build_number: 7 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp16-16.0.6-default_h4c8afb6_7.conda + sha256: a3ca75f5311308d62a732b9a3f8307b5f0e39303fa7e857dcdd247e0bae2aeb7 + md5: 784816790fe438443354d13050fcd67d + depends: + - __osx >=10.13 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 12861346 + timestamp: 1716980259803 +- kind: conda + name: libclang-cpp16 + version: 16.0.6 + build: default_hb63da90_7 + build_number: 7 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp16-16.0.6-default_hb63da90_7.conda + sha256: 613a2a670d7448b0c16971172dc060e7c32a22a63fc11f65cd90d4e70d3b7a74 + md5: 3753e98f8145f5f9b3bfe27575ec3c3a + depends: + - __osx >=11.0 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 11912321 + timestamp: 1716980622468 +- kind: conda + name: libclang-cpp18.1 + version: 18.1.6 + build: default_h127d8a8_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp18.1-18.1.6-default_h127d8a8_0.conda + sha256: 6b7a3179553288d714958cfbcdbc1654f807d6c1f1a7e2081d9f23eb170424e9 + md5: d681ec78d41c1529934e0fc16614e5c8 + depends: + - libgcc-ng >=12 + - libllvm18 >=18.1.6,<18.2.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 19270332 + timestamp: 1716714630714 +- kind: conda + name: libclang-cpp18.1 + version: 18.1.6 + build: default_h7c89ad4_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp18.1-18.1.6-default_h7c89ad4_0.conda + sha256: b269c6ca8d28b5ca0eaa869b829fb5e8efe71085938eb759a62170dfba7f4dbb + md5: 6b081c3b22144317ad58aad7f93dd25a + depends: + - libcxx >=16.0.6 + - libllvm18 >=18.1.6,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 12913697 + timestamp: 1716712990417 +- kind: conda + name: libclang-cpp18.1 + version: 18.1.6 + build: default_ha3b9224_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp18.1-18.1.6-default_ha3b9224_0.conda + sha256: 51b2c33c66f1d350a43139e380026ca9e07996cde5e7773d946cc1d539ad23dc + md5: 9ac0e952bb9f1b281ac415190eb88ff6 + depends: + - libcxx >=16.0.6 + - libllvm18 >=18.1.6,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 13776066 + timestamp: 1716712637323 +- kind: conda + name: libcurl + version: 8.8.0 + build: h7b6f9a7_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.8.0-h7b6f9a7_0.conda + sha256: b83aa249e7c8abc1aa56593ad50d1b4c0a52f5f3d5fd7c489c2ccfc3a548f391 + md5: 245b30f99dc5379ebe1c78899be8d3f5 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.3.0,<4.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: curl + license_family: MIT + size: 364890 + timestamp: 1716378993833 +- kind: conda + name: libcurl + version: 8.8.0 + build: hca28451_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.8.0-hca28451_0.conda + sha256: 45aec0ffc6fe3fd4c0083b815aa102b8103380acc2b6714fb272d921acc68ab2 + md5: f21c27f076a07907e70c49bb57bd0f20 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libgcc-ng >=12 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.3.0,<4.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: curl + license_family: MIT + size: 405535 + timestamp: 1716378550673 +- kind: conda + name: libcurl + version: 8.8.0 + build: hd5e4a3a_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.8.0-hd5e4a3a_0.conda + sha256: 169fb0a11dd3a1f0adbb93b275f9752aa24b64e73d0c8e220aa10213c6ee74ff + md5: 4f86149dc6228f1e5617faa2cce90f94 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: curl + license_family: MIT + size: 334903 + timestamp: 1716379079949 +- kind: conda + name: libcurl + version: 8.8.0 + build: hf9fcc65_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.8.0-hf9fcc65_0.conda + sha256: 1eb3e00586ddbf662877e62d1108bd2ff539fbeee34c52edf1d6c5fa3c9f4435 + md5: 276894efcbca23aa674e280e90bc5673 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.3.0,<4.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: curl + license_family: MIT + size: 385778 + timestamp: 1716378974624 +- kind: conda + name: libcxx + version: 17.0.6 + build: h5f092b4_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-17.0.6-h5f092b4_0.conda + sha256: 119d3d9306f537d4c89dc99ed99b94c396d262f0b06f7833243646f68884f2c2 + md5: a96fd5dda8ce56c86a971e0fa02751d0 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 1248885 + timestamp: 1715020154867 +- kind: conda + name: libcxx + version: 17.0.6 + build: h88467a6_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libcxx-17.0.6-h88467a6_0.conda + sha256: e7b57062c1edfcbd13d2129467c94cbff7f0a988ee75782bf48b1dc0e6300b8b + md5: 0fe355aecb8d24b8bc07c763209adbd9 + depends: + - __osx >=10.13 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 1249309 + timestamp: 1715020018902 +- kind: conda + name: libedit + version: 3.1.20191231 + build: h0678c8f_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + sha256: dbd3c3f2eca1d21c52e4c03b21930bbce414c4592f8ce805801575b9e9256095 + md5: 6016a8a1d0e63cac3de2c352cd40208b + depends: + - ncurses >=6.2,<7.0.0a0 + license: BSD-2-Clause + license_family: BSD + size: 105382 + timestamp: 1597616576726 +- kind: conda + name: libedit + version: 3.1.20191231 + build: hc8eb9b7_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 + sha256: 3912636197933ecfe4692634119e8644904b41a58f30cad9d1fc02f6ba4d9fca + md5: 30e4362988a2623e9eb34337b83e01f9 + depends: + - ncurses >=6.2,<7.0.0a0 + license: BSD-2-Clause + license_family: BSD + size: 96607 + timestamp: 1597616630749 +- kind: conda + name: libedit + version: 3.1.20191231 + build: he28a2e2_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + sha256: a57d37c236d8f7c886e01656f4949d9dcca131d2a0728609c6f7fa338b65f1cf + md5: 4d331e44109e3f0e19b4cb8f9b82f3e1 + depends: + - libgcc-ng >=7.5.0 + - ncurses >=6.2,<7.0.0a0 + license: BSD-2-Clause + license_family: BSD + size: 123878 + timestamp: 1597616541093 +- kind: conda + name: libev + version: '4.33' + build: h10d778d_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + sha256: 0d238488564a7992942aa165ff994eca540f687753b4f0998b29b4e4d030ff43 + md5: 899db79329439820b7e8f8de41bca902 + license: BSD-2-Clause + license_family: BSD + size: 106663 + timestamp: 1702146352558 +- kind: conda + name: libev + version: '4.33' + build: h93a5062_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f + md5: 36d33e440c31857372a72137f78bacf5 + license: BSD-2-Clause + license_family: BSD + size: 107458 + timestamp: 1702146414478 +- kind: conda + name: libev + version: '4.33' + build: hd590300_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 + md5: 172bf1cd1ff8629f2b1179945ed45055 + depends: + - libgcc-ng >=12 + license: BSD-2-Clause + license_family: BSD + size: 112766 + timestamp: 1702146165126 +- kind: conda + name: libexpat + version: 2.6.2 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + sha256: 331bb7c7c05025343ebd79f86ae612b9e1e74d2687b8f3179faec234f986ce19 + md5: e7ba12deb7020dd080c6c70e7b6f6a3d + depends: + - libgcc-ng >=12 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 73730 + timestamp: 1710362120304 +- kind: conda + name: libexpat + version: 2.6.2 + build: h63175ca_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + sha256: 79f612f75108f3e16bbdc127d4885bb74729cf66a8702fca0373dad89d40c4b7 + md5: bc592d03f62779511d392c175dcece64 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 139224 + timestamp: 1710362609641 +- kind: conda + name: libexpat + version: 2.6.2 + build: h73e2aa4_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + sha256: a188a77b275d61159a32ab547f7d17892226e7dac4518d2c6ac3ac8fc8dfde92 + md5: 3d1d51c8f716d97c864d12f7af329526 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 69246 + timestamp: 1710362566073 +- kind: conda + name: libexpat + version: 2.6.2 + build: hebf3989_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + sha256: ba7173ac30064ea901a4c9fb5a51846dcc25512ceb565759be7d18cbf3e5415e + md5: e3cde7cfa87f82f7cb13d482d5e0ad09 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 63655 + timestamp: 1710362424980 +- kind: conda + name: libffi + version: 3.4.2 + build: h0d85af4_5 + build_number: 5 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + sha256: 7a2d27a936ceee6942ea4d397f9c7d136f12549d86f7617e8b6bad51e01a941f + md5: ccb34fb14960ad8b125962d3d79b31a9 + license: MIT + license_family: MIT + size: 51348 + timestamp: 1636488394370 +- kind: conda + name: libffi + version: 3.4.2 + build: h3422bc3_5 + build_number: 5 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + sha256: 41b3d13efb775e340e4dba549ab5c029611ea6918703096b2eaa9c015c0750ca + md5: 086914b672be056eb70fd4285b6783b6 + license: MIT + license_family: MIT + size: 39020 + timestamp: 1636488587153 +- kind: conda + name: libffi + version: 3.4.2 + build: h7f98852_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + sha256: ab6e9856c21709b7b517e940ae7028ae0737546122f83c2aa5d692860c3b149e + md5: d645c6d2ac96843a2bfaccd2d62b3ac3 + depends: + - libgcc-ng >=9.4.0 + license: MIT + license_family: MIT + size: 58292 + timestamp: 1636488182923 +- kind: conda + name: libffi + version: 3.4.2 + build: h8ffe710_5 + build_number: 5 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 + sha256: 1951ab740f80660e9bc07d2ed3aefb874d78c107264fd810f24a1a6211d4b1a5 + md5: 2c96d1b6915b408893f9472569dee135 + depends: + - vc >=14.1,<15.0a0 + - vs2015_runtime >=14.16.27012 + license: MIT + license_family: MIT + size: 42063 + timestamp: 1636489106777 +- kind: conda + name: libgcc-devel_linux-64 + version: 12.3.0 + build: h0223996_107 + build_number: 107 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h0223996_107.conda + sha256: d6623e46608ef1baf2baa14ac77d0aefbc5187f1b9b5423592bfa124054e6753 + md5: 851e9651c9e4cd5dc19f80398eba9a1c + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 2532549 + timestamp: 1715016464312 +- kind: conda + name: libgcc-ng + version: 13.2.0 + build: h77fa898_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h77fa898_7.conda + sha256: 62af2b89acbe74a21606c8410c276e57309c0a2ab8a9e8639e3c8131c0b60c92 + md5: 72ec1b1b04c4d15d4204ece1ecea5978 + depends: + - _libgcc_mutex 0.1 conda_forge + - _openmp_mutex >=4.5 + constrains: + - libgomp 13.2.0 h77fa898_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 775806 + timestamp: 1715016057793 +- kind: conda + name: libgomp + version: 13.2.0 + build: h77fa898_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h77fa898_7.conda + sha256: 781444fa069d3b50e8ed667b750571cacda785761c7fc2a89ece1ac49693d4ad + md5: abf3fec87c2563697defa759dec3d639 + depends: + - _libgcc_mutex 0.1 conda_forge + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 422336 + timestamp: 1715015995979 +- kind: conda + name: libiconv + version: '1.17' + build: h0d3ecfb_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + sha256: bc7de5097b97bcafcf7deaaed505f7ce02f648aac8eccc0d5a47cc599a1d0304 + md5: 69bda57310071cf6d2b86caf11573d2d + license: LGPL-2.1-only + size: 676469 + timestamp: 1702682458114 +- kind: conda + name: libiconv + version: '1.17' + build: hd590300_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda + sha256: 8ac2f6a9f186e76539439e50505d98581472fedb347a20e7d1f36429849f05c9 + md5: d66573916ffcf376178462f1b61c941e + depends: + - libgcc-ng >=12 + license: LGPL-2.1-only + size: 705775 + timestamp: 1702682170569 +- kind: conda + name: libiconv + version: '1.17' + build: hd75f5a5_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + sha256: 23d4923baeca359423a7347c2ed7aaf48c68603df0cf8b87cc94a10b0d4e9a23 + md5: 6c3628d047e151efba7cf08c5e54d1ca + license: LGPL-2.1-only + size: 666538 + timestamp: 1702682713201 +- kind: conda + name: libllvm16 + version: 16.0.6 + build: haab561b_3 + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm16-16.0.6-haab561b_3.conda + sha256: f240f3776b02c39a32ce7397d6f2de072510321c835f4def452fc62e5c3babc0 + md5: 9900d62ede9ce25b569beeeab1da094e + depends: + - libcxx >=16 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 23347663 + timestamp: 1701374993634 +- kind: conda + name: libllvm16 + version: 16.0.6 + build: hbedff68_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libllvm16-16.0.6-hbedff68_3.conda + sha256: ad848dc0bb02b1dbe54324ee5700b050a2e5f63c095f5229b2de58249a3e268e + md5: 8fd56c0adc07a37f93bd44aa61a97c90 + depends: + - libcxx >=16 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 25196932 + timestamp: 1701379796962 +- kind: conda + name: libllvm18 + version: 18.1.6 + build: hb77312f_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.6-hb77312f_0.conda + sha256: 0f529a258d0e586f4d443b5c4df9c36b1fcf5391d867e7e0a2b2cb6084337477 + md5: 1246fc4b9f4db452e69cc297967d4b3e + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.7,<3.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 38428999 + timestamp: 1716642164972 +- kind: conda + name: libllvm18 + version: 18.1.6 + build: hd5e122f_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.6-hd5e122f_0.conda + sha256: af0089345178401d2ca25105408f2a03d2972f0b07338d7623cbf304aa233b15 + md5: de6112a23c73bba1347886f65d16c2b6 + depends: + - __osx >=10.13 + - libcxx >=16 + - libxml2 >=2.12.7,<3.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 27571492 + timestamp: 1716631405049 +- kind: conda + name: libllvm18 + version: 18.1.6 + build: hdac5640_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.6-hdac5640_0.conda + sha256: d91ba61768a9830492081c6798619f8cf55552e7667b3fea141ad08dc77c0869 + md5: 0f810485b34dee7169728fa89b00683b + depends: + - __osx >=11.0 + - libcxx >=16 + - libxml2 >=2.12.7,<3.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 25766518 + timestamp: 1716632069769 +- kind: conda + name: libnghttp2 + version: 1.58.0 + build: h47da74e_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda + sha256: 1910c5306c6aa5bcbd623c3c930c440e9c77a5a019008e1487810e3c1d3716cb + md5: 700ac6ea6d53d5510591c4344d5c989a + depends: + - c-ares >=1.23.0,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.2.0,<4.0a0 + license: MIT + license_family: MIT + size: 631936 + timestamp: 1702130036271 +- kind: conda + name: libnghttp2 + version: 1.58.0 + build: h64cf6d3_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + sha256: 412fd768e787e586602f8e9ea52bf089f3460fc630f6987f0cbd89b70e9a4380 + md5: faecc55c2a8155d9ff1c0ff9a0fef64f + depends: + - __osx >=10.9 + - c-ares >=1.23.0,<2.0a0 + - libcxx >=16.0.6 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.2.0,<4.0a0 + license: MIT + license_family: MIT + size: 599736 + timestamp: 1702130398536 +- kind: conda + name: libnghttp2 + version: 1.58.0 + build: ha4dd798_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda + sha256: fc97aaaf0c6d0f508be313d86c2705b490998d382560df24be918b8e977802cd + md5: 1813e066bfcef82de579a0be8a766df4 + depends: + - __osx >=10.9 + - c-ares >=1.23.0,<2.0a0 + - libcxx >=16.0.6 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.2.0,<4.0a0 + license: MIT + license_family: MIT + size: 565451 + timestamp: 1702130473930 +- kind: conda + name: libnsl + version: 2.0.1 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + sha256: 26d77a3bb4dceeedc2a41bd688564fe71bf2d149fdcf117049970bc02ff1add6 + md5: 30fd6e37fe21f86f4bd26d6ee73eeec7 + depends: + - libgcc-ng >=12 + license: LGPL-2.1-only + license_family: GPL + size: 33408 + timestamp: 1697359010159 +- kind: conda + name: libsanitizer + version: 12.3.0 + build: hb8811af_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-12.3.0-hb8811af_7.conda + sha256: 3f481da2367b5e407a954210b86a828528c0416023315a8d78e6729639c7d072 + md5: ee573415c47ce17f65101d0b3fba396d + depends: + - libgcc-ng >=12.3.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 3939615 + timestamp: 1715016598795 +- kind: conda + name: libsqlite + version: 3.46.0 + build: h1b8f9f3_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.46.0-h1b8f9f3_0.conda + sha256: 63af1a9e3284c7e4952364bafe7267e41e2d9d8bcc0e85a4ea4b0ec02d3693f6 + md5: 5dadfbc1a567fe6e475df4ce3148be09 + depends: + - __osx >=10.13 + - libzlib >=1.2.13,<2.0a0 + license: Unlicense + size: 908643 + timestamp: 1718050720117 +- kind: conda + name: libsqlite + version: 3.46.0 + build: h2466b09_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.46.0-h2466b09_0.conda + sha256: 662bd7e0d63c5b8c31cca19b91649e798319b93568a2ba8d1375efb91eeb251b + md5: 951b0a3a463932e17414cd9f047fa03d + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Unlicense + size: 876677 + timestamp: 1718051113874 +- kind: conda + name: libsqlite + version: 3.46.0 + build: hde9e2c9_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.0-hde9e2c9_0.conda + sha256: daee3f68786231dad457d0dfde3f7f1f9a7f2018adabdbb864226775101341a8 + md5: 18aa975d2094c34aef978060ae7da7d8 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0a0 + license: Unlicense + size: 865346 + timestamp: 1718050628718 +- kind: conda + name: libsqlite + version: 3.46.0 + build: hfb93653_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.46.0-hfb93653_0.conda + sha256: 73048f9cb8647d3d3bfe6021c0b7d663e12cffbe9b4f31bd081e713b0a9ad8f9 + md5: 12300188028c9bc02da965128b91b517 + depends: + - __osx >=11.0 + - libzlib >=1.2.13,<2.0a0 + license: Unlicense + size: 830198 + timestamp: 1718050644825 +- kind: conda + name: libssh2 + version: 1.11.0 + build: h0841786_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + sha256: 50e47fd9c4f7bf841a11647ae7486f65220cfc988ec422a4475fe8d5a823824d + md5: 1f5a58e686b13bcfde88b93f547d23fe + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 271133 + timestamp: 1685837707056 +- kind: conda + name: libssh2 + version: 1.11.0 + build: h7a5bd25_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda + sha256: bb57d0c53289721fff1eeb3103a1c6a988178e88d8a8f4345b0b91a35f0e0015 + md5: 029f7dc931a3b626b94823bc77830b01 + depends: + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 255610 + timestamp: 1685837894256 +- kind: conda + name: libssh2 + version: 1.11.0 + build: h7dfc565_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda + sha256: 813fd04eed2a2d5d9c36e53c554f9c1f08e9324e2922bd60c9c52dbbed2dbcec + md5: dc262d03aae04fe26825062879141a41 + depends: + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.1,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + size: 266806 + timestamp: 1685838242099 +- kind: conda + name: libssh2 + version: 1.11.0 + build: hd019ec5_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + sha256: f3886763b88f4b24265db6036535ef77b7b77ce91b1cbe588c0fbdd861eec515 + md5: ca3a72efba692c59a90d4b9fc0dfe774 + depends: + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 259556 + timestamp: 1685837820566 +- kind: conda + name: libstdcxx-devel_linux-64 + version: 12.3.0 + build: h0223996_107 + build_number: 107 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h0223996_107.conda + sha256: b67931a6ad04effddaf5b18c732ac6154f0f494d5d5189e5e23fbc5a26212389 + md5: 167a1f5d77d8f3c2a638f7eb418429f1 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 11881031 + timestamp: 1715016519463 +- kind: conda + name: libstdcxx-ng + version: 13.2.0 + build: hc0a3c3a_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-hc0a3c3a_7.conda + sha256: 35f1e08be0a84810c9075f5bd008495ac94e6c5fe306dfe4b34546f11fed850f + md5: 53ebd4c833fa01cb2c6353e99f905406 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 3837704 + timestamp: 1715016117360 +- kind: conda + name: libuuid + version: 2.38.1 + build: h0b41bf4_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18 + md5: 40b61aab5c7ba9ff276c41cfffe6b80b + depends: + - libgcc-ng >=12 + license: BSD-3-Clause + license_family: BSD + size: 33601 + timestamp: 1680112270483 +- kind: conda + name: libuv + version: 1.48.0 + build: h67532ce_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.48.0-h67532ce_0.conda + sha256: fb87f7bfd464a3a841d23f418c86a206818da0c4346984392071d9342c9ea367 + md5: c8e7344c74f0d86584f7ecdc9f25c198 + license: MIT + license_family: MIT + size: 407040 + timestamp: 1709913680478 +- kind: conda + name: libuv + version: 1.48.0 + build: h93a5062_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.48.0-h93a5062_0.conda + sha256: 60bed2a7a85096387ab0381cbc32ea2da7f8dd99bd90e440983019c0cdd96ad1 + md5: abfd49e80f13453b62a56be226120ea8 + license: MIT + license_family: MIT + size: 405988 + timestamp: 1709913494015 +- kind: conda + name: libuv + version: 1.48.0 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda + sha256: 6151c51857c2407139ce22fdc956022353e675b2bc96991a9201d51cceaa90b4 + md5: 485e49e1d500d996844df14cabf64d73 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + size: 289753 + timestamp: 1709913743184 +- kind: conda + name: libuv + version: 1.48.0 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.48.0-hd590300_0.conda + sha256: b7c0e8a0c93c2621be7645b37123d4e8d27e8a974da26a3fba47a9c37711aa7f + md5: 7e8b914b1062dd4386e3de4d82a3ead6 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 899979 + timestamp: 1709913354710 +- kind: conda + name: libxcrypt + version: 4.4.36 + build: hd590300_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + size: 100393 + timestamp: 1702724383534 +- kind: conda + name: libxml2 + version: 2.12.7 + build: h3e169fe_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.7-h3e169fe_1.conda + sha256: 75554b5ef4c61a97c1d2ddcaff2d87c5ee120ff6925c2b714e18b20727cafb98 + md5: ddb63049aa7bd9f08f2cdc5a1c144d1a + depends: + - __osx >=10.13 + - icu >=73.2,<74.0a0 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<2.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 619297 + timestamp: 1717546472911 +- kind: conda + name: libxml2 + version: 2.12.7 + build: ha661575_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.7-ha661575_1.conda + sha256: 0ea12032b53d3767564a058ccd5208c0a1724ed2f8074dd22257ff3859ea6a4e + md5: 8ea71a74847498c793b0a8e9054a177a + depends: + - __osx >=11.0 + - icu >=73.2,<74.0a0 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<2.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 588487 + timestamp: 1717546487246 +- kind: conda + name: libxml2 + version: 2.12.7 + build: hc051c1a_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.7-hc051c1a_1.conda + sha256: 576ea9134176636283ff052897bf7a91ffd8ac35b2c505dfde2890ec52849698 + md5: 340278ded8b0dc3a73f3660bbb0adbc6 + depends: + - icu >=73.2,<74.0a0 + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<2.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 704984 + timestamp: 1717546454837 +- kind: conda + name: libzlib + version: 1.3.1 + build: h2466b09_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_1.conda + sha256: b13846a54a15243e15f96fec06b526d8155adc6a1ac2b6ed47a88f6a71a94b68 + md5: d4483ca8afc57ddf1f6dded53b36c17f + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - zlib 1.3.1 *_1 + license: Zlib + license_family: Other + size: 56186 + timestamp: 1716874730539 +- kind: conda + name: libzlib + version: 1.3.1 + build: h4ab18f5_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda + sha256: adf6096f98b537a11ae3729eaa642b0811478f0ea0402ca67b5108fe2cb0010d + md5: 57d7dc60e9325e3de37ff8dffd18e814 + depends: + - libgcc-ng >=12 + constrains: + - zlib 1.3.1 *_1 + license: Zlib + license_family: Other + size: 61574 + timestamp: 1716874187109 +- kind: conda + name: libzlib + version: 1.3.1 + build: h87427d6_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-h87427d6_1.conda + sha256: 80a62db652b1da0ccc100812a1d86e94f75028968991bfb17f9536f3aa72d91d + md5: b7575b5aa92108dcc9aaab0f05f2dbce + depends: + - __osx >=10.13 + constrains: + - zlib 1.3.1 *_1 + license: Zlib + license_family: Other + size: 57372 + timestamp: 1716874211519 +- kind: conda + name: libzlib + version: 1.3.1 + build: hfb2fe0b_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-hfb2fe0b_1.conda + sha256: c34365dd37b0eab27b9693af32a1f7f284955517c2cc91f1b88a7ef4738ff03e + md5: 636077128927cf79fd933276dc3aed47 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.1 *_1 + license: Zlib + license_family: Other + size: 46921 + timestamp: 1716874262512 +- kind: conda + name: llvm-openmp + version: 18.1.6 + build: h15ab845_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.6-h15ab845_0.conda + sha256: b07be564a0539adc6f6e12b921469c925b37799e50a27a9dbe276115e9de689a + md5: 065f974bc7afcef3f94df56394e16154 + depends: + - __osx >=10.13 + constrains: + - openmp 18.1.6|18.1.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 300479 + timestamp: 1716753668057 +- kind: conda + name: llvm-openmp + version: 18.1.6 + build: hde57baf_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.6-hde57baf_0.conda + sha256: ca646e5d47040fb63bec903c3af7b5a9888d58c8cc2acb424e1dd48f9fa4532d + md5: f4565f7e5ce486f33705ff6bfc586688 + depends: + - __osx >=11.0 + constrains: + - openmp 18.1.6|18.1.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 276591 + timestamp: 1716753686325 +- kind: conda + name: llvm-tools + version: 16.0.6 + build: haab561b_3 + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-16.0.6-haab561b_3.conda + sha256: 64cc3547a2b0a3700a9fa0bd1fd3258156900b48ae73fc1a4b391002ca1462bf + md5: ca8e3771122c520fbe72af7c83d6d4cd + depends: + - libllvm16 16.0.6 haab561b_3 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - llvmdev 16.0.6 + - clang 16.0.6.* + - clang-tools 16.0.6.* + - llvm 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 20685770 + timestamp: 1701375136405 +- kind: conda + name: llvm-tools + version: 16.0.6 + build: hbedff68_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-16.0.6-hbedff68_3.conda + sha256: dff3ca83c6945f020ee6d3c62ddb3ed175ae8a357be3689a8836bcfe25ad9882 + md5: e9356b0807462e8f84c1384a8da539a5 + depends: + - libllvm16 16.0.6 hbedff68_3 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - llvmdev 16.0.6 + - clang 16.0.6.* + - clang-tools 16.0.6.* + - llvm 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22221159 + timestamp: 1701379965425 +- kind: conda + name: markupsafe + version: 2.1.5 + build: py312h41838bb_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-2.1.5-py312h41838bb_0.conda + sha256: 8dc8f31f78d00713300da000b6ebaa1943a17c112f267de310d5c3d82950079c + md5: c4a9c25c09cef3901789ca818d9beb10 + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + size: 25742 + timestamp: 1706900456837 +- kind: conda + name: markupsafe + version: 2.1.5 + build: py312h98912ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h98912ed_0.conda + sha256: 273d8efd6c089c534ccbede566394c0ac1e265bfe5d89fe76e80332f3d75a636 + md5: 6ff0b9582da2d4a74a1f9ae1f9ce2af6 + depends: + - libgcc-ng >=12 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + size: 26685 + timestamp: 1706900070330 +- kind: conda + name: markupsafe + version: 2.1.5 + build: py312he37b823_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py312he37b823_0.conda + sha256: 61480b725490f68856dd14e646f51ffc34f77f2c985bd33e3b77c04b2856d97d + md5: ba3a8f8cf8bbdb81394275b1e1d271da + depends: + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + size: 26382 + timestamp: 1706900495057 +- kind: conda + name: markupsafe + version: 2.1.5 + build: py312he70551f_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py312he70551f_0.conda + sha256: f8690a3c87e2e96cebd434a829bb95cac43afe6c439530b336dc3452fe4ce4af + md5: 4950a739b19edaac1ed29ca9474e49ac + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + size: 29060 + timestamp: 1706900374745 +- kind: conda + name: ncurses + version: '6.5' + build: h5846eda_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda + sha256: 6ecc73db0e49143092c0934355ac41583a5d5a48c6914c5f6ca48e562d3a4b79 + md5: 02a888433d165c99bf09784a7b14d900 + license: X11 AND BSD-3-Clause + size: 823601 + timestamp: 1715195267791 +- kind: conda + name: ncurses + version: '6.5' + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda + sha256: 4fc3b384f4072b68853a0013ea83bdfd3d66b0126e2238e1d6e1560747aa7586 + md5: fcea371545eda051b6deafb24889fc69 + depends: + - libgcc-ng >=12 + license: X11 AND BSD-3-Clause + size: 887465 + timestamp: 1715194722503 +- kind: conda + name: ncurses + version: '6.5' + build: hb89a1cb_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda + sha256: 87d7cf716d9d930dab682cb57b3b8d3a61940b47d6703f3529a155c938a6990a + md5: b13ad5724ac9ae98b6b4fd87e4500ba4 + license: X11 AND BSD-3-Clause + size: 795131 + timestamp: 1715194898402 +- kind: conda + name: ninja + version: 1.12.1 + build: h297d8ca_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.12.1-h297d8ca_0.conda + sha256: 40f7b76b07067935f8a5886aab0164067b7aa71eb5ad20b7278618c0c2c98e06 + md5: 3aa1c7e292afeff25a0091ddd7c69b72 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 2198858 + timestamp: 1715440571685 +- kind: conda + name: ninja + version: 1.12.1 + build: h3c5361c_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.12.1-h3c5361c_0.conda + sha256: 230f11a2f73955b67550be09a0c1fd053772f5e01e98d5873547d63ebea73229 + md5: a0ebabd021c8191aeb82793fe43cfdcb + depends: + - __osx >=10.13 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 124942 + timestamp: 1715440780183 +- kind: conda + name: ninja + version: 1.12.1 + build: h420ef59_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.12.1-h420ef59_0.conda + sha256: 11528acfa0f05d0c51639f6b09b51dc6611b801668449bb36c206c4b055be4f4 + md5: 9166c10405d41c95ffde8fcb8e5c3d51 + depends: + - __osx >=11.0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 112576 + timestamp: 1715440927034 +- kind: conda + name: ninja + version: 1.12.1 + build: hc790b64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/ninja-1.12.1-hc790b64_0.conda + sha256: b821cb72cb3ef08fab90a9bae899510e6cf3c23b5da6070d1ec30099dfe6a5be + md5: a557dde55343e03c68cd7e29e7f87279 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 285150 + timestamp: 1715441052517 +- kind: conda + name: openssl + version: 3.3.1 + build: h2466b09_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/openssl-3.3.1-h2466b09_0.conda + sha256: fbd63a41b854370a74e5f7ccc50d67f053d60c08e40389156e7924df0824d297 + md5: 27fe798366ef3a81715b13eedf699e2f + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 8383610 + timestamp: 1717550042871 +- kind: conda + name: openssl + version: 3.3.1 + build: h4ab18f5_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4ab18f5_0.conda + sha256: 9691f8bd6394c5bb0b8d2f47cd1467b91bd5b1df923b69e6b517f54496ee4b50 + md5: a41fa0e391cc9e0d6b78ac69ca047a6c + depends: + - ca-certificates + - libgcc-ng >=12 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 2896170 + timestamp: 1717546157673 +- kind: conda + name: openssl + version: 3.3.1 + build: h87427d6_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.1-h87427d6_0.conda + sha256: 272bee725877f417fef923f5e7852ebfe06b40b6bf3364f4498b2b3f568d5e2c + md5: 1bdad93ae01353340f194c5d879745db + depends: + - __osx >=10.13 + - ca-certificates + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 2547614 + timestamp: 1717546605131 +- kind: conda + name: openssl + version: 3.3.1 + build: hfb2fe0b_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.1-hfb2fe0b_0.conda + sha256: 6cb2d44f027b259be8cba2240bdf21af7b426e4132a73e0052f7173ab8b60ab0 + md5: c4a0bbd96a0da60bf265dac62c87f4e1 + depends: + - __osx >=11.0 + - ca-certificates + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 2891941 + timestamp: 1717545846389 +- kind: conda + name: python + version: 3.12.3 + build: h1411813_0_cpython + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.3-h1411813_0_cpython.conda + sha256: 3b327ffc152a245011011d1d730781577a8274fde1cf6243f073749ead8f1c2a + md5: df1448ec6cbf8eceb03d29003cf72ae6 + depends: + - __osx >=10.9 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.6.2,<3.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.45.2,<4.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4.20240210,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + size: 14557341 + timestamp: 1713208068012 +- kind: conda + name: python + version: 3.12.3 + build: h2628c8c_0_cpython + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/python-3.12.3-h2628c8c_0_cpython.conda + sha256: 1a95494abe572a8819c933f978df89f00bde72ea9432d46a70632599e8029ea4 + md5: f07c8c5dd98767f9a652de5d039b284e + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.6.2,<3.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.45.2,<4.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.2.1,<4.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + size: 16179248 + timestamp: 1713205644673 +- kind: conda + name: python + version: 3.12.3 + build: h4a7b5fc_0_cpython + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.3-h4a7b5fc_0_cpython.conda + sha256: c761fb3713ea66bce3889b33b6f400afb2dd192d1fc2686446e9d8166cfcec6b + md5: 8643ab37bece6ae8f112464068d9df9c + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.6.2,<3.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.45.2,<4.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4.20240210,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + size: 13207557 + timestamp: 1713206576646 +- kind: conda + name: python + version: 3.12.3 + build: hab00c5b_0_cpython + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + sha256: f9865bcbff69f15fd89a33a2da12ad616e98d65ce7c83c644b92e66e5016b227 + md5: 2540b74d304f71d3e89c81209db4db84 + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.6.2,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc-ng >=12 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.45.2,<4.0a0 + - libuuid >=2.38.1,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4.20240210,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + size: 31991381 + timestamp: 1713208036041 +- kind: conda + name: python_abi + version: '3.12' + build: 4_cp312 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda + sha256: 182a329de10a4165f6e8a3804caf751f918f6ea6176dd4e5abcdae1ed3095bf6 + md5: dccc2d142812964fcc6abdc97b672dff + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + size: 6385 + timestamp: 1695147396604 +- kind: conda + name: python_abi + version: '3.12' + build: 4_cp312 + build_number: 4 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.12-4_cp312.conda + sha256: 82c154d95c1637604671a02a89e72f1382e89a4269265a03506496bd928f6f14 + md5: 87201ac4314b911b74197e588cca3639 + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + size: 6496 + timestamp: 1695147498447 +- kind: conda + name: python_abi + version: '3.12' + build: 4_cp312 + build_number: 4 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda + sha256: db25428e4f24f8693ffa39f3ff6dfbb8fd53bc298764b775b57edab1c697560f + md5: bbb3a02c78b2d8219d7213f76d644a2a + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + size: 6508 + timestamp: 1695147497048 +- kind: conda + name: python_abi + version: '3.12' + build: 4_cp312 + build_number: 4 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.12-4_cp312.conda + sha256: 488f8519d04b48f59bd6fde21ebe2d7a527718ff28aac86a8b53aa63658bdef6 + md5: 17f4ccf6be9ded08bd0a376f489ac1a6 + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + size: 6785 + timestamp: 1695147430513 +- kind: conda + name: pyyaml + version: 6.0.1 + build: py312h02f2b3b_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py312h02f2b3b_1.conda + sha256: b6b4027b89c17b9bbd8089aec3e44bc29f802a7d5668d5a75b5358d7ed9705ca + md5: a0c843e52a1c4422d8657dd76e9eb994 + depends: + - python >=3.12.0rc3,<3.13.0a0 + - python >=3.12.0rc3,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 182705 + timestamp: 1695373895409 +- kind: conda + name: pyyaml + version: 6.0.1 + build: py312h104f124_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py312h104f124_1.conda + sha256: 04aa180782cb675b960c0bf4aad439b4a7a08553c6af74d0b8e5df9a0c7cc4f4 + md5: 260ed90aaf06061edabd7209638cf03b + depends: + - python >=3.12.0rc3,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 185636 + timestamp: 1695373742454 +- kind: conda + name: pyyaml + version: 6.0.1 + build: py312h98912ed_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.1-py312h98912ed_1.conda + sha256: 7f347a10a7121b08d79d21cd4f438c07c23479ea0c74dfb89d6dc416f791bb7f + md5: e3fd78d8d490af1d84763b9fe3f2e552 + depends: + - libgcc-ng >=12 + - python >=3.12.0rc3,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 196583 + timestamp: 1695373632212 +- kind: conda + name: pyyaml + version: 6.0.1 + build: py312he70551f_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.1-py312he70551f_1.conda + sha256: a72fa8152791b4738432f270e70b3a9a4d583ef059a78aa1c62f4b4ab7b15494 + md5: f91e0baa89ba21166916624ba7bfb422 + depends: + - python >=3.12.0rc3,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 167932 + timestamp: 1695374097139 +- kind: conda + name: readline + version: '8.2' + build: h8228510_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + sha256: 5435cf39d039387fbdc977b0a762357ea909a7694d9528ab40f005e9208744d7 + md5: 47d31b792659ce70f470b5c82fdfb7a4 + depends: + - libgcc-ng >=12 + - ncurses >=6.3,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 281456 + timestamp: 1679532220005 +- kind: conda + name: readline + version: '8.2' + build: h92ec313_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + sha256: a1dfa679ac3f6007362386576a704ad2d0d7a02e98f5d0b115f207a2da63e884 + md5: 8cbb776a2f641b943d413b3e19df71f4 + depends: + - ncurses >=6.3,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 250351 + timestamp: 1679532511311 +- kind: conda + name: readline + version: '8.2' + build: h9e318b2_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + sha256: 41e7d30a097d9b060037f0c6a2b1d4c4ae7e942c06c943d23f9d481548478568 + md5: f17f77f2acf4d344734bda76829ce14e + depends: + - ncurses >=6.3,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 255870 + timestamp: 1679532707590 +- kind: conda + name: rhash + version: 1.4.4 + build: h0dc2134_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + sha256: f1ae47e8c4e46f856faf5d8ee1e5291f55627aa93401b61a877f18ade5780c87 + md5: 55a2ada70c8a208c01f77978f2783121 + license: MIT + license_family: MIT + size: 177229 + timestamp: 1693456080514 +- kind: conda + name: rhash + version: 1.4.4 + build: hb547adb_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + sha256: 3ab595e2280ed2118b6b1e8ce7e5949da2047846c81b6af1bbf5ac859d062edd + md5: 710c4b1abf65b697c1d9716eba16dbb0 + license: MIT + license_family: MIT + size: 177491 + timestamp: 1693456037505 +- kind: conda + name: rhash + version: 1.4.4 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda + sha256: 12711d2d4a808a503c2e49b25d26ecb351435521e814c154e682dd2be71c2611 + md5: ec972a9a2925ac8d7a19eb9606561fff + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 185144 + timestamp: 1693455923632 +- kind: conda + name: rust + version: 1.75.0 + build: h4ff7c5d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.75.0-h4ff7c5d_0.conda + sha256: 8bd35dcc0e9761d7f02500ed907e6ee8992c3549250361e40ff5016f84cef215 + md5: 12b6a710ed0f1f366fedbf9d69b7b277 + depends: + - rust-std-aarch64-apple-darwin 1.75.0 hf6ec828_0 + license: MIT + license_family: MIT + size: 181697449 + timestamp: 1704208767306 +- kind: conda + name: rust + version: 1.75.0 + build: h70c747d_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/rust-1.75.0-h70c747d_0.conda + sha256: 5de27c76796ce0dd0ef7496f7c7f9c33a4e4cfa59112f8a1d7b2ada41794609a + md5: d2112c5913c6a3741eecff0c3ab02e7e + depends: + - gcc_impl_linux-64 + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + - rust-std-x86_64-unknown-linux-gnu 1.75.0 h2c6d0dc_0 + license: MIT + license_family: MIT + size: 190432074 + timestamp: 1704209051045 +- kind: conda + name: rust + version: 1.75.0 + build: h7e1429e_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/rust-1.75.0-h7e1429e_0.conda + sha256: 715783725eb9f5689bf57dda8eff8ca85df8940336129e82a836ab8e10aefae1 + md5: 21ab11c8f798546e46f023093f650866 + depends: + - rust-std-x86_64-apple-darwin 1.75.0 h38e4360_0 + license: MIT + license_family: MIT + size: 191324119 + timestamp: 1704208696296 +- kind: conda + name: rust + version: 1.75.0 + build: hf8d6059_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/rust-1.75.0-hf8d6059_0.conda + sha256: bb0e39570b63bf10c859afcc1593c41d4e9b164e63f78835403f79cbb3145d4d + md5: 68ac0e9721e34c115201a76c63bd82c8 + depends: + - rust-std-x86_64-pc-windows-msvc 1.75.0 h17fc481_0 + license: MIT + license_family: MIT + size: 186456319 + timestamp: 1704211980549 +- kind: conda + name: rust-std-aarch64-apple-darwin + version: 1.75.0 + build: hf6ec828_0 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.75.0-hf6ec828_0.conda + sha256: 19d2d1247e239c204352e4419f8a35a5abe2b9ec1e02c151ac611c2d50f2edab + md5: dd34d3d31a2b900e59582e8616bdeca8 + depends: + - __unix + constrains: + - rust >=1.75.0,<1.75.1.0a0 + license: MIT + license_family: MIT + size: 29617229 + timestamp: 1704208512989 +- kind: conda + name: rust-std-x86_64-apple-darwin + version: 1.75.0 + build: h38e4360_0 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.75.0-h38e4360_0.conda + sha256: bbcbb5f8643dd61605f6edb6487b18497511669267091f578b29e4902ccb421c + md5: ddfe0984ccdd936ee23ce8b0c4c88d6a + depends: + - __unix + constrains: + - rust >=1.75.0,<1.75.1.0a0 + license: MIT + license_family: MIT + size: 30638012 + timestamp: 1704208441871 +- kind: conda + name: rust-std-x86_64-pc-windows-msvc + version: 1.75.0 + build: h17fc481_0 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.75.0-h17fc481_0.conda + sha256: e7f62368332a48b8c7b44e27204cbf6c6d71fd433f6d7a24c20dacd623557503 + md5: 376e875d5c8e957a3ef44d24eff109eb + depends: + - __win + constrains: + - rust >=1.75.0,<1.75.1.0a0 + license: MIT + license_family: MIT + size: 24987788 + timestamp: 1704211520005 +- kind: conda + name: rust-std-x86_64-unknown-linux-gnu + version: 1.75.0 + build: h2c6d0dc_0 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.75.0-h2c6d0dc_0.conda + sha256: 4ae02c3fadece8b4c0b0a214f21b4fd8e47ec81a332c503fdd21a659a472f108 + md5: 46ab571e9b711ed713cd515395d187dd + depends: + - __unix + constrains: + - rust >=1.75.0,<1.75.1.0a0 + license: MIT + license_family: MIT + size: 33042935 + timestamp: 1704208890522 +- kind: conda + name: sigtool + version: 0.1.3 + build: h44b9a77_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + sha256: 70791ae00a3756830cb50451db55f63e2a42a2fa2a8f1bab1ebd36bbb7d55bff + md5: 4a2cac04f86a4540b8c9b8d8f597848f + depends: + - openssl >=3.0.0,<4.0a0 + license: MIT + license_family: MIT + size: 210264 + timestamp: 1643442231687 +- kind: conda + name: sigtool + version: 0.1.3 + build: h88f4db0_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + sha256: 46fdeadf8f8d725819c4306838cdfd1099cd8fe3e17bd78862a5dfdcd6de61cf + md5: fbfb84b9de9a6939cb165c02c69b1865 + depends: + - openssl >=3.0.0,<4.0a0 + license: MIT + license_family: MIT + size: 213817 + timestamp: 1643442169866 +- kind: conda + name: six + version: 1.16.0 + build: pyh6c4a22f_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 + sha256: a85c38227b446f42c5b90d9b642f2c0567880c15d72492d8da074a59c8f91dd6 + md5: e5f25f8dbc060e9a8d912e432202afc2 + depends: + - python + license: MIT + license_family: MIT + size: 14259 + timestamp: 1620240338595 +- 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: tapi + version: 1100.0.11 + build: h9ce4665_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 + sha256: 34b18ce8d1518b67e333ca1d3af733c3976ecbdf3a36b727f9b4dedddcc588fa + md5: f9ff42ccf809a21ba6f8607f8de36108 + depends: + - libcxx >=10.0.0.a0 + license: NCSA + license_family: MIT + size: 201044 + timestamp: 1602664232074 +- kind: conda + name: tapi + version: 1100.0.11 + build: he4954df_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 + sha256: 1709265fbee693a9e8b4126b0a3e68a6c4718b05821c659279c1af051f2d40f3 + md5: d83362e7d0513f35f454bc50b0ca591d + depends: + - libcxx >=11.0.0.a0 + license: NCSA + license_family: MIT + size: 191416 + timestamp: 1602687595316 +- kind: conda + name: tk + version: 8.6.13 + build: h1abcd95_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + sha256: 30412b2e9de4ff82d8c2a7e5d06a15f4f4fef1809a72138b6ccb53a33b26faf5 + md5: bf830ba5afc507c6232d4ef0fb1a882d + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: TCL + license_family: BSD + size: 3270220 + timestamp: 1699202389792 +- kind: conda + name: tk + version: 8.6.13 + build: h5083fa2_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + sha256: 72457ad031b4c048e5891f3f6cb27a53cb479db68a52d965f796910e71a403a8 + md5: b50a57ba89c32b62428b71a875291c9b + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: TCL + license_family: BSD + size: 3145523 + timestamp: 1699202432999 +- kind: conda + name: tk + version: 8.6.13 + build: h5226925_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + sha256: 2c4e914f521ccb2718946645108c9bd3fc3216ba69aea20c2c3cedbd8db32bb1 + md5: fc048363eb8f03cd1737600a5d08aafe + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: TCL + license_family: BSD + size: 3503410 + timestamp: 1699202577803 +- kind: conda + name: tk + version: 8.6.13 + build: noxft_h4845f30_101 + build_number: 101 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e + md5: d453b98d9c83e71da0741bb0ff4d76bc + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + license: TCL + license_family: BSD + size: 3318875 + timestamp: 1699202167581 +- kind: conda + name: tzdata + version: 2024a + build: h0c530f3_0 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + sha256: 7b2b69c54ec62a243eb6fba2391b5e443421608c3ae5dbff938ad33ca8db5122 + md5: 161081fc7cec0bfda0d86d7cb595f8d8 + license: LicenseRef-Public-Domain + size: 119815 + timestamp: 1706886945727 +- kind: conda + name: ucrt + version: 10.0.22621.0 + build: h57928b3_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + sha256: f29cdaf8712008f6b419b8b1a403923b00ab2504bfe0fb2ba8eb60e72d4f14c6 + md5: 72608f6cd3e5898229c3ea16deb1ac43 + constrains: + - vs2015_runtime >=14.29.30037 + license: LicenseRef-Proprietary + license_family: PROPRIETARY + size: 1283972 + timestamp: 1666630199266 +- kind: conda + name: vc + version: '14.3' + build: ha32ba9b_20 + build_number: 20 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-ha32ba9b_20.conda + sha256: 16cb562ce210ee089060f4aa52f3225a571c83885632a870ea2297d460e3bb00 + md5: 2abfb5cb1b9d41a50f765d60f0be563d + depends: + - vc14_runtime >=14.38.33135 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + size: 17122 + timestamp: 1716231244564 +- kind: conda + name: vc14_runtime + version: 14.38.33135 + build: h835141b_20 + build_number: 20 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33135-h835141b_20.conda + sha256: 05b07e0dd3fd49dcc98a365ff661ed6b65e2f0266b4bb03d273131ffdba663be + md5: e971b35a5765862fabc4ba6e5ddf9470 + depends: + - ucrt >=10.0.20348.0 + constrains: + - vs2015_runtime 14.38.33135.* *_20 + license: LicenseRef-ProprietaryMicrosoft + license_family: Proprietary + size: 744189 + timestamp: 1716231234745 +- kind: conda + name: vs2015_runtime + version: 14.38.33135 + build: h22015db_20 + build_number: 20 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33135-h22015db_20.conda + sha256: 2cebabc39766ea051e577762d813ad4151e9d0ff96f3ff3374d575a272951416 + md5: bb4f5ab332e46e1b022d8842e72905b1 + depends: + - vc14_runtime >=14.38.33135 + license: BSD-3-Clause + license_family: BSD + size: 17124 + timestamp: 1716231247457 +- kind: conda + name: vs2019_win-64 + version: 19.29.30139 + build: he1865b1_20 + build_number: 20 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/vs2019_win-64-19.29.30139-he1865b1_20.conda + sha256: b9b3faf4fa20301ad1886cfde20d339ea6c2e95de8f4710e0b49af1ca1d3a657 + md5: bc2f92e632f5c6b0d94e365546c7fc6e + depends: + - vswhere + constrains: + - vs_win-64 2019.11 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + size: 19744 + timestamp: 1716231200159 +- kind: conda + name: vswhere + version: 3.1.4 + build: h57928b3_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/vswhere-3.1.4-h57928b3_0.conda + sha256: 553c41fc1a883415a39444313f8d99236685529776fdd04e8d97288b73496002 + md5: b1d1d6a1f874d8c93a57b5efece52f03 + license: MIT + license_family: MIT + size: 218421 + timestamp: 1682376911339 +- kind: conda + name: xz + version: 5.2.6 + build: h166bdaf_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + sha256: 03a6d28ded42af8a347345f82f3eebdd6807a08526d47899a42d62d319609162 + md5: 2161070d867d1b1204ea749c8eec4ef0 + depends: + - libgcc-ng >=12 + license: LGPL-2.1 and GPL-2.0 + size: 418368 + timestamp: 1660346797927 +- kind: conda + name: xz + version: 5.2.6 + build: h57fd34a_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + sha256: 59d78af0c3e071021cfe82dc40134c19dab8cdf804324b62940f5c8cd71803ec + md5: 39c6b54e94014701dd157f4f576ed211 + license: LGPL-2.1 and GPL-2.0 + size: 235693 + timestamp: 1660346961024 +- kind: conda + name: xz + version: 5.2.6 + build: h775f41a_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + sha256: eb09823f34cc2dd663c0ec4ab13f246f45dcd52e5b8c47b9864361de5204a1c8 + md5: a72f9d4ea13d55d745ff1ed594747f10 + license: LGPL-2.1 and GPL-2.0 + size: 238119 + timestamp: 1660346964847 +- kind: conda + name: xz + version: 5.2.6 + build: h8d14728_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + sha256: 54d9778f75a02723784dc63aff4126ff6e6749ba21d11a6d03c1f4775f269fe0 + md5: 515d77642eaa3639413c6b1bc3f94219 + depends: + - vc >=14.1,<15 + - vs2015_runtime >=14.16.27033 + license: LGPL-2.1 and GPL-2.0 + size: 217804 + timestamp: 1660346976440 +- kind: conda + name: yaml + version: 0.2.5 + build: h0d85af4_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 + sha256: 5301417e2c8dea45b401ffee8df3957d2447d4ce80c83c5ff151fc6bfe1c4148 + md5: d7e08fcf8259d742156188e8762b4d20 + license: MIT + license_family: MIT + size: 84237 + timestamp: 1641347062780 +- kind: conda + name: yaml + version: 0.2.5 + build: h3422bc3_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 + sha256: 93181a04ba8cfecfdfb162fc958436d868cc37db504c58078eab4c1a3e57fbb7 + md5: 4bb3f014845110883a3c5ee811fd84b4 + license: MIT + license_family: MIT + size: 88016 + timestamp: 1641347076660 +- kind: conda + name: yaml + version: 0.2.5 + build: h7f98852_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 + sha256: a4e34c710eeb26945bdbdaba82d3d74f60a78f54a874ec10d373811a5d217535 + md5: 4cb3ad778ec2d5a7acbdf254eb1c42ae + depends: + - libgcc-ng >=9.4.0 + license: MIT + license_family: MIT + size: 89141 + timestamp: 1641346969816 +- kind: conda + name: yaml + version: 0.2.5 + build: h8ffe710_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h8ffe710_2.tar.bz2 + sha256: 4e2246383003acbad9682c7c63178e2e715ad0eb84f03a8df1fbfba455dfedc5 + md5: adbfb9f45d1004a26763652246a33764 + depends: + - vc >=14.1,<15.0a0 + - vs2015_runtime >=14.16.27012 + license: MIT + license_family: MIT + size: 63274 + timestamp: 1641347623319 +- kind: conda + name: zstd + version: 1.5.6 + build: h0ea2cb4_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.6-h0ea2cb4_0.conda + sha256: 768e30dc513568491818fb068ee867c57c514b553915536da09e5d10b4ebf3c3 + md5: 9a17230f95733c04dc40a2b1e5491d74 + depends: + - libzlib >=1.2.13,<2.0.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + size: 349143 + timestamp: 1714723445995 +- kind: conda + name: zstd + version: 1.5.6 + build: h915ae27_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.6-h915ae27_0.conda + sha256: efa04a98cb149643fa54c4dad5a0179e36a5fbc88427ea0eec88ceed87fd0f96 + md5: 4cb2cd56f039b129bb0e491c1164167e + depends: + - __osx >=10.9 + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + size: 498900 + timestamp: 1714723303098 +- kind: conda + name: zstd + version: 1.5.6 + build: ha6fb4c9_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda + sha256: c558b9cc01d9c1444031bd1ce4b9cff86f9085765f17627a6cd85fc623c8a02b + md5: 4d056880988120e29d75bfff282e0f45 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + size: 554846 + timestamp: 1714722996770 +- kind: conda + name: zstd + version: 1.5.6 + build: hb46c0d2_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda + sha256: 2d4fd1ff7ee79cd954ca8e81abf11d9d49954dd1fef80f27289e2402ae9c2e09 + md5: d96942c06c3e84bfcc5efb038724a7fd + depends: + - __osx >=11.0 + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + size: 405089 + timestamp: 1714723101397 diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 0000000..d8d0f9c --- /dev/null +++ b/pixi.toml @@ -0,0 +1,63 @@ +[project] +name = "resolvo" +authors = ["Bas Zalmstra "] +channels = ["conda-forge"] +platforms = ["linux-64", "win-64", "osx-arm64", "osx-64"] + +[tasks] +format = {depends_on = ["format-rust", "format-cpp", "format-cmake"] } +test = {depends_on = ["test-rust", "test-cpp"] } + +# ---- Build Rust using Cargo ---- +[feature.build-rust.dependencies] +rust = "~=1.75.0" + +[feature.test-rust.tasks.test-rust] +cmd = "cargo test" + +[feature.test-rust.tasks.format-rust] +cmd = "cargo fmt" + +[environments.test-rust] +features = ["build-rust", "test-rust"] +solve-group = "default" + +# ---- Build C++ using CMake ---- +[feature.build-cpp.dependencies] +cmake = ">=3.29.4,<3.30" +cxx-compiler = ">=1.7.0,<1.8" +ninja = ">=1.12.1,<1.13" + +[feature.build-cpp.tasks.configure] +cmd = "cmake -GNinja -S . -B build -DRESOLVO_BUILD_TESTING=ON" +inputs = ["CMakeLists.txt"] +outputs = ["build/CMakeFiles/"] + +[feature.build-cpp.tasks.build-cpp] +cmd = ["cmake", "--build", "build"] +depends-on = ["configure"] +inputs = ["CMakeLists.txt", "cpp/**/*", "src/**"] +outputs = ["build/bin/*"] + +[feature.build-cpp.tasks.test-cpp] +cmd = "ctest --test-dir build" +depends_on = ["build-cpp"] + +[environments.test-cpp] +features = ["build-cpp", "build-rust"] +solve-group = "default" + +# ---- Format C++ ---- +[feature.format-cpp.dependencies] +clang-format = ">=18.1.6,<18.2" +cmake-format = ">=0.6.13,<0.7" + +[feature.format-cpp.tasks.format-cpp] +cmd = "clang-format -i cpp/include/*.h cpp/tests/*.cpp" + +[feature.format-cpp.tasks.format-cmake] +cmd = "cmake-format -i CMakeLists.txt cpp/CMakeLists.txt cpp/tests/CMakeLists.txt" + +[environments.format-cpp] +features=["format-cpp"] +solve-group="default" diff --git a/recipe/recipe.yaml b/recipe/recipe.yaml new file mode 100644 index 0000000..871d188 --- /dev/null +++ b/recipe/recipe.yaml @@ -0,0 +1,30 @@ +package: + name: resolvo-cpp + version: 0.1.0 + +source: + - path: ../ + +build: + number: 0 + script: + - if: win + then: | + cmake %CMAKE_ARGS% -GNinja %SRC_DIR% + ninja install + else: | + cmake ${CMAKE_ARGS} -GNinja $SRC_DIR -DRust_CARGO_TARGET=${CARGO_BUILD_TARGET} + ninja install + +requirements: + build: + - ${{ compiler('cxx') }} + - ${{ compiler('rust') }} + - cmake + - ninja + +about: + license: BSD-3-Clause + summary: C++ bindings for resolvo, a universal package resolver. + repository: https://github.com/mamba-org/resolvo + diff --git a/recipe/variant_config.yaml b/recipe/variant_config.yaml new file mode 100644 index 0000000..d2c9ab8 --- /dev/null +++ b/recipe/variant_config.yaml @@ -0,0 +1 @@ +rust_compiler_version: ">=1.75" diff --git a/src/internal/id.rs b/src/internal/id.rs index 4d2ab59..916db98 100644 --- a/src/internal/id.rs +++ b/src/internal/id.rs @@ -5,7 +5,9 @@ use crate::{internal::arena::ArenaId, Interner}; /// The id associated to a package name #[repr(transparent)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct NameId(u32); +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(transparent))] +pub struct NameId(pub u32); impl ArenaId for NameId { fn from_usize(x: usize) -> Self { @@ -20,7 +22,9 @@ impl ArenaId for NameId { /// The id associated with a generic string #[repr(transparent)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] -pub struct StringId(u32); +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(transparent))] +pub struct StringId(pub u32); impl ArenaId for StringId { fn from_usize(x: usize) -> Self { @@ -35,7 +39,9 @@ impl ArenaId for StringId { /// The id associated with a VersionSet. #[repr(transparent)] #[derive(Clone, Default, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] -pub struct VersionSetId(u32); +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(transparent))] +pub struct VersionSetId(pub u32); impl ArenaId for VersionSetId { fn from_usize(x: usize) -> Self { @@ -50,7 +56,9 @@ impl ArenaId for VersionSetId { /// The id associated to a solvable #[repr(transparent)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] -pub struct SolvableId(u32); +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(transparent))] +pub struct SolvableId(pub u32); /// Internally used id for solvables that can also represent root and null. #[repr(transparent)] diff --git a/src/internal/mapping.rs b/src/internal/mapping.rs index 14c67c1..34cf4a4 100644 --- a/src/internal/mapping.rs +++ b/src/internal/mapping.rs @@ -1,16 +1,17 @@ +use std::{cmp, iter::FusedIterator, marker::PhantomData}; + use crate::internal::arena::ArenaId; -use std::cmp; -use std::iter::FusedIterator; -use std::marker::PhantomData; const VALUES_PER_CHUNK: usize = 128; -/// A `Mapping` holds a collection of `TValue`s that can be addressed by `TId`s. You can -/// think of it as a HashMap, optimized for the case in which we know the `TId`s are -/// contiguous. +/// A `Mapping` holds a collection of `TValue`s that can be addressed by +/// `TId`s. You can think of it as a HashMap, optimized for the +/// case in which we know the `TId`s are contiguous. +#[derive(Clone)] pub struct Mapping { chunks: Vec<[Option; VALUES_PER_CHUNK]>, len: usize, + max: usize, _phantom: PhantomData, } @@ -35,6 +36,7 @@ impl Mapping { Self { chunks, len: 0, + max: 0, _phantom: Default::default(), } } @@ -49,7 +51,8 @@ impl Mapping { /// Insert into the mapping with the specific value pub fn insert(&mut self, id: TId, value: TValue) { - let (chunk, offset) = Self::chunk_and_offset(id.to_usize()); + let idx = id.to_usize(); + let (chunk, offset) = Self::chunk_and_offset(idx); // Resize to fit if needed if chunk >= self.chunks.len() { @@ -58,6 +61,7 @@ impl Mapping { } self.chunks[chunk][offset] = Some(value); self.len += 1; + self.max = self.max.max(idx); } /// Get a specific value in the mapping with bound checks @@ -95,7 +99,9 @@ impl Mapping { /// Get a specific value in the mapping without bound checks /// /// # Safety - /// The caller must uphold most of the safety requirements for `get_unchecked`. i.e. the id having been inserted into the Mapping before. + /// The caller must uphold most of the safety requirements for + /// `get_unchecked`. i.e. the id having been inserted into the Mapping + /// before. pub unsafe fn get_unchecked(&self, id: TId) -> &TValue { let (chunk, offset) = Self::chunk_and_offset(id.to_usize()); self.chunks @@ -108,7 +114,9 @@ impl Mapping { /// Get a specific value in the mapping without bound checks /// /// # Safety - /// The caller must uphold most of the safety requirements for `get_unchecked_mut`. i.e. the id having been inserted into the Mapping before. + /// The caller must uphold most of the safety requirements for + /// `get_unchecked_mut`. i.e. the id having been inserted into the Mapping + /// before. pub unsafe fn get_unchecked_mut(&mut self, id: TId) -> &mut TValue { let (chunk, offset) = Self::chunk_and_offset(id.to_usize()); self.chunks @@ -128,6 +136,11 @@ impl Mapping { self.len == 0 } + /// Returns the maximum id that has been inserted + pub(crate) fn max(&self) -> usize { + self.max + } + /// Defines the number of slots that can be used /// theses slots are not initialized pub fn slots(&self) -> usize { @@ -177,6 +190,35 @@ impl<'a, TId: ArenaId, TValue> Iterator for MappingIter<'a, TId, TValue> { impl<'a, TId: ArenaId, TValue> FusedIterator for MappingIter<'a, TId, TValue> {} +#[cfg(feature = "serde")] +impl serde::Serialize for Mapping { + fn serialize(&self, serializer: S) -> Result { + self.chunks + .iter() + .flatten() + .take(self.max()) + .collect::>() + .serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, K: ArenaId, V: serde::Deserialize<'de>> serde::Deserialize<'de> for Mapping { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let values = Vec::>::deserialize(deserializer)?; + let mut mapping = Mapping::with_capacity(values.len()); + for (i, value) in values.into_iter().enumerate() { + if let Some(value) = value { + mapping.insert(K::from_usize(i), value); + } + } + Ok(mapping) + } +} + #[cfg(test)] mod tests { use crate::internal::arena::ArenaId; diff --git a/src/lib.rs b/src/lib.rs index c8f9d70..40bac7d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ pub(crate) mod internal; pub mod problem; pub mod runtime; +pub mod snapshot; mod solver; pub mod utils; @@ -171,6 +172,8 @@ pub struct Candidates { /// Holds information about the dependencies of a package. #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(untagged))] pub enum Dependencies { /// The dependencies are known. Known(KnownDependencies), @@ -184,9 +187,14 @@ pub enum Dependencies { /// Holds information about the dependencies of a package when they are known. #[derive(Default, Clone, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct KnownDependencies { /// Defines which packages should be installed alongside the depending /// package and the constraints applied to the package. + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub requirements: Vec, /// Defines additional constraints on packages that may or may not be part @@ -196,5 +204,9 @@ pub struct KnownDependencies { /// package also added to the solution. /// /// This is often useful to use for optional dependencies. + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub constrains: Vec, } diff --git a/src/snapshot.rs b/src/snapshot.rs new file mode 100644 index 0000000..279759d --- /dev/null +++ b/src/snapshot.rs @@ -0,0 +1,448 @@ +//! Provides [`DependencySnapshot`], an object that can capture a snapshot of a +//! dependency provider. This can be very useful to abstract over all the +//! ecosystem specific code and provide a serializable object that can later be +//! reused to solve dependencies. +//! +//! The [`DependencySnapshot`] can be serialized to disk if the `serde` feature +//! is enabled. +//! +//! The [`DependencySnapshot`] implements the [`DependencyProvider`] trait, +//! allowing it to be used as a dependency provider for the solver. + +use std::{any::Any, collections::VecDeque, fmt::Display, time::SystemTime}; + +use ahash::HashSet; +use futures::FutureExt; + +use crate::{ + internal::arena::ArenaId, Candidates, Dependencies, DependencyProvider, Interner, Mapping, + NameId, SolvableId, SolverCache, StringId, VersionSetId, +}; + +/// A single solvable in a [`DependencySnapshot`]. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Solvable { + /// The string representation of this version set. + pub display: String, + + /// The package name of this solvable. + pub name: NameId, + + /// The order of this solvable compared to other solvables with the same + /// `name`. + pub order: u32, + + /// The dependencies of the solvable + pub dependencies: Dependencies, + + /// Whether the dependencies of this solvable are available right + /// away or if they need to be fetched. + pub hint_dependencies_available: bool, +} + +/// Information about a single version set in a [`DependencySnapshot`]. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct VersionSet { + /// The package name that this version set references. + pub name: NameId, + + /// The string representation of this version set. + pub display: String, + + /// The candidates that match this version set. + pub matching_candidates: HashSet, +} + +/// A single package in a [`DependencySnapshot`]. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Package { + /// The name of this package + pub name: String, + + /// All the solvables for this package. + pub solvables: Vec, + + /// Excluded packages + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] + pub excluded: Vec<(SolvableId, StringId)>, +} + +/// A snapshot of an object that implements [`DependencyProvider`]. +#[derive(Clone, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct DependencySnapshot { + /// All the solvables in the snapshot + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Mapping::is_empty") + )] + pub solvables: Mapping, + + /// All the requirements in the snapshot + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Mapping::is_empty") + )] + pub requirements: Mapping, + + /// All the packages in the snapshot + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Mapping::is_empty") + )] + pub packages: Mapping, + + /// All the strings in the snapshot + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Mapping::is_empty") + )] + pub strings: Mapping, +} + +impl DependencySnapshot { + /// Construct a new [`DependencySnapshot`] from a [`DependencyProvider`] + /// capturing its entire state. This function will recursively call all + /// methods on the provider with the given `names`, `version_sets`, and + /// `solvables`. + /// + /// This function assumes that the passed in [`DependencyProvider`] does not + /// yield and will block until the snapshot is fully constructed. If you + /// want to construct a snapshot from a provider that might yield, use + /// [`Self::from_provider_async`] instead. + pub fn from_provider( + provider: impl DependencyProvider, + names: impl IntoIterator, + version_sets: impl IntoIterator, + solvables: impl IntoIterator, + ) -> Result> { + Self::from_provider_async(provider, names, version_sets, solvables) + .now_or_never() + .expect( + "the DependencyProvider seems to have yielded. Use `from_provider_async` instead.", + ) + } + + /// Construct a new [`DependencySnapshot`] from a [`DependencyProvider`] + /// capturing its entire state. This function will recursively call all + /// methods on the provider with the given `names`, `version_sets`, and + /// `solvables`. + pub async fn from_provider_async( + provider: impl DependencyProvider, + names: impl IntoIterator, + version_sets: impl IntoIterator, + solvables: impl IntoIterator, + ) -> Result> { + #[derive(Hash, Copy, Clone, Debug, Eq, PartialEq)] + pub enum Element { + Solvable(SolvableId), + VersionSet(VersionSetId), + Package(NameId), + String(StringId), + } + + let cache = SolverCache::new(provider); + + let mut result = Self { + solvables: Mapping::new(), + requirements: Mapping::new(), + packages: Mapping::new(), + strings: Mapping::new(), + }; + + let mut queue = names + .into_iter() + .map(Element::Package) + .chain(version_sets.into_iter().map(Element::VersionSet)) + .chain(solvables.into_iter().map(Element::Solvable)) + .collect::>(); + let mut seen = queue.iter().copied().collect::>(); + let mut available_hints = HashSet::default(); + while let Some(element) = queue.pop_front() { + match element { + Element::Package(name) => { + let display = cache.provider().display_name(name).to_string(); + let candidates = cache.get_or_cache_candidates(name).await?; + for solvable in candidates.candidates.iter() { + if seen.insert(Element::Solvable(*solvable)) { + queue.push_back(Element::Solvable(*solvable)); + } + } + for &(excluded, reason) in &candidates.excluded { + if seen.insert(Element::Solvable(excluded)) { + queue.push_back(Element::Solvable(excluded)); + } + if seen.insert(Element::String(reason)) { + queue.push_back(Element::String(reason)); + } + } + available_hints.extend(candidates.hint_dependencies_available.iter().copied()); + + let package = Package { + name: display, + solvables: candidates.candidates.clone(), + excluded: candidates.excluded.clone(), + }; + + result.packages.insert(name, package); + } + Element::Solvable(solvable_id) => { + let name = cache.provider().solvable_name(solvable_id); + if seen.insert(Element::Package(name)) { + queue.push_back(Element::Package(name)); + }; + + let dependencies = cache.get_or_cache_dependencies(solvable_id).await?; + match &dependencies { + Dependencies::Unknown(reason) => { + if seen.insert(Element::String(*reason)) { + queue.push_back(Element::String(*reason)); + } + } + Dependencies::Known(deps) => { + for &dep in deps.requirements.iter().chain(deps.constrains.iter()) { + if seen.insert(Element::VersionSet(dep)) { + queue.push_back(Element::VersionSet(dep)); + } + } + } + } + + let solvable = Solvable { + display: cache.provider().display_solvable(solvable_id).to_string(), + name, + order: 0, + dependencies: dependencies.clone(), + hint_dependencies_available: cache + .are_dependencies_available_for(solvable_id), + }; + + result.solvables.insert(solvable_id, solvable); + } + Element::String(string_id) => { + let string = cache.provider().display_string(string_id).to_string(); + result.strings.insert(string_id, string); + } + Element::VersionSet(version_set_id) => { + let name = cache.provider().version_set_name(version_set_id); + if seen.insert(Element::Package(name)) { + queue.push_back(Element::Package(name)); + }; + + let display = cache + .provider() + .display_version_set(version_set_id) + .to_string(); + let matching_candidates = cache + .get_or_cache_matching_candidates(version_set_id) + .await?; + + for matching_candidate in matching_candidates.iter() { + if seen.insert(Element::Solvable(*matching_candidate)) { + queue.push_back(Element::Solvable(*matching_candidate)); + } + } + + let version_set = VersionSet { + name, + display, + matching_candidates: matching_candidates.iter().copied().collect(), + }; + + result.requirements.insert(version_set_id, version_set); + } + } + } + + // Compute the order of the solvables + for (_, package) in result.packages.iter() { + let mut solvables = package.solvables.clone(); + cache + .provider() + .sort_candidates(&cache, &mut solvables) + .await; + + for (order, solvable) in solvables.into_iter().enumerate() { + let solvable = result + .solvables + .get_mut(solvable) + .expect("missing solvable"); + solvable.order = order as u32; + } + } + + Ok(result) + } + + /// Returns an object that implements the [`DependencyProvider`] trait for + /// this snapshot. + pub fn provider(&self) -> SnapshotProvider<'_> { + SnapshotProvider::new(self) + } +} + +/// Provides a [`DependencyProvider`] implementation for a +/// [`DependencySnapshot`]. +pub struct SnapshotProvider<'s> { + snapshot: &'s DependencySnapshot, + + additional_version_sets: Vec, + stop_time: Option, +} + +impl<'s> From<&'s DependencySnapshot> for SnapshotProvider<'s> { + fn from(value: &'s DependencySnapshot) -> Self { + Self::new(value) + } +} + +impl<'s> SnapshotProvider<'s> { + /// Create a new [`SnapshotProvider`] from a [`DependencySnapshot`]. + pub fn new(snapshot: &'s DependencySnapshot) -> Self { + Self { + snapshot, + additional_version_sets: Vec::new(), + stop_time: None, + } + } + + /// Adds a timeout to this provider. Solving will stop when the specified + /// time is reached. + pub fn with_timeout(self, stop_time: SystemTime) -> Self { + Self { + stop_time: Some(stop_time), + ..self + } + } + + /// Adds another requirement that matches any version of a package + pub fn add_package_requirement(&mut self, name: NameId) -> VersionSetId { + let id = self.snapshot.requirements.max() + self.additional_version_sets.len(); + + let package = self.package(name); + + let version_set = VersionSet { + name, + display: "*".to_string(), + matching_candidates: package.solvables.iter().copied().collect(), + }; + + self.additional_version_sets.push(version_set); + VersionSetId::from_usize(id) + } + + fn solvable(&self, solvable: SolvableId) -> &Solvable { + self.snapshot + .solvables + .get(solvable) + .expect("missing solvable") + } + + fn package(&self, name_id: NameId) -> &Package { + self.snapshot + .packages + .get(name_id) + .expect("missing package") + } + + fn string(&self, string_id: StringId) -> &String { + self.snapshot + .strings + .get(string_id) + .expect("missing string") + } + + fn version_set(&self, version_set: VersionSetId) -> &VersionSet { + let idx = version_set.to_usize(); + let max_idx = self.snapshot.requirements.max(); + if idx >= max_idx { + &self.additional_version_sets[idx - max_idx] + } else { + self.snapshot + .requirements + .get(version_set) + .expect("missing version set") + } + } +} + +impl<'s> Interner for SnapshotProvider<'s> { + fn display_solvable(&self, solvable: SolvableId) -> impl Display + '_ { + &self.solvable(solvable).display + } + + fn display_name(&self, name: NameId) -> impl Display + '_ { + &self.package(name).name + } + + fn display_version_set(&self, version_set: VersionSetId) -> impl Display + '_ { + &self.version_set(version_set).display + } + + fn display_string(&self, string_id: StringId) -> impl Display + '_ { + self.string(string_id) + } + + fn version_set_name(&self, version_set: VersionSetId) -> NameId { + self.version_set(version_set).name + } + + fn solvable_name(&self, solvable: SolvableId) -> NameId { + self.solvable(solvable).name + } +} + +impl<'s> DependencyProvider for SnapshotProvider<'s> { + async fn filter_candidates( + &self, + candidates: &[SolvableId], + version_set: VersionSetId, + inverse: bool, + ) -> Vec { + let version_set = self.version_set(version_set); + candidates + .iter() + .copied() + .filter(|c| version_set.matching_candidates.contains(c) != inverse) + .collect() + } + + async fn get_candidates(&self, name: NameId) -> Option { + let package = self.package(name); + Some(Candidates { + candidates: package.solvables.clone(), + favored: None, + locked: None, + excluded: package.excluded.clone(), + hint_dependencies_available: package + .solvables + .iter() + .copied() + .filter(|&s| self.solvable(s).hint_dependencies_available) + .collect(), + }) + } + + async fn sort_candidates(&self, _solver: &SolverCache, solvables: &mut [SolvableId]) { + solvables.sort_by_key(|&s| self.solvable(s).order); + } + + async fn get_dependencies(&self, solvable: SolvableId) -> Dependencies { + self.solvable(solvable).dependencies.clone() + } + + fn should_cancel_with_value(&self) -> Option> { + if let Some(stop_time) = &self.stop_time { + if SystemTime::now() > *stop_time { + return Some(Box::new(())); + } + } + None + } +} diff --git a/src/solver/cache.rs b/src/solver/cache.rs index 55125fd..cd4cc9b 100644 --- a/src/solver/cache.rs +++ b/src/solver/cache.rs @@ -171,14 +171,26 @@ impl SolverCache { match self.version_set_candidates.get(&version_set_id) { Some(candidates) => Ok(candidates), None => { - let package_name = self.provider.version_set_name(version_set_id); - let candidates = self.get_or_cache_candidates(package_name).await?; + let package_name_id = self.provider.version_set_name(version_set_id); + + tracing::trace!( + "Getting matching candidates for package: {}", + self.provider.display_name(package_name_id) + ); + + let candidates = self.get_or_cache_candidates(package_name_id).await?; + tracing::trace!("Got {:?} matching candidates", candidates.candidates.len()); let matching_candidates = self .provider .filter_candidates(&candidates.candidates, version_set_id, false) .await; + tracing::trace!( + "Filtered {:?} matching candidates", + matching_candidates.len() + ); + Ok(self .version_set_candidates .insert(version_set_id, matching_candidates)) @@ -197,10 +209,20 @@ impl SolverCache { match self.version_set_inverse_candidates.get(&version_set_id) { Some(candidates) => Ok(candidates), None => { - let package_name = self.provider.version_set_name(version_set_id); - let candidates = self.get_or_cache_candidates(package_name).await?; + let package_name_id = self.provider.version_set_name(version_set_id); - let matching_candidates = self + tracing::trace!( + "Getting NON-matching candidates for package: {:?}", + self.provider.display_name(package_name_id).to_string() + ); + + let candidates = self.get_or_cache_candidates(package_name_id).await?; + tracing::trace!( + "Got {:?} NON-matching candidates", + candidates.candidates.len() + ); + + let matching_candidates: Vec = self .provider .filter_candidates(&candidates.candidates, version_set_id, true) .await @@ -208,6 +230,11 @@ impl SolverCache { .map(Into::into) .collect(); + tracing::trace!( + "Filtered {:?} matching candidates", + matching_candidates.len() + ); + Ok(self .version_set_inverse_candidates .insert(version_set_id, matching_candidates)) @@ -227,11 +254,16 @@ impl SolverCache { match self.version_set_to_sorted_candidates.get(&version_set_id) { Some(candidates) => Ok(candidates), None => { - let package_name = self.provider.version_set_name(version_set_id); + let package_name_id = self.provider.version_set_name(version_set_id); + tracing::trace!( + "Getting sorted matching candidates for package: {:?}", + self.provider.display_name(package_name_id).to_string() + ); + let matching_candidates = self .get_or_cache_matching_candidates(version_set_id) .await?; - let candidates = self.get_or_cache_candidates(package_name).await?; + let candidates = self.get_or_cache_candidates(package_name_id).await?; // Sort all the candidates in order in which they should be tried by the solver. let mut sorted_candidates = Vec::new(); diff --git a/src/solver/clause.rs b/src/solver/clause.rs index 2e4ccce..5d7dca7 100644 --- a/src/solver/clause.rs +++ b/src/solver/clause.rs @@ -615,48 +615,56 @@ pub(crate) struct ClauseDisplay<'i, I: Interner> { impl<'i, I: Interner> Display for ClauseDisplay<'i, I> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self.kind { - Clause::InstallRoot => write!(f, "install root"), + Clause::InstallRoot => write!(f, "InstallRoot"), Clause::Excluded(solvable_id, reason) => { write!( f, - "{} excluded because: {}", + "Excluded({}({:?}), {})", solvable_id.display(self.interner), + solvable_id, self.interner.display_string(reason) ) } - Clause::Learnt(learnt_id) => write!(f, "learnt clause {learnt_id:?}"), + Clause::Learnt(learnt_id) => write!(f, "Learnt({learnt_id:?})"), Clause::Requires(solvable_id, version_set_id) => { write!( f, - "{} requires {} {}", + "Requires({}({:?}), {})", solvable_id.display(self.interner), - self.interner - .display_name(self.interner.version_set_name(version_set_id)), + solvable_id, self.interner.display_version_set(version_set_id) ) } Clause::Constrains(s1, s2, version_set_id) => { write!( f, - "{} excludes {} by {}", + "Constrains({}({:?}), {}({:?}), {})", s1.display(self.interner), + s1, s2.display(self.interner), - self.interner.display_version_set(version_set_id), + s2, + self.interner.display_version_set(version_set_id) ) } - Clause::Lock(locked, forbidden) => { + Clause::ForbidMultipleInstances(s1, s2, name) => { write!( f, - "{} is locked, so {} is forbidden", - locked.display(self.interner), - forbidden.display(self.interner), + "ForbidMultipleInstances({}({:?}), {}({:?}), {})", + s1.display(self.interner), + s1, + s2.var_id.display(self.interner), + s2, + self.interner.display_name(name) ) } - Clause::ForbidMultipleInstances(_, _, name_id) => { + Clause::Lock(locked, other) => { write!( f, - "only one {} allowed", - self.interner.display_name(name_id) + "Lock({}({:?}), {}({:?}))", + locked.display(self.interner), + locked, + other.display(self.interner), + other, ) } } diff --git a/src/solver/mod.rs b/src/solver/mod.rs index 91bcc11..ae4ed86 100644 --- a/src/solver/mod.rs +++ b/src/solver/mod.rs @@ -1,12 +1,12 @@ -use std::sync::atomic::{AtomicU32, Ordering}; -use std::{any::Any, cell::RefCell, collections::HashSet, future::ready, ops::ControlFlow}; - pub use cache::SolverCache; use clause::{Clause, ClauseState, Literal}; use decision::Decision; use decision_tracker::DecisionTracker; use futures::{stream::FuturesUnordered, FutureExt, StreamExt}; use itertools::{chain, Itertools}; +use std::fmt::Display; +use std::sync::atomic::{AtomicU32, Ordering}; +use std::{any::Any, cell::RefCell, collections::HashSet, future::ready, ops::ControlFlow}; use watch_map::WatchMap; use crate::{ @@ -110,11 +110,29 @@ impl From> for UnsolvableOrCancelled { } /// An error during the propagation step +#[derive(Debug)] pub(crate) enum PropagationError { Conflict(VarId, bool, ClauseId), Cancelled(Box), } +impl Display for PropagationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PropagationError::Conflict(solvable, value, clause) => { + write!( + f, + "conflict while propagating solvable {:?}, value {} caused by clause {:?}", + solvable, value, clause + ) + } + PropagationError::Cancelled(_) => { + write!(f, "propagation was cancelled") + } + } + } +} + impl Solver { /// Returns the dependency provider used by this instance. pub fn provider(&self) -> &D { @@ -171,7 +189,7 @@ impl Solver { // Run SAT self.run_sat()?; - let steps = self + let steps: Vec = self .decision_tracker .stack() .filter_map(|d| { @@ -186,6 +204,14 @@ impl Solver { .filter_map(InternalSolvableId::as_solvable) .collect(); + tracing::trace!("Solvables found:"); + for step in &steps { + tracing::trace!( + " - {}", + InternalSolvableId::from(*step).display(self.provider()) + ); + } + Ok(steps) } @@ -203,6 +229,8 @@ impl Solver { ) -> Result> { let mut output = AddClauseOutput::default(); + tracing::trace!("Add clauses for solvables"); + pub enum TaskResult<'i> { Dependencies { solvable_id: InternalSolvableId, @@ -321,7 +349,7 @@ impl Solver { let dependency_name = self.provider().version_set_name(version_set_id); if clauses_added_for_package.insert(dependency_name) { tracing::trace!( - "┝━ adding clauses for package '{}'", + "┝━ Adding clauses for package '{}'", self.provider().display_name(dependency_name), ); @@ -381,7 +409,7 @@ impl Solver { } => { // Get the solvable information and request its requirements and constraints tracing::trace!( - "package candidates available for {}", + "Package candidates available for {}", self.provider().display_name(name_id) ); @@ -488,7 +516,7 @@ impl Solver { candidates, } => { tracing::trace!( - "sorted candidates available for {} {}", + "Sorted candidates available for {} {}", self.provider() .display_name(self.provider().version_set_name(version_set_id)), self.provider().display_version_set(version_set_id), @@ -570,6 +598,8 @@ impl Solver { } } + tracing::trace!("Done adding clauses for solvables"); + Ok(output) } @@ -601,6 +631,12 @@ impl Solver { let mut level = 0; loop { + if level == 0 { + tracing::trace!("Level 0: Resetting the decision loop"); + } else { + tracing::trace!("Level {}: Starting the decision loop", level); + } + // A level of 0 means the decision loop has been completely reset because a // partial solution was invalidated by newly added clauses. if level == 0 { @@ -612,7 +648,7 @@ impl Solver { // were injected when calling `Solver::solve`. If we can find a // solution were the root is installable we found a // solution that satisfies the user requirements. - tracing::info!("╤══ install at level {level}",); + tracing::trace!("╤══ Install at level {level}",); self.decision_tracker .try_add_decision( Decision::new( @@ -629,15 +665,20 @@ impl Solver { .async_runtime .block_on(self.add_clauses_for_solvables(vec![InternalSolvableId::root()]))?; if let Err(clause_id) = self.process_add_clause_output(output) { + tracing::trace!("Unsolvable: {:?}", clause_id); return Err(UnsolvableOrCancelled::Unsolvable( self.analyze_unsolvable(clause_id), )); } } + tracing::trace!("Level {}: Propagating", level); + // Propagate decisions from assignments above let propagate_result = self.propagate(level); + tracing::trace!("Propagate result: {:?}", propagate_result); + // Handle propagation errors match propagate_result { Ok(()) => {} @@ -664,7 +705,9 @@ impl Solver { // Enter the solver loop, return immediately if no new assignments have been // made. + tracing::trace!("Level {}: Resolving dependencies", level); level = self.resolve_dependencies(level)?; + tracing::trace!("Level {}: Done resolving dependencies", level); // We have a partial solution. E.g. there is a solution that satisfies all the // clauses that have been added so far. @@ -689,11 +732,16 @@ impl Solver { if new_solvables.is_empty() { // If no new literals were selected this solution is complete and we can return. + tracing::trace!( + "Level {}: No new solvables selected, solution is complete", + level + ); return Ok(()); } + tracing::debug!("==== Found newly selected solvables"); tracing::debug!( - "====\n==Found newly selected solvables\n- {}\n====", + " - {}", new_solvables .iter() .copied() @@ -703,6 +751,7 @@ impl Solver { self.clauses.borrow()[derived_from].display(self.provider()), ))) ); + tracing::debug!("===="); // Concurrently get the solvable's clauses let output = self.async_runtime.block_on(self.add_clauses_for_solvables( @@ -711,7 +760,7 @@ impl Solver { // Serially process the outputs, to reduce the need for synchronization for &clause_id in &output.conflicting_clauses { - tracing::debug!("├─ added clause {clause} introduces a conflict which invalidates the partial solution", + tracing::debug!("├─ Added clause {clause} introduces a conflict which invalidates the partial solution", clause=self.clauses.borrow()[clause_id].display(self.provider())); } @@ -758,6 +807,8 @@ impl Solver { /// it was provided by the user, and set its value to true. fn resolve_dependencies(&mut self, mut level: u32) -> Result { loop { + tracing::trace!("Loop in resolve_dependencies: Level {}: Deciding", level); + // Make a decision. If no decision could be made it means the problem is // satisfyable. let Some((candidate, required_by, clause_id)) = self.decide() else { @@ -827,7 +878,7 @@ impl Solver { } if let Some((count, (candidate, _solvable_id, clause_id))) = best_decision { - tracing::info!( + tracing::trace!( "deciding to assign {}, ({}, {} possible candidates)", self.provider().display_solvable(candidate), self.clauses.borrow()[clause_id].display(self.provider()), @@ -864,7 +915,7 @@ impl Solver { ) -> Result { level += 1; - tracing::info!( + tracing::trace!( "╤══ Install {} at level {level} (required by {})", solvable.display(self.provider()), required_by.display(self.provider()) @@ -1005,7 +1056,7 @@ impl Solver { if decided { tracing::trace!( - "├─ Propagate assertion {} = {}", + "Negative assertions derived from other rules: Propagate assertion {} = {}", solvable_id.display(self.provider()), value ); diff --git a/tests/snapshots/solver__snapshot.snap b/tests/snapshots/solver__snapshot.snap new file mode 100644 index 0000000..224e308 --- /dev/null +++ b/tests/snapshots/solver__snapshot.snap @@ -0,0 +1,8 @@ +--- +source: tests/solver.rs +assertion_line: 1121 +expression: "solve_for_snapshot(snapshot_provider, &[menu_req])" +--- +dropdown=2 +icons=2 +menu=15 diff --git a/tests/solver.rs b/tests/solver.rs index b25f9f3..9a04c91 100644 --- a/tests/solver.rs +++ b/tests/solver.rs @@ -16,8 +16,10 @@ use std::{ use ahash::HashMap; use indexmap::IndexMap; +use insta::assert_snapshot; use itertools::Itertools; use resolvo::{ + snapshot::{DependencySnapshot, SnapshotProvider}, utils::{Pool, Range}, Candidates, Dependencies, DependencyProvider, Interner, KnownDependencies, NameId, SolvableId, Solver, SolverCache, StringId, UnsolvableOrCancelled, VersionSetId, @@ -152,7 +154,7 @@ impl FromStr for Spec { /// This provides sorting functionality for our `BundleBox` packaging system #[derive(Default)] struct BundleBoxProvider { - pool: Rc>>, + pool: Pool>, packages: IndexMap>, favored: HashMap, locked: HashMap, @@ -169,6 +171,7 @@ struct BundleBoxProvider { requested_dependencies: RefCell>, } +#[derive(Debug, Clone)] struct BundleBoxPackageDependencies { dependencies: Vec, constrains: Vec, @@ -179,6 +182,12 @@ impl BundleBoxProvider { Default::default() } + pub fn package_name(&self, name: &str) -> NameId { + self.pool + .lookup_package_name(&name.to_string()) + .expect("package missing") + } + pub fn requirements(&self, requirements: &[&str]) -> Vec { requirements .iter() @@ -223,6 +232,8 @@ impl BundleBoxProvider { dependencies: &[&str], constrains: &[&str], ) { + self.pool.intern_package_name(package_name); + let dependencies = dependencies .iter() .map(|dep| Spec::from_str(dep)) @@ -259,6 +270,15 @@ impl BundleBoxProvider { value } } + + pub fn into_snapshot(self) -> DependencySnapshot { + let name_ids = self + .packages + .keys() + .filter_map(|name| self.pool.lookup_package_name(name)) + .collect::>(); + DependencySnapshot::from_provider(self, name_ids, [], []).unwrap() + } } impl Interner for BundleBoxProvider { @@ -1089,3 +1109,57 @@ fn test_constraints() { b=1 "###); } + +#[test] +fn test_snapshot() { + let provider = BundleBoxProvider::from_packages(&[ + ("menu", 15, vec!["dropdown 2..3"]), + ("menu", 10, vec!["dropdown 1..2"]), + ("dropdown", 2, vec!["icons 2"]), + ("dropdown", 1, vec!["intl 3"]), + ("icons", 2, vec![]), + ("icons", 1, vec![]), + ("intl", 5, vec![]), + ("intl", 3, vec![]), + ]); + + let menu_name_id = provider.package_name("menu"); + + let snapshot = provider.into_snapshot(); + + #[cfg(feature = "serde")] + serialize_snapshot(&snapshot, "snapshot_pubgrub_menu.json"); + + let mut snapshot_provider = snapshot.provider(); + + let menu_req = snapshot_provider.add_package_requirement(menu_name_id); + + assert_snapshot!(solve_for_snapshot(snapshot_provider, &[menu_req])); +} + +#[cfg(feature = "serde")] +fn serialize_snapshot(snapshot: &DependencySnapshot, destination: impl AsRef) { + let file = std::io::BufWriter::new(std::fs::File::create(destination.as_ref()).unwrap()); + serde_json::to_writer_pretty(file, snapshot).unwrap() +} + +fn solve_for_snapshot(provider: SnapshotProvider, root_reqs: &[VersionSetId]) -> String { + let mut solver = Solver::new(provider); + match solver.solve(root_reqs.to_vec(), Vec::new()) { + Ok(solvables) => transaction_to_string(solver.provider(), &solvables), + Err(UnsolvableOrCancelled::Unsolvable(problem)) => { + // Write the problem graphviz to stderr + let graph = problem.graph(&solver); + let mut output = stderr(); + writeln!(output, "UNSOLVABLE:").unwrap(); + graph + .graphviz(&mut output, solver.provider(), true) + .unwrap(); + writeln!(output, "\n").unwrap(); + + // Format a user friendly error message + problem.display_user_friendly(&solver).to_string() + } + Err(UnsolvableOrCancelled::Cancelled(reason)) => *reason.downcast().unwrap(), + } +} diff --git a/tools/solve-snapshot/Cargo.toml b/tools/solve-snapshot/Cargo.toml new file mode 100644 index 0000000..6cefb05 --- /dev/null +++ b/tools/solve-snapshot/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "solve-snapshot" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +resolvo = { path = "../..", features = ["serde"] } +clap = { version = "4.5", features = ["derive"] } +csv = "1.3" +serde_json = "1.0" +serde = { version = "1.0.196", features = ["derive"] } diff --git a/tools/solve-snapshot/src/main.rs b/tools/solve-snapshot/src/main.rs new file mode 100644 index 0000000..0ae50d2 --- /dev/null +++ b/tools/solve-snapshot/src/main.rs @@ -0,0 +1,84 @@ +use std::{ + fs::File, + io::BufReader, + ops::Add, + time::{Duration, Instant, SystemTime}, +}; + +use clap::Parser; +use csv::WriterBuilder; +use resolvo::{snapshot::DependencySnapshot, Solver, UnsolvableOrCancelled}; + +#[derive(Parser)] +#[clap(version = "0.1.0", author = "Bas Zalmstra ")] +struct Opts { + snapshot: String, +} + +#[derive(Debug, serde::Serialize)] +struct Record { + package: String, + duration: f64, + error: Option, + records: Option, +} + +fn main() { + let opts: Opts = Opts::parse(); + + eprintln!("Loading snapshot ..."); + let snapshot_file = BufReader::new(File::open(&opts.snapshot).unwrap()); + let snapshot: DependencySnapshot = serde_json::from_reader(snapshot_file).unwrap(); + + let mut writer = WriterBuilder::new() + .has_headers(true) + .from_path("timings.csv") + .unwrap(); + + for (i, (package_name_id, package)) in snapshot.packages.iter().enumerate() { + eprint!( + "solving {} ({i}/{}) ... ", + &package.name, + snapshot.packages.len() + ); + let start = Instant::now(); + + let mut provider = snapshot + .provider() + .with_timeout(SystemTime::now().add(Duration::from_secs(60))); + let package_requirement = provider.add_package_requirement(package_name_id); + let mut solver = Solver::new(provider); + let mut records = None; + let mut error = None; + match solver.solve(vec![package_requirement], vec![]) { + Ok(solution) => { + eprintln!("OK"); + records = Some(solution.len()) + } + Err(UnsolvableOrCancelled::Unsolvable(problem)) => { + eprintln!("FAIL"); + error = Some(problem.display_user_friendly(&solver).to_string()); + } + Err(_) => { + eprintln!("CANCELLED"); + } + } + + let duration = start.elapsed(); + + writer + .serialize(Record { + package: package.name.clone(), + duration: duration.as_secs_f64(), + error, + records, + }) + .unwrap(); + + if i % 100 == 0 { + writer.flush().unwrap(); + } + } + + writer.flush().unwrap(); +}