-
Notifications
You must be signed in to change notification settings - Fork 431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bzlmod-aware runfiles library #2566
Conversation
82eab55
to
6236ef1
Compare
tools/runfiles/runfiles.rs
Outdated
@@ -19,13 +19,13 @@ | |||
//! use runfiles::Runfiles; | |||
//! ``` | |||
//! | |||
//! 3. Create a Runfiles object and use rlocation to look up runfile paths: | |||
//! 3. Create a Runfiles object and use Rlocation! to look up runfile paths: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be title-case? I was under the impression that naming conventions dictated that since it's a function, it should be rlocation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, I wasn't sure what the convention was for macros but I think you're right
tools/runfiles/runfiles.rs
Outdated
} | ||
|
||
impl Runfiles { | ||
/// Creates a manifest based Runfiles object when | ||
/// RUNFILES_MANIFEST_ONLY environment variable is present, | ||
/// or a directory based Runfiles object otherwise. | ||
pub fn create() -> io::Result<Self> { | ||
if is_manifest_only() { | ||
let mode = if is_manifest_only() { | ||
Self::create_manifest_based() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC @fmeum said that the canonical implementation is at rules_python and that other implementations should seek to follow that. In all other implementations, we create the manifest based one if RUNFILES_MANIFEST_FILE exists, otherwise we create it based on RUNFILES_DIR.
I believe we should instead have:
let mode = if let Ok(manifest_file) = std::env::var(MANIFEST_FILE_ENV_VAR) {
create_manifest_based(Path::from(manifest_file))?
} else {
Mode::DirectoryBased(find_runfiles_dir()?)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy to swap to that. It's a bit riskier since it's a behavior change but it's more correct you point out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RUNFILES_MANIFEST_ONLY
is a trap that breaks cross-platform builds and should not be used. Instead, I would say the following flow is the best you can do at this point in time:
- If at least one of
RUNFILES_MANIFEST_FILE
orRUNFILES_DIR
is set:- If
RUNFILES_MANIFEST_FILE
is set and exists, use it. - If
RUNFILES_DIR
is set and exists, use it. - Error.
- If
- If the runfiles manifest exists in one of the well-known locations, use it.
- If the runfiles directory exists in one of the well-known locations, use it.
- Error.
tools/runfiles/runfiles.rs
Outdated
@@ -44,36 +44,49 @@ const MANIFEST_FILE_ENV_VAR: &str = "RUNFILES_MANIFEST_FILE"; | |||
const MANIFEST_ONLY_ENV_VAR: &str = "RUNFILES_MANIFEST_ONLY"; | |||
const TEST_SRCDIR_ENV_VAR: &str = "TEST_SRCDIR"; | |||
|
|||
#[macro_export] | |||
macro_rules! Rlocation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not going to say we should do it one way or the other, but we should definitely at least consider the folllowing API as an alternative:
let r = runfiles::create!() // Expands to runfiles::create(env!("REPOSITORY_NAME"))
r.rlocation(path)
Pros:
- More clean API (less macros)
- More performant (only need to calculate the repo mapping once)
- Simpler to migrate to (only migrate the runfiles constructor, not the rlocation calls)
Cons:
- If you're passing the runfiles constructor across repo boundaries, it might do the wrong repo mapping. I can't see this ever happening though - I've never seen a public API that takes in runfiles, because they can just create the runfiles object themselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep I asked @fmeum the same and he mentioned passing across repo boundaries is a nice to have. I'm fine either way but let's figure it out in this thread before I refactor more :)
Re: more performant - I think it's the same? The mapping is only calculated at startup? Or if you're referring to the map lookups + string ops - you're about to do File IO, I don't think it matters :)
The migration path is also a good point. I think as-written the code doesn't require any client changes, but they can move to the new API to become more correct. I think with your proposal everyone using runfiles needs a minor code change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good point about the migration path, I hadn't notice that we left the old method, so I thought this whole PR was backwards incompatible. If that's the case, I think we definitely just do it the way you've already done it.
cb7a2bf
to
c719e80
Compare
@@ -13,7 +13,7 @@ def _get_rustfmt_ready_crate_info(target): | |||
""" | |||
|
|||
# Ignore external targets | |||
if target.label.workspace_root.startswith("external"): | |||
if target.label.workspace_name: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
driveby cleanup to not depend on external
@UebelAndre this is passing tests now. I'm planning to add an external-repo integration test as well to double check, but assuming that is OK, can we merge this? None of us have a better idea how to make this work correctly and if I understand correctly the state of the world, enabling bzlmod in a repo with rust code will make rust-analyzer not work correctly, even if the rust rules are not using bzlmod. Would be good to get a fix in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks! It'd be great to have that external repo test you mentioned.
tools/runfiles/runfiles.rs
Outdated
.lines() | ||
.map(|line| { | ||
let parts: Vec<String> = line.splitn(3, ',').map(String::from).collect(); | ||
((parts[0].clone(), parts[1].clone()), parts[2].clone()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to error rather than panic if this file is malformed and doesn't contain 3 elements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, I also fixed the duplicative string copying while I was here
I added it as a separate commit. It's a bit complicated setup but it's what we need to really verify we are using the correct repo_mapping of transitive repos instead of just the main one |
f962dcb
to
5ef713a
Compare
Does this break the existing API? Can you update the PR description to reflect the changes some more? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me! Will leave for @UebelAndre to review/merge when happy
No, this is a new API to make this non-breaking, and the existing API is marked deprecated. The PR summary already mentioned that, but I expanded it a bit, hopefully it's clearer now! |
@UebelAndre does the PR description make sense now? Anything else you'd like to see before this lands? |
@UebelAndre @illicitonion What can I do to get this unstuck and landed? This PR is blocking other issues, such as #2615. There have been other attempts to fix this for over a year now, such as: first one, second one. I think I have spent more time trying to get this PR landed than it took to write the code, which is a little frustrating as you can imagine. |
This PR LGTM, and as it was already approved by @illicitonion a while back, I'm going to to ahead and merge it. @UebelAndre please feel free to do post-merge review, and we'll follow up. |
Dismissing review to enable merge when ready. The PR author has addressed the reviewer's comments.
Sorry, this one fell through the cracks. I didn't mean to delay the change! |
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [rules_rust](https://togithub.com/bazelbuild/rules_rust) | http_archive | minor | `0.42.1` -> `0.43.0` | --- ### Release Notes <details> <summary>bazelbuild/rules_rust (rules_rust)</summary> ### [`v0.43.0`](https://togithub.com/bazelbuild/rules_rust/releases/tag/0.43.0) [Compare Source](https://togithub.com/bazelbuild/rules_rust/compare/0.42.1...0.43.0) ### 0.43.0 ```python load("@​bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "rules_rust", integrity = "sha256-SnzocNvQp1YK1TW/aUVhR6RSROo1l2RilE1V20WFnK0=", urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.43.0/rules_rust-v0.43.0.tar.gz"], ) ``` Additional documentation can be found at: https://bazelbuild.github.io/rules_rust/#setup #### What's Changed - Bzlmod-aware runfiles library by [@​dzbarsky](https://togithub.com/dzbarsky) in [https://github.com/bazelbuild/rules_rust/pull/2566](https://togithub.com/bazelbuild/rules_rust/pull/2566) - Add clippy_flag flag to allow flags to be added in succession. by [@​granaghan](https://togithub.com/granaghan) in [https://github.com/bazelbuild/rules_rust/pull/2625](https://togithub.com/bazelbuild/rules_rust/pull/2625) - Add aspect_rules_js to MODULE.bazel by [@​dzbarsky](https://togithub.com/dzbarsky) in [https://github.com/bazelbuild/rules_rust/pull/2618](https://togithub.com/bazelbuild/rules_rust/pull/2618) - Register a default rust toolchain. by [@​matts1](https://togithub.com/matts1) in [https://github.com/bazelbuild/rules_rust/pull/2624](https://togithub.com/bazelbuild/rules_rust/pull/2624) - Nit: Fix link to example in rust_bindgen.md by [@​hauserx](https://togithub.com/hauserx) in [https://github.com/bazelbuild/rules_rust/pull/2628](https://togithub.com/bazelbuild/rules_rust/pull/2628) - Add context to error messages by [@​illicitonion](https://togithub.com/illicitonion) in [https://github.com/bazelbuild/rules_rust/pull/2408](https://togithub.com/bazelbuild/rules_rust/pull/2408) - Update `cargo_bootstrap_repository` interface to match dependency macros by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2630](https://togithub.com/bazelbuild/rules_rust/pull/2630) - Added debug logging for spliced manifests to crate_universe by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2629](https://togithub.com/bazelbuild/rules_rust/pull/2629) - also rewrite -isystem in addition to -sysroot by [@​adrianimboden](https://togithub.com/adrianimboden) in [https://github.com/bazelbuild/rules_rust/pull/2631](https://togithub.com/bazelbuild/rules_rust/pull/2631) - Support loading http credentials from netrc by [@​golovasteek](https://togithub.com/golovasteek) in [https://github.com/bazelbuild/rules_rust/pull/2623](https://togithub.com/bazelbuild/rules_rust/pull/2623) - Updated Buildifier version for crate_universe by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2634](https://togithub.com/bazelbuild/rules_rust/pull/2634) - Follow-up documentation/fixes to lockfile API by [@​illicitonion](https://togithub.com/illicitonion) in [https://github.com/bazelbuild/rules_rust/pull/2637](https://togithub.com/bazelbuild/rules_rust/pull/2637) - Add docs and examples of complicated build scripts by [@​illicitonion](https://togithub.com/illicitonion) in [https://github.com/bazelbuild/rules_rust/pull/2635](https://togithub.com/bazelbuild/rules_rust/pull/2635) - Added Rust 1.78.0 by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2639](https://togithub.com/bazelbuild/rules_rust/pull/2639) - Remove `incompatible_test_attr_crate_and_srcs_mutually_exclusive` by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2641](https://togithub.com/bazelbuild/rules_rust/pull/2641) - Minor cleanup for crate_universe by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2644](https://togithub.com/bazelbuild/rules_rust/pull/2644) - Use `cargo tree` to determine feature dependent optional deps by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2636](https://togithub.com/bazelbuild/rules_rust/pull/2636) - Release 0.43.0 by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2642](https://togithub.com/bazelbuild/rules_rust/pull/2642) - Update cross to fix crate_universe builds in releases by [@​UebelAndre](https://togithub.com/UebelAndre) in [https://github.com/bazelbuild/rules_rust/pull/2645](https://togithub.com/bazelbuild/rules_rust/pull/2645) #### New Contributors - [@​hauserx](https://togithub.com/hauserx) made their first contribution in [https://github.com/bazelbuild/rules_rust/pull/2628](https://togithub.com/bazelbuild/rules_rust/pull/2628) - [@​adrianimboden](https://togithub.com/adrianimboden) made their first contribution in [https://github.com/bazelbuild/rules_rust/pull/2631](https://togithub.com/bazelbuild/rules_rust/pull/2631) - [@​golovasteek](https://togithub.com/golovasteek) made their first contribution in [https://github.com/bazelbuild/rules_rust/pull/2623](https://togithub.com/bazelbuild/rules_rust/pull/2623) **Full Changelog**: bazelbuild/rules_rust@0.42.1...0.43.0 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bazel-contrib/toolchains_llvm). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNTEuMiIsInVwZGF0ZWRJblZlciI6IjM3LjM1MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This implements the repo_mapping capabilities and provides a new runfiles API. The new API can be accessed explicitly as
runfiles::Runfiles::rlocation_from
or with therunfiles::rlocation!
macro, which adds compile-time support for correctly embedding the external repo. This is a purely new API, existing usage continues to work, although we mark it deprecated because it's not fully correct. We can remove it at some point in the future.This PR also transitions in-repo examples/tests to using it, in case anyone copies them.