From 4d11c0bf2920f3e413cdcb25f0eef0558641b635 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Sun, 18 Jan 2026 17:09:27 -0800 Subject: [PATCH 1/3] Add integration test for external relative path deps (issue #3089) This test reproduces the bug where crate_universe fails when a Cargo workspace member has a path dependency pointing outside the Cargo workspace root (but still inside the Bazel workspace). The test is expected to fail until the bug is fixed. --- .bazelci/presubmit.yml | 6 + .../external_relative_path_deps/.bazelversion | 1 + .../external_relative_path_deps/.gitignore | 1 + .../external_relative_path_deps/BUILD.bazel | 1 + .../external_relative_path_deps/MODULE.bazel | 38 ++ .../MODULE.bazel.lock | 382 ++++++++++++++++++ .../external_relative_path_deps/README.md | 40 ++ .../WORKSPACE.bazel | 1 + .../cargo_workspace/BUILD.bazel | 4 + .../cargo_workspace/Cargo.lock | 14 + .../cargo_workspace/Cargo.toml | 3 + .../cargo_workspace/member/BUILD.bazel | 16 + .../cargo_workspace/member/Cargo.toml | 11 + .../cargo_workspace/member/src/lib.rs | 6 + .../external_crate/Cargo.toml | 6 + .../external_crate/src/lib.rs | 4 + 16 files changed, 534 insertions(+) create mode 100644 test/integration/external_relative_path_deps/.bazelversion create mode 100644 test/integration/external_relative_path_deps/.gitignore create mode 100644 test/integration/external_relative_path_deps/BUILD.bazel create mode 100644 test/integration/external_relative_path_deps/MODULE.bazel create mode 100644 test/integration/external_relative_path_deps/MODULE.bazel.lock create mode 100644 test/integration/external_relative_path_deps/README.md create mode 100644 test/integration/external_relative_path_deps/WORKSPACE.bazel create mode 100644 test/integration/external_relative_path_deps/cargo_workspace/BUILD.bazel create mode 100644 test/integration/external_relative_path_deps/cargo_workspace/Cargo.lock create mode 100644 test/integration/external_relative_path_deps/cargo_workspace/Cargo.toml create mode 100644 test/integration/external_relative_path_deps/cargo_workspace/member/BUILD.bazel create mode 100644 test/integration/external_relative_path_deps/cargo_workspace/member/Cargo.toml create mode 100644 test/integration/external_relative_path_deps/cargo_workspace/member/src/lib.rs create mode 100644 test/integration/external_relative_path_deps/external_crate/Cargo.toml create mode 100644 test/integration/external_relative_path_deps/external_crate/src/lib.rs diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 5763e9d4f1..b569f0cd82 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -637,6 +637,12 @@ tasks: build_targets: - "@rust_toolchains//:all" - "//..." + external_relative_path_deps: + name: External relative path deps (issue 3089) + platform: ubuntu2204 + working_directory: test/integration/external_relative_path_deps + build_targets: + - "//..." android_examples_ubuntu2204: name: Android Examples platform: ubuntu2204 diff --git a/test/integration/external_relative_path_deps/.bazelversion b/test/integration/external_relative_path_deps/.bazelversion new file mode 100644 index 0000000000..ae9a76b924 --- /dev/null +++ b/test/integration/external_relative_path_deps/.bazelversion @@ -0,0 +1 @@ +8.0.0 diff --git a/test/integration/external_relative_path_deps/.gitignore b/test/integration/external_relative_path_deps/.gitignore new file mode 100644 index 0000000000..a6ef824c1f --- /dev/null +++ b/test/integration/external_relative_path_deps/.gitignore @@ -0,0 +1 @@ +/bazel-* diff --git a/test/integration/external_relative_path_deps/BUILD.bazel b/test/integration/external_relative_path_deps/BUILD.bazel new file mode 100644 index 0000000000..820fa8f26d --- /dev/null +++ b/test/integration/external_relative_path_deps/BUILD.bazel @@ -0,0 +1 @@ +# Empty BUILD file for workspace root diff --git a/test/integration/external_relative_path_deps/MODULE.bazel b/test/integration/external_relative_path_deps/MODULE.bazel new file mode 100644 index 0000000000..e6da5e5f1e --- /dev/null +++ b/test/integration/external_relative_path_deps/MODULE.bazel @@ -0,0 +1,38 @@ +"""Test for external relative path dependencies (issue #3089)""" + +module( + name = "external_relative_path_deps_test", + version = "0.0.0", +) + +bazel_dep(name = "rules_rust", version = "0.0.0") +local_path_override( + module_name = "rules_rust", + path = "../../..", +) + +rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") +rust.toolchain(edition = "2021") +use_repo(rust, "rust_toolchains") + +register_toolchains("@rust_toolchains//:all") + +# Test: crate_universe with Cargo workspace where a member has a path dependency +# that goes OUTSIDE the Cargo workspace root (but still inside the Bazel workspace). +# +# Structure: +# external_crate/ <- Outside Cargo workspace +# cargo_workspace/ <- Cargo workspace root +# Cargo.toml <- [workspace] members = ["member"] +# member/ +# Cargo.toml <- external_crate = { path = "../../external_crate" } +# +# This should work but currently fails because crate_universe doesn't copy +# the external path dependency into the temp splicing directory. +crate = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate") +crate.from_cargo( + name = "crates", + cargo_lockfile = "//cargo_workspace:Cargo.lock", + manifests = ["//cargo_workspace:Cargo.toml"], +) +use_repo(crate, "crates") diff --git a/test/integration/external_relative_path_deps/MODULE.bazel.lock b/test/integration/external_relative_path_deps/MODULE.bazel.lock new file mode 100644 index 0000000000..3f76cb589e --- /dev/null +++ b/test/integration/external_relative_path_deps/MODULE.bazel.lock @@ -0,0 +1,382 @@ +{ + "lockFileVersion": 16, + "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.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da", + "https://bcr.bazel.build/modules/apple_support/1.24.1/MODULE.bazel": "f46e8ddad60aef170ee92b2f3d00ef66c147ceafea68b6877cb45bd91737f5f8", + "https://bcr.bazel.build/modules/apple_support/1.24.1/source.json": "cf725267cbacc5f028ef13bb77e7f2c2e0066923a4dab1025e4a0511b1ed258a", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "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.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.32.0/MODULE.bazel": "095d67022a58cb20f7e20e1aefecfa65257a222c18a938e2914fd257b5f1ccdc", + "https://bcr.bazel.build/modules/bazel_features/1.32.0/source.json": "2546c766986a6541f0bacd3e8542a1f621e2b14a80ea9e88c6f89f7eedf64ae1", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "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.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", + "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", + "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "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.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "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/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", + "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4", + "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_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.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac", + "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.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.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", + "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", + "https://bcr.bazel.build/modules/rules_cc/0.2.8/source.json": "85087982aca15f31307bd52698316b28faa31bd2c3095a41f456afec0131344c", + "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_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", + "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.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", + "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", + "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.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", + "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", + "https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960", + "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/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", + "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", + "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.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", + "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.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", + "https://bcr.bazel.build/modules/rules_python/0.40.0/source.json": "939d4bd2e3110f27bfb360292986bb79fd8dcefb874358ccd6cdaa7bda029320", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "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/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.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", + "https://bcr.bazel.build/modules/stardoc/0.7.1/source.json": "b6500ffcd7b48cd72c29bb67bcac781e12701cc0d6d55d266a652583cfcdab01", + "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.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" + }, + "selectedYankedVersions": {}, + "moduleExtensions": { + "@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": { + "general": { + "bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=", + "usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "compatibility_proxy": { + "repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule", + "attributes": {} + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_java+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { + "general": { + "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=", + "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "com_github_jetbrains_kotlin_git": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", + "attributes": { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" + ], + "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" + } + }, + "com_github_jetbrains_kotlin": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository", + "attributes": { + "git_repository_name": "com_github_jetbrains_kotlin_git", + "compiler_version": "1.9.23" + } + }, + "com_github_google_ksp": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository", + "attributes": { + "urls": [ + "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" + ], + "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", + "strip_version": "1.9.23-1.0.20" + } + }, + "com_github_pinterest_ktlint": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", + "urls": [ + "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" + ], + "executable": true + } + }, + "rules_android": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + "strip_prefix": "rules_android-0.1.1", + "urls": [ + "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_kotlin+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_rust+//crate_universe/private:internal_extensions.bzl%cu_nr": { + "general": { + "bzlTransitiveDigest": "h9wcsupr1TvM+IjSqO1m9hZWrBFbgwAqak9LCEhtav8=", + "usagesDigest": "oUK0ytEbfl+CaIzEjRqZCnsb5eUCZOx9usreQy09/3o=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "cargo_bazel_bootstrap": { + "repoRuleId": "@@rules_rust+//cargo/private:cargo_bootstrap.bzl%cargo_bootstrap_repository", + "attributes": { + "srcs": [ + "@@rules_rust+//crate_universe:src/api.rs", + "@@rules_rust+//crate_universe:src/api/lockfile.rs", + "@@rules_rust+//crate_universe:src/cli.rs", + "@@rules_rust+//crate_universe:src/cli/generate.rs", + "@@rules_rust+//crate_universe:src/cli/query.rs", + "@@rules_rust+//crate_universe:src/cli/render.rs", + "@@rules_rust+//crate_universe:src/cli/splice.rs", + "@@rules_rust+//crate_universe:src/cli/vendor.rs", + "@@rules_rust+//crate_universe:src/config.rs", + "@@rules_rust+//crate_universe:src/context.rs", + "@@rules_rust+//crate_universe:src/context/crate_context.rs", + "@@rules_rust+//crate_universe:src/context/platforms.rs", + "@@rules_rust+//crate_universe:src/lib.rs", + "@@rules_rust+//crate_universe:src/lockfile.rs", + "@@rules_rust+//crate_universe:src/main.rs", + "@@rules_rust+//crate_universe:src/metadata.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_bin.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_resolver.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_rustc_wrapper.bat", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_rustc_wrapper.sh", + "@@rules_rust+//crate_universe:src/metadata/dependency.rs", + "@@rules_rust+//crate_universe:src/metadata/metadata_annotation.rs", + "@@rules_rust+//crate_universe:src/rendering.rs", + "@@rules_rust+//crate_universe:src/rendering/template_engine.rs", + "@@rules_rust+//crate_universe:src/rendering/templates/module_bzl.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/header.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/aliases_map.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/deps_map.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/repo_git.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/repo_http.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/vendor_module.j2", + "@@rules_rust+//crate_universe:src/rendering/verbatim/alias_rules.bzl", + "@@rules_rust+//crate_universe:src/select.rs", + "@@rules_rust+//crate_universe:src/splicing.rs", + "@@rules_rust+//crate_universe:src/splicing/cargo_config.rs", + "@@rules_rust+//crate_universe:src/splicing/crate_index_lookup.rs", + "@@rules_rust+//crate_universe:src/splicing/splicer.rs", + "@@rules_rust+//crate_universe:src/test.rs", + "@@rules_rust+//crate_universe:src/utils.rs", + "@@rules_rust+//crate_universe:src/utils/starlark.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/glob.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/label.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_dict.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_list.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_scalar.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_set.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/serialize.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/target_compatible_with.rs", + "@@rules_rust+//crate_universe:src/utils/symlink.rs", + "@@rules_rust+//crate_universe:src/utils/target_triple.rs" + ], + "binary": "cargo-bazel", + "cargo_lockfile": "@@rules_rust+//crate_universe:Cargo.lock", + "cargo_toml": "@@rules_rust+//crate_universe:Cargo.toml", + "version": "1.86.0", + "timeout": 900, + "rust_toolchain_cargo_template": "@rust_host_tools//:bin/{tool}", + "rust_toolchain_rustc_template": "@rust_host_tools//:bin/{tool}", + "compressed_windows_toolchain_names": false + } + } + }, + "moduleExtensionMetadata": { + "explicitRootModuleDirectDeps": [ + "cargo_bazel_bootstrap" + ], + "explicitRootModuleDirectDevDeps": [], + "useAllRepos": "NO", + "reproducible": false + }, + "recordedRepoMappingEntries": [ + [ + "bazel_features+", + "bazel_features_globals", + "bazel_features++version_extension+bazel_features_globals" + ], + [ + "bazel_features+", + "bazel_features_version", + "bazel_features++version_extension+bazel_features_version" + ], + [ + "rules_cc+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_cc+", + "rules_cc", + "rules_cc+" + ], + [ + "rules_rust+", + "bazel_features", + "bazel_features+" + ], + [ + "rules_rust+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "rules_rust+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_rust+", + "cargo_bazel_bootstrap", + "rules_rust++cu_nr+cargo_bazel_bootstrap" + ], + [ + "rules_rust+", + "cui", + "rules_rust++cu+cui" + ], + [ + "rules_rust+", + "rrc", + "rules_rust++i2+rrc" + ], + [ + "rules_rust+", + "rules_cc", + "rules_cc+" + ], + [ + "rules_rust+", + "rules_rust", + "rules_rust+" + ] + ] + } + } + } +} diff --git a/test/integration/external_relative_path_deps/README.md b/test/integration/external_relative_path_deps/README.md new file mode 100644 index 0000000000..6609bf7398 --- /dev/null +++ b/test/integration/external_relative_path_deps/README.md @@ -0,0 +1,40 @@ +# External Relative Path Dependencies Test (Issue #3089) + +This test validates that crate_universe correctly handles Cargo workspace members +with path dependencies that point **outside the Cargo workspace root** (but still +inside the Bazel workspace). + +## Structure + +``` +external_relative_path_deps/ # Bazel workspace root +├── MODULE.bazel +├── BUILD.bazel +├── external_crate/ # Outside Cargo workspace, inside Bazel workspace +│ ├── Cargo.toml +│ └── src/lib.rs +└── cargo_workspace/ # Cargo workspace root + ├── Cargo.toml # [workspace] with members = ["member"] + ├── Cargo.lock + └── member/ + ├── Cargo.toml # Has path = "../../external_crate" + └── src/lib.rs +``` + +## The Bug + +When `cargo_workspace/member/Cargo.toml` has: +```toml +[dependencies] +external_crate = { path = "../../external_crate" } +``` + +crate_universe fails because it doesn't copy `external_crate` into the temp +directory used for splicing. + +## Running the test + +```sh +cd test/integration/external_relative_path_deps +bazel build //cargo_workspace/member +``` diff --git a/test/integration/external_relative_path_deps/WORKSPACE.bazel b/test/integration/external_relative_path_deps/WORKSPACE.bazel new file mode 100644 index 0000000000..5e304c5b2b --- /dev/null +++ b/test/integration/external_relative_path_deps/WORKSPACE.bazel @@ -0,0 +1 @@ +# Empty WORKSPACE for Bazel compatibility diff --git a/test/integration/external_relative_path_deps/cargo_workspace/BUILD.bazel b/test/integration/external_relative_path_deps/cargo_workspace/BUILD.bazel new file mode 100644 index 0000000000..969e08488f --- /dev/null +++ b/test/integration/external_relative_path_deps/cargo_workspace/BUILD.bazel @@ -0,0 +1,4 @@ +exports_files([ + "Cargo.toml", + "Cargo.lock", +]) diff --git a/test/integration/external_relative_path_deps/cargo_workspace/Cargo.lock b/test/integration/external_relative_path_deps/cargo_workspace/Cargo.lock new file mode 100644 index 0000000000..72137c2db5 --- /dev/null +++ b/test/integration/external_relative_path_deps/cargo_workspace/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "external_crate" +version = "0.1.0" + +[[package]] +name = "member" +version = "0.1.0" +dependencies = [ + "external_crate", +] diff --git a/test/integration/external_relative_path_deps/cargo_workspace/Cargo.toml b/test/integration/external_relative_path_deps/cargo_workspace/Cargo.toml new file mode 100644 index 0000000000..515ce5ab6c --- /dev/null +++ b/test/integration/external_relative_path_deps/cargo_workspace/Cargo.toml @@ -0,0 +1,3 @@ +[workspace] +members = ["member"] +resolver = "2" diff --git a/test/integration/external_relative_path_deps/cargo_workspace/member/BUILD.bazel b/test/integration/external_relative_path_deps/cargo_workspace/member/BUILD.bazel new file mode 100644 index 0000000000..16ba0e1055 --- /dev/null +++ b/test/integration/external_relative_path_deps/cargo_workspace/member/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") + +rust_library( + name = "member", + srcs = ["src/lib.rs"], + deps = [ + # The external_crate dependency should be resolved by crate_universe + # even though it's located outside the Cargo workspace via path = "../../external_crate" + "@crates//:external_crate", + ], +) + +rust_test( + name = "member_test", + crate = ":member", +) diff --git a/test/integration/external_relative_path_deps/cargo_workspace/member/Cargo.toml b/test/integration/external_relative_path_deps/cargo_workspace/member/Cargo.toml new file mode 100644 index 0000000000..fa32f4bbb8 --- /dev/null +++ b/test/integration/external_relative_path_deps/cargo_workspace/member/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "member" +version = "0.1.0" +edition = "2021" + +[lib] + +[dependencies] +# This path dependency goes OUTSIDE the Cargo workspace root. +# This is the scenario from issue #3089. +external_crate = { path = "../../external_crate" } diff --git a/test/integration/external_relative_path_deps/cargo_workspace/member/src/lib.rs b/test/integration/external_relative_path_deps/cargo_workspace/member/src/lib.rs new file mode 100644 index 0000000000..eab873163a --- /dev/null +++ b/test/integration/external_relative_path_deps/cargo_workspace/member/src/lib.rs @@ -0,0 +1,6 @@ +use external_crate; + +/// Re-exports the greeting from external_crate. +pub fn say_hello() -> &'static str { + external_crate::greet() +} diff --git a/test/integration/external_relative_path_deps/external_crate/Cargo.toml b/test/integration/external_relative_path_deps/external_crate/Cargo.toml new file mode 100644 index 0000000000..dfe317bef3 --- /dev/null +++ b/test/integration/external_relative_path_deps/external_crate/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "external_crate" +version = "0.1.0" +edition = "2021" + +[lib] diff --git a/test/integration/external_relative_path_deps/external_crate/src/lib.rs b/test/integration/external_relative_path_deps/external_crate/src/lib.rs new file mode 100644 index 0000000000..6f1c19bc03 --- /dev/null +++ b/test/integration/external_relative_path_deps/external_crate/src/lib.rs @@ -0,0 +1,4 @@ +/// Returns a greeting from the external crate. +pub fn greet() -> &'static str { + "Hello from external_crate!" +} From acc63d7633ff1cb4f3c41760e5300c248b8df4c4 Mon Sep 17 00:00:00 2001 From: Malte Poll Date: Tue, 24 Mar 2026 11:55:44 +0000 Subject: [PATCH 2/3] Extend relative path dep test to include Cargo workspace --- .../external_relative_path_deps/.bazelignore | 3 ++ .../external_relative_path_deps/MODULE.bazel | 27 ++++++++++----- .../MODULE.bazel.lock | 6 ++-- .../cargo_workspace/Cargo.lock | 10 ++++++ .../cargo_workspace/Cargo.toml | 4 +++ .../cargo_workspace/member/BUILD.bazel | 7 ++-- .../cargo_workspace/member/Cargo.toml | 9 +++-- .../cargo_workspace/member/src/lib.rs | 34 +++++++++++++++++-- .../external_crate_b/Cargo.toml | 6 ++++ .../external_crate_b/src/lib.rs | 4 +++ .../external_workspace/Cargo.toml | 3 ++ .../ext_ws_crate/Cargo.toml | 6 ++++ .../ext_ws_crate/src/lib.rs | 4 +++ 13 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 test/integration/external_relative_path_deps/.bazelignore create mode 100644 test/integration/external_relative_path_deps/external_crate_b/Cargo.toml create mode 100644 test/integration/external_relative_path_deps/external_crate_b/src/lib.rs create mode 100644 test/integration/external_relative_path_deps/external_workspace/Cargo.toml create mode 100644 test/integration/external_relative_path_deps/external_workspace/ext_ws_crate/Cargo.toml create mode 100644 test/integration/external_relative_path_deps/external_workspace/ext_ws_crate/src/lib.rs diff --git a/test/integration/external_relative_path_deps/.bazelignore b/test/integration/external_relative_path_deps/.bazelignore new file mode 100644 index 0000000000..6fe753a9bd --- /dev/null +++ b/test/integration/external_relative_path_deps/.bazelignore @@ -0,0 +1,3 @@ +external_crate/ +external_crate_b/ +external_workspace/ diff --git a/test/integration/external_relative_path_deps/MODULE.bazel b/test/integration/external_relative_path_deps/MODULE.bazel index e6da5e5f1e..8184a50cc2 100644 --- a/test/integration/external_relative_path_deps/MODULE.bazel +++ b/test/integration/external_relative_path_deps/MODULE.bazel @@ -17,22 +17,31 @@ use_repo(rust, "rust_toolchains") register_toolchains("@rust_toolchains//:all") -# Test: crate_universe with Cargo workspace where a member has a path dependency -# that goes OUTSIDE the Cargo workspace root (but still inside the Bazel workspace). +# Test: crate_universe with Cargo workspace where a member has path dependencies +# that go OUTSIDE the Cargo workspace root (but still inside the Bazel workspace). # # Structure: -# external_crate/ <- Outside Cargo workspace -# cargo_workspace/ <- Cargo workspace root -# Cargo.toml <- [workspace] members = ["member"] +# external_crate/ <- Outside Cargo workspace (standalone) +# external_crate_b/ <- Outside Cargo workspace (standalone) +# external_workspace/ <- Separate Cargo workspace +# ext_ws_crate/ <- Member of external_workspace +# cargo_workspace/ <- Primary Cargo workspace +# Cargo.toml <- [workspace] with [workspace.dependencies] for external_crate + ext_ws_crate # member/ -# Cargo.toml <- external_crate = { path = "../../external_crate" } +# Cargo.toml <- external_crate via workspace = true, +# external_crate_b via direct path dep, +# ext_ws_crate via workspace = true # -# This should work but currently fails because crate_universe doesn't copy -# the external path dependency into the temp splicing directory. +# Tests three code paths: workspace-inherited external path deps, direct +# external path deps declared inline in a member, and external path deps +# from a crate that belongs to a different Cargo workspace. crate = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate") crate.from_cargo( name = "crates", cargo_lockfile = "//cargo_workspace:Cargo.lock", - manifests = ["//cargo_workspace:Cargo.toml"], + manifests = [ + "//cargo_workspace:Cargo.toml", + "//:external_workspace/ext_ws_crate/Cargo.toml", + ], ) use_repo(crate, "crates") diff --git a/test/integration/external_relative_path_deps/MODULE.bazel.lock b/test/integration/external_relative_path_deps/MODULE.bazel.lock index 3f76cb589e..93bada1866 100644 --- a/test/integration/external_relative_path_deps/MODULE.bazel.lock +++ b/test/integration/external_relative_path_deps/MODULE.bazel.lock @@ -233,8 +233,8 @@ }, "@@rules_rust+//crate_universe/private:internal_extensions.bzl%cu_nr": { "general": { - "bzlTransitiveDigest": "h9wcsupr1TvM+IjSqO1m9hZWrBFbgwAqak9LCEhtav8=", - "usagesDigest": "oUK0ytEbfl+CaIzEjRqZCnsb5eUCZOx9usreQy09/3o=", + "bzlTransitiveDigest": "Lst2lMpOzFV9C04lgQsrDWSpTsSYPVnJogVLNBT7qUM=", + "usagesDigest": "qhmy4zrnFb6knNQRx2XBCVfHObom0vnflm+sibd7SA0=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -298,7 +298,7 @@ "binary": "cargo-bazel", "cargo_lockfile": "@@rules_rust+//crate_universe:Cargo.lock", "cargo_toml": "@@rules_rust+//crate_universe:Cargo.toml", - "version": "1.86.0", + "version": "1.94.0", "timeout": 900, "rust_toolchain_cargo_template": "@rust_host_tools//:bin/{tool}", "rust_toolchain_rustc_template": "@rust_host_tools//:bin/{tool}", diff --git a/test/integration/external_relative_path_deps/cargo_workspace/Cargo.lock b/test/integration/external_relative_path_deps/cargo_workspace/Cargo.lock index 72137c2db5..446d1aac58 100644 --- a/test/integration/external_relative_path_deps/cargo_workspace/Cargo.lock +++ b/test/integration/external_relative_path_deps/cargo_workspace/Cargo.lock @@ -2,13 +2,23 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ext_ws_crate" +version = "0.1.0" + [[package]] name = "external_crate" version = "0.1.0" +[[package]] +name = "external_crate_b" +version = "0.1.0" + [[package]] name = "member" version = "0.1.0" dependencies = [ + "ext_ws_crate", "external_crate", + "external_crate_b", ] diff --git a/test/integration/external_relative_path_deps/cargo_workspace/Cargo.toml b/test/integration/external_relative_path_deps/cargo_workspace/Cargo.toml index 515ce5ab6c..bb09fd3d11 100644 --- a/test/integration/external_relative_path_deps/cargo_workspace/Cargo.toml +++ b/test/integration/external_relative_path_deps/cargo_workspace/Cargo.toml @@ -1,3 +1,7 @@ [workspace] members = ["member"] resolver = "2" + +[workspace.dependencies] +external_crate = { path = "../external_crate" } +ext_ws_crate = { path = "../external_workspace/ext_ws_crate" } diff --git a/test/integration/external_relative_path_deps/cargo_workspace/member/BUILD.bazel b/test/integration/external_relative_path_deps/cargo_workspace/member/BUILD.bazel index 16ba0e1055..3119b0c56b 100644 --- a/test/integration/external_relative_path_deps/cargo_workspace/member/BUILD.bazel +++ b/test/integration/external_relative_path_deps/cargo_workspace/member/BUILD.bazel @@ -4,9 +4,12 @@ rust_library( name = "member", srcs = ["src/lib.rs"], deps = [ - # The external_crate dependency should be resolved by crate_universe - # even though it's located outside the Cargo workspace via path = "../../external_crate" + # Workspace dep: declared in [workspace.dependencies] with a path outside the workspace. "@crates//:external_crate", + # Direct dep: declared inline with a path outside the workspace. + "@crates//:external_crate_b", + # Workspace dep from a different Cargo workspace. + "@crates//:ext_ws_crate", ], ) diff --git a/test/integration/external_relative_path_deps/cargo_workspace/member/Cargo.toml b/test/integration/external_relative_path_deps/cargo_workspace/member/Cargo.toml index fa32f4bbb8..677130d23e 100644 --- a/test/integration/external_relative_path_deps/cargo_workspace/member/Cargo.toml +++ b/test/integration/external_relative_path_deps/cargo_workspace/member/Cargo.toml @@ -6,6 +6,9 @@ edition = "2021" [lib] [dependencies] -# This path dependency goes OUTSIDE the Cargo workspace root. -# This is the scenario from issue #3089. -external_crate = { path = "../../external_crate" } +# Inherited from [workspace.dependencies]. Path goes outside the workspace. +external_crate.workspace = true +# Direct path dep that also goes outside the workspace. +external_crate_b = { path = "../../external_crate_b" } +# Inherited from [workspace.dependencies]. Path goes to a crate in a different Cargo workspace. +ext_ws_crate.workspace = true diff --git a/test/integration/external_relative_path_deps/cargo_workspace/member/src/lib.rs b/test/integration/external_relative_path_deps/cargo_workspace/member/src/lib.rs index eab873163a..1b6dafe562 100644 --- a/test/integration/external_relative_path_deps/cargo_workspace/member/src/lib.rs +++ b/test/integration/external_relative_path_deps/cargo_workspace/member/src/lib.rs @@ -1,6 +1,34 @@ -use external_crate; - -/// Re-exports the greeting from external_crate. +/// Re-exports the greeting from external_crate (workspace dep). pub fn say_hello() -> &'static str { external_crate::greet() } + +/// Re-exports the greeting from external_crate_b (direct dep). +pub fn say_hello_b() -> &'static str { + external_crate_b::greet() +} + +/// Re-exports the greeting from ext_ws_crate (belongs to a different Cargo workspace). +pub fn say_hello_ext_ws() -> &'static str { + ext_ws_crate::greet() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_workspace_dep() { + assert_eq!(say_hello(), "Hello from external_crate!"); + } + + #[test] + fn test_direct_dep() { + assert_eq!(say_hello_b(), "Hello from external_crate_b!"); + } + + #[test] + fn test_ext_workspace_dep() { + assert_eq!(say_hello_ext_ws(), "Hello from ext_ws_crate!"); + } +} diff --git a/test/integration/external_relative_path_deps/external_crate_b/Cargo.toml b/test/integration/external_relative_path_deps/external_crate_b/Cargo.toml new file mode 100644 index 0000000000..73d43dda5c --- /dev/null +++ b/test/integration/external_relative_path_deps/external_crate_b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "external_crate_b" +version = "0.1.0" +edition = "2021" + +[lib] diff --git a/test/integration/external_relative_path_deps/external_crate_b/src/lib.rs b/test/integration/external_relative_path_deps/external_crate_b/src/lib.rs new file mode 100644 index 0000000000..14ce9e79a6 --- /dev/null +++ b/test/integration/external_relative_path_deps/external_crate_b/src/lib.rs @@ -0,0 +1,4 @@ +/// Returns a greeting from external_crate_b. +pub fn greet() -> &'static str { + "Hello from external_crate_b!" +} diff --git a/test/integration/external_relative_path_deps/external_workspace/Cargo.toml b/test/integration/external_relative_path_deps/external_workspace/Cargo.toml new file mode 100644 index 0000000000..52b9616f11 --- /dev/null +++ b/test/integration/external_relative_path_deps/external_workspace/Cargo.toml @@ -0,0 +1,3 @@ +[workspace] +members = ["ext_ws_crate"] +resolver = "2" diff --git a/test/integration/external_relative_path_deps/external_workspace/ext_ws_crate/Cargo.toml b/test/integration/external_relative_path_deps/external_workspace/ext_ws_crate/Cargo.toml new file mode 100644 index 0000000000..ae8c8cef06 --- /dev/null +++ b/test/integration/external_relative_path_deps/external_workspace/ext_ws_crate/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ext_ws_crate" +version = "0.1.0" +edition = "2021" + +[lib] diff --git a/test/integration/external_relative_path_deps/external_workspace/ext_ws_crate/src/lib.rs b/test/integration/external_relative_path_deps/external_workspace/ext_ws_crate/src/lib.rs new file mode 100644 index 0000000000..2c3d89e7a4 --- /dev/null +++ b/test/integration/external_relative_path_deps/external_workspace/ext_ws_crate/src/lib.rs @@ -0,0 +1,4 @@ +/// Returns a greeting from ext_ws_crate (belongs to external_workspace). +pub fn greet() -> &'static str { + "Hello from ext_ws_crate!" +} From 275962d1a87664e2ccf35a0ca9d5e8bd4bd9e92b Mon Sep 17 00:00:00 2001 From: Malte Poll Date: Tue, 24 Mar 2026 10:57:46 +0000 Subject: [PATCH 3/3] Support splicing manifests from multiple Cargo workspaces When manifests come from different Cargo workspaces (e.g. a primary workspace depending on crates in a separate external workspace), splicing previously failed with "manifests are not allowed to come from different workspaces". This change: - Adds `main_manifest` to SplicingManifest so the splicer can disambiguate which workspace root is primary when multiple are found. - Nests the spliced workspace at its repo-relative depth inside the temp dir so that `../` path deps resolve within the temp dir instead of escaping into unwritable system directories. - Collects path deps from `[workspace.dependencies]` in addition to per-package deps. - Symlinks entire foreign workspace root directories (not just crate dirs) so Cargo can walk up and resolve `dep.workspace = true` inherited dependencies. - Wires `main_manifest` through extensions.bzl and crates_vendor.bzl. - Calls symlink_external_path_deps from the cargo_tree_resolver so `cargo tree` also sees external path deps. This fixes https://github.com/bazelbuild/rules_rust/issues/3089, along with adding support for multiple workspaces in the splicer. Co-Authored-By: Steve Barrau <98589981+stevebarrau@users.noreply.github.com> --- crate_universe/extensions.bzl | 8 +- crate_universe/private/crates_vendor.bzl | 4 +- crate_universe/private/local_crate_mirror.bzl | 16 +- crate_universe/src/cli/generate.rs | 9 +- .../src/metadata/cargo_tree_resolver.rs | 29 ++ .../src/metadata/metadata_annotation.rs | 31 +- crate_universe/src/splicing.rs | 19 +- crate_universe/src/splicing/splicer.rs | 335 +++++++++++++++++- .../MODULE.bazel.lock | 119 ++++++- 9 files changed, 548 insertions(+), 22 deletions(-) diff --git a/crate_universe/extensions.bzl b/crate_universe/extensions.bzl index 4e078c01e2..026ab40c2f 100644 --- a/crate_universe/extensions.bzl +++ b/crate_universe/extensions.bzl @@ -562,7 +562,8 @@ def _generate_hub_and_spokes( strip_internal_dependencies_from_cargo_lockfile, cargo_lockfile = None, manifests = {}, - packages = {}): + packages = {}, + main_manifest = None): """Generates repositories for the transitive closure of crates defined by manifests and packages. Args: @@ -618,6 +619,7 @@ def _generate_hub_and_spokes( cargo_config = cfg.cargo_config, manifests = manifests, manifest_to_path = module_ctx.path, + main_manifest = main_manifest, ), ) @@ -1155,10 +1157,13 @@ def _crate_impl(module_ctx): manifests = {} packages = {} + main_manifest = None # Only `from_cargo` instances will have `manifests`. if hasattr(cfg, "manifests"): manifests = {str(module_ctx.path(m)): str(m) for m in cfg.manifests} + if cfg.manifests: + main_manifest = str(module_ctx.path(cfg.manifests[0])) packages = { p.package_alias or p.package: _package_to_json(p) @@ -1178,6 +1183,7 @@ def _crate_impl(module_ctx): packages = packages, skip_cargo_lockfile_overwrite = cfg.skip_cargo_lockfile_overwrite, strip_internal_dependencies_from_cargo_lockfile = cfg.strip_internal_dependencies_from_cargo_lockfile, + main_manifest = main_manifest, ) metadata_kwargs = {} diff --git a/crate_universe/private/crates_vendor.bzl b/crate_universe/private/crates_vendor.bzl index e1da222746..180657d111 100644 --- a/crate_universe/private/crates_vendor.bzl +++ b/crate_universe/private/crates_vendor.bzl @@ -230,6 +230,7 @@ def _write_splicing_manifest(ctx): cargo_config = ctx.attr.cargo_config, manifests = manifests, manifest_to_path = _prepare_manifest_path, + main_manifest = _prepare_manifest_path(ctx.attr.manifests[0]) if ctx.attr.manifests else None, ), ) @@ -240,7 +241,7 @@ def _write_splicing_manifest(ctx): runfiles = [manifest] + ctx.files.manifests + ([ctx.file.cargo_config] if ctx.attr.cargo_config else []) return args, env, runfiles -def generate_splicing_manifest(*, packages, splicing_config, cargo_config, manifests, manifest_to_path): +def generate_splicing_manifest(*, packages, splicing_config, cargo_config, manifests, manifest_to_path, main_manifest = None): # Deserialize information about direct packages direct_packages_info = { # Ensure the data is using kebab-case as that's what `cargo_toml::DependencyDetail` expects. @@ -252,6 +253,7 @@ def generate_splicing_manifest(*, packages, splicing_config, cargo_config, manif "cargo_config": str(manifest_to_path(cargo_config)) if cargo_config else None, "direct_packages": direct_packages_info, "manifests": manifests, + "main_manifest": main_manifest, } return json.encode_indent( diff --git a/crate_universe/private/local_crate_mirror.bzl b/crate_universe/private/local_crate_mirror.bzl index 06fed9571f..96204d6f1a 100644 --- a/crate_universe/private/local_crate_mirror.bzl +++ b/crate_universe/private/local_crate_mirror.bzl @@ -6,7 +6,14 @@ load("//crate_universe/private:urls.bzl", "CARGO_BAZEL_SHA256S", "CARGO_BAZEL_UR load("//rust/platform:triple.bzl", "get_host_triple") def _local_crate_mirror_impl(repository_ctx): - path = repository_ctx.path(repository_ctx.attr.path) + raw_path = repository_ctx.attr.path + if raw_path.startswith("/"): + # Absolute path (backward compatibility) + path = repository_ctx.path(raw_path) + else: + # Workspace-relative path — resolve using anchor + workspace_root = repository_ctx.path(repository_ctx.attr._workspace_root_anchor).dirname + path = workspace_root.get_child(raw_path) host_triple = get_host_triple(repository_ctx) @@ -53,8 +60,11 @@ This is effectively a `local_repository` rule implementation, but where the `BUI doc = "JSON serialized instance of a crate_universe::context::SingleBuildFileRenderContext", ), "path": attr.string( - # TODO: Verify what happens if this is not an absolute path. - doc = "Absolute path to the BUILD.bazel file to generate.", + doc = "Path to the crate directory. Can be absolute or workspace-relative.", + ), + "_workspace_root_anchor": attr.label( + default = "@@//:MODULE.bazel", + allow_single_file = True, ), "quiet": attr.bool( doc = "If stdout and stderr should not be printed to the terminal.", diff --git a/crate_universe/src/cli/generate.rs b/crate_universe/src/cli/generate.rs index f4e4c1f773..1de3e6c8eb 100644 --- a/crate_universe/src/cli/generate.rs +++ b/crate_universe/src/cli/generate.rs @@ -286,7 +286,14 @@ fn write_paths_to_track< let source_annotation_manifests: BTreeSet<_> = source_annotations .filter_map(|v| { if let SourceAnnotation::Path { path } = v { - Some(path.join("Cargo.toml")) + let abs = if path.is_relative() { + nonhermetic_root_bazel_workspace_dir + .join(path) + .join("Cargo.toml") + } else { + path.join("Cargo.toml") + }; + Some(abs) } else { None } diff --git a/crate_universe/src/metadata/cargo_tree_resolver.rs b/crate_universe/src/metadata/cargo_tree_resolver.rs index bf95edf038..12886dfb65 100644 --- a/crate_universe/src/metadata/cargo_tree_resolver.rs +++ b/crate_universe/src/metadata/cargo_tree_resolver.rs @@ -16,6 +16,7 @@ use url::Url; use crate::config::CrateId; use crate::metadata::cargo_bin::Cargo; use crate::select::{Select, SelectableScalar}; +use crate::splicing::splicer::symlink_external_path_deps; use crate::utils::symlink::symlink; use crate::utils::target_triple::TargetTriple; @@ -526,6 +527,34 @@ impl TreeResolver { ) })?; + // Symlink any path dependencies that live outside the workspace root + symlink_external_path_deps( + pristine_manifest_path.as_std_path(), + pristine_root.as_std_path(), + output_dir, + )?; + + // Also handle workspace members' external path deps + let manifest = cargo_toml::Manifest::from_path(pristine_manifest_path.as_std_path()) + .with_context(|| format!("Failed to parse manifest at {}", pristine_manifest_path))?; + if let Some(ref workspace) = manifest.workspace { + for member_pattern in &workspace.members { + let glob_pattern = pristine_root.join(member_pattern).to_string(); + if let Ok(entries) = glob::glob(&glob_pattern) { + for entry in entries.flatten() { + let member_manifest = entry.join("Cargo.toml"); + if member_manifest.exists() { + symlink_external_path_deps( + &member_manifest, + pristine_root.as_std_path(), + output_dir, + )?; + } + } + } + } + } + let cargo_metadata = self .cargo_bin .metadata_command_with_options( diff --git a/crate_universe/src/metadata/metadata_annotation.rs b/crate_universe/src/metadata/metadata_annotation.rs index fb0c62ba52..6b553c3d50 100644 --- a/crate_universe/src/metadata/metadata_annotation.rs +++ b/crate_universe/src/metadata/metadata_annotation.rs @@ -305,9 +305,8 @@ impl LockfileAnnotation { new_path.push(relative_lockfile_path); } else { // If path in lockfile is not under Bazel root, we are - // likely in a temporary directory, so rebase to Bazel - // root. - new_path.push(nonhermetic_root_bazel_workspace_dir); + // likely in a temporary directory, so use + // workspace_prefix to get the workspace-relative path. if let Some(prefix) = workspace_metadata.workspace_prefix.as_ref() { @@ -318,7 +317,31 @@ impl LockfileAnnotation { new_path.push(suffix); new_path } - Err(_) => Utf8PathBuf::from(path_in_lockfile), + Err(_) => { + // The path dep is outside the Cargo workspace root + // (e.g. an external path dep). When we nest the + // workspace at its repo-relative depth inside the + // temp dir, external deps are also at their correct + // repo-relative positions. Compute the temp dir root + // by stripping workspace_prefix from workspace_root, + // then rebase the path to the real Bazel workspace. + let temp_dir_root = workspace_metadata + .workspace_prefix + .as_ref() + .and_then(|prefix| { + metadata + .workspace_root + .as_str() + .strip_suffix(prefix.as_str()) + }); + if let Some(repo_relative) = temp_dir_root.and_then(|root| { + Utf8Path::new(path_in_lockfile).strip_prefix(root).ok() + }) { + Utf8PathBuf::from(repo_relative) + } else { + Utf8PathBuf::from(path_in_lockfile) + } + } }; return Ok(SourceAnnotation::Path { path }); } diff --git a/crate_universe/src/splicing.rs b/crate_universe/src/splicing.rs index 6381c783f4..3ec29f5f6d 100644 --- a/crate_universe/src/splicing.rs +++ b/crate_universe/src/splicing.rs @@ -2,7 +2,7 @@ pub(crate) mod cargo_config; mod crate_index_lookup; -mod splicer; +pub(crate) mod splicer; use std::collections::{BTreeMap, BTreeSet}; use std::fs; @@ -41,6 +41,11 @@ pub(crate) struct SplicingManifest { /// The Cargo resolver version to use for splicing pub(crate) resolver_version: cargo_toml::Resolver, + + /// The path of the "main" manifest (first in the manifests list). + /// Used to disambiguate when manifests come from multiple Cargo workspaces. + #[serde(default)] + pub(crate) main_manifest: Option, } impl FromStr for SplicingManifest { @@ -61,6 +66,7 @@ impl SplicingManifest { let Self { manifests, cargo_config, + main_manifest, .. } = self; @@ -88,9 +94,19 @@ impl SplicingManifest { Utf8PathBuf::from(resolved_path) }); + // Resolve the main manifest path + let main_manifest = main_manifest.map(|path| { + let resolved_path = path + .to_string() + .replace("${build_workspace_directory}", &workspace_dir_str) + .replace("${output_base}", &output_base_str); + Utf8PathBuf::from(resolved_path) + }); + Self { manifests, cargo_config, + main_manifest, ..self } } @@ -678,6 +694,7 @@ mod test { ]), cargo_config: None, resolver_version: cargo_toml::Resolver::V2, + main_manifest: None, }; let metadata = SplicingMetadata::try_from(manifest).unwrap(); let metadata = serde_json::to_string(&metadata).unwrap(); diff --git a/crate_universe/src/splicing/splicer.rs b/crate_universe/src/splicing/splicer.rs index 0f57a078e6..8d77e423a5 100644 --- a/crate_universe/src/splicing/splicer.rs +++ b/crate_universe/src/splicing/splicer.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashSet}; use std::fs; -use std::path::Path; +use std::path::{Component, Path, PathBuf}; use anyhow::{bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; @@ -59,10 +59,30 @@ impl<'a> SplicerKind<'a> { manifests: &'a BTreeMap, splicing_manifest: &'a SplicingManifest, ) -> Result { - let workspace_roots: HashSet = + let mut workspace_roots: HashSet = manifests.keys().filter_map(parent_workspace).collect(); if workspace_roots.len() > 1 { - bail!("When splicing manifests, manifests are not allowed to from from different workspaces. Saw manifests which belong to the following workspaces: {}", workspace_roots.iter().map(|wr| wr.to_string()).collect::>().join(", ")); + // When a main_manifest is provided, we can disambiguate by keeping only + // the workspace root that is an ancestor of the main manifest. Foreign + // workspace roots (e.g. from external path deps) are dropped. Their + // crates are handled via symlinks during splicing. + if let Some(main) = &splicing_manifest.main_manifest { + let before_count = workspace_roots.len(); + workspace_roots.retain(|root| { + let root_dir = root.parent().unwrap_or(root.as_path()); + main.starts_with(root_dir) + }); + if workspace_roots.len() != 1 { + bail!("When splicing manifests, manifests are not allowed to from from different workspaces. Saw manifests which belong to the following workspaces: {}", manifests.keys().filter_map(parent_workspace).collect::>().iter().map(|wr| wr.to_string()).collect::>().join(", ")); + } + let dropped = before_count - 1; + eprintln!( + "INFO: Ignoring {} foreign workspace root(s); using main manifest: {}", + dropped, main + ); + } else { + bail!("When splicing manifests, manifests are not allowed to from from different workspaces. Saw manifests which belong to the following workspaces: {}", workspace_roots.iter().map(|wr| wr.to_string()).collect::>().join(", ")); + } } if let Some((path, manifest)) = workspace_roots @@ -158,15 +178,61 @@ impl<'a> SplicerKind<'a> { .parent() .expect("Every manifest should have a parent directory"); + // Nest the workspace inside the temp dir at the same depth relative to + // the Bazel repo root. This ensures that external path dependencies + // using `../` resolve to paths *inside* the temp dir rather than + // escaping into unwritable system directories. + let nested_ws_dir = if let Some(rel) = pathdiff::diff_paths( + manifest_dir.as_str(), + nonhermetic_root_bazel_workspace_dir.as_str(), + ) { + if !rel.to_string_lossy().starts_with("..") { + let nested = + workspace_dir.join(Utf8Path::from_path(&rel).unwrap_or(Utf8Path::new(""))); + fs::create_dir_all(nested.as_std_path())?; + nested + } else { + workspace_dir.to_path_buf() + } + } else { + workspace_dir.to_path_buf() + }; + // Link the sources of the root manifest into the new workspace symlink_roots( manifest_dir.as_std_path(), - workspace_dir.as_std_path(), + nested_ws_dir.as_std_path(), Some(IGNORE_LIST), )?; + // Symlink any path dependencies that live outside the workspace root + symlink_external_path_deps( + path.as_std_path(), + manifest_dir.as_std_path(), + nested_ws_dir.as_std_path(), + )?; + + // Also handle workspace members' external path deps + if let Some(ref workspace) = manifest.workspace { + for member_pattern in &workspace.members { + let glob_pattern = manifest_dir.join(member_pattern).to_string(); + if let Ok(entries) = glob::glob(&glob_pattern) { + for entry in entries.flatten() { + let member_manifest = entry.join("Cargo.toml"); + if member_manifest.exists() { + symlink_external_path_deps( + &member_manifest, + manifest_dir.as_std_path(), + nested_ws_dir.as_std_path(), + )?; + } + } + } + } + } + // Optionally install the cargo config after contents have been symlinked - Self::setup_cargo_config(&splicing_manifest.cargo_config, workspace_dir.as_std_path())?; + Self::setup_cargo_config(&splicing_manifest.cargo_config, nested_ws_dir.as_std_path())?; // Add any additional dependencies to the root package if !splicing_manifest.direct_packages.is_empty() { @@ -177,7 +243,7 @@ impl<'a> SplicerKind<'a> { )?; } - let root_manifest_path = workspace_dir.join("Cargo.toml"); + let root_manifest_path = nested_ws_dir.join("Cargo.toml"); let member_manifests = BTreeMap::from([(*path, String::new())]); // Write the generated metadata to the manifest @@ -203,15 +269,40 @@ impl<'a> SplicerKind<'a> { .parent() .expect("Every manifest should have a parent directory"); + // Nest the package inside the temp dir at the same depth relative to + // the Bazel repo root (same rationale as splice_workspace). + let nested_dir = if let Some(rel) = pathdiff::diff_paths( + manifest_dir.as_str(), + nonhermetic_root_bazel_workspace_dir.as_str(), + ) { + if !rel.to_string_lossy().starts_with("..") { + let nested = + workspace_dir.join(Utf8Path::from_path(&rel).unwrap_or(Utf8Path::new(""))); + fs::create_dir_all(nested.as_std_path())?; + nested + } else { + workspace_dir.to_path_buf() + } + } else { + workspace_dir.to_path_buf() + }; + // Link the sources of the root manifest into the new workspace symlink_roots( manifest_dir.as_std_path(), - workspace_dir.as_std_path(), + nested_dir.as_std_path(), Some(IGNORE_LIST), )?; + // Symlink any path dependencies that live outside the package root + symlink_external_path_deps( + path.as_std_path(), + manifest_dir.as_std_path(), + nested_dir.as_std_path(), + )?; + // Optionally install the cargo config after contents have been symlinked - Self::setup_cargo_config(&splicing_manifest.cargo_config, workspace_dir.as_std_path())?; + Self::setup_cargo_config(&splicing_manifest.cargo_config, nested_dir.as_std_path())?; // Ensure the root package manifest has a populated `workspace` member let mut manifest = (*manifest).clone(); @@ -229,7 +320,7 @@ impl<'a> SplicerKind<'a> { )?; } - let root_manifest_path = workspace_dir.join("Cargo.toml"); + let root_manifest_path = nested_dir.join("Cargo.toml"); let member_manifests = BTreeMap::from([(*path, String::new())]); // Write the generated metadata to the manifest @@ -669,6 +760,158 @@ pub(crate) fn symlink_roots( Ok(()) } +/// Resolve `..` components in a path without requiring the path to exist on disk. +fn normalize_path(path: &Path) -> PathBuf { + let mut result = Vec::new(); + for component in path.components() { + match component { + Component::ParentDir => { + // map_or used instead of is_none_or for compatibility with older Rust versions + #[allow(unknown_lints, clippy::unnecessary_map_or)] + if result.last().map_or(true, |c| *c == Component::ParentDir) { + result.push(Component::ParentDir); + } else { + result.pop(); + } + } + Component::CurDir => {} + other => result.push(other), + } + } + result.iter().collect() +} + +/// Extract path strings from a `DepsSet`. +fn collect_path_deps_from_deps(deps: &cargo_toml::DepsSet) -> Vec { + deps.values() + .filter_map(|dep| dep.detail().and_then(|d| d.path.clone())) + .collect() +} + +/// Collect all path dependency strings from a manifest (deps, dev-deps, build-deps, +/// target-specific deps, and patch sections). +fn collect_path_deps_from_manifest(manifest: &cargo_toml::Manifest) -> Vec { + let mut paths = Vec::new(); + paths.extend(collect_path_deps_from_deps(&manifest.dependencies)); + paths.extend(collect_path_deps_from_deps(&manifest.dev_dependencies)); + paths.extend(collect_path_deps_from_deps(&manifest.build_dependencies)); + + for target in manifest.target.values() { + paths.extend(collect_path_deps_from_deps(&target.dependencies)); + paths.extend(collect_path_deps_from_deps(&target.dev_dependencies)); + paths.extend(collect_path_deps_from_deps(&target.build_dependencies)); + } + + for registry_deps in manifest.patch.values() { + paths.extend(collect_path_deps_from_deps(registry_deps)); + } + + if let Some(ref workspace) = manifest.workspace { + paths.extend(collect_path_deps_from_deps(&workspace.dependencies)); + } + + paths +} + +/// For each path dependency in the manifest that escapes `workspace_root` (via `..`), +/// create a symlink in the destination tree so that the relative path still resolves. +pub(crate) fn symlink_external_path_deps( + manifest_path: &Path, + workspace_root: &Path, + dest_workspace_root: &Path, +) -> Result<()> { + let manifest = cargo_toml::Manifest::from_path(manifest_path) + .with_context(|| format!("Failed to parse manifest at {}", manifest_path.display()))?; + let dep_paths = collect_path_deps_from_manifest(&manifest); + + let manifest_dir = manifest_path + .parent() + .expect("manifest path should have a parent"); + let manifest_rel = pathdiff::diff_paths(manifest_dir, workspace_root) + .unwrap_or_else(|| manifest_dir.to_path_buf()); + + for dep_path in dep_paths { + let dep = Path::new(&dep_path); + if dep.is_absolute() { + continue; + } + let relative_from_ws = normalize_path(&manifest_rel.join(dep)); + // Only handle deps that escape the workspace root (start with `..`) + if relative_from_ws.components().next() != Some(Component::ParentDir) { + continue; + } + + let actual_source = manifest_dir + .join(dep) + .canonicalize() + .with_context(|| format!("Failed to canonicalize external path dep: {dep_path}"))?; + + let dest_manifest_dir = dest_workspace_root.join(&manifest_rel); + let dest_dep_path = normalize_path(&dest_manifest_dir.join(dep)); + + // If the dep belongs to a foreign Cargo workspace, symlink the entire + // foreign workspace root directory instead of just the crate dir. This + // allows Cargo to walk up and find the workspace root (needed to resolve + // `workspace = true` inherited dependencies). + let dep_manifest = actual_source.join("Cargo.toml"); + let symlink_done = if dep_manifest.exists() { + if let Some(foreign_ws_root) = parent_workspace( + &Utf8PathBuf::from_path_buf(dep_manifest) + .unwrap_or_else(|p| Utf8PathBuf::from(p.to_string_lossy().as_ref())), + ) { + let foreign_ws_dir = foreign_ws_root + .parent() + .expect("workspace root should have a parent"); + // Compute where the foreign workspace root sits in the dest tree + if let Some(rel_from_dep_to_ws) = pathdiff::diff_paths( + foreign_ws_dir.as_str(), + actual_source.to_string_lossy().as_ref(), + ) { + let dest_foreign_ws_dir = + normalize_path(&dest_dep_path.join(&rel_from_dep_to_ws)); + if !dest_foreign_ws_dir.exists() { + if let Some(parent) = dest_foreign_ws_dir.parent() { + fs::create_dir_all(parent)?; + } + symlink(foreign_ws_dir.as_std_path(), &dest_foreign_ws_dir).with_context( + || { + format!( + "Failed to symlink foreign workspace root dir: {} -> {}", + foreign_ws_dir, + dest_foreign_ws_dir.display() + ) + }, + )?; + } + true // The crate dir is now accessible through the workspace symlink + } else { + false + } + } else { + false + } + } else { + false + }; + + // If we didn't symlink via the foreign workspace root, symlink the crate + // directory directly (standalone crate with no parent workspace). + if !symlink_done && !dest_dep_path.exists() { + if let Some(parent) = dest_dep_path.parent() { + fs::create_dir_all(parent)?; + } + symlink(&actual_source, &dest_dep_path).with_context(|| { + format!( + "Failed to symlink external path dep: {} -> {}", + actual_source.display(), + dest_dep_path.display() + ) + })?; + } + } + Ok(()) +} + #[cfg(test)] mod test { use super::*; @@ -1085,7 +1328,7 @@ mod test { } #[test] - fn splice_workspace_report_external_workspace_members() { + fn splice_workspace_report_external_workspace_members_without_main_manifest() { let (mut splicing_manifest, _cache_dir) = mock_splicing_manifest_with_workspace(); // Add a new package from an existing external workspace @@ -1135,6 +1378,9 @@ mod test { Label::from_str("@remote_dep//external_workspace_member:Cargo.toml").unwrap(), ); + // Without main_manifest set, splicing should fail + assert!(splicing_manifest.main_manifest.is_none()); + // Splice the workspace let workspace_root = tempfile::tempdir().unwrap(); let workspace_manifest = @@ -1153,6 +1399,75 @@ mod test { ); } + #[test] + fn splice_workspace_allows_foreign_workspace_with_main_manifest() { + let (mut splicing_manifest, cache_dir) = mock_splicing_manifest_with_workspace(); + + // Add a new package from an existing external workspace + let external_workspace_root = tempfile::tempdir().unwrap(); + let external_manifest = Utf8PathBuf::try_from( + external_workspace_root + .as_ref() + .join("external_workspace_member") + .join("Cargo.toml"), + ) + .unwrap(); + fs::create_dir_all(external_manifest.parent().unwrap()).unwrap(); + + fs::write( + external_workspace_root.as_ref().join("Cargo.toml"), + textwrap::dedent( + r#" + [workspace] + [package] + name = "external_workspace_root" + version = "0.0.1" + + [lib] + path = "lib.rs" + "#, + ), + ) + .unwrap(); + + fs::write( + &external_manifest, + textwrap::dedent( + r#" + [package] + name = "external_workspace_member" + version = "0.0.1" + + [lib] + path = "lib.rs" + "#, + ), + ) + .unwrap(); + + splicing_manifest.manifests.insert( + external_manifest.clone(), + Label::from_str("@remote_dep//external_workspace_member:Cargo.toml").unwrap(), + ); + + let primary_root = + Utf8PathBuf::try_from(cache_dir.as_ref().join("root_pkg").join("Cargo.toml")).unwrap(); + splicing_manifest.main_manifest = Some(primary_root); + + // Splice the workspace — should succeed now + let workspace_root = tempfile::tempdir().unwrap(); + let workspace_manifest = + Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) + .unwrap() + .splice_workspace(Utf8Path::new("/doesnotexist/unused/repo/root")); + + assert!( + workspace_manifest.is_ok(), + "Expected splicing to succeed with main_manifest set, but got: {:?}", + workspace_manifest.err() + ); + } + #[test] fn splice_workspace_no_root_pkg() { let (splicing_manifest, cache_dir) = mock_splicing_manifest_with_workspace_in_root(); diff --git a/test/integration/external_relative_path_deps/MODULE.bazel.lock b/test/integration/external_relative_path_deps/MODULE.bazel.lock index 93bada1866..93e5ad9dc9 100644 --- a/test/integration/external_relative_path_deps/MODULE.bazel.lock +++ b/test/integration/external_relative_path_deps/MODULE.bazel.lock @@ -231,9 +231,126 @@ ] } }, + "@@rules_rust+//crate_universe:extensions.bzl%crate": { + "general": { + "bzlTransitiveDigest": "XERmJZNX/mFSLGtN4QK/J9McAhZtyYPZpiZ68bT0SgE=", + "usagesDigest": "NaP9wkF3RdLx5wfgesXNRfbHkiG+rPHIvFq84WUb0sk=", + "recordedFileInputs": { + "@@//cargo_workspace/Cargo.lock": "bd22b9a98345f7a52ed35f6ea2f5f5a91e538ee8001ac63c4eec0b34fa9472e7", + "@@//cargo_workspace/Cargo.toml": "21e7296c5ea140501bff06bbe66b437036576226e71ed0603ae712770371ece6", + "@@//cargo_workspace/member/Cargo.toml": "3ed2c130e98853ac6cfa024a91811bead4c3f41a39dda9de653c833173885704", + "@@//external_crate/Cargo.toml": "1ca512cde1a11da193461e2ee4d9941d7cdf1010b2753da69ff9504eea5b5166", + "@@//external_crate_b/Cargo.toml": "5638b8348ab6095bb69107ed082c892c488c75e5cfe966e57fb9b12a2955b048", + "@@//external_workspace/ext_ws_crate/Cargo.toml": "7ab2433563a46ea3b43d08fb3c39b0e0aa52cf9c71bcd446470ab81756e18f54" + }, + "recordedDirentsInputs": {}, + "envVariables": { + "CARGO_BAZEL_DEBUG": null, + "CARGO_BAZEL_GENERATOR_SHA256": null, + "CARGO_BAZEL_GENERATOR_URL": null, + "CARGO_BAZEL_ISOLATED": null, + "CARGO_BAZEL_REPIN": null, + "CARGO_BAZEL_REPIN_ONLY": null, + "CARGO_BAZEL_TIMEOUT": null, + "REPIN": null + }, + "generatedRepoSpecs": { + "crates": { + "repoRuleId": "@@rules_rust+//crate_universe:extensions.bzl%_generate_repo", + "attributes": { + "contents": { + "BUILD.bazel": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'external_relative_path_deps_test'\n###############################################################################\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files(\n [\n \"cargo-bazel.json\",\n \"crates.bzl\",\n \"defs.bzl\",\n ] + glob(\n allow_empty = True,\n include = [\"*.bazel\"],\n ),\n)\n\nfilegroup(\n name = \"srcs\",\n srcs = glob(\n allow_empty = True,\n include = [\n \"*.bazel\",\n \"*.bzl\",\n ],\n ),\n)\n\n# Workspace Member Dependencies\nalias(\n name = \"ext_ws_crate-0.1.0\",\n actual = \"@crates__ext_ws_crate-0.1.0//:ext_ws_crate\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"ext_ws_crate\",\n actual = \"@crates__ext_ws_crate-0.1.0//:ext_ws_crate\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"external_crate-0.1.0\",\n actual = \"@crates__external_crate-0.1.0//:external_crate\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"external_crate\",\n actual = \"@crates__external_crate-0.1.0//:external_crate\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"external_crate_b-0.1.0\",\n actual = \"@crates__external_crate_b-0.1.0//:external_crate_b\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"external_crate_b\",\n actual = \"@crates__external_crate_b-0.1.0//:external_crate_b\",\n tags = [\"manual\"],\n)\n", + "alias_rules.bzl": "\"\"\"Alias that transitions its target to `compilation_mode=opt`. Use `transition_alias=\"opt\"` to enable.\"\"\"\n\nload(\"@rules_cc//cc:defs.bzl\", \"CcInfo\")\nload(\"@rules_rust//rust:rust_common.bzl\", \"COMMON_PROVIDERS\")\n\ndef _transition_alias_impl(ctx):\n # `ctx.attr.actual` is a list of 1 item due to the transition\n providers = [ctx.attr.actual[0][provider] for provider in COMMON_PROVIDERS]\n if CcInfo in ctx.attr.actual[0]:\n providers.append(ctx.attr.actual[0][CcInfo])\n return providers\n\ndef _change_compilation_mode(compilation_mode):\n def _change_compilation_mode_impl(_settings, _attr):\n return {\n \"//command_line_option:compilation_mode\": compilation_mode,\n }\n\n return transition(\n implementation = _change_compilation_mode_impl,\n inputs = [],\n outputs = [\n \"//command_line_option:compilation_mode\",\n ],\n )\n\ndef _transition_alias_rule(compilation_mode):\n return rule(\n implementation = _transition_alias_impl,\n provides = COMMON_PROVIDERS,\n attrs = {\n \"actual\": attr.label(\n mandatory = True,\n doc = \"`rust_library()` target to transition to `compilation_mode=opt`.\",\n providers = COMMON_PROVIDERS,\n cfg = _change_compilation_mode(compilation_mode),\n ),\n \"_allowlist_function_transition\": attr.label(\n default = \"@bazel_tools//tools/allowlists/function_transition_allowlist\",\n ),\n },\n doc = \"Transitions a Rust library crate to the `compilation_mode=opt`.\",\n )\n\ntransition_alias_dbg = _transition_alias_rule(\"dbg\")\ntransition_alias_fastbuild = _transition_alias_rule(\"fastbuild\")\ntransition_alias_opt = _transition_alias_rule(\"opt\")\n", + "defs.bzl": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'external_relative_path_deps_test'\n###############################################################################\n\"\"\"\n# `crates_repository` API\n\n- [aliases](#aliases)\n- [crate_deps](#crate_deps)\n- [all_crate_deps](#all_crate_deps)\n- [crate_repositories](#crate_repositories)\n\n\"\"\"\n\nload(\"@bazel_tools//tools/build_defs/repo:git.bzl\", \"new_git_repository\")\nload(\"@bazel_tools//tools/build_defs/repo:http.bzl\", \"http_archive\")\nload(\"@bazel_tools//tools/build_defs/repo:utils.bzl\", \"maybe\")\nload(\"@bazel_skylib//lib:selects.bzl\", \"selects\")\nload(\"@rules_rust//crate_universe/private:local_crate_mirror.bzl\", \"local_crate_mirror\")\n\n###############################################################################\n# MACROS API\n###############################################################################\n\n# An identifier that represent common dependencies (unconditional).\n_COMMON_CONDITION = \"\"\n\ndef _flatten_dependency_maps(all_dependency_maps):\n \"\"\"Flatten a list of dependency maps into one dictionary.\n\n Dependency maps have the following structure:\n\n ```python\n DEPENDENCIES_MAP = {\n # The first key in the map is a Bazel package\n # name of the workspace this file is defined in.\n \"workspace_member_package\": {\n\n # Not all dependencies are supported for all platforms.\n # the condition key is the condition required to be true\n # on the host platform.\n \"condition\": {\n\n # An alias to a crate target. # The label of the crate target the\n # Aliases are only crate names. # package name refers to.\n \"package_name\": \"@full//:label\",\n }\n }\n }\n ```\n\n Args:\n all_dependency_maps (list): A list of dicts as described above\n\n Returns:\n dict: A dictionary as described above\n \"\"\"\n dependencies = {}\n\n for workspace_deps_map in all_dependency_maps:\n for pkg_name, conditional_deps_map in workspace_deps_map.items():\n if pkg_name not in dependencies:\n non_frozen_map = dict()\n for key, values in conditional_deps_map.items():\n non_frozen_map.update({key: dict(values.items())})\n dependencies.setdefault(pkg_name, non_frozen_map)\n continue\n\n for condition, deps_map in conditional_deps_map.items():\n # If the condition has not been recorded, do so and continue\n if condition not in dependencies[pkg_name]:\n dependencies[pkg_name].setdefault(condition, dict(deps_map.items()))\n continue\n\n # Alert on any miss-matched dependencies\n inconsistent_entries = []\n for crate_name, crate_label in deps_map.items():\n existing = dependencies[pkg_name][condition].get(crate_name)\n if existing and existing != crate_label:\n inconsistent_entries.append((crate_name, existing, crate_label))\n dependencies[pkg_name][condition].update({crate_name: crate_label})\n\n return dependencies\n\ndef crate_deps(deps, package_name = None):\n \"\"\"Finds the fully qualified label of the requested crates for the package where this macro is called.\n\n Args:\n deps (list): The desired list of crate targets.\n package_name (str, optional): The package name of the set of dependencies to look up.\n Defaults to `native.package_name()`.\n\n Returns:\n list: A list of labels to generated rust targets (str)\n \"\"\"\n\n if not deps:\n return []\n\n if package_name == None:\n package_name = native.package_name()\n\n # Join both sets of dependencies\n dependencies = _flatten_dependency_maps([\n _NORMAL_DEPENDENCIES,\n _NORMAL_DEV_DEPENDENCIES,\n _PROC_MACRO_DEPENDENCIES,\n _PROC_MACRO_DEV_DEPENDENCIES,\n _BUILD_DEPENDENCIES,\n _BUILD_PROC_MACRO_DEPENDENCIES,\n ]).pop(package_name, {})\n\n # Combine all conditional packages so we can easily index over a flat list\n # TODO: Perhaps this should actually return select statements and maintain\n # the conditionals of the dependencies\n flat_deps = {}\n for deps_set in dependencies.values():\n for crate_name, crate_label in deps_set.items():\n flat_deps.update({crate_name: crate_label})\n\n missing_crates = []\n crate_targets = []\n for crate_target in deps:\n if crate_target not in flat_deps:\n missing_crates.append(crate_target)\n else:\n crate_targets.append(flat_deps[crate_target])\n\n if missing_crates:\n fail(\"Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`\".format(\n missing_crates,\n package_name,\n dependencies,\n ))\n\n return crate_targets\n\ndef all_crate_deps(\n normal = False, \n normal_dev = False, \n proc_macro = False, \n proc_macro_dev = False,\n build = False,\n build_proc_macro = False,\n package_name = None):\n \"\"\"Finds the fully qualified label of all requested direct crate dependencies \\\n for the package where this macro is called.\n\n If no parameters are set, all normal dependencies are returned. Setting any one flag will\n otherwise impact the contents of the returned list.\n\n Args:\n normal (bool, optional): If True, normal dependencies are included in the\n output list.\n normal_dev (bool, optional): If True, normal dev dependencies will be\n included in the output list.\n proc_macro (bool, optional): If True, proc_macro dependencies are included\n in the output list.\n proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are\n included in the output list.\n build (bool, optional): If True, build dependencies are included\n in the output list.\n build_proc_macro (bool, optional): If True, build proc_macro dependencies are\n included in the output list.\n package_name (str, optional): The package name of the set of dependencies to look up.\n Defaults to `native.package_name()` when unset.\n\n Returns:\n list: A list of labels to generated rust targets (str)\n \"\"\"\n\n if package_name == None:\n package_name = native.package_name()\n\n # Determine the relevant maps to use\n all_dependency_maps = []\n if normal:\n all_dependency_maps.append(_NORMAL_DEPENDENCIES)\n if normal_dev:\n all_dependency_maps.append(_NORMAL_DEV_DEPENDENCIES)\n if proc_macro:\n all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES)\n if proc_macro_dev:\n all_dependency_maps.append(_PROC_MACRO_DEV_DEPENDENCIES)\n if build:\n all_dependency_maps.append(_BUILD_DEPENDENCIES)\n if build_proc_macro:\n all_dependency_maps.append(_BUILD_PROC_MACRO_DEPENDENCIES)\n\n # Default to always using normal dependencies\n if not all_dependency_maps:\n all_dependency_maps.append(_NORMAL_DEPENDENCIES)\n\n dependencies = _flatten_dependency_maps(all_dependency_maps).pop(package_name, None)\n\n if not dependencies:\n if dependencies == None:\n fail(\"Tried to get all_crate_deps for package \" + package_name + \" but that package had no Cargo.toml file\")\n else:\n return []\n\n crate_deps = list(dependencies.pop(_COMMON_CONDITION, {}).values())\n for condition, deps in dependencies.items():\n crate_deps += selects.with_or({\n tuple(_CONDITIONS[condition]): deps.values(),\n \"//conditions:default\": [],\n })\n\n return crate_deps\n\ndef aliases(\n normal = False,\n normal_dev = False,\n proc_macro = False,\n proc_macro_dev = False,\n build = False,\n build_proc_macro = False,\n package_name = None):\n \"\"\"Produces a map of Crate alias names to their original label\n\n If no dependency kinds are specified, `normal` and `proc_macro` are used by default.\n Setting any one flag will otherwise determine the contents of the returned dict.\n\n Args:\n normal (bool, optional): If True, normal dependencies are included in the\n output list.\n normal_dev (bool, optional): If True, normal dev dependencies will be\n included in the output list..\n proc_macro (bool, optional): If True, proc_macro dependencies are included\n in the output list.\n proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are\n included in the output list.\n build (bool, optional): If True, build dependencies are included\n in the output list.\n build_proc_macro (bool, optional): If True, build proc_macro dependencies are\n included in the output list.\n package_name (str, optional): The package name of the set of dependencies to look up.\n Defaults to `native.package_name()` when unset.\n\n Returns:\n dict: The aliases of all associated packages\n \"\"\"\n if package_name == None:\n package_name = native.package_name()\n\n # Determine the relevant maps to use\n all_aliases_maps = []\n if normal:\n all_aliases_maps.append(_NORMAL_ALIASES)\n if normal_dev:\n all_aliases_maps.append(_NORMAL_DEV_ALIASES)\n if proc_macro:\n all_aliases_maps.append(_PROC_MACRO_ALIASES)\n if proc_macro_dev:\n all_aliases_maps.append(_PROC_MACRO_DEV_ALIASES)\n if build:\n all_aliases_maps.append(_BUILD_ALIASES)\n if build_proc_macro:\n all_aliases_maps.append(_BUILD_PROC_MACRO_ALIASES)\n\n # Default to always using normal aliases\n if not all_aliases_maps:\n all_aliases_maps.append(_NORMAL_ALIASES)\n all_aliases_maps.append(_PROC_MACRO_ALIASES)\n\n aliases = _flatten_dependency_maps(all_aliases_maps).pop(package_name, None)\n\n if not aliases:\n return dict()\n\n common_items = aliases.pop(_COMMON_CONDITION, {}).items()\n\n # If there are only common items in the dictionary, immediately return them\n if not len(aliases.keys()) == 1:\n return dict(common_items)\n\n # Build a single select statement where each conditional has accounted for the\n # common set of aliases.\n crate_aliases = {\"//conditions:default\": dict(common_items)}\n for condition, deps in aliases.items():\n condition_triples = _CONDITIONS[condition]\n for triple in condition_triples:\n if triple in crate_aliases:\n crate_aliases[triple].update(deps)\n else:\n crate_aliases.update({triple: dict(deps.items() + common_items)})\n\n return select(crate_aliases)\n\n###############################################################################\n# WORKSPACE MEMBER DEPS AND ALIASES\n###############################################################################\n\n_NORMAL_DEPENDENCIES = {\n \"cargo_workspace/member\": {\n _COMMON_CONDITION: {\n \"ext_ws_crate\": Label(\"@crates//:ext_ws_crate-0.1.0\"),\n \"external_crate\": Label(\"@crates//:external_crate-0.1.0\"),\n \"external_crate_b\": Label(\"@crates//:external_crate_b-0.1.0\"),\n },\n },\n}\n\n\n_NORMAL_ALIASES = {\n \"cargo_workspace/member\": {\n _COMMON_CONDITION: {\n },\n },\n}\n\n\n_NORMAL_DEV_DEPENDENCIES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_NORMAL_DEV_ALIASES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_PROC_MACRO_DEPENDENCIES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_PROC_MACRO_ALIASES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_PROC_MACRO_DEV_DEPENDENCIES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_PROC_MACRO_DEV_ALIASES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_BUILD_DEPENDENCIES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_BUILD_ALIASES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_BUILD_PROC_MACRO_DEPENDENCIES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_BUILD_PROC_MACRO_ALIASES = {\n \"cargo_workspace/member\": {\n },\n}\n\n\n_CONDITIONS = {\n \"aarch64-apple-darwin\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n \"aarch64-unknown-linux-gnu\": [\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\"],\n \"wasm32-unknown-unknown\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\"],\n \"wasm32-wasip1\": [\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"x86_64-pc-windows-msvc\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\"],\n \"x86_64-unknown-linux-gnu\": [\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\"],\n \"x86_64-unknown-nixos-gnu\": [\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n}\n\n###############################################################################\n\ndef crate_repositories():\n \"\"\"A macro for defining repositories for all generated crates.\n\n Returns:\n A list of repos visible to the module through the module extension.\n \"\"\"\n\n local_crate_mirror(\n name = \"crates__ext_ws_crate-0.1.0\",\n options_json = \"{\\\"config\\\":{\\\"repository_name\\\":\\\"crates\\\",\\\"build_file_template\\\":\\\"@crates//crates:BUILD.{name}-{version}.bazel\\\",\\\"crate_label_template\\\":\\\"@{repository}__{name}-{version}//:{target}\\\",\\\"crate_alias_template\\\":\\\"@{repository}//:{name}-{version}\\\",\\\"crates_module_template\\\":\\\"@crates//crates:{file}\\\",\\\"crate_repository_template\\\":\\\"{repository}__{name}-{version}\\\",\\\"default_alias_rule\\\":\\\"alias\\\",\\\"default_package_name\\\":null,\\\"generate_target_compatible_with\\\":true,\\\"platforms_template\\\":\\\"@rules_rust//rust/platform:{triple}\\\",\\\"regen_command\\\":\\\"bazel mod show_repo 'external_relative_path_deps_test'\\\",\\\"vendor_mode\\\":\\\"remote\\\",\\\"generate_rules_license_metadata\\\":false,\\\"generate_cargo_toml_env_vars\\\":true},\\\"supported_platform_triples\\\":[\\\"aarch64-apple-darwin\\\",\\\"aarch64-unknown-linux-gnu\\\",\\\"wasm32-unknown-unknown\\\",\\\"wasm32-wasip1\\\",\\\"x86_64-pc-windows-msvc\\\",\\\"x86_64-unknown-linux-gnu\\\",\\\"x86_64-unknown-nixos-gnu\\\"],\\\"platform_conditions\\\":{\\\"aarch64-apple-darwin\\\":[\\\"aarch64-apple-darwin\\\"],\\\"aarch64-unknown-linux-gnu\\\":[\\\"aarch64-unknown-linux-gnu\\\"],\\\"wasm32-unknown-unknown\\\":[\\\"wasm32-unknown-unknown\\\"],\\\"wasm32-wasip1\\\":[\\\"wasm32-wasip1\\\"],\\\"x86_64-pc-windows-msvc\\\":[\\\"x86_64-pc-windows-msvc\\\"],\\\"x86_64-unknown-linux-gnu\\\":[\\\"x86_64-unknown-linux-gnu\\\"],\\\"x86_64-unknown-nixos-gnu\\\":[\\\"x86_64-unknown-nixos-gnu\\\"]},\\\"crate_context\\\":{\\\"name\\\":\\\"ext_ws_crate\\\",\\\"version\\\":\\\"0.1.0\\\",\\\"package_url\\\":null,\\\"repository\\\":{\\\"Path\\\":{\\\"path\\\":\\\"external_workspace/ext_ws_crate\\\"}},\\\"targets\\\":[{\\\"Library\\\":{\\\"crate_name\\\":\\\"ext_ws_crate\\\",\\\"crate_root\\\":\\\"src/lib.rs\\\",\\\"srcs\\\":{\\\"allow_empty\\\":true,\\\"include\\\":[\\\"**/*.rs\\\"]}}}],\\\"library_target_name\\\":\\\"ext_ws_crate\\\",\\\"common_attrs\\\":{\\\"compile_data_glob\\\":[\\\"**\\\"],\\\"edition\\\":\\\"2021\\\",\\\"version\\\":\\\"0.1.0\\\"},\\\"license\\\":null,\\\"license_ids\\\":[],\\\"license_file\\\":null}}\",\n path = \"external_workspace/ext_ws_crate\",\n )\n\n local_crate_mirror(\n name = \"crates__external_crate-0.1.0\",\n options_json = \"{\\\"config\\\":{\\\"repository_name\\\":\\\"crates\\\",\\\"build_file_template\\\":\\\"@crates//crates:BUILD.{name}-{version}.bazel\\\",\\\"crate_label_template\\\":\\\"@{repository}__{name}-{version}//:{target}\\\",\\\"crate_alias_template\\\":\\\"@{repository}//:{name}-{version}\\\",\\\"crates_module_template\\\":\\\"@crates//crates:{file}\\\",\\\"crate_repository_template\\\":\\\"{repository}__{name}-{version}\\\",\\\"default_alias_rule\\\":\\\"alias\\\",\\\"default_package_name\\\":null,\\\"generate_target_compatible_with\\\":true,\\\"platforms_template\\\":\\\"@rules_rust//rust/platform:{triple}\\\",\\\"regen_command\\\":\\\"bazel mod show_repo 'external_relative_path_deps_test'\\\",\\\"vendor_mode\\\":\\\"remote\\\",\\\"generate_rules_license_metadata\\\":false,\\\"generate_cargo_toml_env_vars\\\":true},\\\"supported_platform_triples\\\":[\\\"aarch64-apple-darwin\\\",\\\"aarch64-unknown-linux-gnu\\\",\\\"wasm32-unknown-unknown\\\",\\\"wasm32-wasip1\\\",\\\"x86_64-pc-windows-msvc\\\",\\\"x86_64-unknown-linux-gnu\\\",\\\"x86_64-unknown-nixos-gnu\\\"],\\\"platform_conditions\\\":{\\\"aarch64-apple-darwin\\\":[\\\"aarch64-apple-darwin\\\"],\\\"aarch64-unknown-linux-gnu\\\":[\\\"aarch64-unknown-linux-gnu\\\"],\\\"wasm32-unknown-unknown\\\":[\\\"wasm32-unknown-unknown\\\"],\\\"wasm32-wasip1\\\":[\\\"wasm32-wasip1\\\"],\\\"x86_64-pc-windows-msvc\\\":[\\\"x86_64-pc-windows-msvc\\\"],\\\"x86_64-unknown-linux-gnu\\\":[\\\"x86_64-unknown-linux-gnu\\\"],\\\"x86_64-unknown-nixos-gnu\\\":[\\\"x86_64-unknown-nixos-gnu\\\"]},\\\"crate_context\\\":{\\\"name\\\":\\\"external_crate\\\",\\\"version\\\":\\\"0.1.0\\\",\\\"package_url\\\":null,\\\"repository\\\":{\\\"Path\\\":{\\\"path\\\":\\\"external_crate\\\"}},\\\"targets\\\":[{\\\"Library\\\":{\\\"crate_name\\\":\\\"external_crate\\\",\\\"crate_root\\\":\\\"src/lib.rs\\\",\\\"srcs\\\":{\\\"allow_empty\\\":true,\\\"include\\\":[\\\"**/*.rs\\\"]}}}],\\\"library_target_name\\\":\\\"external_crate\\\",\\\"common_attrs\\\":{\\\"compile_data_glob\\\":[\\\"**\\\"],\\\"edition\\\":\\\"2021\\\",\\\"version\\\":\\\"0.1.0\\\"},\\\"license\\\":null,\\\"license_ids\\\":[],\\\"license_file\\\":null}}\",\n path = \"external_crate\",\n )\n\n local_crate_mirror(\n name = \"crates__external_crate_b-0.1.0\",\n options_json = \"{\\\"config\\\":{\\\"repository_name\\\":\\\"crates\\\",\\\"build_file_template\\\":\\\"@crates//crates:BUILD.{name}-{version}.bazel\\\",\\\"crate_label_template\\\":\\\"@{repository}__{name}-{version}//:{target}\\\",\\\"crate_alias_template\\\":\\\"@{repository}//:{name}-{version}\\\",\\\"crates_module_template\\\":\\\"@crates//crates:{file}\\\",\\\"crate_repository_template\\\":\\\"{repository}__{name}-{version}\\\",\\\"default_alias_rule\\\":\\\"alias\\\",\\\"default_package_name\\\":null,\\\"generate_target_compatible_with\\\":true,\\\"platforms_template\\\":\\\"@rules_rust//rust/platform:{triple}\\\",\\\"regen_command\\\":\\\"bazel mod show_repo 'external_relative_path_deps_test'\\\",\\\"vendor_mode\\\":\\\"remote\\\",\\\"generate_rules_license_metadata\\\":false,\\\"generate_cargo_toml_env_vars\\\":true},\\\"supported_platform_triples\\\":[\\\"aarch64-apple-darwin\\\",\\\"aarch64-unknown-linux-gnu\\\",\\\"wasm32-unknown-unknown\\\",\\\"wasm32-wasip1\\\",\\\"x86_64-pc-windows-msvc\\\",\\\"x86_64-unknown-linux-gnu\\\",\\\"x86_64-unknown-nixos-gnu\\\"],\\\"platform_conditions\\\":{\\\"aarch64-apple-darwin\\\":[\\\"aarch64-apple-darwin\\\"],\\\"aarch64-unknown-linux-gnu\\\":[\\\"aarch64-unknown-linux-gnu\\\"],\\\"wasm32-unknown-unknown\\\":[\\\"wasm32-unknown-unknown\\\"],\\\"wasm32-wasip1\\\":[\\\"wasm32-wasip1\\\"],\\\"x86_64-pc-windows-msvc\\\":[\\\"x86_64-pc-windows-msvc\\\"],\\\"x86_64-unknown-linux-gnu\\\":[\\\"x86_64-unknown-linux-gnu\\\"],\\\"x86_64-unknown-nixos-gnu\\\":[\\\"x86_64-unknown-nixos-gnu\\\"]},\\\"crate_context\\\":{\\\"name\\\":\\\"external_crate_b\\\",\\\"version\\\":\\\"0.1.0\\\",\\\"package_url\\\":null,\\\"repository\\\":{\\\"Path\\\":{\\\"path\\\":\\\"external_crate_b\\\"}},\\\"targets\\\":[{\\\"Library\\\":{\\\"crate_name\\\":\\\"external_crate_b\\\",\\\"crate_root\\\":\\\"src/lib.rs\\\",\\\"srcs\\\":{\\\"allow_empty\\\":true,\\\"include\\\":[\\\"**/*.rs\\\"]}}}],\\\"library_target_name\\\":\\\"external_crate_b\\\",\\\"common_attrs\\\":{\\\"compile_data_glob\\\":[\\\"**\\\"],\\\"edition\\\":\\\"2021\\\",\\\"version\\\":\\\"0.1.0\\\"},\\\"license\\\":null,\\\"license_ids\\\":[],\\\"license_file\\\":null}}\",\n path = \"external_crate_b\",\n )\n return [\n struct(repo=\"crates__ext_ws_crate-0.1.0\", is_dev_dep = False),\n struct(repo=\"crates__external_crate-0.1.0\", is_dev_dep = False),\n struct(repo=\"crates__external_crate_b-0.1.0\", is_dev_dep = False),\n ]\n" + } + } + }, + "crates__ext_ws_crate-0.1.0": { + "repoRuleId": "@@rules_rust+//crate_universe/private:local_crate_mirror.bzl%local_crate_mirror", + "attributes": { + "options_json": "{\"config\":{\"build_file_template\":\"@crates//crates:BUILD.{name}-{version}.bazel\",\"crate_alias_template\":\"@{repository}//:{name}-{version}\",\"crate_label_template\":\"@{repository}__{name}-{version}//:{target}\",\"crate_repository_template\":\"{repository}__{name}-{version}\",\"crates_module_template\":\"@crates//crates:{file}\",\"default_alias_rule\":\"alias\",\"default_package_name\":null,\"generate_cargo_toml_env_vars\":true,\"generate_rules_license_metadata\":false,\"generate_target_compatible_with\":true,\"platforms_template\":\"@rules_rust//rust/platform:{triple}\",\"regen_command\":\"bazel mod show_repo 'external_relative_path_deps_test'\",\"repository_name\":\"crates\",\"vendor_mode\":\"remote\"},\"crate_context\":{\"common_attrs\":{\"compile_data_glob\":[\"**\"],\"edition\":\"2021\",\"version\":\"0.1.0\"},\"library_target_name\":\"ext_ws_crate\",\"license\":null,\"license_file\":null,\"license_ids\":[],\"name\":\"ext_ws_crate\",\"package_url\":null,\"repository\":{\"Path\":{\"path\":\"external_workspace/ext_ws_crate\"}},\"targets\":[{\"Library\":{\"crate_name\":\"ext_ws_crate\",\"crate_root\":\"src/lib.rs\",\"srcs\":{\"allow_empty\":true,\"include\":[\"**/*.rs\"]}}}],\"version\":\"0.1.0\"},\"platform_conditions\":{\"aarch64-apple-darwin\":[\"aarch64-apple-darwin\"],\"aarch64-unknown-linux-gnu\":[\"aarch64-unknown-linux-gnu\"],\"wasm32-unknown-unknown\":[\"wasm32-unknown-unknown\"],\"wasm32-wasip1\":[\"wasm32-wasip1\"],\"x86_64-pc-windows-msvc\":[\"x86_64-pc-windows-msvc\"],\"x86_64-unknown-linux-gnu\":[\"x86_64-unknown-linux-gnu\"],\"x86_64-unknown-nixos-gnu\":[\"x86_64-unknown-nixos-gnu\"]},\"supported_platform_triples\":[\"aarch64-apple-darwin\",\"aarch64-unknown-linux-gnu\",\"wasm32-unknown-unknown\",\"wasm32-wasip1\",\"x86_64-pc-windows-msvc\",\"x86_64-unknown-linux-gnu\",\"x86_64-unknown-nixos-gnu\"]}", + "path": "external_workspace/ext_ws_crate", + "generator": "@cargo_bazel_bootstrap//:cargo-bazel" + } + }, + "crates__external_crate-0.1.0": { + "repoRuleId": "@@rules_rust+//crate_universe/private:local_crate_mirror.bzl%local_crate_mirror", + "attributes": { + "options_json": "{\"config\":{\"build_file_template\":\"@crates//crates:BUILD.{name}-{version}.bazel\",\"crate_alias_template\":\"@{repository}//:{name}-{version}\",\"crate_label_template\":\"@{repository}__{name}-{version}//:{target}\",\"crate_repository_template\":\"{repository}__{name}-{version}\",\"crates_module_template\":\"@crates//crates:{file}\",\"default_alias_rule\":\"alias\",\"default_package_name\":null,\"generate_cargo_toml_env_vars\":true,\"generate_rules_license_metadata\":false,\"generate_target_compatible_with\":true,\"platforms_template\":\"@rules_rust//rust/platform:{triple}\",\"regen_command\":\"bazel mod show_repo 'external_relative_path_deps_test'\",\"repository_name\":\"crates\",\"vendor_mode\":\"remote\"},\"crate_context\":{\"common_attrs\":{\"compile_data_glob\":[\"**\"],\"edition\":\"2021\",\"version\":\"0.1.0\"},\"library_target_name\":\"external_crate\",\"license\":null,\"license_file\":null,\"license_ids\":[],\"name\":\"external_crate\",\"package_url\":null,\"repository\":{\"Path\":{\"path\":\"external_crate\"}},\"targets\":[{\"Library\":{\"crate_name\":\"external_crate\",\"crate_root\":\"src/lib.rs\",\"srcs\":{\"allow_empty\":true,\"include\":[\"**/*.rs\"]}}}],\"version\":\"0.1.0\"},\"platform_conditions\":{\"aarch64-apple-darwin\":[\"aarch64-apple-darwin\"],\"aarch64-unknown-linux-gnu\":[\"aarch64-unknown-linux-gnu\"],\"wasm32-unknown-unknown\":[\"wasm32-unknown-unknown\"],\"wasm32-wasip1\":[\"wasm32-wasip1\"],\"x86_64-pc-windows-msvc\":[\"x86_64-pc-windows-msvc\"],\"x86_64-unknown-linux-gnu\":[\"x86_64-unknown-linux-gnu\"],\"x86_64-unknown-nixos-gnu\":[\"x86_64-unknown-nixos-gnu\"]},\"supported_platform_triples\":[\"aarch64-apple-darwin\",\"aarch64-unknown-linux-gnu\",\"wasm32-unknown-unknown\",\"wasm32-wasip1\",\"x86_64-pc-windows-msvc\",\"x86_64-unknown-linux-gnu\",\"x86_64-unknown-nixos-gnu\"]}", + "path": "external_crate", + "generator": "@cargo_bazel_bootstrap//:cargo-bazel" + } + }, + "crates__external_crate_b-0.1.0": { + "repoRuleId": "@@rules_rust+//crate_universe/private:local_crate_mirror.bzl%local_crate_mirror", + "attributes": { + "options_json": "{\"config\":{\"build_file_template\":\"@crates//crates:BUILD.{name}-{version}.bazel\",\"crate_alias_template\":\"@{repository}//:{name}-{version}\",\"crate_label_template\":\"@{repository}__{name}-{version}//:{target}\",\"crate_repository_template\":\"{repository}__{name}-{version}\",\"crates_module_template\":\"@crates//crates:{file}\",\"default_alias_rule\":\"alias\",\"default_package_name\":null,\"generate_cargo_toml_env_vars\":true,\"generate_rules_license_metadata\":false,\"generate_target_compatible_with\":true,\"platforms_template\":\"@rules_rust//rust/platform:{triple}\",\"regen_command\":\"bazel mod show_repo 'external_relative_path_deps_test'\",\"repository_name\":\"crates\",\"vendor_mode\":\"remote\"},\"crate_context\":{\"common_attrs\":{\"compile_data_glob\":[\"**\"],\"edition\":\"2021\",\"version\":\"0.1.0\"},\"library_target_name\":\"external_crate_b\",\"license\":null,\"license_file\":null,\"license_ids\":[],\"name\":\"external_crate_b\",\"package_url\":null,\"repository\":{\"Path\":{\"path\":\"external_crate_b\"}},\"targets\":[{\"Library\":{\"crate_name\":\"external_crate_b\",\"crate_root\":\"src/lib.rs\",\"srcs\":{\"allow_empty\":true,\"include\":[\"**/*.rs\"]}}}],\"version\":\"0.1.0\"},\"platform_conditions\":{\"aarch64-apple-darwin\":[\"aarch64-apple-darwin\"],\"aarch64-unknown-linux-gnu\":[\"aarch64-unknown-linux-gnu\"],\"wasm32-unknown-unknown\":[\"wasm32-unknown-unknown\"],\"wasm32-wasip1\":[\"wasm32-wasip1\"],\"x86_64-pc-windows-msvc\":[\"x86_64-pc-windows-msvc\"],\"x86_64-unknown-linux-gnu\":[\"x86_64-unknown-linux-gnu\"],\"x86_64-unknown-nixos-gnu\":[\"x86_64-unknown-nixos-gnu\"]},\"supported_platform_triples\":[\"aarch64-apple-darwin\",\"aarch64-unknown-linux-gnu\",\"wasm32-unknown-unknown\",\"wasm32-wasip1\",\"x86_64-pc-windows-msvc\",\"x86_64-unknown-linux-gnu\",\"x86_64-unknown-nixos-gnu\"]}", + "path": "external_crate_b", + "generator": "@cargo_bazel_bootstrap//:cargo-bazel" + } + } + }, + "moduleExtensionMetadata": { + "useAllRepos": "NO", + "reproducible": false + }, + "recordedRepoMappingEntries": [ + [ + "bazel_features+", + "bazel_features_globals", + "bazel_features++version_extension+bazel_features_globals" + ], + [ + "bazel_features+", + "bazel_features_version", + "bazel_features++version_extension+bazel_features_version" + ], + [ + "rules_cc+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_cc+", + "rules_cc", + "rules_cc+" + ], + [ + "rules_rust+", + "bazel_features", + "bazel_features+" + ], + [ + "rules_rust+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "rules_rust+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_rust+", + "cargo_bazel_bootstrap", + "rules_rust++cu_nr+cargo_bazel_bootstrap" + ], + [ + "rules_rust+", + "rules_cc", + "rules_cc+" + ], + [ + "rules_rust+", + "rules_rust", + "rules_rust+" + ] + ] + } + }, "@@rules_rust+//crate_universe/private:internal_extensions.bzl%cu_nr": { "general": { - "bzlTransitiveDigest": "Lst2lMpOzFV9C04lgQsrDWSpTsSYPVnJogVLNBT7qUM=", + "bzlTransitiveDigest": "1kGklr6UrYdp0ud6Tfpy8l8QoPE41wJxdXI085HNLMc=", "usagesDigest": "qhmy4zrnFb6knNQRx2XBCVfHObom0vnflm+sibd7SA0=", "recordedFileInputs": {}, "recordedDirentsInputs": {},