-
Notifications
You must be signed in to change notification settings - Fork 533
feat(rust_common): allow compile actions to declare more outdirs #3737
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
Open
alexeagle
wants to merge
8
commits into
bazelbuild:main
Choose a base branch
from
alexeagle:extra_rust_outdirs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
e410375
feat(rust_common): allow compile actions to declare that extra folder…
alexeagle 1db278d
fmt
alexeagle 20458bb
fmt
alexeagle 0aab520
code review: panic instead
alexeagle 1c3df52
add sh_test checking content of extra outdir
alexeagle 9d3d8a5
add note about paths are relative
alexeagle b482e4f
fmt
alexeagle c8a8b04
rm some files that are mistakenly not gitignored
alexeagle File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| load("@bazel_skylib//rules:select_file.bzl", "select_file") | ||
| load("@rules_shell//shell:sh_test.bzl", "sh_test") | ||
| load("//rust:defs.bzl", "rust_library", "rust_proc_macro") | ||
| load(":extra_outdirs_test.bzl", "extra_outdirs_test_suite") | ||
|
|
||
| rust_proc_macro( | ||
| name = "write_outdirs_macro", | ||
| srcs = ["proc_macro.rs"], | ||
| edition = "2018", | ||
| visibility = ["//test:__subpackages__"], | ||
| ) | ||
|
|
||
| rust_library( | ||
| name = "lib", | ||
| srcs = ["lib.rs"], | ||
| edition = "2018", | ||
| ) | ||
|
|
||
| rust_library( | ||
| name = "lib_with_outdirs", | ||
| srcs = ["lib_with_outdirs.rs"], | ||
| edition = "2018", | ||
| extra_outdirs = [ | ||
| "test_dir", | ||
| "another_dir", | ||
| ], | ||
| proc_macro_deps = [":write_outdirs_macro"], | ||
| rustc_env = { | ||
| "EXTRA_OUTDIRS": "test_dir,another_dir", | ||
| }, | ||
| ) | ||
|
|
||
| extra_outdirs_test_suite( | ||
alexeagle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| name = "extra_outdirs_test_suite", | ||
| ) | ||
|
|
||
| select_file( | ||
| name = "lib_with_outdirs_select_file", | ||
| srcs = ":lib_with_outdirs", | ||
| subpath = "test_dir", | ||
| visibility = ["//visibility:public"], | ||
| ) | ||
|
|
||
| sh_test( | ||
| name = "outdirs_content_test", | ||
| srcs = ["outdirs_content_test.sh"], | ||
| args = [ | ||
| "$(rlocationpath :lib_with_outdirs_select_file)", | ||
| ], | ||
| data = [ | ||
| ":lib_with_outdirs_select_file", | ||
| ], | ||
| deps = ["@rules_shell//shell/runfiles"], | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| """Unittest to verify extra_outdirs attribute adds directories to action outputs.""" | ||
|
|
||
| load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") | ||
| load("//test/unit:common.bzl", "assert_action_mnemonic") | ||
|
|
||
| def _extra_outdirs_present_test(ctx): | ||
| env = analysistest.begin(ctx) | ||
| target = analysistest.target_under_test(env) | ||
|
|
||
| # Find the Rustc action | ||
| rustc_action = [action for action in target.actions if action.mnemonic == "Rustc"][0] | ||
| assert_action_mnemonic(env, rustc_action, "Rustc") | ||
|
|
||
| # Get all outputs from the action | ||
| outputs = rustc_action.outputs.to_list() | ||
|
|
||
| # Check that the expected directories are in the outputs | ||
| expected_dirs = ctx.attr.expected_outdirs | ||
| found_dirs = [] | ||
|
|
||
| for output in outputs: | ||
| # Check if this output is a directory | ||
| # and if its basename matches one of our expected directories | ||
| if output.is_directory: | ||
| if output.basename in expected_dirs: | ||
| found_dirs.append(output.basename) | ||
|
|
||
| # Verify all expected directories were found | ||
| asserts.equals( | ||
| env, | ||
| sorted(found_dirs), | ||
| sorted(expected_dirs), | ||
| "Expected to find directories {expected} in action outputs, but found {found}".format( | ||
| expected = expected_dirs, | ||
| found = found_dirs, | ||
| ), | ||
| ) | ||
|
|
||
| return analysistest.end(env) | ||
|
|
||
| def _extra_outdirs_not_present_test(ctx): | ||
| env = analysistest.begin(ctx) | ||
| target = analysistest.target_under_test(env) | ||
|
|
||
| # Find the Rustc action | ||
| rustc_action = [action for action in target.actions if action.mnemonic == "Rustc"][0] | ||
| assert_action_mnemonic(env, rustc_action, "Rustc") | ||
|
|
||
| # Get all outputs from the action | ||
| outputs = rustc_action.outputs.to_list() | ||
|
|
||
| # Check that no extra directories are present | ||
| # We expect only the standard outputs (rlib, rmeta if pipelining, etc.) | ||
| # but not any extra_outdirs directories | ||
| unexpected_dirs = [] | ||
| for output in outputs: | ||
| if output.is_directory: | ||
| # Standard directories like .dSYM are okay, but we shouldn't have | ||
| # any of the extra_outdirs we're testing for | ||
| if output.basename in ["test_dir", "another_dir"]: | ||
| unexpected_dirs.append(output.basename) | ||
|
|
||
| asserts.equals( | ||
| env, | ||
| [], | ||
| unexpected_dirs, | ||
| "Expected no extra_outdirs directories, but found {found}".format( | ||
| found = unexpected_dirs, | ||
| ), | ||
| ) | ||
|
|
||
| return analysistest.end(env) | ||
|
|
||
| extra_outdirs_present_test = analysistest.make( | ||
| _extra_outdirs_present_test, | ||
| attrs = { | ||
| "expected_outdirs": attr.string_list( | ||
| mandatory = True, | ||
| doc = "List of expected output directory names", | ||
| ), | ||
| }, | ||
| ) | ||
|
|
||
| extra_outdirs_not_present_test = analysistest.make(_extra_outdirs_not_present_test) | ||
|
|
||
| def extra_outdirs_test_suite(name): | ||
| """Entry-point macro called from the BUILD file. | ||
|
|
||
| Args: | ||
| name (str): Name of the macro. | ||
| """ | ||
| extra_outdirs_not_present_test( | ||
| name = "extra_outdirs_not_present_test", | ||
| target_under_test = ":lib", | ||
| ) | ||
|
|
||
| extra_outdirs_present_test( | ||
| name = "extra_outdirs_present_test", | ||
| target_under_test = ":lib_with_outdirs", | ||
| expected_outdirs = ["test_dir", "another_dir"], | ||
| ) | ||
|
|
||
| native.test_suite( | ||
| name = name, | ||
| tests = [ | ||
| ":extra_outdirs_not_present_test", | ||
| ":extra_outdirs_present_test", | ||
| ], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| pub fn call() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| use write_outdirs_macro::write_to_outdirs; | ||
|
|
||
| write_to_outdirs!(); | ||
|
|
||
| pub fn call() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| #! /bin/bash | ||
| ls -alR | ||
|
|
||
| # --- begin runfiles.bash initialization v3 --- | ||
| # Copy-pasted from the Bazel Bash runfiles library v3. | ||
| set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash | ||
| # shellcheck disable=SC1090 | ||
| source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ | ||
| source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ | ||
| source "$0.runfiles/$f" 2>/dev/null || \ | ||
| source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ | ||
| source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ | ||
| { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e | ||
| # --- end runfiles.bash initialization v3 --- | ||
| set -euo pipefail | ||
|
|
||
| for dir in "$@"; do | ||
| if [ ! -d "$(rlocation "$dir")" ]; then | ||
| echo "Directory $dir does not exist" | ||
| exit 1 | ||
| fi | ||
| if [ ! -f "$(rlocation "$dir")/marker.txt" ]; then | ||
| echo "Marker file in directory $dir does not exist" | ||
| exit 1 | ||
| fi | ||
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // Similar to | ||
| // https://github.com/napi-rs/napi-rs/blob/main/crates/macro/src/expand/typedef/type_def.rs#L11-L12 | ||
| // this proc macro has a side-effect of writing extra metadata directories. | ||
| use proc_macro::TokenStream; | ||
| use std::env; | ||
| use std::fs; | ||
| use std::path::PathBuf; | ||
|
|
||
| #[proc_macro] | ||
| pub fn write_to_outdirs(_item: TokenStream) -> TokenStream { | ||
| // Read the list of directories to write to from an environment variable | ||
| let outdirs = env::var("EXTRA_OUTDIRS") | ||
| .expect("EXTRA_OUTDIRS environment variable must be set"); | ||
|
|
||
| // Read the output directory paths from Bazel | ||
| // Format: EXTRA_OUTDIRS_PATHS=dir1:path1,dir2:path2 | ||
| let outdirs_paths = env::var("EXTRA_OUTDIRS_PATHS") | ||
| .expect("EXTRA_OUTDIRS_PATHS environment variable must be set"); | ||
|
|
||
| // Create a map of directory name to output path | ||
| let mut path_map = std::collections::HashMap::new(); | ||
| for entry in outdirs_paths.split(',') { | ||
| if let Some((dir, path)) = entry.split_once(':') { | ||
| path_map.insert(dir.trim(), path.trim()); | ||
| } | ||
| } | ||
|
|
||
| // Write to the output directories declared by Bazel | ||
| for dir in outdirs.split(',') { | ||
| let dir = dir.trim(); | ||
| if !dir.is_empty() { | ||
| // Get the output path for this directory | ||
| let dir_path = if let Some(path) = path_map.get(dir) { | ||
| PathBuf::from(path) | ||
| } else { | ||
| // Fallback to directory name if path not found | ||
| PathBuf::from(dir) | ||
| }; | ||
|
|
||
| // Create the directory if it doesn't exist | ||
| if let Err(e) = fs::create_dir_all(&dir_path) { | ||
| panic!("Failed to create directory {}: {:?}", dir_path.display(), e); | ||
| } | ||
| // Write a marker file to ensure the directory is created | ||
| let marker_file = dir_path.join("marker.txt"); | ||
| if let Err(e) = fs::write(&marker_file, "created by proc-macro") { | ||
| panic!("Failed to write marker file to {}: {:?}", marker_file.display(), e); | ||
| } | ||
| } | ||
| } | ||
| TokenStream::new() | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Can you make sure the output dirs support location expansion? That's how I'd expect this to be used.
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 added to the docstring:
"The paths are always relative to the output directory of the current Bazel package."
I would not expect them to support location expansion, but only because https://bazel.build/rules/lib/toplevel/attr#output_list doesn't have an equivalent output_dir_list, so there's no way during analysis to resolve such expansions.
Seems like a missing feature in Bazel to me.
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.
Wait, why is
output_dir_listneeded? Does it matter if you're expanding a file or directory?