diff --git a/.bazelignore b/.bazelignore
new file mode 100644
index 000000000..bc1620e4c
--- /dev/null
+++ b/.bazelignore
@@ -0,0 +1,5 @@
+.cache
+.venv
+docs/.site
+public
+target
diff --git a/.bazeliskrc b/.bazeliskrc
new file mode 100644
index 000000000..b2fd13d58
--- /dev/null
+++ b/.bazeliskrc
@@ -0,0 +1,2 @@
+# Bazelisk runs `bazel/bazel` in place of the Bazel release it fetched.
+BAZELISK_WRAPPER_DIRECTORY=bazel
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 000000000..f000c3531
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,5 @@
+# The output root is placed in `.cache` (see `bazel/shim.py`), and the repo contents cache cannot live in-tree.
+common --repo_contents_cache=
+
+# Keeps the convenience symlinks out of the repository root.
+build --symlink_prefix=.cache/bazel-
diff --git a/.bazelversion b/.bazelversion
new file mode 100644
index 000000000..47da986f8
--- /dev/null
+++ b/.bazelversion
@@ -0,0 +1 @@
+9.1.0
diff --git a/.cargo/mutants.toml b/.cargo/mutants.toml
index 3cea57009..5316c05fa 100644
--- a/.cargo/mutants.toml
+++ b/.cargo/mutants.toml
@@ -5,7 +5,7 @@ additional_cargo_test_args = [
"fail-fast",
]
build_timeout_multiplier = 5.0
-exclude_globs = ["pkgs/dev/**", "pkgs/pow/**"]
+exclude_globs = ["meta/dev/**", "pkgs/pow/**"]
features = ["full"]
gitignore = true
profile = "mutants"
diff --git a/.editorconfig b/.editorconfig
index 4bc07da6b..d935d28e5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,8 +11,14 @@ trim_trailing_whitespace = true
[*.Dockerfile]
indent_size = 4
+[*.bat]
+end_of_line = crlf
+
[*.md]
trim_trailing_whitespace = false
-[Justfile]
+[{Justfile,*.just}]
+indent_size = 4
+
+[{*.bzl,BUILD.bazel,MODULE.bazel}]
indent_size = 4
diff --git a/.gitattributes b/.gitattributes
index bd37aec13..4bc64229b 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,6 @@
* text=auto eol=lf
-fuzz/*/corpora/** binary linguist-generated
+*.bat text eol=crlf
+*.lock linguist-generated
+*.lock.yml linguist-generated
+*.rs diff=rust
+fuzz/*/corpora/** binary linguist-generated
diff --git a/.github/workflows/build_bazel.yml b/.github/workflows/build_bazel.yml
new file mode 100644
index 000000000..af6ba0260
--- /dev/null
+++ b/.github/workflows/build_bazel.yml
@@ -0,0 +1,55 @@
+name: Build with Bazel
+
+on:
+ push:
+ branches: [develop]
+ pull_request:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ contents: read
+
+jobs:
+ bazel:
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+ - ubuntu-24.04
+ - ubuntu-24.04-arm
+ - macos-latest
+ - macos-15-intel
+ - windows-latest
+
+ name: ${{ matrix.os }} (bazel)
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 1
+
+ - name: Install just
+ uses: taiki-e/install-action@v2
+ with:
+ tool: just
+
+ # Windows images ship Bazel beside Bazelisk, and either may come first.
+ - name: Uninstall Bazel
+ if: runner.os == 'Windows'
+ shell: pwsh
+ run: |
+ if (choco list bazel --exact --limit-output) {
+ choco uninstall bazel --yes --no-progress
+ }
+
+ - name: Build every target
+ run: just zbuild
+
+ - name: Check the output root
+ shell: bash
+ run: test -d .cache/bazel/install
diff --git a/.github/workflows/build_cross.yml b/.github/workflows/build_cross.yml
index da0de8475..22975fac6 100644
--- a/.github/workflows/build_cross.yml
+++ b/.github/workflows/build_cross.yml
@@ -41,7 +41,7 @@ jobs:
run: nix develop ./contrib/nix#dev --command true
- name: Validate toolchains
- run: nix develop ./contrib/nix#dev --command ./contrib/nix/smoke_test.sh
+ run: nix develop ./contrib/nix#dev --command ./contrib/smoke_test.py
build:
name: ${{ matrix.target }}
diff --git a/Cargo.lock b/Cargo.lock
index 49c4205bc..4e75755fb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -424,6 +424,10 @@ dependencies = [
"xxhash-rust",
]
+[[package]]
+name = "dash-meta-bazel"
+version = "0.0.0"
+
[[package]]
name = "dash-num"
version = "0.2.0-beta"
diff --git a/Cargo.toml b/Cargo.toml
index 971dcab8c..bef3fdf20 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
[workspace]
members = [
- "pkgs/dev",
+ "meta/bazel",
+ "meta/dev",
"pkgs/num",
"pkgs/params",
"pkgs/p2p_core",
diff --git a/Justfile b/Justfile
index 686da55b1..4112afd5f 100644
--- a/Justfile
+++ b/Justfile
@@ -8,6 +8,8 @@ export RUSTDOCFLAGS := "-D warnings"
mod fuzz "fuzz/mod.just"
+import "bazel/mod.just"
+
each := "cargo hack --workspace --exclude-features default --each-feature"
powerset := "cargo hack --workspace --exclude-features default --feature-powerset"
@@ -51,3 +53,6 @@ test:
{{ each }} test --doc
cargo doc --workspace --no-deps --features full
{{ each }} test --benches
+
+zbuild *flags:
+ bazel build {{ flags }} //...
diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 000000000..7df18876a
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,4 @@
+module(
+ name = "dash_base_sdk",
+ version = "0.0.0",
+)
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
new file mode 100644
index 000000000..23f8dcfbd
--- /dev/null
+++ b/MODULE.bazel.lock
@@ -0,0 +1,192 @@
+{
+ "lockFileVersion": 26,
+ "registryFileHashes": {
+ "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
+ "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c",
+ "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896",
+ "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
+ "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e",
+ "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1",
+ "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4",
+ "https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d",
+ "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
+ "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101",
+ "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
+ "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
+ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
+ "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a",
+ "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65",
+ "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
+ "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
+ "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
+ "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6",
+ "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
+ "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080",
+ "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb",
+ "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f",
+ "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd",
+ "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
+ "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
+ "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
+ "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
+ "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46",
+ "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000",
+ "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
+ "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
+ "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9",
+ "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
+ "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
+ "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
+ "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
+ "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
+ "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
+ "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
+ "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580",
+ "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96",
+ "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
+ "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
+ "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95",
+ "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
+ "https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d",
+ "https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42",
+ "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
+ "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a",
+ "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4",
+ "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
+ "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a",
+ "https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68",
+ "https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07",
+ "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642",
+ "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
+ "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
+ "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
+ "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
+ "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
+ "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
+ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
+ "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
+ "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
+ "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
+ "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
+ "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d",
+ "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6",
+ "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
+ "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
+ "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
+ "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
+ "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
+ "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
+ "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96",
+ "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e",
+ "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
+ "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
+ "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
+ "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
+ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
+ "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
+ "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
+ "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
+ "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6",
+ "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8",
+ "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8",
+ "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
+ "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
+ "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b",
+ "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c",
+ "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
+ "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046",
+ "https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd",
+ "https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400",
+ "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66",
+ "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
+ "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
+ "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
+ "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
+ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
+ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f",
+ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b",
+ "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
+ "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
+ "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
+ },
+ "selectedYankedVersions": {},
+ "moduleExtensions": {},
+ "facts": {}
+}
diff --git a/bazel/bazel b/bazel/bazel
new file mode 120000
index 000000000..3f3a0b1ea
--- /dev/null
+++ b/bazel/bazel
@@ -0,0 +1 @@
+shim.py
\ No newline at end of file
diff --git a/bazel/bazel.bat b/bazel/bazel.bat
new file mode 100644
index 000000000..f0750acf7
--- /dev/null
+++ b/bazel/bazel.bat
@@ -0,0 +1,3 @@
+@echo off
+python "%~dp0shim.py" %*
+exit /b %ERRORLEVEL%
diff --git a/bazel/mod.just b/bazel/mod.just
new file mode 100644
index 000000000..36e939e23
--- /dev/null
+++ b/bazel/mod.just
@@ -0,0 +1,4 @@
+# Bazel settings shared by the root and crate justfiles.
+
+# Read by bazelisk, which otherwise downloads Bazel into the user's cache.
+export BAZELISK_HOME := justfile_directory() + "/.cache/bazelisk"
diff --git a/bazel/shim.py b/bazel/shim.py
new file mode 100755
index 000000000..8c92f9197
--- /dev/null
+++ b/bazel/shim.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+# coding: latin-1
+
+#
+# Copyright (c) 2026-present, The Dash Core developers
+# SPDX-License-Identifier: MIT
+# See the accompanying file LICENSE or https://opensource.org/license/MIT
+#
+
+"""Shim that runs Bazel with its output root in `.cache/bazel`."""
+
+from __future__ import annotations
+
+import os
+import subprocess
+import sys
+from pathlib import Path
+
+OUTPUT_ROOT = Path(__file__).resolve().parents[1] / ".cache" / "bazel"
+
+
+def main() -> int:
+ real = os.environ.get("BAZEL_REAL")
+ if not real:
+ print("bazel: run bazelisk, which sets BAZEL_REAL", file=sys.stderr)
+ return 2
+ argv = [real, f"--output_user_root={OUTPUT_ROOT}", *sys.argv[1:]]
+ if os.name == "nt":
+ return subprocess.run(argv, check=False).returncode # noqa: S603
+ os.execv(real, argv) # noqa: S606
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/contrib/README.md b/contrib/README.md
index 1e43c618f..33a222606 100644
--- a/contrib/README.md
+++ b/contrib/README.md
@@ -100,6 +100,33 @@ cargo install --locked cargo-deny
sudo dnf install -y cargo-deny git just nodejs24
```
+## Bazel
+
+> [!NOTE]
+> Bazel isn't installed directly. Instead, [Bazelisk](https://github.com/bazelbuild/bazelisk) is installed as `bazel`,
+> which uses the version pinned by [`.bazelversion`](../.bazelversion). It is accompanied by
+> [buildifier](https://github.com/bazelbuild/buildtools), used to lint Starlark (the DSL used by Bazel) files.
+
+
+### macOS (with [Homebrew](https://brew.sh/))
+
+> [!WARNING]
+> `bazelisk` conflicts with the `bazel` formula. If the latter has been installed, it must be uninstalled first.
+
+```bash
+brew install bazelisk buildifier
+```
+
+
+### Linux/WSL
+
+Neither Bazelisk nor buildifier are available in official Debian or Fedora repositories. Both are published to the npm
+registry and can be installed with the `npm` CLI tool (a part of Node.js, an existing dependency).
+
+```bash
+npm install -g @bazel/bazelisk @bazel/buildifier
+```
+
diff --git a/contrib/docker/docker-compose.yml b/contrib/docker/docker-compose.yml
index 50bd9b970..544941b2e 100644
--- a/contrib/docker/docker-compose.yml
+++ b/contrib/docker/docker-compose.yml
@@ -34,6 +34,10 @@ services:
nix_daemon:
condition: "service_healthy"
init: true
+ # `fhs-run` uses bubblewrap, which needs user namespaces and unmasked procfs generally denied by Docker by default.
+ security_opt:
+ - "seccomp=unconfined"
+ - "systempaths=unconfined"
user: "${HOST_UID:-1000}:${HOST_GID:-1000}"
environment:
NIX_REMOTE: "daemon"
diff --git a/contrib/docker/entrypoint b/contrib/docker/entrypoint
index bba2dbcdf..ce8cd1998 100755
--- a/contrib/docker/entrypoint
+++ b/contrib/docker/entrypoint
@@ -26,7 +26,7 @@ if ! git rev-parse --git-dir > /dev/null 2>&1; then
fi
if (( $# > 0 )); then
- exec nix develop ./contrib/nix#dev --command "$@"
+ exec nix develop ./contrib/nix#dev --command fhs-run "$@"
else
- exec nix develop ./contrib/nix#dev
+ exec nix develop ./contrib/nix#dev --command fhs-run bash
fi
diff --git a/contrib/nix/flake.lock b/contrib/nix/flake.lock
index 13cdec4d7..fc49ffcff 100644
--- a/contrib/nix/flake.lock
+++ b/contrib/nix/flake.lock
@@ -16,6 +16,22 @@
"type": "github"
}
},
+ "nixpkgs-llvm": {
+ "locked": {
+ "lastModified": 1745533402,
+ "narHash": "sha256-gDcMJdnBJg7ncP+eqENwH9pOW0azcCOW5y50N+jKdL8=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "3e2cf88148e732abc1d259286123e06a9d8c964a",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "3e2cf88148e732abc1d259286123e06a9d8c964a",
+ "type": "github"
+ }
+ },
"nixpkgs-unstable": {
"locked": {
"lastModified": 1789632929,
@@ -81,6 +97,7 @@
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
+ "nixpkgs-llvm": "nixpkgs-llvm",
"nixpkgs-unstable": "nixpkgs-unstable",
"pyproject-build-systems": "pyproject-build-systems",
"pyproject-nix": "pyproject-nix",
diff --git a/contrib/nix/flake.nix b/contrib/nix/flake.nix
index 7d3b27de3..911c1ba43 100644
--- a/contrib/nix/flake.nix
+++ b/contrib/nix/flake.nix
@@ -8,6 +8,8 @@
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ nixpkgs-llvm.url = "github:NixOS/nixpkgs/3e2cf88148e732abc1d259286123e06a9d8c964a";
+
pyproject-build-systems = {
url = "github:pyproject-nix/build-system-pkgs";
inputs.nixpkgs.follows = "nixpkgs";
@@ -35,6 +37,7 @@
outputs =
{
nixpkgs,
+ nixpkgs-llvm,
nixpkgs-unstable,
rust-overlay,
...
@@ -63,18 +66,24 @@
inherit system;
config.allowUnfree = true;
};
+ llvm = (import nixpkgs-llvm { inherit system; }).llvmPackages_20;
}
);
in
{
devShells = eachSystem (
- { pkgs, unstable }:
+ {
+ pkgs,
+ unstable,
+ llvm,
+ }:
let
ctx = import ./shell/common.nix {
inherit
pkgs
lib
inputs
+ llvm
unstable
;
root = ../..;
diff --git a/contrib/nix/mods/bazel.nix b/contrib/nix/mods/bazel.nix
new file mode 100644
index 000000000..f6761d9db
--- /dev/null
+++ b/contrib/nix/mods/bazel.nix
@@ -0,0 +1,23 @@
+# Bazel through bazelisk, with buildifier.
+
+{ pkgs }:
+
+let
+ # nixpkgs builds Bazel from source, whose lockfiles differ from those of the
+ # release binaries. Bazelisk fetches the release hosts without Nix run too.
+ bazelisk = pkgs.writeShellScriptBin "bazel" ''
+ exec ${pkgs.bazelisk}/bin/bazelisk "$@"
+ '';
+in
+{
+ packages = [
+ bazelisk
+ pkgs.buildifier
+ ];
+
+ shellHook = ''
+ if root=$(git rev-parse --show-toplevel 2> /dev/null); then
+ export BAZELISK_HOME="$root/.cache/bazelisk"
+ fi
+ '';
+}
diff --git a/contrib/nix/mods/compiler_rt.nix b/contrib/nix/mods/compiler_rt.nix
new file mode 100644
index 000000000..69131f9cb
--- /dev/null
+++ b/contrib/nix/mods/compiler_rt.nix
@@ -0,0 +1,54 @@
+# The clang resource directory drivers compile and link with
+
+{ pkgs, llvm }:
+
+let
+ macos = pkgs.stdenvNoCC.mkDerivation {
+ pname = "macos-compiler-rt";
+ version = "20.1.3";
+
+ src = pkgs.fetchurl {
+ url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-20.1.3-hc6f8467_0.conda";
+ hash = "sha256-DNAy1cTVF7Toej8nY599YWBlvrtLhwtXbb4+LW2Lyzc=";
+ };
+
+ nativeBuildInputs = [
+ pkgs.unzip
+ pkgs.zstd
+ ];
+
+ # A `.conda` package is a zip holding the payload as a zstd tarball.
+ unpackPhase = ''
+ runHook preUnpack
+ unzip -q "$src" 'pkg-*.tar.zst'
+ mkdir payload
+ tar --zstd -xf pkg-*.tar.zst -C payload
+ runHook postUnpack
+ '';
+
+ dontConfigure = true;
+ dontBuild = true;
+
+ installPhase = ''
+ runHook preInstall
+ mkdir -p "$out"
+ cp -a payload/lib "$out/"
+ runHook postInstall
+ '';
+
+ # The fixup phase would treat target Mach-O archives as host binaries.
+ dontFixup = true;
+
+ meta.license = llvm.compiler-rt.meta.license;
+ };
+in
+pkgs.symlinkJoin {
+ name = "clang-resource-dir";
+ paths = [
+ # Supplies clang's builtin headers.
+ llvm.clang-unwrapped.lib
+ # nixpkgs builds compiler-rt for the host alone, while conda-forge's
+ # universal archives serve macOS targets from any host.
+ macos
+ ];
+}
diff --git a/contrib/nix/mods/cxx.nix b/contrib/nix/mods/cxx.nix
index 66b78482d..b65278ca3 100644
--- a/contrib/nix/mods/cxx.nix
+++ b/contrib/nix/mods/cxx.nix
@@ -3,15 +3,14 @@
{
pkgs,
lib,
+ llvm,
xcodeSdk ? null,
}:
let
- llvm = pkgs.llvmPackages_20;
-
# clang -print-resource-dir names the main output, but the builtin headers are
# split into .lib, so the flag has to be passed explicitly.
- resourceDir = "${llvm.clang-unwrapped.lib}/lib/clang/20";
+ resourceDir = "${import ./compiler_rt.nix { inherit pkgs llvm; }}/lib/clang/20";
# --ld-path names lld directly, where -fuse-ld=lld would find the nixpkgs
# bintools wrapper on PATH. Mach-O needs ld64.
@@ -85,7 +84,7 @@ let
darwinFlags =
_:
[
- "-isysroot ${xcodeSdk}"
+ "-isysroot ${xcodeSdk.sysroot}"
"-nostdlibinc"
"-iwithsysroot/usr/include"
"-iframeworkwithsysroot/System/Library/Frameworks"
@@ -208,7 +207,7 @@ in
# Adding clang to packages would not displace the cc-wrapper the default
# stdenv puts on PATH, so the shell is built against this stdenv instead.
compiler = {
- stdenv = llvm.stdenv;
+ stdenv = pkgs.overrideCC pkgs.stdenv llvm.clang;
packages = [ llvm.bintools ];
};
@@ -225,8 +224,9 @@ in
# both are set shell-wide rather than per target. A native macOS build
# has to resolve against the same pinned SDK as a cross target.
darwin = lib.optionalAttrs (lib.any (t: (defFor t).kind == "darwin") targets) {
+ MACOS_SDK_VERSION = xcodeSdk.sdkVersion;
MACOSX_DEPLOYMENT_TARGET = xcodeSdk.minVersion;
- SDKROOT = "${xcodeSdk}";
+ SDKROOT = xcodeSdk.sysroot;
};
in
{
diff --git a/contrib/nix/mods/fhs.nix b/contrib/nix/mods/fhs.nix
new file mode 100644
index 000000000..edb912585
--- /dev/null
+++ b/contrib/nix/mods/fhs.nix
@@ -0,0 +1,33 @@
+# An FHS layout like that of standard (non-NixOS) Linux distributions
+
+{ pkgs, lib }:
+
+let
+ run = pkgs.buildFHSEnv {
+ name = "fhs-run";
+ targetPkgs = p: [
+ p.bash
+ p.bzip2
+ p.coreutils
+ p.diffutils
+ p.file
+ p.findutils
+ p.gawk
+ p.gnugrep
+ p.gnused
+ p.gnutar
+ p.gzip
+ # The C and C++ runtimes a binary built against glibc expects.
+ p.stdenv.cc.cc.lib
+ p.unzip
+ p.which
+ p.xz
+ p.zlib
+ p.zstd
+ ];
+ runScript = "env";
+ };
+in
+{
+ packages = lib.optional pkgs.stdenv.hostPlatform.isLinux run;
+}
diff --git a/contrib/nix/mods/python.nix b/contrib/nix/mods/python.nix
index 5bd5ae253..d670eb05f 100644
--- a/contrib/nix/mods/python.nix
+++ b/contrib/nix/mods/python.nix
@@ -25,6 +25,12 @@ let
(old.nativeBuildInputs or [ ]) ++ final.resolveBuildSystem { setuptools = [ ]; };
});
+ # `lief` links the C++ runtime, `autoPatchelfHook` has to find it for Linux.
+ lief = prev.lief.overrideAttrs (old: {
+ buildInputs =
+ (old.buildInputs or [ ]) ++ lib.optional pkgs.stdenv.hostPlatform.isLinux pkgs.stdenv.cc.cc.lib;
+ });
+
# Narrow rebuild triggers to relevant files to avoid pulling in the whole
# source tree and thrashing the cache for it.
dash-base-sdk = prev.dash-base-sdk.overrideAttrs (_: {
diff --git a/contrib/nix/mods/xcode_sdk.nix b/contrib/nix/mods/xcode_sdk.nix
index 695e64270..db4e0f314 100644
--- a/contrib/nix/mods/xcode_sdk.nix
+++ b/contrib/nix/mods/xcode_sdk.nix
@@ -3,40 +3,127 @@
{ pkgs }:
let
+ inherit (pkgs) lib;
+
# Xcode release and build ID
version = "26.1.1-17B100";
-in
-pkgs.stdenvNoCC.mkDerivation {
- inherit version;
+ sdkVersion = "26.1";
- # Archive contains stubs and headers, nothing to configure, build or fix
- dontBuild = true;
- dontConfigure = true;
- dontFixup = true;
+ platform = "Platforms/MacOSX.platform";
+ sdks = "${platform}/Developer/SDKs";
+ sdk = "${sdks}/MacOSX${sdkVersion}.sdk";
+
+ # `xcrun` finds an SDK through the plists, which the archive lacks.
+ plist =
+ entries:
+ pkgs.writeText "Info.plist" ''
+
+
+
+ ${
+ lib.concatStrings (
+ lib.mapAttrsToList (key: value: " ${key}${value}\n") entries
+ )
+ }
+ '';
+ # clang reads the SDK version from `SDKSettings.json`. Without the file,
+ # binaries record the deployment target as their SDK version.
+ sdkSettings = pkgs.writeText "SDKSettings.json" (
+ builtins.toJSON {
+ CanonicalName = "macosx${sdkVersion}";
+ DefaultDeploymentTarget = sdkVersion;
+ DisplayName = "macOS ${sdkVersion}";
+ IsBaseSDK = "YES";
+ MaximumDeploymentTarget = "${sdkVersion}.99";
+ Version = sdkVersion;
+ SupportedTargets.macosx = {
+ Archs = [
+ "arm64"
+ "arm64e"
+ "x86_64"
+ "x86_64h"
+ ];
+ DefaultDeploymentTarget = sdkVersion;
+ LLVMTargetTripleSys = "macos";
+ LLVMTargetTripleVendor = "apple";
+ MaximumDeploymentTarget = "${sdkVersion}.99";
+ MinimumDeploymentTarget = "10.13";
+ };
+ }
+ );
+in
+
+pkgs.stdenvNoCC.mkDerivation (finalAttrs: {
pname = "xcode-sdk";
+ inherit version;
+
+ # The archive holds a bare sysroot, so `installPhase` builds the
+ # DEVELOPER_DIR around it.
src = pkgs.fetchurl {
url = "https://bitcoincore.org/depends-sources/sdks/Xcode-${version}-extracted-SDK-with-libcxx-headers.tar";
hash = "sha256-lgD6k2RN9nTukWteLIprqNrPYxmWpl3JItADuYteo7E=";
};
+ dontConfigure = true;
+ dontBuild = true;
+
installPhase = ''
runHook preInstall
- mkdir -p $out
- cp -a ./* $out/
+
+ mkdir -p "$out/${sdk}" "$out/Toolchains/XcodeDefault.xctoolchain"
+ cp -a ./* "$out/${sdk}/"
+ ln -s "MacOSX${sdkVersion}.sdk" "$out/${sdks}/MacOSX.sdk"
+
+ cp ${sdkSettings} "$out/${sdk}/SDKSettings.json"
+ cp ${
+ plist {
+ CanonicalName = "macosx${sdkVersion}";
+ DisplayName = "macOS ${sdkVersion}";
+ IsBaseSDK = "YES";
+ MaximumDeploymentTarget = "${sdkVersion}.99";
+ Version = sdkVersion;
+ }
+ } "$out/${sdk}/SDKSettings.plist"
+ cp ${
+ plist {
+ FamilyIdentifier = "macosx";
+ FamilyName = "macOS";
+ Identifier = "com.apple.platform.macosx";
+ Name = "macosx";
+ Type = "Platform";
+ Version = sdkVersion;
+ }
+ } "$out/${platform}/Info.plist"
+ cp ${
+ plist { Identifier = "com.apple.dt.toolchain.XcodeDefault"; }
+ } "$out/Toolchains/XcodeDefault.xctoolchain/ToolchainInfo.plist"
+
+ # Apple's `xcrun` accepts a DEVELOPER_DIR only if it holds `usr/bin/xcrun`.
+ ${lib.optionalString pkgs.stdenv.hostPlatform.isDarwin ''
+ mkdir -p "$out/usr/bin"
+ ln -s ${lib.getExe' pkgs.xcbuild "xcrun"} "$out/usr/bin/xcrun"
+ ''}
+
runHook postInstall
'';
+ # The fixup phase would treat target Mach-O stubs as host binaries.
+ dontFixup = true;
+
passthru = {
- # Target macOS version binaries are expected to support.
+ # `$out` is a DEVELOPER_DIR, so the sysroot is named separately.
+ sysroot = "${finalAttrs.finalPackage}/${sdk}";
+ inherit sdkVersion;
+ # The target deployment version (i.e. minimum macOS version).
minVersion = "14.0";
- # ld64 version clang is told to assume, as lld reports its own.
+ # lld is not ld64, and clang gates linker flags on its version.
linkerVersion = "711";
};
meta = {
description = "macOS SDK extracted from Xcode, with libc++ headers";
- license = pkgs.lib.licenses.unfree;
+ license = lib.licenses.unfree;
};
-}
+})
diff --git a/contrib/nix/shell/ci.nix b/contrib/nix/shell/ci.nix
index a881895ab..ff1219072 100644
--- a/contrib/nix/shell/ci.nix
+++ b/contrib/nix/shell/ci.nix
@@ -12,8 +12,10 @@
compose [
(cxx.forTargets crossTargets)
(cxx.forWasm commonTargets)
+ mods.bazel
mods.codeql
mods.cxx
+ mods.fhs
mods.nixpkgs
mods.python
mods.rust
diff --git a/contrib/nix/shell/common.nix b/contrib/nix/shell/common.nix
index d9fb98ef3..5fdc32716 100644
--- a/contrib/nix/shell/common.nix
+++ b/contrib/nix/shell/common.nix
@@ -4,6 +4,7 @@
pkgs,
lib,
inputs,
+ llvm,
root,
unstable,
}:
@@ -13,7 +14,7 @@ let
commonTargets = [ "wasm32-unknown-unknown" ];
cxx = import ../mods/cxx.nix {
- inherit pkgs lib;
+ inherit pkgs lib llvm;
xcodeSdk = import ../mods/xcode_sdk.nix { inherit pkgs; };
};
@@ -88,8 +89,10 @@ in
;
mods = lib.mapAttrs (name: m: m // { _name = name; }) {
+ bazel = import ../mods/bazel.nix { inherit pkgs; };
codeql = import ../mods/codeql.nix { inherit pkgs unstable; };
cxx = cxx.compiler;
+ fhs = import ../mods/fhs.nix { inherit pkgs lib; };
nixpkgs = import ../mods/nixpkgs.nix { inherit pkgs; };
python = import ../mods/python.nix {
inherit pkgs lib;
diff --git a/contrib/nix/smoke_test.sh b/contrib/nix/smoke_test.sh
deleted file mode 100755
index 82173a82b..000000000
--- a/contrib/nix/smoke_test.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env bash
-
-set -uo pipefail
-
-out="${1:-$(mktemp -d)}"
-mkdir -p "${out}"
-printf '#include \nint main(void) { puts("Hello, world!"); return 0; }\n' > "${out}/hello.c"
-printf '#include \nint main() { std::cout << "Hello, world!\\n"; }\n' > "${out}/hello.cpp"
-printf 'fn main() { println!("Hello, world!"); }\n' > "${out}/hello.rs"
-printf 'int add(int a, int b) { return a + b; }\n' > "${out}/free.c"
-
-status=0
-
-# `--macho` is a `llvm-objdump` flag, the GNU equivalent is unsupported.
-objdump=$(command -v llvm-objdump || command -v objdump || true)
-
-say() {
- printf ' %-26s %-4s %s\n' "$1" "$2" "$3"
-}
-
-produced() {
- local found=("${1}"*)
- [[ -e "${found[0]}" ]]
-}
-
-try() {
- local name="$1" lang="$2" bin="${out}/${1}.${2}" src="${out}/${SRC:-hello}.${2}"
- local want="${MACOSX_DEPLOYMENT_TARGET:-}" got kind
- shift 2
- if [[ -z "$1" ]]; then
- say "${name}" "${lang}" skipped
- return
- fi
- rm -f -- "${bin}"*
- if ! "$@" "${src}" -o "${bin}" || ! produced "${bin}"; then
- say "${name}" "${lang}" FAILED
- status=1
- return
- fi
- # An unreadable load command is a failure, not a reason to skip the check.
- if [[ "${name}" == *-apple-darwin ]]; then
- got=$("${objdump:-false}" --macho --private-headers "${bin}"* 2> /dev/null |
- awk '$1 == "minos" { print $2; exit }')
- if [[ -z "${want}" || "${got}" != "${want}" ]]; then
- say "${name}" "${lang}" "FAILED, minos ${got:-unknown}, wanted ${want:-}"
- status=1
- return
- fi
- fi
- kind=$(file -b "${bin}"* 2> /dev/null | head -1)
- say "${name}" "${lang}" "${kind:-built}"
-}
-
-try host c "${CC:-cc}"
-try host cpp "${CXX:-c++}"
-try host rs rustc
-
-for target in \
- aarch64-apple-darwin \
- x86_64-apple-darwin \
- aarch64-unknown-linux-gnu \
- x86_64-unknown-linux-gnu \
- x86_64-pc-windows-gnu \
- wasm32-unknown-unknown;
-do
- cc="CC_${target//-/_}"
- cxx="CXX_${target//-/_}"
- driver="${!cc:-}"
- rust="${driver:+rustc}"
- linker="${driver}"
- if [[ "${target}" == wasm32-* ]]; then
- # rustc links wasm32 with its own rust-lld.
- rust=rustc
- linker=
- SRC=free try "${target}" c "${driver}" -c
- else
- try "${target}" c "${driver}"
- fi
- try "${target}" cpp "${!cxx:-}"
- try "${target}" rs "${rust}" "--target=${target}" ${linker:+"-Clinker=${linker}"}
-done
-
-exit "${status}"
diff --git a/contrib/probes/free.c b/contrib/probes/free.c
new file mode 100644
index 000000000..2bca74961
--- /dev/null
+++ b/contrib/probes/free.c
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: CC0-1.0
+
+int add(int a, int b)
+{
+ return a + b;
+}
diff --git a/contrib/probes/hello.c b/contrib/probes/hello.c
new file mode 100644
index 000000000..386fd7d41
--- /dev/null
+++ b/contrib/probes/hello.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: CC0-1.0
+
+#if defined(_WIN32)
+#include
+#elif defined(__APPLE__)
+#include
+#include
+#include
+#elif defined(__linux__)
+#include
+#include
+#include
+#else
+#error "no system interface is known for this target"
+#endif
+
+static const char greeting[] = "Hello, world!\n";
+
+#if defined(_WIN32)
+static int say(const char* text, DWORD length)
+{
+ HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD written = 0;
+ return out != INVALID_HANDLE_VALUE && WriteFile(out, text, length, &written, NULL) && written == length;
+}
+#elif defined(__APPLE__)
+static int say(const char* text, size_t length)
+{
+ // Any Mach call proves the kernel headers and libSystem resolved.
+ if (mach_task_self() == MACH_PORT_NULL) {
+ return 0;
+ }
+ // Checking for a release past the deployment target calls into
+ // compiler-rt, which the SDK does not ship.
+ qos_class_t qos = QOS_CLASS_DEFAULT;
+ if (__builtin_available(macOS 15.0, *)) {
+ qos = QOS_CLASS_USER_INITIATED;
+ }
+ dispatch_queue_t queue = dispatch_get_global_queue(qos, 0);
+ dispatch_semaphore_t done = dispatch_semaphore_create(0);
+ dispatch_data_t data = dispatch_data_create(text, length, queue, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
+ __block int failed = 1;
+ dispatch_write(STDOUT_FILENO, data, queue, ^(dispatch_data_t rest, int error) {
+ failed = rest != NULL || error != 0;
+ dispatch_semaphore_signal(done);
+ });
+ dispatch_semaphore_wait(done, DISPATCH_TIME_FOREVER);
+ return !failed;
+}
+#elif defined(__linux__)
+_Static_assert(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0), "the UAPI headers predate Linux 5.10");
+
+static int say(const char* text, size_t length)
+{
+ return syscall(SYS_write, STDOUT_FILENO, text, length) == (long)length;
+}
+#endif
+
+int main(void)
+{
+ return say(greeting, sizeof(greeting) - 1) ? 0 : 1;
+}
diff --git a/contrib/probes/hello.cpp b/contrib/probes/hello.cpp
new file mode 100644
index 000000000..e5de6c701
--- /dev/null
+++ b/contrib/probes/hello.cpp
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: CC0-1.0
+
+#if defined(_WIN32)
+#include
+#elif defined(__APPLE__)
+#include
+#include
+#include
+#elif defined(__linux__)
+#include
+#include
+#include
+#else
+#error "no system interface is known for this target"
+#endif
+
+#include
+
+namespace {
+
+#if defined(_WIN32)
+bool say(const std::string& text)
+{
+ HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD written = 0;
+ const auto length = static_cast(text.size());
+ return out != INVALID_HANDLE_VALUE && WriteFile(out, text.data(), length, &written, nullptr) && written == length;
+}
+#elif defined(__APPLE__)
+bool say(const std::string& text)
+{
+ // Any Mach call proves the kernel headers and libSystem resolved.
+ if (mach_task_self() == MACH_PORT_NULL) {
+ return false;
+ }
+ // Checking for a release past the deployment target calls into
+ // compiler-rt, which the SDK does not ship.
+ qos_class_t qos = QOS_CLASS_DEFAULT;
+ if (__builtin_available(macOS 15.0, *)) {
+ qos = QOS_CLASS_USER_INITIATED;
+ }
+ dispatch_queue_t queue = dispatch_get_global_queue(qos, 0);
+ dispatch_semaphore_t done = dispatch_semaphore_create(0);
+ dispatch_data_t data = dispatch_data_create(text.data(), text.size(), queue, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
+ __block bool failed = true;
+ dispatch_write(STDOUT_FILENO, data, queue, ^(dispatch_data_t rest, int error) {
+ failed = rest != nullptr || error != 0;
+ dispatch_semaphore_signal(done);
+ });
+ dispatch_semaphore_wait(done, DISPATCH_TIME_FOREVER);
+ return !failed;
+}
+#elif defined(__linux__)
+static_assert(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0), "the UAPI headers predate Linux 5.10");
+
+bool say(const std::string& text)
+{
+ return syscall(SYS_write, STDOUT_FILENO, text.data(), text.size()) == static_cast(text.size());
+}
+#endif
+
+} // namespace
+
+int main()
+{
+ const std::string greeting = std::string("Hello") + ", world!\n";
+ return say(greeting) ? 0 : 1;
+}
diff --git a/contrib/smoke_test.py b/contrib/smoke_test.py
new file mode 100755
index 000000000..1fc0d075c
--- /dev/null
+++ b/contrib/smoke_test.py
@@ -0,0 +1,313 @@
+#!/usr/bin/env python3
+# coding: latin-1
+
+#
+# Copyright (c) 2026-present, The Dash Core developers
+# SPDX-License-Identifier: MIT
+# See the accompanying file LICENSE or https://opensource.org/license/MIT
+#
+
+"""Build and test a probe for every supported target.
+
+Usage:
+
+ nix develop ./contrib/nix#dev --command ./contrib/smoke_test.py
+ ./contrib/smoke_test.py --keep /tmp/smoke
+"""
+
+from __future__ import annotations
+
+import argparse
+import contextlib
+import dataclasses
+import os
+import platform
+import subprocess
+import sys
+import tempfile
+from dataclasses import dataclass
+from pathlib import Path
+
+import lief
+from common import (
+ RETCODE_ERR,
+ RETCODE_PASS,
+ format_table,
+)
+
+# What every host binary prints.
+GREETING = "Hello, world!"
+
+# Programs every toolchain builds, beside this script.
+PROBES = Path(__file__).resolve().parent / "probes"
+
+# Rust needs nothing beyond its own standard library to greet.
+HELLO_RS = 'fn main() { println!("Hello, world!"); }\n'
+
+# LIEF reads no WebAssembly, which is told apart by its magic and version.
+WASM_PREAMBLE = b"\0asm\x01\0\0\0"
+
+# Seconds a build or a probe may run before it counts as hung.
+TIMEOUT = 120
+
+# Each target the devshell may carry drivers for, with the format and
+# architecture its binaries must have. Mach-O versions come from the
+# environment.
+TARGETS = [
+ ("aarch64-apple-darwin", "Mach-O", "arm64"),
+ ("x86_64-apple-darwin", "Mach-O", "x86_64"),
+ ("aarch64-unknown-linux-gnu", "ELF", "arm64"),
+ ("x86_64-unknown-linux-gnu", "ELF", "x86_64"),
+ ("x86_64-pc-windows-gnu", "PE", "x86_64"),
+ ("wasm32-unknown-unknown", "wasm", "wasm32"),
+]
+
+
+@dataclass(frozen=True)
+class Kind:
+ """The format, architecture and Mach-O versions of a binary."""
+
+ fmt: str
+ arch: str
+ minos: str | None = None
+ sdk: str | None = None
+
+ def __str__(self) -> str:
+ minos = f", minos {self.minos}" if self.minos else ""
+ sdk = f", sdk {self.sdk}" if self.sdk else ""
+ return f"{self.fmt} {self.arch}{minos}{sdk}"
+
+ def satisfies(self, want: Kind) -> bool:
+ """Return whether this binary is what *want* asks for."""
+ same = (self.fmt, self.arch) == (want.fmt, want.arch)
+ minos = want.minos in (None, self.minos)
+ return same and minos and want.sdk in (None, self.sdk)
+
+ @staticmethod
+ def of(path: Path) -> Kind | None:
+ """Return the format and architecture *path* carries, or None."""
+ try:
+ with path.open("rb") as f:
+ if f.read(len(WASM_PREAMBLE)) == WASM_PREAMBLE:
+ return Kind("wasm", "wasm32")
+ except OSError:
+ return None
+
+ binary = lief.parse(str(path))
+ if binary is None:
+ return None
+ fmt = binary.format.name.replace("MACHO", "Mach-O")
+ arch = binary.abstract.header.architecture.name.lower()
+ minos = sdk = None
+ if isinstance(binary, lief.MachO.Binary) and binary.has_build_version:
+ minos = _version(binary.build_version.minos)
+ sdk = _version(binary.build_version.sdk)
+ return Kind(fmt, arch, minos, sdk)
+
+
+def _version(parts: list[int]) -> str:
+ """Return a Mach-O `major.minor.patch` version, dropping a zero patch."""
+ major, minor, patch = parts
+ return f"{major}.{minor}" + (f".{patch}" if patch else "")
+
+
+def _canonical(version: str | None) -> str | None:
+ """Return *version* as `_version` spells it, so `14` matches `14.0`."""
+ if not version:
+ return None
+ try:
+ parts = [int(part) for part in version.split(".")]
+ except ValueError:
+ return version
+ return _version([*parts, 0, 0][:3])
+
+
+class Report:
+ """Collects one row per binary and whether every row passed."""
+
+ def __init__(self) -> None:
+ self.rows: list[tuple[str, str, str]] = []
+ self.failed = False
+
+ def add(self, name: str, lang: str, result: str, *, ok: bool = True) -> None:
+ self.rows.append((name, lang, result if ok else f"FAILED, {result}"))
+ self.failed |= not ok
+
+ def held(
+ self, name: str, lang: str, path: Path, want: Kind, *, note: str = ""
+ ) -> bool:
+ """Record whether the binary at *path*, or with a suffix, is *want*."""
+ found = next(iter(_outputs(path)), None)
+ got = Kind.of(found) if found is not None else None
+ if got is None:
+ self.add(name, lang, "nothing recognisable was built", ok=False)
+ elif not got.satisfies(want):
+ self.add(name, lang, f"{got}, wanted {want}", ok=False)
+ else:
+ self.add(name, lang, f"{got}{note}")
+ return True
+ return False
+
+ def greets(self, name: str, lang: str, path: Path, want: Kind) -> None:
+ """Record whether the host binary at *path* is *want* and greets."""
+ try:
+ result = _run([str(path)])
+ except (OSError, subprocess.TimeoutExpired) as exc:
+ self.add(name, lang, _unfinished(exc), ok=False)
+ return
+ if result.returncode != 0:
+ self.add(name, lang, f"exited with {result.returncode}", ok=False)
+ return
+ if result.stdout.strip() != GREETING:
+ self.add(name, lang, "no greeting", ok=False)
+ return
+ self.held(name, lang, path, want, note=", ran")
+
+
+class Builder:
+ """Builds the probes into one directory and records each result."""
+
+ def __init__(self, report: Report, out: Path) -> None:
+ self.report = report
+ self.out = out
+ self.src = {
+ "c": PROBES / "hello.c",
+ "cpp": PROBES / "hello.cpp",
+ "rs": out / "hello.rs",
+ "free": PROBES / "free.c",
+ }
+ self.src["rs"].write_text(HELLO_RS, encoding="utf-8")
+
+ def build(self, name: str, lang: str, argv: list[str]) -> Path | None:
+ """Return the binary *argv* built, or None after recording why not."""
+ binary = self.out / f"{name}.{lang}"
+ for stale in _outputs(binary):
+ stale.unlink()
+ try:
+ result = _run([*argv, "-o", str(binary)])
+ except (OSError, subprocess.TimeoutExpired) as exc:
+ self.report.add(name, lang, _unfinished(exc), ok=False)
+ return None
+ if result.returncode != 0:
+ # The first error names the cause; the drivers' last line rarely does.
+ lines = result.stderr.strip().splitlines()
+ cause = next((ln for ln in lines if "error" in ln), None)
+ cause = cause or (lines[-1] if lines else "no output")
+ self.report.add(name, lang, cause, ok=False)
+ return None
+ return binary
+
+ def host(self) -> None:
+ """Build with the host compilers, then run what they built."""
+ want = host_kind()
+ for lang, compiler in (
+ ("c", os.environ.get("CC", "cc")),
+ ("cpp", os.environ.get("CXX", "c++")),
+ ("rs", "rustc"),
+ ):
+ binary = self.build("host", lang, [compiler, str(self.src[lang])])
+ if binary is not None:
+ self.report.greets("host", lang, binary, want)
+
+ def target(self, triple: str, want: Kind) -> None:
+ """Build with the drivers the devshell carries for *triple*."""
+ key = triple.replace("-", "_")
+ cc = os.environ.get(f"CC_{key}")
+ cxx = os.environ.get(f"CXX_{key}")
+ if want.fmt == "Mach-O":
+ minos = _canonical(os.environ.get("MACOSX_DEPLOYMENT_TARGET"))
+ # Set only when clang reads the version from `SDKSettings.json`.
+ sdk = _canonical(os.environ.get("MACOS_SDK_VERSION"))
+ if (cc or cxx) and not (minos and sdk):
+ unset = "MACOSX_DEPLOYMENT_TARGET" if not minos else "MACOS_SDK_VERSION"
+ self.report.add(triple, "all", f"no {unset}", ok=False)
+ return
+ want = dataclasses.replace(want, minos=minos, sdk=sdk)
+
+ rs = str(self.src["rs"])
+ # wasm32 has no libc to greet through, so it builds a bare object.
+ if want.fmt == "wasm":
+ free = str(self.src["free"])
+ langs = [("c", [cc, "-c", free] if cc else None), ("cpp", None)]
+ # rustc links wasm32 with its own rust-lld, so it needs no driver.
+ rust = ["rustc", f"--target={triple}", rs]
+ else:
+ langs = [
+ ("c", [cc, str(self.src["c"])] if cc else None),
+ ("cpp", [cxx, str(self.src["cpp"])] if cxx else None),
+ ]
+ rust = None
+ if cc:
+ rust = ["rustc", f"--target={triple}", f"-Clinker={cc}", rs]
+
+ for lang, argv in [*langs, ("rs", rust)]:
+ if argv is None:
+ self.report.add(triple, lang, "skipped")
+ continue
+ binary = self.build(triple, lang, argv)
+ if binary is not None:
+ self.report.held(triple, lang, binary, want)
+
+
+def _run(argv: list[str]) -> subprocess.CompletedProcess[str]:
+ return subprocess.run( # noqa: S603
+ argv, capture_output=True, check=False, text=True, timeout=TIMEOUT
+ )
+
+
+def _unfinished(exc: OSError | subprocess.TimeoutExpired) -> str:
+ """Return why a command never finished, for its report row."""
+ if isinstance(exc, subprocess.TimeoutExpired):
+ return f"timed out after {TIMEOUT}s"
+ return f"could not run, {(exc.strerror or str(exc)).lower()}"
+
+
+def _outputs(binary: Path) -> list[Path]:
+ """Return *binary* and any file a driver named after it plus a suffix."""
+ return sorted(
+ p
+ for p in binary.parent.glob(binary.name + "*")
+ if p.name == binary.name or p.name.startswith(binary.name + ".")
+ )
+
+
+def host_kind() -> Kind:
+ """Return what a binary built for the host is."""
+ machine = platform.machine().lower()
+ machine = {"aarch64": "arm64", "amd64": "x86_64"}.get(machine, machine)
+ fmt = "Mach-O" if platform.system() == "Darwin" else "ELF"
+ return Kind(fmt, machine)
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
+ parser.add_argument(
+ "--keep",
+ type=Path,
+ metavar="DIR",
+ help="build into DIR and keep it, instead of a temporary directory",
+ )
+ args = parser.parse_args()
+ lief.logging.disable()
+
+ report = Report()
+ scratch = (
+ contextlib.nullcontext(str(args.keep))
+ if args.keep
+ else tempfile.TemporaryDirectory(prefix="smoke-")
+ )
+ with scratch as where:
+ # Absolute, so running a host binary never searches PATH.
+ out = Path(where).resolve()
+ out.mkdir(parents=True, exist_ok=True)
+ builder = Builder(report, out)
+ builder.host()
+ for triple, fmt, arch in TARGETS:
+ builder.target(triple, Kind(fmt, arch))
+ print(format_table(("target", "lang", "result"), report.rows))
+
+ return RETCODE_ERR if report.failed else RETCODE_PASS
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/docs/dev/devshells.md b/docs/dev/devshells.md
index 097d6297a..dfe75b74b 100644
--- a/docs/dev/devshells.md
+++ b/docs/dev/devshells.md
@@ -22,6 +22,12 @@
then generate an updated lockfile by running `uv lock` in the shell. Then re-enter a fresh devshell, it should take on
the new definitions.
+* **Linux devshells expect a standard layout**
+
+ Binaries built for standard Linux systems look for dynamic loaders and libraries at paths NixOS leaves empty.
+ `fhs-run ` runs a command in an [FHS](https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html) layout
+ typical of Linux distributions, and `fhs-run bash` opens a shell in it. The Docker container enters it by default.
+
* **Pinned versions of tools don't match against manual setup**
Manual setup installs PyPI-sourced dependencies with `.dev`. Not every PyPI package is written in Python nor does it
diff --git a/maint/README.md b/maint/README.md
index e2ae40bcf..278fc9140 100644
--- a/maint/README.md
+++ b/maint/README.md
@@ -15,6 +15,7 @@ use [`lint_all.py`](./lint_all.py).
| Name | Purpose | Verbs | Depends on |
| ---- | ------- | ---------- | ---------- |
| [`lint_commit.py`](./lint/lint_commit.py) | Lint commit names against [`commit.toml`](./commit.toml) | `run` | `git` |
+| [`lint_bazel.py`](./lint/lint_bazel.py) | Lint Starlark files with `buildifier` | `check`, `apply`, `apply-all` | `buildifier` |
| [`lint_cargo.py`](./lint/lint_cargo.py) | Deny dependencies per [`deny.toml`](../.cargo/deny.toml), check/format TOML files against [`taplo.toml`](./taplo.toml) | `check` , `apply`, `apply-all` | `cargo-deny` (deny dependencies), `taplo` (TOML formatting) |
| [`lint_codeql.py`](./lint/lint_codeql.py) | Query Rust sources against [`maint/codeql/rust/*.ql`](./codeql/rust) | `check`, `apply`, `apply-all`, `run`, `run-all` | `codeql`, `rustc` |
| [`lint_javascript.py`](./lint/lint_javascript.py) | Lint Javascript sources against [`eslint.config.mjs`](js/eslint.config.mjs) | *None* | `npx` (part of Node.js), `eslint` (auto-retrieved by script) |
diff --git a/maint/codeql/rust/codeql-config.yml b/maint/codeql/rust/codeql-config.yml
index da2c0c08a..033dc18df 100644
--- a/maint/codeql/rust/codeql-config.yml
+++ b/maint/codeql/rust/codeql-config.yml
@@ -1,5 +1,6 @@
disable-default-queries: true
paths-ignore:
+ - .cache
- public
- target
queries:
diff --git a/maint/codeql/rust/lib/crates.qll b/maint/codeql/rust/lib/crates.qll
index 79ce18387..7b2473888 100644
--- a/maint/codeql/rust/lib/crates.qll
+++ b/maint/codeql/rust/lib/crates.qll
@@ -24,9 +24,9 @@ private string packageName(string segments) {
/** Holds if a crate directory named `crate` holds `f`. */
private predicate encloses(string crate, File f) {
exists(string path | path = f.getAbsolutePath() |
- crate = packageName(path.regexpCapture(".*/pkgs/([^/]+)/.*", 1))
+ crate = packageName(path.regexpCapture(".*/(?:meta|pkgs)/([^/]+)/.*", 1))
or
- crate = packageName(path.regexpCapture(".*/pkgs/([^/]+/[^/]+)/.*", 1))
+ crate = packageName(path.regexpCapture(".*/(?:meta|pkgs)/([^/]+/[^/]+)/.*", 1))
or
crate = packageName(path.regexpCapture(".*/fuzz/([^/]+)/.*", 1)) + "-fuzz"
)
diff --git a/maint/codeql/rust/lib/files.qll b/maint/codeql/rust/lib/files.qll
index 904597cd6..684b0decb 100644
--- a/maint/codeql/rust/lib/files.qll
+++ b/maint/codeql/rust/lib/files.qll
@@ -33,7 +33,7 @@ File fileOf(Locatable n) { result = n.getLocation().getFile() }
/** Materialises the repo-root-relative path for source files. */
pragma[nomagic]
predicate fileRelPath(File f, string relPath) {
- relPath = f.getAbsolutePath().regexpCapture(".*/(pkgs/.*)", 1)
+ relPath = f.getAbsolutePath().regexpCapture(".*/((?:meta|pkgs)/.*)", 1)
}
/** Holds if `f` belongs to a crate in this workspace. */
diff --git a/maint/codeql/rust/lib/filters.qll b/maint/codeql/rust/lib/filters.qll
index 5e37777b1..5b1714ed9 100644
--- a/maint/codeql/rust/lib/filters.qll
+++ b/maint/codeql/rust/lib/filters.qll
@@ -86,7 +86,7 @@ predicate hasLifetime(TypeItem t) {
string cratePrefix(TypeItem t) {
exists(string path |
path = fileOf(t).getAbsolutePath() and
- result = path.regexpCapture("(.*/pkgs/[^/]+/).*", 1)
+ result = path.regexpCapture("(.*/(?:meta|pkgs)/[^/]+/).*", 1)
)
}
diff --git a/maint/common.py b/maint/common.py
index 0a469d43b..4c0e2a3d0 100644
--- a/maint/common.py
+++ b/maint/common.py
@@ -36,7 +36,7 @@
CARGO_WORKSPACES: tuple[str, ...] = (".", "docs/samples", "fuzz")
# Rust source roots the analysers scan, relative to the repository root.
-SOURCE_DIRS: tuple[str, ...] = ("pkgs", "docs/samples", "fuzz")
+SOURCE_DIRS: tuple[str, ...] = ("meta", "pkgs", "docs/samples", "fuzz")
# Assumed base branch for codebase.
DEFAULT_BASE = "develop"
diff --git a/maint/lint/lint_bazel.py b/maint/lint/lint_bazel.py
new file mode 100755
index 000000000..e05eb2166
--- /dev/null
+++ b/maint/lint/lint_bazel.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+# coding: latin-1
+
+#
+# Copyright (c) 2026-present, The Dash Core developers
+# SPDX-License-Identifier: MIT
+# See the accompanying file LICENSE or https://opensource.org/license/MIT
+#
+
+"""Validate Bazel's build definitions (in Starlark) with buildifier."""
+
+from __future__ import annotations
+
+import sys
+from pathlib import Path
+
+from common import (
+ DEFAULT_BASE,
+ RETCODE_ERR,
+ RETCODE_SKIP,
+ declare_verbs,
+ formatted,
+ relay,
+ repo_files,
+ require_bin,
+ root_dir,
+ touched,
+)
+
+# Base name of this script (equivalent to argv[0]).
+SCRIPT = Path(__file__).stem
+
+# Spellings of a Starlark file buildifier understands.
+STARLARK_SUFFIXES: tuple[str, ...] = (".bazel", ".bzl")
+
+
+def _check_format(
+ repo_root: Path,
+ *,
+ fix: bool,
+ only: list[str] | None = None,
+) -> int | None:
+ """Format and lint Starlark, or None when buildifier is absent."""
+ try:
+ buildifier = require_bin("buildifier")
+ except FileNotFoundError as e:
+ print(f"{e}, skipping the Starlark check", file=sys.stderr)
+ return None
+
+ sources = (
+ repo_files(repo_root, *(f"*{s}" for s in STARLARK_SUFFIXES))
+ if only is None
+ else [Path(n) for n in only]
+ )
+ mode = "fix" if fix else "check"
+ return formatted(
+ SCRIPT,
+ "Starlark file",
+ sources,
+ lambda paths: [
+ buildifier,
+ f"--mode={mode}",
+ f"--lint={'fix' if fix else 'warn'}",
+ *[str(p) for p in paths],
+ ],
+ fix=fix,
+ scoped=only is not None,
+ cwd=repo_root,
+ output=lambda out, err: (
+ relay(out, repo_root),
+ relay(err, repo_root, stream=sys.stderr),
+ ),
+ )
+
+
+def main() -> int:
+ args = declare_verbs(
+ "Validate Starlark.",
+ {
+ "check": "report every Starlark fault, changing nothing",
+ "apply": f"also rewrite Starlark this branch changed vs {DEFAULT_BASE}",
+ "apply-all": "also rewrite every Starlark file in the tree",
+ },
+ ).parse_args(sys.argv[1:])
+ repo_root = root_dir()
+
+ fix = args.verb.startswith("apply")
+ only = touched(repo_root, STARLARK_SUFFIXES) if args.verb == "apply" else None
+ verdict = _check_format(repo_root, fix=fix, only=only)
+
+ return RETCODE_SKIP if verdict is None else verdict
+
+
+if __name__ == "__main__":
+ try:
+ sys.exit(main())
+ except Exception as exc: # noqa: BLE001
+ print(exc, file=sys.stderr)
+ sys.exit(RETCODE_ERR)
diff --git a/maint/lint/lint_cargo.py b/maint/lint/lint_cargo.py
index 9f5b2b98c..df415f181 100755
--- a/maint/lint/lint_cargo.py
+++ b/maint/lint/lint_cargo.py
@@ -9,8 +9,7 @@
"""Validate and enforce constraints across Rust's build system, cargo.
-Includes a TOML formatter using taplo that affects all TOML files regardless of
-provenance or origin, exclusions must be defined in 'maint/taplo.toml'
+taplo formats tracked TOML files except those excluded by 'maint/taplo.toml'.
"""
from __future__ import annotations
@@ -27,6 +26,7 @@
declare_verbs,
formatted,
relay,
+ repo_files,
require_bin,
root_dir,
touched,
@@ -60,12 +60,15 @@ def shorten(out: str, err: str) -> None:
drop=lambda line: line.lstrip().startswith("INFO"),
)
- # None, not an empty list: with no paths taplo finds its own through
- # 'maint/taplo.toml', so there is no count to report for the whole tree.
+ sources = (
+ repo_files(repo_root, "*.toml")
+ if only is None
+ else [Path(name) for name in only]
+ )
return formatted(
SCRIPT,
"TOML file",
- None if only is None else [Path(name) for name in only],
+ sources,
lambda paths: [
taplo, "fmt",
"--config", str(repo_root / "maint" / "taplo.toml"),
diff --git a/maint/lint/lint_symlinks.py b/maint/lint/lint_symlinks.py
index 799623062..78dddb621 100755
--- a/maint/lint/lint_symlinks.py
+++ b/maint/lint/lint_symlinks.py
@@ -15,7 +15,7 @@
- They must not dangle (i.e. point to non-existent resources)
- They must not have a depth >1 (i.e. cannot point to another symlink)
- They must not point to resources outside the repository (to prevent escapes)
-- They must not appear inside a crate directory (`pkgs/`)
+- They must not appear inside a publishable crate directory (`pkgs/`)
"""
from __future__ import annotations
@@ -109,7 +109,8 @@ def main() -> int:
faults.append(f"{path} -> {target}: {fault}")
elif path.startswith("pkgs/"):
faults.append(
- f"{path} -> {target}: symlink inside a crate directory is prohibited",
+ f"{path} -> {target}: symlink inside a publishable crate directory "
+ "is prohibited",
)
elif mode in _MODE_FILE:
fault = _hard_link_fault(repo_root, path)
diff --git a/maint/semgrep/rust/cargo.yml b/maint/semgrep/rust/cargo.yml
index 74f03eb5d..18c0721ec 100644
--- a/maint/semgrep/rust/cargo.yml
+++ b/maint/semgrep/rust/cargo.yml
@@ -4,6 +4,6 @@ rules:
severity: ERROR
languages: [generic]
paths:
- include: [/pkgs/**/Cargo.toml]
- exclude: [/pkgs/dev/Cargo.toml]
+ include: [/meta/**/Cargo.toml, /pkgs/**/Cargo.toml]
+ exclude: [/meta/dev/Cargo.toml]
pattern-regex: \b(serde[-_]json|json5)\b
diff --git a/maint/semgrep/rust/workspace.yml b/maint/semgrep/rust/workspace.yml
index 50e660b8f..0dee6a683 100644
--- a/maint/semgrep/rust/workspace.yml
+++ b/maint/semgrep/rust/workspace.yml
@@ -4,7 +4,7 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
pattern-regex: |-
(?xm)
^[ \t]* # line start, optional indent
@@ -19,13 +19,15 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs]
exclude:
- "**/lib.rs"
- "**/main.rs"
- "**/mod.rs"
- "**/build.rs"
+ - /meta/**/tests/**
- /pkgs/**/tests/**
+ - /meta/**/bench/**
- /pkgs/**/bench/**
pattern-regex: '(?m)^\s*#!\['
@@ -34,7 +36,7 @@ rules:
severity: ERROR
languages: [generic]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
exclude: ["**/lib.rs", "**/main.rs", "**/mod.rs"]
options:
generic_multiline: true
@@ -50,7 +52,7 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
patterns:
- pattern-regex: |-
(?xm)
@@ -81,7 +83,7 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
pattern-regex: 'derive\([^)]*(?\s+for\b'
- id: macro-export-no-serde-cfg
@@ -106,6 +108,7 @@ rules:
languages: [rust]
paths:
include:
+ - /meta/**/*.rs
- /pkgs/**/*.rs
exclude:
- /pkgs/types/marker/**
@@ -125,6 +128,7 @@ rules:
languages: [rust]
paths:
include:
+ - /meta/**/*.rs
- /pkgs/**/*.rs
exclude:
- /pkgs/types/marker/**
@@ -139,6 +143,7 @@ rules:
languages: [rust]
paths:
include:
+ - /meta/**/*.rs
- /pkgs/**/*.rs
exclude:
- /pkgs/types/marker/**
@@ -153,9 +158,11 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs]
exclude:
+ - /meta/**/prelude.rs
- /pkgs/**/prelude.rs
+ - /meta/**/prelude/mod.rs
- /pkgs/**/prelude/mod.rs
- /docs/samples/**
pattern-regex: '\buse\s+(::)?alloc(::|\s)'
@@ -165,9 +172,11 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs]
exclude:
+ - /meta/**/prelude.rs
- /pkgs/**/prelude.rs
+ - /meta/**/prelude/mod.rs
- /pkgs/**/prelude/mod.rs
- /docs/samples/**
pattern-regex: '\buse\s+crate::prelude::[^*]'
@@ -177,7 +186,7 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
patterns:
- pattern-either:
- pattern: |
@@ -193,8 +202,8 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
- exclude: [/pkgs/**/tests/**, /pkgs/**/bench/**]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ exclude: [/meta/**/tests/**, /meta/**/bench/**, /pkgs/**/tests/**, /pkgs/**/bench/**]
patterns:
- pattern-either:
- pattern: |
@@ -222,7 +231,7 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
pattern-regex: '^\s*//[/!]?\s*[-=]{4,}|^\s*//\s+--\s'
- id: style-latin1-source
@@ -230,7 +239,7 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
pattern-regex: '[^\x00-\xFF]'
- id: typeid-no-manual-impl
@@ -239,6 +248,7 @@ rules:
languages: [rust]
paths:
include:
+ - /meta/**/*.rs
- /pkgs/**/*.rs
- /docs/samples/**/*.rs
- /fuzz/**/*.rs
@@ -251,7 +261,7 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
exclude: ["**/lib.rs", "**/mod.rs"]
pattern-regex: '^\s*pub\s+use\s'
@@ -260,7 +270,7 @@ rules:
severity: ERROR
languages: [rust]
paths:
- include: [/pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
+ include: [/meta/**/*.rs, /pkgs/**/*.rs, /docs/samples/**/*.rs, /fuzz/**/*.rs]
exclude:
- /pkgs/types/src/entity.rs # declares the generator
- /pkgs/types/src/secret.rs # declares its secret sibling
diff --git a/meta/bazel/BUILD.bazel b/meta/bazel/BUILD.bazel
new file mode 100644
index 000000000..c0e902eab
--- /dev/null
+++ b/meta/bazel/BUILD.bazel
@@ -0,0 +1,5 @@
+# Exported for crate_universe, which resolves the crate graph from it.
+exports_files(
+ ["Cargo.toml"],
+ visibility = ["//visibility:public"],
+)
diff --git a/meta/bazel/Cargo.toml b/meta/bazel/Cargo.toml
new file mode 100644
index 000000000..9b50637c7
--- /dev/null
+++ b/meta/bazel/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "dash-meta-bazel"
+version = "0.0.0"
+description = "Crate used for dependency graph resolution by Bazel"
+publish = false
+authors.workspace = true
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+
+[lib]
+bench = false
+
+[features]
+default = []
+std = []
+full = ["std"]
+
+[lints]
+workspace = true
diff --git a/meta/bazel/src/lib.rs b/meta/bazel/src/lib.rs
new file mode 100644
index 000000000..b5b29cbd4
--- /dev/null
+++ b/meta/bazel/src/lib.rs
@@ -0,0 +1,13 @@
+//
+// Copyright (c) 2026-present, The Dash Core developers
+// SPDX-License-Identifier: MIT
+// See the accompanying file LICENSE or https://opensource.org/license/MIT
+//
+
+//! Anchor for the crate graph Bazel resolves.
+
+#![no_std]
+
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std;
diff --git a/pkgs/dev/Cargo.toml b/meta/dev/Cargo.toml
similarity index 77%
rename from pkgs/dev/Cargo.toml
rename to meta/dev/Cargo.toml
index a526d6c9e..fe7b25e08 100644
--- a/pkgs/dev/Cargo.toml
+++ b/meta/dev/Cargo.toml
@@ -50,7 +50,7 @@ bin = [
[build-dependencies]
built = { version = "0.7", features = ["dependency-tree", "git2"] }
-dash-types = { version = "0.2.0-beta", path = "../types", default-features = false, features = [
+dash-types = { version = "0.2.0-beta", path = "../../pkgs/types", default-features = false, features = [
"codec",
] }
proc-macro2 = "1"
@@ -60,13 +60,13 @@ xxhash-rust = { version = "0.8", features = ["xxh32"] }
[dependencies]
bitcoin-consensus-encoding = { workspace = true, features = ["alloc"] }
cfg-if = "1"
-dash-num = { version = "0.2.0-beta", path = "../num", optional = true, features = [
+dash-num = { version = "0.2.0-beta", path = "../../pkgs/num", optional = true, features = [
"codec",
] }
-dash-params = { version = "0.0.0", path = "../params", optional = true }
-dash-pow = { version = "0.1.0-beta", path = "../pow", default-features = false, optional = true }
-dash-primitives = { version = "0.0.0", path = "../primitives" }
-dash-types = { version = "0.2.0-beta", path = "../types", default-features = false, features = [
+dash-params = { version = "0.0.0", path = "../../pkgs/params", optional = true }
+dash-pow = { version = "0.1.0-beta", path = "../../pkgs/pow", default-features = false, optional = true }
+dash-primitives = { version = "0.0.0", path = "../../pkgs/primitives" }
+dash-types = { version = "0.2.0-beta", path = "../../pkgs/types", default-features = false, features = [
"codec",
] }
hex-conservative = { workspace = true, features = [
diff --git a/pkgs/dev/build.rs b/meta/dev/build.rs
similarity index 100%
rename from pkgs/dev/build.rs
rename to meta/dev/build.rs
diff --git a/pkgs/dev/src/bin/bsdk_util/bspcheck.rs b/meta/dev/src/bin/bsdk_util/bspcheck.rs
similarity index 100%
rename from pkgs/dev/src/bin/bsdk_util/bspcheck.rs
rename to meta/dev/src/bin/bsdk_util/bspcheck.rs
diff --git a/pkgs/dev/src/bin/bsdk_util/logging.rs b/meta/dev/src/bin/bsdk_util/logging.rs
similarity index 100%
rename from pkgs/dev/src/bin/bsdk_util/logging.rs
rename to meta/dev/src/bin/bsdk_util/logging.rs
diff --git a/pkgs/dev/src/bin/bsdk_util/main.rs b/meta/dev/src/bin/bsdk_util/main.rs
similarity index 100%
rename from pkgs/dev/src/bin/bsdk_util/main.rs
rename to meta/dev/src/bin/bsdk_util/main.rs
diff --git a/pkgs/dev/src/bin/bsdk_util/platform.rs b/meta/dev/src/bin/bsdk_util/platform.rs
similarity index 100%
rename from pkgs/dev/src/bin/bsdk_util/platform.rs
rename to meta/dev/src/bin/bsdk_util/platform.rs
diff --git a/pkgs/dev/src/bin/bsdk_util/policy.rs b/meta/dev/src/bin/bsdk_util/policy.rs
similarity index 100%
rename from pkgs/dev/src/bin/bsdk_util/policy.rs
rename to meta/dev/src/bin/bsdk_util/policy.rs
diff --git a/pkgs/dev/src/corpus.rs b/meta/dev/src/corpus.rs
similarity index 100%
rename from pkgs/dev/src/corpus.rs
rename to meta/dev/src/corpus.rs
diff --git a/pkgs/dev/src/encode.rs b/meta/dev/src/encode.rs
similarity index 100%
rename from pkgs/dev/src/encode.rs
rename to meta/dev/src/encode.rs
diff --git a/pkgs/dev/src/json.rs b/meta/dev/src/json.rs
similarity index 100%
rename from pkgs/dev/src/json.rs
rename to meta/dev/src/json.rs
diff --git a/pkgs/dev/src/lambda.rs b/meta/dev/src/lambda.rs
similarity index 100%
rename from pkgs/dev/src/lambda.rs
rename to meta/dev/src/lambda.rs
diff --git a/pkgs/dev/src/lib.rs b/meta/dev/src/lib.rs
similarity index 100%
rename from pkgs/dev/src/lib.rs
rename to meta/dev/src/lib.rs
diff --git a/pkgs/dev/src/prelude.rs b/meta/dev/src/prelude.rs
similarity index 100%
rename from pkgs/dev/src/prelude.rs
rename to meta/dev/src/prelude.rs
diff --git a/pkgs/num/Cargo.toml b/pkgs/num/Cargo.toml
index 8d6117513..3d9f8b978 100644
--- a/pkgs/num/Cargo.toml
+++ b/pkgs/num/Cargo.toml
@@ -61,7 +61,7 @@ serde = { workspace = true, features = [
], optional = true }
[dev-dependencies]
-dash-dev = { path = "../dev", features = ["full"] }
+dash-dev = { path = "../../meta/dev", features = ["full"] }
divan = { workspace = true }
rstest = { workspace = true }
serde = { workspace = true, features = ["derive", "std"] }
diff --git a/pkgs/p2p_core/Cargo.toml b/pkgs/p2p_core/Cargo.toml
index c4d231b5e..73f3870bc 100644
--- a/pkgs/p2p_core/Cargo.toml
+++ b/pkgs/p2p_core/Cargo.toml
@@ -54,7 +54,7 @@ serde = { workspace = true, features = [
thiserror = { workspace = true }
[dev-dependencies]
-dash-dev = { version = "0.0.0", path = "../dev", features = ["full"] }
+dash-dev = { version = "0.0.0", path = "../../meta/dev", features = ["full"] }
hex-conservative = { workspace = true, features = ["std"] }
rstest = { workspace = true }
serde = { workspace = true, features = ["derive", "std"] }
diff --git a/pkgs/pkc/Cargo.toml b/pkgs/pkc/Cargo.toml
index e10c6faab..aa67fe0db 100644
--- a/pkgs/pkc/Cargo.toml
+++ b/pkgs/pkc/Cargo.toml
@@ -62,7 +62,7 @@ zeroize = { workspace = true, features = ["alloc", "derive"] }
[dev-dependencies]
bitcoin-consensus-encoding = { workspace = true, features = ["alloc"] }
-dash-dev = { path = "../dev", features = ["full"] }
+dash-dev = { path = "../../meta/dev", features = ["full"] }
divan = { workspace = true }
getrandom = { version = "0.4", features = ["sys_rng"] }
hex-conservative = { workspace = true, features = ["std"] }
diff --git a/pkgs/pow/Cargo.toml b/pkgs/pow/Cargo.toml
index 8faca25d9..9d35d06be 100644
--- a/pkgs/pow/Cargo.toml
+++ b/pkgs/pow/Cargo.toml
@@ -41,7 +41,7 @@ digest = { workspace = true }
wide = { workspace = true }
[dev-dependencies]
-dash-dev = { path = "../dev", features = ["full"] }
+dash-dev = { path = "../../meta/dev", features = ["full"] }
divan = { workspace = true }
hex-conservative = { workspace = true }
rstest = { workspace = true }
diff --git a/pkgs/primitives/Cargo.toml b/pkgs/primitives/Cargo.toml
index 9da00480c..a85d06b47 100644
--- a/pkgs/primitives/Cargo.toml
+++ b/pkgs/primitives/Cargo.toml
@@ -66,7 +66,7 @@ serde = { workspace = true, features = [
thiserror = { workspace = true }
[dev-dependencies]
-dash-dev = { version = "0.0.0", path = "../dev", features = ["full"] }
+dash-dev = { version = "0.0.0", path = "../../meta/dev", features = ["full"] }
rstest = { workspace = true }
serde = { workspace = true, features = ["derive", "std"] }
diff --git a/pyproject.toml b/pyproject.toml
index b6afca52c..8576dcee0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,6 +6,7 @@ requires-python = ">=3.11"
[project.optional-dependencies]
dev = ["dash-base-sdk[tools,lib]"]
lib = [
+ "lief>=1.0",
"Markdown>=3.7",
"pygments-styles>=0.3.0",
"pymarkdownlnt>=0.9.37",
diff --git a/uv.lock b/uv.lock
index b6cc0a4a7..7e9ba213d 100644
--- a/uv.lock
+++ b/uv.lock
@@ -448,6 +448,7 @@ source = { editable = "." }
[package.optional-dependencies]
dev = [
+ { name = "lief" },
{ name = "markdown" },
{ name = "pygments-styles" },
{ name = "pymarkdownlnt" },
@@ -459,6 +460,7 @@ dev = [
{ name = "zensical" },
]
lib = [
+ { name = "lief" },
{ name = "markdown" },
{ name = "pygments-styles" },
{ name = "pymarkdownlnt" },
@@ -475,6 +477,7 @@ tools = [
[package.metadata]
requires-dist = [
{ name = "dash-base-sdk", extras = ["tools", "lib"], marker = "extra == 'dev'" },
+ { name = "lief", marker = "extra == 'lib'", specifier = ">=1.0" },
{ name = "markdown", marker = "extra == 'lib'", specifier = ">=3.7" },
{ name = "pygments-styles", marker = "extra == 'lib'", specifier = ">=0.3.0" },
{ name = "pymarkdownlnt", marker = "extra == 'lib'", specifier = ">=0.9.37" },
@@ -658,6 +661,66 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" },
]
+[[package]]
+name = "lief"
+version = "1.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0e/05/30df8a9af4f9b183b5e89373626cf019bd98f46fe52728ab74cacd31d76a/lief-1.0.0.tar.gz", hash = "sha256:811b2354f48fa08c49b106eafc9c1b26006371dc24d3d04bfdd9939863df6e6a", size = 7774, upload-time = "2026-07-12T14:12:09.152Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/21/64/300f5789ea54d4dcd6385132aee6b0bb6b135518b345bd2bc56949061e2d/lief-1.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e9037bda164285b2a59ee3910dfb70e775b2e3ba793edc565725e0bf926b09e9", size = 3286965, upload-time = "2026-07-12T14:10:22.129Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/7d/6b814a223c9e2a1a10bb476359488fb247921b38468251325b3e83f06bed/lief-1.0.0-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:2edb6c75944a90e1f9b6fb0e086844b7d00311344149f4007dd4f029476f8fe2", size = 3375351, upload-time = "2026-07-12T14:10:23.759Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/21/097f7f28157870491d648c65befd3a66163eb42f23bd12d1bbda59e94c5e/lief-1.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:95fb7dc84960068ab881bc681e646cab55f3d736c07bb07e91d5cbc8738885a7", size = 3610243, upload-time = "2026-07-12T14:10:25.303Z" },
+ { url = "https://files.pythonhosted.org/packages/92/2d/48a2713e5750cfd3ccd0e59662050b91273b1fbf09b4cad88a216335f947/lief-1.0.0-cp311-cp311-manylinux_2_28_i686.whl", hash = "sha256:ea1220b0b68a9b2cd6d1b3f05276c877d136f5b39e3a01d3433df70a92803071", size = 3753319, upload-time = "2026-07-12T14:10:27.022Z" },
+ { url = "https://files.pythonhosted.org/packages/0d/61/ca1a9d8ec16bc0075849cb4be47e7d5e5dae8d354d2ef32eb619ad204f8c/lief-1.0.0-cp311-cp311-manylinux_2_28_riscv64.whl", hash = "sha256:5aa92fa9501d60c0dbc8fe88d40fa9f19708fad958674eaea1b52cf4217e734d", size = 3693124, upload-time = "2026-07-12T14:10:28.497Z" },
+ { url = "https://files.pythonhosted.org/packages/09/b5/36e2ce60fcd60d2cc20f743ad50d437380c3f9f51d9b2942b230f0c05b72/lief-1.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:96277e45d58de45a33249079dac43e50db1c96da162fbe1ad02fbaa82e3bd06f", size = 3670339, upload-time = "2026-07-12T14:10:30.354Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/bf/bf9690141bb137bc99e94c38722a69ae2da428ad8c9e972136b28e5a56eb/lief-1.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:514ba1c9c94f0cd09986bfb1db71fd678acd19f826058fe9cefbba0e7b9a5d86", size = 3918692, upload-time = "2026-07-12T14:10:32.005Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/cb/54a449fa7590348c21022f6aba3544d4b576474a1a13d5187482eb0b6867/lief-1.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7ed5d9511cd7313bb56c95c4f580e8e332615ae0bd45e05b43990f1b563ceef3", size = 4196769, upload-time = "2026-07-12T14:10:34.106Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/58/5d09f19505daf08faf557a92f0af36ee5f1866bbdcc43977fd690c80f599/lief-1.0.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:37810cadad1fd796b6a681fe7eac084489103a7b2fed306776f9932b38c8d4ac", size = 3971579, upload-time = "2026-07-12T14:10:35.873Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/60/5440b2604553f95240b214549c73e29e9e7786f9b173a21fe5cc1fa833b2/lief-1.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:34d12d846529e5d5157a7feaf54d1bd8b6c2905cb6c46cc1f7c94fa9e9bd1f6a", size = 3963306, upload-time = "2026-07-12T14:10:37.592Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/07/0341a4de77c3a1b1223a7a996514b5995cb3b6ec7499d28ffadc5998fb59/lief-1.0.0-cp311-cp311-win32.whl", hash = "sha256:1a20cd029b539eb5888882b377617544da012e1bbb2ce575a524c87aaec1102b", size = 3722521, upload-time = "2026-07-12T14:22:41.152Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/b0/74f50ca24b9a70ba75e4eed3d1a5f3dbf0608965b7adaf98f3afd14db0e2/lief-1.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbaf64c338086da0a5d67b0e440b7010f2fd4b1d6edc68db303693759320ebfb", size = 4011319, upload-time = "2026-07-12T14:10:39.338Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/36/01f6b6ba1efce59b538e86b4c5abbc3cfc11b18ae88e974f0aace834737a/lief-1.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:a9b7bae94a3a160af9b52f15265e55a59a1f3bb305ae9280cfe9ce84cf2c5d0e", size = 3766358, upload-time = "2026-07-12T14:10:40.917Z" },
+ { url = "https://files.pythonhosted.org/packages/da/b0/9f231000f0b1d0d227fa4b3a6a66aff4d5168dcc642c697605e0df739b4f/lief-1.0.0-cp312-abi3-macosx_11_0_arm64.whl", hash = "sha256:92bf3b06c19a1ebd9e7978de47cc61040752ec452f7906bc3aac8d57abb23a8b", size = 3285262, upload-time = "2026-07-12T14:10:42.576Z" },
+ { url = "https://files.pythonhosted.org/packages/03/68/4eaec5e731fa53d764d60767037fccb4ca55d1f2cf1679edaa8ae0f3a07f/lief-1.0.0-cp312-abi3-macosx_11_0_x86_64.whl", hash = "sha256:48e360eea660d019312e377954f327e4fe0918781ee45e9056cd641f50bb6355", size = 3376474, upload-time = "2026-07-12T14:10:44.265Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/f8/3aba2989bd9f48e796de5260a19acb2af1e6562b147e32a2a26e418a9b58/lief-1.0.0-cp312-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a9e4b9e165bde0163624e159c8c7a096e3d6f671371c70d008baac7ac1f04f0d", size = 3604777, upload-time = "2026-07-12T14:10:46.006Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/f4/73adc62ede9d8159d7b3bde312270f9ce33886647caa183db24c4e804d7e/lief-1.0.0-cp312-abi3-manylinux_2_28_i686.whl", hash = "sha256:6b5d975f45e8830bc12da346d3dd317803d8852f1b61838e655741178e46d300", size = 3753256, upload-time = "2026-07-12T14:10:47.739Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/c1/b7093423a74b60f48a74c59c5cb84c20723a02484264c8b2d43662ef5761/lief-1.0.0-cp312-abi3-manylinux_2_28_riscv64.whl", hash = "sha256:5ab0c89879066a36467fb8b85485710e40ea982c90f46de3486d6633b1d43e2f", size = 3692596, upload-time = "2026-07-12T14:10:49.725Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/d7/6e8135da80a63d8ee413f169eda8c331817bf6f1496fc5647722b105aa19/lief-1.0.0-cp312-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:41ff868f5328fc8e5237a9e1f4718590e0ee9180c1422b3e4948b7116ba4517c", size = 3674893, upload-time = "2026-07-12T14:10:51.489Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/06/3b7f72f9fad8d36631aa6ba4a92edab9241806502b4d5d01f345aeb435f8/lief-1.0.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:30c48bb32afdcea98df04cd456e7199e84a629396faf475ca9c8880a4b4c1ce3", size = 3913123, upload-time = "2026-07-12T14:10:53.055Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/67/ec0046772e0c40a1274c42034382e93c26e33157ea917aa2ff4ba9b8be2b/lief-1.0.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:f58e26e2e4d110cd6a42d86ab497cd4bedc47d72690fae557023ac536d85edcc", size = 4197779, upload-time = "2026-07-12T14:10:54.789Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/50/554f682a5feb40ccf0663679bcbb479d7d4f6381d516d42859a9ead39f41/lief-1.0.0-cp312-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:f6c2007bf96704cedc5cee8ae303ba7008840b9a2214ca9f4f43a6faa703834f", size = 3972848, upload-time = "2026-07-12T14:10:56.402Z" },
+ { url = "https://files.pythonhosted.org/packages/da/ca/b113461f25a01a9165713de7f4ac7518ea21fb6e3939971d16d56a469c10/lief-1.0.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:714c96894048f15c8fcecbe6ef4a95416a0f256a20cc6130f8f2398ee717ca06", size = 3969432, upload-time = "2026-07-12T14:10:58.093Z" },
+ { url = "https://files.pythonhosted.org/packages/87/e5/b7bcab0256eb2f15d71652d5578f338b4cac1629a35b5bef2607f41d0be9/lief-1.0.0-cp312-abi3-win32.whl", hash = "sha256:d552235f6c7b999b1837946b61cc64537501fac4fda1663c2cb76482b27b609f", size = 3720709, upload-time = "2026-07-12T14:22:43.058Z" },
+ { url = "https://files.pythonhosted.org/packages/83/16/950c16d246c52a32b47aca19ade2919dfc9192cc4c45c92635c36d3a8b6b/lief-1.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:ca7774b0d88f4528a1c153d7a9d2798800d6389847b966861fad9f2edb17a593", size = 4018974, upload-time = "2026-07-12T14:10:59.857Z" },
+ { url = "https://files.pythonhosted.org/packages/91/2a/cc514b5ec9ec187335f2e8ab545d7b110a5f931d430a0bd2917563aefae4/lief-1.0.0-cp312-abi3-win_arm64.whl", hash = "sha256:956ee963e2a2ed318d08fd9fe4ff948906c483db1b88f7a62dac24db76ffa4b0", size = 3771788, upload-time = "2026-07-12T14:11:01.607Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/0e/e8fb688a7f282bc8fca82448c0e590fbba67ae754b29b4746d1aaa51ce46/lief-1.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:23253bbc154ff0dc5253a8929a2a407d11d459694c409d053b93308e623125ff", size = 3349507, upload-time = "2026-07-12T14:11:03.309Z" },
+ { url = "https://files.pythonhosted.org/packages/63/96/c7d4ea1e4f43f53be57d979244bd6426aa94b059d1f3cebd8bcc46bf6222/lief-1.0.0-cp314-cp314t-macosx_11_0_x86_64.whl", hash = "sha256:ecd440475e677c6834af996d34a2babbad1af6a3addaaa3822fd021972c41311", size = 3432213, upload-time = "2026-07-12T14:11:05.041Z" },
+ { url = "https://files.pythonhosted.org/packages/13/4d/58f8947e7459c2089abb03d6f63b9c12a5a9e103fed571ac43869ef8313d/lief-1.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:0e4c0934c27bea29752bdac494c2611c676d27d54139c96098f57b22d065deeb", size = 3664092, upload-time = "2026-07-12T14:11:06.62Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/1e/679f32b5ffee1d370358d5e94c030d047b409873489d2049365c15356d04/lief-1.0.0-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:4d2f1565110abc06070c0f6dcababab64606721fd1401477857558d9575ad663", size = 3805718, upload-time = "2026-07-12T14:11:08.336Z" },
+ { url = "https://files.pythonhosted.org/packages/c7/05/f65b1ab1eb0e345dbbad62407ba9f8d82acf19268b8c1aff9e5355f5e7ca/lief-1.0.0-cp314-cp314t-manylinux_2_28_riscv64.whl", hash = "sha256:25ea4a80545eb4d1ffe75f49fceca526ce85130bd263bcd81a0fa66178ab1e7f", size = 3750775, upload-time = "2026-07-12T14:11:10.312Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/85/02e39735843ed44572126575deda5c9ebcb614412132afeeba5b8a2a3ed4/lief-1.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:18b05ce0244be151c58fedbd8b08687ed69713533cab9af23060a73f4441e847", size = 3731535, upload-time = "2026-07-12T14:11:12.064Z" },
+ { url = "https://files.pythonhosted.org/packages/64/45/0664acd97c955380cf40f1ae00f33cc6f4e01373cde4782986d54d17aac7/lief-1.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:26777c1ec1ac55d3b981cad0fdb61d38de21da4b83810d637a5f4d0190470bf6", size = 3975553, upload-time = "2026-07-12T14:11:13.868Z" },
+ { url = "https://files.pythonhosted.org/packages/be/ee/4a3ee9db6cba043a5579f939ffacda1c7825f49907221eae911358982aae/lief-1.0.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5881e7698fb9b7ea6398dc86db78c6ae65331d7473c713d5a24318e264048334", size = 4250798, upload-time = "2026-07-12T14:11:15.617Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/80/86ecc653817067d945ef92577a58d27aa359b9f2038c69e457b710b1560a/lief-1.0.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6be55884009b1eea2314c6d918a945c8bc72584928957771956b600fdcecaa19", size = 4029644, upload-time = "2026-07-12T14:11:17.164Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/af/cd42f2569b35af9744d2832f0f9698a73ed5b8aebfc5056dab69b0c2732a/lief-1.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f12816bb3d4781fdc98db4df312a8da744c5a93f587fa4919124fcb9b277d510", size = 4027250, upload-time = "2026-07-12T14:11:19.333Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/4d/0797e4e048179c31400322a2765a30f9dd11d1c968b829578b909452566f/lief-1.0.0-cp314-cp314t-win32.whl", hash = "sha256:b5f954b86f6c99437a461ed794bbc2d5e003e6a24e462b49f4978bce228b3801", size = 3787154, upload-time = "2026-07-12T14:22:44.99Z" },
+ { url = "https://files.pythonhosted.org/packages/13/51/b80054950752fd581c60f9c01fbca3f700a3fdd47307d0f6ae19714bb550/lief-1.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:4680aeaa0eb9f21540f37ab5f97820fdf8f08b9c67c42b4435e232ca8cc22a27", size = 4073853, upload-time = "2026-07-12T14:11:21.286Z" },
+ { url = "https://files.pythonhosted.org/packages/03/c5/3e8dab85764e5eafa8812ef5914acde47981d01c131084bcbdda9893c449/lief-1.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:7677a7b8fffd4de096d7ca1db64d1a6c3007e02650ed256fb93b2f3f9ea74097", size = 3804579, upload-time = "2026-07-12T14:11:23.349Z" },
+ { url = "https://files.pythonhosted.org/packages/08/43/760246b541ccb5e8c30195ad8a2870ba00a37fb010585d6a63a6aac8ad91/lief-1.0.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:47c60ba68c3a1f53d872bb004a4e7d2a6f2572372d79a362fa3bd3369f5b8945", size = 3349476, upload-time = "2026-07-12T14:11:25.766Z" },
+ { url = "https://files.pythonhosted.org/packages/da/2d/d0800b3f0aceb65388a236628c20e58d781abe71a17448307e8746b0c11f/lief-1.0.0-cp315-cp315t-macosx_11_0_x86_64.whl", hash = "sha256:caad33b4fe1eebf8d18acac3a8e2bbfc10f89706f7555e459e6d2588eb8f80fd", size = 3432749, upload-time = "2026-07-12T14:11:27.823Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/16/3e10313c41726a2a72beb6b9e63d20537f18cf1b1509a31d0b4e58169272/lief-1.0.0-cp315-cp315t-manylinux_2_28_aarch64.whl", hash = "sha256:23f42c7f4ae2df5492eb3a4ed449a2ae16bec107d9baf987bd618fde1ce53564", size = 3663917, upload-time = "2026-07-12T14:11:29.574Z" },
+ { url = "https://files.pythonhosted.org/packages/24/31/12545f5a978e9018d95d6f8ccc97253ddffeb5d54101cc02f3c92a9f339a/lief-1.0.0-cp315-cp315t-manylinux_2_28_i686.whl", hash = "sha256:980aeaff59734b48927b3f9a2915c7d834c16d75d9a36a581e4f0dbd082481a8", size = 3805856, upload-time = "2026-07-12T14:11:31.498Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/eb/6541a331c98e490381818ae461e3a02ae12f033661b9f41887b76e09d702/lief-1.0.0-cp315-cp315t-manylinux_2_28_riscv64.whl", hash = "sha256:6a02dcd93c9dba14d3f007bc3a2a84ebf2706b704a5ab32ea6bf71987d4a9f5b", size = 3750666, upload-time = "2026-07-12T14:11:33.565Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/98/b8c18c255e66845ae60dbec0df6fdb38a0d7f07518c7be73f1b3d38b50dd/lief-1.0.0-cp315-cp315t-manylinux_2_28_x86_64.whl", hash = "sha256:fcaf9a28f004bc5f49637dd1a5cdfb8f937feb58febb5f70ebec29c0c1c3584c", size = 3731457, upload-time = "2026-07-12T14:11:36.2Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/4a/d8f2eb1f1ad1541fdb0c1508f610b49e8edb7dd39b74a53e882675e36da6/lief-1.0.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:4e6ae6b3bfd4bc4b2f8a805d0dc74b00de9da173d9a4b2bd581d774bb2cdd19d", size = 3975439, upload-time = "2026-07-12T14:11:37.962Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/74/a33c39eace7d326641ba058edc98c4c9045ef02e43a75002663707db0613/lief-1.0.0-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:2ee72db426d304a37d7bcfe246de3ea1e524ff95104c39f132b88835e6408fa6", size = 4250339, upload-time = "2026-07-12T14:11:39.695Z" },
+ { url = "https://files.pythonhosted.org/packages/76/88/997c8880adf63e116d2eddf2062fe517baed454a154a3d49b149776033d5/lief-1.0.0-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:0628dea883631d33a84498e79c96e9cffff24ed898f9204d139ab1a51e079478", size = 4029632, upload-time = "2026-07-12T14:11:42.178Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/5a/8592eba660355fa299919f7aef4c18dad330d1172b2303d3f0a59ac82409/lief-1.0.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:5f7f187745c81a81231d9785bed73bae90f495531c5ea40449370e37441b45a2", size = 4027501, upload-time = "2026-07-12T14:11:43.979Z" },
+ { url = "https://files.pythonhosted.org/packages/46/72/2755e9afde286bef1a1501b02a1025487bcac0ad857be6e24f8ab22d5ab9/lief-1.0.0-cp315-cp315t-win32.whl", hash = "sha256:7a9c376fd607a9480777d0928ae37fd48547937b3a54bb5d130512061e5e953c", size = 3787315, upload-time = "2026-07-12T14:22:46.611Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/46/bd2e04e3b8afa0a7068d80218add90ebb9a4b90fbad60987312d934d7a9f/lief-1.0.0-cp315-cp315t-win_amd64.whl", hash = "sha256:4d49b2fa555163692dbecba147a55847abf641fee3c6d72315db14d084b4a160", size = 4073797, upload-time = "2026-07-12T14:11:45.671Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/ce/dea3c1f1a2c04b6de4a8040bd16c5a081d06db8ea18e15dc715988b8df58/lief-1.0.0-cp315-cp315t-win_arm64.whl", hash = "sha256:580e786d72fc34a0402b0af66ed755e668293946705b8193b766c501f00bc448", size = 3804488, upload-time = "2026-07-12T14:11:47.346Z" },
+]
+
[[package]]
name = "markdown"
version = "3.10.3"