From f9a82786b44287d26de3a7689bcb94cbe3ed5311 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 05:58:59 -0700 Subject: [PATCH 01/19] Updated `//util/launcher` to be more commonly usable and updated rustdoc rules to use it --- rust/private/BUILD.bazel | 1 + rust/private/rust.bzl | 96 +++------------------ rust/private/rustdoc_test.bzl | 125 ++++++++------------------- util/launcher/BUILD.bazel | 8 ++ util/launcher/launcher.bzl | 150 +++++++++++++++++++++++++++++++++ util/launcher/launcher_main.rs | 25 ++++-- 6 files changed, 226 insertions(+), 179 deletions(-) create mode 100644 util/launcher/launcher.bzl diff --git a/rust/private/BUILD.bazel b/rust/private/BUILD.bazel index 119af07117..b88dae1188 100644 --- a/rust/private/BUILD.bazel +++ b/rust/private/BUILD.bazel @@ -8,5 +8,6 @@ bzl_library( visibility = ["//rust:__subpackages__"], deps = [ "//rust/platform:rules", + "//util/launcher:bzl_lib", ], ) diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index 6fc07e5716..15b47920e6 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -20,9 +20,9 @@ load( "crate_name_from_attr", "dedent", "determine_output_hash", - "expand_dict_value_locations", "find_toolchain", ) +load("//util/launcher:launcher.bzl", "create_launcher") # TODO(marco): Separate each rule into its own file. @@ -304,88 +304,6 @@ def _rust_binary_impl(ctx): ), ) -def _create_test_launcher(ctx, toolchain, output, providers): - """Create a process wrapper to ensure runtime environment variables are defined for the test binary - - Args: - ctx (ctx): The rule's context object - toolchain (rust_toolchain): The current rust toolchain - output (File): The output File that will be produced, depends on crate type. - providers (list): Providers from a rust compile action. See `rustc_compile_action` - - Returns: - list: A list of providers similar to `rustc_compile_action` but with modified default info - """ - - # TODO: It's unclear if the toolchain is in the same configuration as the `_launcher` attribute - # This should be investigated but for now, we generally assume if the target environment is windows, - # the execution environment is windows. - if toolchain.os == "windows": - launcher_filename = ctx.label.name + ".launcher.exe" - else: - launcher_filename = ctx.label.name + ".launcher" - - launcher = ctx.actions.declare_file(launcher_filename) - - # Because returned executables must be created from the same rule, the - # launcher target is simply symlinked and exposed. - ctx.actions.symlink( - output = launcher, - target_file = ctx.executable._launcher, - is_executable = True, - ) - - # Get data attribute - data = getattr(ctx.attr, "data", []) - - # Expand the environment variables and write them to a file - environ_file = ctx.actions.declare_file(launcher_filename + ".launchfiles/env") - environ = expand_dict_value_locations( - ctx, - getattr(ctx.attr, "env", {}), - data, - ) - - # Convert the environment variables into a list to be written into a file. - environ_list = [] - for key, value in sorted(environ.items()): - environ_list.extend([key, value]) - - ctx.actions.write( - output = environ_file, - content = "\n".join(environ_list), - ) - - launcher_files = [environ_file] - - # Replace the `DefaultInfo` provider in the returned list - default_info = None - for i in range(len(providers)): - if type(providers[i]) == "DefaultInfo": - default_info = providers[i] - providers.pop(i) - break - - if not default_info: - fail("No DefaultInfo provider returned from `rustc_compile_action`") - - providers.extend([ - DefaultInfo( - files = default_info.files, - runfiles = default_info.default_runfiles.merge( - # The output is now also considered a runfile - ctx.runfiles(files = launcher_files + [output]), - ), - executable = launcher, - ), - OutputGroupInfo( - launcher_files = depset(launcher_files), - output = depset([output]), - ), - ]) - - return providers - def _rust_test_common(ctx, toolchain, output): """Builds a Rust test binary. @@ -452,7 +370,17 @@ def _rust_test_common(ctx, toolchain, output): rust_flags = ["--test"] if ctx.attr.use_libtest_harness else ["--cfg", "test"], ) - return _create_test_launcher(ctx, toolchain, output, providers) + env = getattr(ctx.attr, "env", {}) + data = getattr(ctx.attr, "data", []) + + return create_launcher( + ctx = ctx, + toolchain = toolchain, + providers = providers, + env = env, + data = data, + executable = output, + ) def _rust_test_impl(ctx): """The implementation of the `rust_test` rule diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 7eda389010..cd6da6d9e5 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -15,6 +15,7 @@ # buildifier: disable=module-docstring load("//rust/private:common.bzl", "rust_common") load("//rust/private:utils.bzl", "find_toolchain", "get_lib_name", "get_preferred_artifact") +load("//util/launcher:launcher.bzl", "create_launcher") def _rust_doc_test_impl(ctx): """The implementation for the `rust_doc_test` rule @@ -41,11 +42,7 @@ def _rust_doc_test_impl(ctx): # Construct rustdoc test command, which will be written to a shell script # to be executed to run the test. - flags = _build_rustdoc_flags(dep_info, crate_info) - if toolchain.os != "windows": - rust_doc_test = _build_rustdoc_test_bash_script(ctx, toolchain, flags, crate_info) - else: - rust_doc_test = _build_rustdoc_test_batch_script(ctx, toolchain, flags, crate_info) + flags = _build_rustdoc_flags(dep_info, crate_info, toolchain) # The test script compiles the crate and runs it, so it needs both compile and runtime inputs. compile_inputs = depset( @@ -61,13 +58,26 @@ def _rust_doc_test_impl(ctx): ], ) - return [DefaultInfo( - runfiles = ctx.runfiles( - files = compile_inputs.to_list(), - collect_data = True, - ), - executable = rust_doc_test, - )] + rustdoc = ctx.actions.declare_file(ctx.label.name + toolchain.binary_ext) + ctx.actions.symlink( + output = rustdoc, + target_file = toolchain.rust_doc, + is_executable = True, + ) + + return create_launcher( + ctx = ctx, + args = [ + "--test", + crate_info.root.path, + "--crate-name={}".format(crate_info.name), + ] + flags, + toolchain = toolchain, + providers = [DefaultInfo( + runfiles = ctx.runfiles(transitive_files = compile_inputs), + )], + executable = rustdoc, + ) # TODO: Replace with bazel-skylib's `path.dirname`. This requires addressing some dependency issues or # generating docs will break. @@ -82,12 +92,13 @@ def _dirname(path_str): """ return "/".join(path_str.split("/")[:-1]) -def _build_rustdoc_flags(dep_info, crate_info): +def _build_rustdoc_flags(dep_info, crate_info, toolchain): """Constructs the rustdoc script used to test `crate`. Args: dep_info (DepInfo): The DepInfo provider crate_info (CrateInfo): The CrateInfo provider + toolchain (rust_toolchain): The curret `rust_toolchain`. Returns: list: A list of rustdoc flags (str) @@ -121,80 +132,6 @@ def _build_rustdoc_flags(dep_info, crate_info): return link_search_flags + link_flags + edition_flags -_rustdoc_test_bash_script = """\ -#!/usr/bin/env bash - -set -e; - -{rust_doc} --test \\ - {crate_root} \\ - --crate-name={crate_name} \\ - {flags} -""" - -def _build_rustdoc_test_bash_script(ctx, toolchain, flags, crate_info): - """Generates a helper script for executing a rustdoc test for unix systems - - Args: - ctx (ctx): The `rust_doc_test` rule's context object - toolchain (ToolchainInfo): A rustdoc toolchain - flags (list): A list of rustdoc flags (str) - crate_info (CrateInfo): The CrateInfo provider - - Returns: - File: An executable containing information for a rustdoc test - """ - rust_doc_test = ctx.actions.declare_file( - ctx.label.name + ".sh", - ) - ctx.actions.write( - output = rust_doc_test, - content = _rustdoc_test_bash_script.format( - rust_doc = toolchain.rust_doc.short_path, - crate_root = crate_info.root.path, - crate_name = crate_info.name, - # TODO: Should be possible to do this with ctx.actions.Args, but can't seem to get them as a str and into the template. - flags = " \\\n ".join(flags), - ), - is_executable = True, - ) - return rust_doc_test - -_rustdoc_test_batch_script = """\ -{rust_doc} --test ^ - {crate_root} ^ - --crate-name={crate_name} ^ - {flags} -""" - -def _build_rustdoc_test_batch_script(ctx, toolchain, flags, crate_info): - """Generates a helper script for executing a rustdoc test for windows systems - - Args: - ctx (ctx): The `rust_doc_test` rule's context object - toolchain (ToolchainInfo): A rustdoc toolchain - flags (list): A list of rustdoc flags (str) - crate_info (CrateInfo): The CrateInfo provider - - Returns: - File: An executable containing information for a rustdoc test - """ - rust_doc_test = ctx.actions.declare_file( - ctx.label.name + ".bat", - ) - ctx.actions.write( - output = rust_doc_test, - content = _rustdoc_test_batch_script.format( - rust_doc = toolchain.rust_doc.short_path.replace("/", "\\"), - crate_root = crate_info.root.path, - crate_name = crate_info.name, - # TODO: Should be possible to do this with ctx.actions.Args, but can't seem to get them as a str and into the template. - flags = " ^\n ".join(flags), - ), - is_executable = True, - ) - return rust_doc_test - rust_doc_test = rule( implementation = _rust_doc_test_impl, attrs = { @@ -212,10 +149,20 @@ rust_doc_test = rule( doc = "__deprecated__: use `crate`", providers = [rust_common.crate_info], ), + "_launcher": attr.label( + executable = True, + default = Label("//util/launcher:launcher"), + cfg = "exec", + doc = ( + "A launcher executable for loading environment and argument files passed in via the " + + "`env` attribute and ensuring the variables are set for the underlying test executable." + ), + ), }, - executable = True, test = True, - toolchains = [str(Label("//rust:toolchain"))], + toolchains = [ + str(Label("//rust:toolchain")), + ], incompatible_use_toolchain_transition = True, doc = """Runs Rust documentation tests. diff --git a/util/launcher/BUILD.bazel b/util/launcher/BUILD.bazel index 8b52057ea6..c3c0139749 100644 --- a/util/launcher/BUILD.bazel +++ b/util/launcher/BUILD.bazel @@ -1,3 +1,4 @@ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//rust:rust.bzl", "rust_binary") package(default_visibility = ["//visibility:public"]) @@ -7,3 +8,10 @@ rust_binary( srcs = ["launcher_main.rs"], edition = "2018", ) + +bzl_library( + name = "bzl_lib", + srcs = glob( + ["**/*.bzl"], + ), +) diff --git a/util/launcher/launcher.bzl b/util/launcher/launcher.bzl new file mode 100644 index 0000000000..4d9e8cb557 --- /dev/null +++ b/util/launcher/launcher.bzl @@ -0,0 +1,150 @@ +"""Rust executable launcher module""" + +# buildifier: disable=bzl-visibility +load("//rust/private:utils.bzl", "expand_dict_value_locations") + +def _write_environ(ctx, launcher_filename, env, data): + file = ctx.actions.declare_file(launcher_filename + ".launchfiles/env") + environ = expand_dict_value_locations( + ctx, + env, + data, + ) + + # Convert the environment variables into a list to be written into a file. + environ_list = [] + for key, value in sorted(environ.items()): + environ_list.extend([key, value]) + + ctx.actions.write( + output = file, + content = "\n".join(environ_list), + ) + + return file + +def _write_args(ctx, launcher_filename, args, data): + # Convert the arguments list into a dictionary so args can benefit from + # the existing expand_dict_value_locations functionality + args_dict = {"{}".format(i): args[i] for i in range(0, len(args))} + + file = ctx.actions.declare_file(launcher_filename + ".launchfiles/args") + expanded_args = expand_dict_value_locations( + ctx, + args_dict, + data, + ) + + ctx.actions.write( + output = file, + content = "\n".join(expanded_args.values()), + ) + + return file + +def _write_executable(ctx, launcher_filename, executable = None): + file = ctx.actions.declare_file(launcher_filename + ".launchfiles/exec") + + ctx.actions.write( + output = file, + content = executable.path if executable else "", + ) + + return file + +def _merge_providers(ctx, providers, launcher, launcher_files, executable = None): + # Replace the `DefaultInfo` provider in the returned list + default_info = None + for i in range(len(providers)): + if type(providers[i]) == "DefaultInfo": + default_info = providers[i] + providers.pop(i) + break + + if not default_info: + fail("list must contain a `DefaultInfo` provider") + + # Additionally update the `OutputGroupInfo` provider + output_group_info = None + for i in range(len(providers)): + if type(providers[i]) == "OutputGroupInfo": + output_group_info = providers[i] + providers.pop(i) + break + + if output_group_info: + output_group_info = OutputGroupInfo( + launcher_files = depset(launcher_files), + output = depset([executable or default_info.files_to_run.executable]), + **output_group_info + ) + else: + output_group_info = OutputGroupInfo( + launcher_files = depset(launcher_files), + output = depset([executable or default_info.files_to_run.executable]), + ) + + providers.extend([ + DefaultInfo( + files = default_info.files, + runfiles = default_info.default_runfiles.merge( + # The original executable is now also considered a runfile + ctx.runfiles(files = launcher_files + [ + executable or default_info.files_to_run.executable, + ]), + ), + executable = launcher, + ), + output_group_info, + ]) + + return providers + +def create_launcher(ctx, toolchain, args = [], env = {}, data = [], providers = [], executable = None): + """Create a process wrapper to ensure runtime environment variables are defined for the test binary + + Args: + ctx (ctx): The rule's context object + toolchain (rust_toolchain): The current rust toolchain + args (list, optional): Optional arguments to include in the lancher + env (dict, optional): Optional environment variables to include in the lancher + data (list, optional): Targets to use when performing location expansion on `args` and `env`. + providers (list, optional): Providers from a rust compile action. See `rustc_compile_action` + executable (File, optional): An optional executable for the launcher to wrap + + Returns: + list: A list of providers similar to `rustc_compile_action` but with modified default info + """ + + # TODO: It's unclear if the toolchain is in the same configuration as the `_launcher` attribute + # This should be investigated but for now, we generally assume if the target environment is windows, + # the execution environment is windows. + if toolchain.os == "windows": + launcher_filename = ctx.label.name + ".launcher.exe" + else: + launcher_filename = ctx.label.name + ".launcher" + + launcher = ctx.actions.declare_file(launcher_filename) + + # Because returned executables must be created from the same rule, the + # launcher target is simply symlinked and exposed. + ctx.actions.symlink( + output = launcher, + target_file = ctx.executable._launcher, + is_executable = True, + ) + + # Expand the environment variables and write them to a file + launcher_files = [ + _write_environ(ctx, launcher_filename, env, data), + _write_args(ctx, launcher_filename, args, data), + _write_executable(ctx, launcher_filename, executable), + ] + + return _merge_providers( + ctx = ctx, + providers = providers, + launcher = launcher, + launcher_files = launcher_files, + executable = executable, + ) diff --git a/util/launcher/launcher_main.rs b/util/launcher/launcher_main.rs index 006d051911..64802530b2 100644 --- a/util/launcher/launcher_main.rs +++ b/util/launcher/launcher_main.rs @@ -11,6 +11,9 @@ use std::os::unix::process::CommandExt; /// This string must match the one found in `_create_test_launcher` const LAUNCHFILES_ENV_PATH: &str = ".launchfiles/env"; +/// This string must match the one found in `_create_test_launcher` +const LAUNCHFILES_ARGS_PATH: &str = ".launchfiles/args"; + /// Load environment variables from a uniquly formatted fn environ() -> BTreeMap { let mut environ = BTreeMap::new(); @@ -48,9 +51,10 @@ fn environ() -> BTreeMap { environ } -/// Locate the executable based on the name of the launcher executable +/// Locate the underlying executable intended to be started under the launcher fn executable() -> PathBuf { - // Consume the first argument (argv[0]) + // When no executable is provided explicitly via the launcher file, fallback + // to searching for the executable based on the name of the launcher itself. let mut exec_path = std::env::args().next().expect("arg 0 was not set"); let stem_index = exec_path .rfind(".launcher") @@ -67,7 +71,16 @@ fn executable() -> PathBuf { /// Parse the command line arguments but skip the first element which /// is the path to the test runner executable. fn args() -> Vec { - std::env::args().skip(1).collect() + // Load the environment file into a map + let args_path = std::env::args().next().expect("arg 0 was not set") + LAUNCHFILES_ARGS_PATH; + let file = File::open(args_path).expect("Failed to load the environment file"); + + // Note that arguments from the args file always go first + BufReader::new(file) + .lines() + .map(|line| line.expect("Failed to read file")) + .chain(std::env::args().skip(1)) + .collect() } /// Simply replace the current process with our test @@ -85,13 +98,13 @@ fn exec(environ: BTreeMap, executable: PathBuf, args: Vec, executable: PathBuf, args: Vec) { - let output = Command::new(executable) + let result = Command::new(executable) .envs(environ.iter()) .args(args) - .output() + .status() .expect("Failed to run process"); - std::process::exit(output.status.code().unwrap_or(1)); + std::process::exit(result.code().unwrap_or(1)); } /// Main entrypoint From c6eb59859d232b2532dd19409cd7fa668c96e71d Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 06:30:45 -0700 Subject: [PATCH 02/19] test --- rust/private/rustdoc_test.bzl | 5 +++++ rust/private/toolchain_utils.bzl | 26 ++++++++++++++++++++++++++ util/launcher/launcher_main.rs | 7 ++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index cd6da6d9e5..75fa1d02cc 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -14,6 +14,7 @@ # buildifier: disable=module-docstring load("//rust/private:common.bzl", "rust_common") +load("//rust/private:toolchain_utils.bzl", "find_sysroot") load("//rust/private:utils.bzl", "find_toolchain", "get_lib_name", "get_preferred_artifact") load("//util/launcher:launcher.bzl", "create_launcher") @@ -114,6 +115,10 @@ def _build_rustdoc_flags(dep_info, crate_info, toolchain): link_flags += ["--extern=" + c.name + "=" + c.dep.output.short_path for c in d.direct_crates.to_list()] link_search_flags += ["-Ldependency={}".format(_dirname(c.output.short_path)) for c in d.transitive_crates.to_list()] + sysroot = find_sysroot(toolchain, short_path = True) + if sysroot: + link_search_flags.extend(["--sysroot", "${{pwd}}/{}".format(sysroot)]) + # TODO(hlopko): use the more robust logic from rustc.bzl also here, through a reasonable API. for lib_to_link in dep_info.transitive_noncrates.to_list(): is_static = bool(lib_to_link.static_library or lib_to_link.pic_static_library) diff --git a/rust/private/toolchain_utils.bzl b/rust/private/toolchain_utils.bzl index f26acf298b..99095e7143 100644 --- a/rust/private/toolchain_utils.bzl +++ b/rust/private/toolchain_utils.bzl @@ -1,5 +1,31 @@ """A module defining toolchain utilities""" +def find_sysroot(rust_toolchain, short_path = False): + """Locate the sysroot for a given toolchain + + Args: + rust_toolchain (rust_toolchain): A rust toolchain + short_path (bool): Whether or not to use a short path to the sysroot + + Returns: + str, optional: The path of the toolchain's sysroot + """ + + # Sysroot is determined by using a rust stdlib file, expected to be at + # `${SYSROOT}/lib/rustlib/${target_triple}/lib`, and strip the known + # directories from the sysroot path. + rust_stdlib_files = rust_toolchain.rust_lib.files.to_list() + if rust_stdlib_files: + # Determine the sysroot by taking a rust stdlib file, expected to be `${sysroot}/lib` + if short_path: + split = rust_stdlib_files[0].short_path.rsplit("/", 5) + else: + split = rust_stdlib_files[0].path.rsplit("/", 5) + sysroot = split[0] + return sysroot + + return None + def _toolchain_files_impl(ctx): toolchain = ctx.toolchains[str(Label("//rust:toolchain"))] diff --git a/util/launcher/launcher_main.rs b/util/launcher/launcher_main.rs index 64802530b2..7e237e1ef6 100644 --- a/util/launcher/launcher_main.rs +++ b/util/launcher/launcher_main.rs @@ -75,10 +75,15 @@ fn args() -> Vec { let args_path = std::env::args().next().expect("arg 0 was not set") + LAUNCHFILES_ARGS_PATH; let file = File::open(args_path).expect("Failed to load the environment file"); + // Variables will have the `${pwd}` variable replaced which is rendered by + // `@rules_rust//rust/private:util.bzl::expand_dict_value_locations` + let pwd = std::env::current_dir().expect("Failed to get current working directory"); + let pwd_str = pwd.to_string_lossy(); + // Note that arguments from the args file always go first BufReader::new(file) .lines() - .map(|line| line.expect("Failed to read file")) + .map(|line| line.expect("Failed to read file").replace("${pwd}", &pwd_str)) .chain(std::env::args().skip(1)) .collect() } From 865d15f11f0e0e68fa9700f941ab1e5f8c712915 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 07:24:07 -0700 Subject: [PATCH 03/19] test --- util/launcher/launcher_main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/launcher/launcher_main.rs b/util/launcher/launcher_main.rs index 7e237e1ef6..547229d227 100644 --- a/util/launcher/launcher_main.rs +++ b/util/launcher/launcher_main.rs @@ -83,7 +83,10 @@ fn args() -> Vec { // Note that arguments from the args file always go first BufReader::new(file) .lines() - .map(|line| line.expect("Failed to read file").replace("${pwd}", &pwd_str)) + .map(|line| { + line.expect("Failed to read file") + .replace("${pwd}", &pwd_str) + }) .chain(std::env::args().skip(1)) .collect() } From 29c88815562764446fdf9c34c9aa9d98c8cbe4e9 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 07:42:57 -0700 Subject: [PATCH 04/19] test2 --- rust/private/rustdoc_test.bzl | 67 ++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 75fa1d02cc..18a106dc53 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -13,11 +13,32 @@ # limitations under the License. # buildifier: disable=module-docstring +load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "C_COMPILE_ACTION_NAME") load("//rust/private:common.bzl", "rust_common") load("//rust/private:toolchain_utils.bzl", "find_sysroot") -load("//rust/private:utils.bzl", "find_toolchain", "get_lib_name", "get_preferred_artifact") +load("//rust/private:utils.bzl", "find_cc_toolchain", "find_toolchain", "get_lib_name", "get_preferred_artifact") load("//util/launcher:launcher.bzl", "create_launcher") +def get_cc_compile_env(cc_toolchain, feature_configuration): + """Gather cc environment variables from the given `cc_toolchain` + + Args: + cc_toolchain (cc_toolchain): The current rule's `cc_toolchain`. + feature_configuration (FeatureConfiguration): Class used to construct command lines from CROSSTOOL features. + + Returns: + dict: Returns environment variables to be set for given action. + """ + compile_variables = cc_common.create_compile_variables( + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + ) + return cc_common.get_environment_variables( + feature_configuration = feature_configuration, + action_name = C_COMPILE_ACTION_NAME, + variables = compile_variables, + ) + def _rust_doc_test_impl(ctx): """The implementation for the `rust_doc_test` rule @@ -43,7 +64,7 @@ def _rust_doc_test_impl(ctx): # Construct rustdoc test command, which will be written to a shell script # to be executed to run the test. - flags = _build_rustdoc_flags(dep_info, crate_info, toolchain) + flags, env, toolchain_tools = _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain) # The test script compiles the crate and runs it, so it needs both compile and runtime inputs. compile_inputs = depset( @@ -56,7 +77,7 @@ def _rust_doc_test_impl(ctx): dep_info.transitive_libs, toolchain.rustc_lib.files, toolchain.rust_lib.files, - ], + ] + toolchain_tools, ) rustdoc = ctx.actions.declare_file(ctx.label.name + toolchain.binary_ext) @@ -73,6 +94,7 @@ def _rust_doc_test_impl(ctx): crate_info.root.path, "--crate-name={}".format(crate_info.name), ] + flags, + env = env, toolchain = toolchain, providers = [DefaultInfo( runfiles = ctx.runfiles(transitive_files = compile_inputs), @@ -93,10 +115,11 @@ def _dirname(path_str): """ return "/".join(path_str.split("/")[:-1]) -def _build_rustdoc_flags(dep_info, crate_info, toolchain): +def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): """Constructs the rustdoc script used to test `crate`. Args: + ctx (ctx): The rule's context object. dep_info (DepInfo): The DepInfo provider crate_info (CrateInfo): The CrateInfo provider toolchain (rust_toolchain): The curret `rust_toolchain`. @@ -135,7 +158,36 @@ def _build_rustdoc_flags(dep_info, crate_info, toolchain): edition_flags = ["--edition={}".format(crate_info.edition)] if crate_info.edition != "2015" else [] - return link_search_flags + link_flags + edition_flags + flags = link_search_flags + link_flags + edition_flags + + # Build a set of environment variables to use for the test + env = {} + toolchain_tools = [] + cc_toolchain, feature_configuration = find_cc_toolchain(ctx) + cc_env = get_cc_compile_env(cc_toolchain, feature_configuration) + + # MSVC requires INCLUDE to be set + include = cc_env.get("INCLUDE") + if include: + env["INCLUDE"] = include + + if cc_toolchain: + toolchain_tools.append(cc_toolchain.all_files) + + cc_executable = cc_toolchain.compiler_executable + if cc_executable: + env["CC"] = cc_executable + ar_executable = cc_toolchain.ar_executable + if ar_executable: + # The default MacOS toolchain uses libtool as ar_executable not ar. + # This doesn't work when used as $AR, so simply don't set it - tools will probably fall back to + # /usr/bin/ar which is probably good enough. + if not ar_executable.endswith("libtool"): + env["AR"] = ar_executable + if cc_toolchain.sysroot: + env["SYSROOT"] = cc_toolchain.sysroot + + return flags, env, toolchain_tools rust_doc_test = rule( implementation = _rust_doc_test_impl, @@ -154,6 +206,9 @@ rust_doc_test = rule( doc = "__deprecated__: use `crate`", providers = [rust_common.crate_info], ), + "_cc_toolchain": attr.label( + default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), + ), "_launcher": attr.label( executable = True, default = Label("//util/launcher:launcher"), @@ -165,8 +220,10 @@ rust_doc_test = rule( ), }, test = True, + fragments = ["cpp"], toolchains = [ str(Label("//rust:toolchain")), + "@bazel_tools//tools/cpp:toolchain_type", ], incompatible_use_toolchain_transition = True, doc = """Runs Rust documentation tests. From 36ac11ce3e64c55ebd17a51c6cc48c107dddcad8 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 07:47:22 -0700 Subject: [PATCH 05/19] test --- util/launcher/launcher_main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/launcher/launcher_main.rs b/util/launcher/launcher_main.rs index 547229d227..1987e3a621 100644 --- a/util/launcher/launcher_main.rs +++ b/util/launcher/launcher_main.rs @@ -94,6 +94,10 @@ fn args() -> Vec { /// Simply replace the current process with our test #[cfg(target_family = "unix")] fn exec(environ: BTreeMap, executable: PathBuf, args: Vec) { + println!("{:?}", std::env::current_dir()); + println!("{:#?}", args); + println!("{:#?}", environ); + println!("{:?}", executable); let error = Command::new(&executable) .envs(environ.iter()) .args(args) From b4dd6b407c9b87e65abe88892516ac72a151fd8f Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 07:52:44 -0700 Subject: [PATCH 06/19] test3 --- rust/private/rustdoc_test.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 18a106dc53..c2e3f5f38a 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -141,6 +141,7 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): sysroot = find_sysroot(toolchain, short_path = True) if sysroot: link_search_flags.extend(["--sysroot", "${{pwd}}/{}".format(sysroot)]) + link_search_flags.extend(["--target", toolchain.target_flag_value]) # TODO(hlopko): use the more robust logic from rustc.bzl also here, through a reasonable API. for lib_to_link in dep_info.transitive_noncrates.to_list(): From ac3f6094bad600702e4e8c80b8b15b85982c8155 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 07:53:27 -0700 Subject: [PATCH 07/19] test --- util/launcher/launcher_main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/launcher/launcher_main.rs b/util/launcher/launcher_main.rs index 1987e3a621..a7a587223a 100644 --- a/util/launcher/launcher_main.rs +++ b/util/launcher/launcher_main.rs @@ -110,6 +110,10 @@ fn exec(environ: BTreeMap, executable: PathBuf, args: Vec, executable: PathBuf, args: Vec) { + println!("{:?}", std::env::current_dir()); + println!("{:#?}", args); + println!("{:#?}", environ); + println!("{:?}", executable); let result = Command::new(executable) .envs(environ.iter()) .args(args) From 8eb319328035115b32ec9825889d272faadeb4f3 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 07:58:25 -0700 Subject: [PATCH 08/19] keep --- .bazelci/presubmit.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 8eec83ae11..f3fb75e9f1 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -45,10 +45,6 @@ tasks: - "//test/..." - "@examples//..." - "-//test/conflicting_deps:conflicting_deps_test" - # rust_doc_test is likely not fully sandboxed - - "-//test/chained_direct_deps:mod3_doc_test" - - "-@examples//fibonacci:fibonacci_doc_test" - - "-@examples//hello_lib:hello_lib_doc_test" - "-@examples//ffi/rust_calling_c/simple/..." # See https://github.com/bazelbuild/bazel/issues/9987 - "-@examples//ffi/rust_calling_c:matrix_dylib_test" From 8ca7e53870378d8e8d9951acba265e8ff79019df Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 08:00:23 -0700 Subject: [PATCH 09/19] more test --- rust/private/rustdoc_test.bzl | 1 + util/launcher/launcher.bzl | 7 +++++++ util/launcher/launcher_main.rs | 9 +++++++++ 3 files changed, 17 insertions(+) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index c2e3f5f38a..92965f75c6 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -188,6 +188,7 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): if cc_toolchain.sysroot: env["SYSROOT"] = cc_toolchain.sysroot + env["SYSROOT"] = "${{pwd}}/{}".format(sysroot) return flags, env, toolchain_tools rust_doc_test = rule( diff --git a/util/launcher/launcher.bzl b/util/launcher/launcher.bzl index 4d9e8cb557..f1229b8574 100644 --- a/util/launcher/launcher.bzl +++ b/util/launcher/launcher.bzl @@ -84,6 +84,13 @@ def _merge_providers(ctx, providers, launcher, launcher_files, executable = None output = depset([executable or default_info.files_to_run.executable]), ) + print(ctx.label, default_info.default_runfiles.merge( + # The original executable is now also considered a runfile + ctx.runfiles(files = launcher_files + [ + executable or default_info.files_to_run.executable, + ]), + ).files) + providers.extend([ DefaultInfo( files = default_info.files, diff --git a/util/launcher/launcher_main.rs b/util/launcher/launcher_main.rs index a7a587223a..a8cb0b5cf4 100644 --- a/util/launcher/launcher_main.rs +++ b/util/launcher/launcher_main.rs @@ -98,6 +98,14 @@ fn exec(environ: BTreeMap, executable: PathBuf, args: Vec, executable: PathBuf, args: Vec Date: Tue, 10 Aug 2021 08:56:11 -0700 Subject: [PATCH 10/19] more --- util/launcher/launcher.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/util/launcher/launcher.bzl b/util/launcher/launcher.bzl index f1229b8574..d359fc7af0 100644 --- a/util/launcher/launcher.bzl +++ b/util/launcher/launcher.bzl @@ -84,6 +84,7 @@ def _merge_providers(ctx, providers, launcher, launcher_files, executable = None output = depset([executable or default_info.files_to_run.executable]), ) + # buildifier: disable=print print(ctx.label, default_info.default_runfiles.merge( # The original executable is now also considered a runfile ctx.runfiles(files = launcher_files + [ From 68235769acb9e278767d6c0e8fff6b1e35bfa371 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 09:56:14 -0700 Subject: [PATCH 11/19] tree test --- util/launcher/launcher_main.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/util/launcher/launcher_main.rs b/util/launcher/launcher_main.rs index a8cb0b5cf4..3aacfe3c87 100644 --- a/util/launcher/launcher_main.rs +++ b/util/launcher/launcher_main.rs @@ -91,6 +91,22 @@ fn args() -> Vec { .collect() } +fn print_tree(start: &str) { + println!("Name: {}", start); + for path in std::fs::read_dir(&start).unwrap() { + let path_buf = path.unwrap().path(); + if path_buf.is_file() { + println!("Name: {}", path_buf.display()); + } + } + for path in std::fs::read_dir(&start).unwrap() { + let path_buf = path.unwrap().path(); + if path_buf.is_dir() { + print_tree(path_buf.to_str().unwrap()); + } + } +} + /// Simply replace the current process with our test #[cfg(target_family = "unix")] fn exec(environ: BTreeMap, executable: PathBuf, args: Vec) { @@ -100,10 +116,7 @@ fn exec(environ: BTreeMap, executable: PathBuf, args: Vec, executable: PathBuf, args: Vec Date: Tue, 10 Aug 2021 10:20:37 -0700 Subject: [PATCH 12/19] arg test --- rust/private/rustdoc_test.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 92965f75c6..a9378cc02c 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -140,8 +140,8 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): sysroot = find_sysroot(toolchain, short_path = True) if sysroot: - link_search_flags.extend(["--sysroot", "${{pwd}}/{}".format(sysroot)]) - link_search_flags.extend(["--target", toolchain.target_flag_value]) + link_search_flags.append("--sysroot=${{pwd}}/{}".format(sysroot)) + link_search_flags.append("--target={}".format(toolchain.target_flag_value)) # TODO(hlopko): use the more robust logic from rustc.bzl also here, through a reasonable API. for lib_to_link in dep_info.transitive_noncrates.to_list(): From 4b14f0af90549873b18d55b9d318927046e1867f Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 10:25:11 -0700 Subject: [PATCH 13/19] maybe? --- rust/private/rustdoc_test.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index a9378cc02c..8de6dc040d 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -97,6 +97,7 @@ def _rust_doc_test_impl(ctx): env = env, toolchain = toolchain, providers = [DefaultInfo( + files = toolchain.rustc_lib.files, runfiles = ctx.runfiles(transitive_files = compile_inputs), )], executable = rustdoc, From 4c0f356219b651cb7fbe6503c1d57cff58851c81 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 10:28:31 -0700 Subject: [PATCH 14/19] explicit test --- rust/private/rustdoc_test.bzl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 8de6dc040d..049cc0f01e 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -139,6 +139,14 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): link_flags += ["--extern=" + c.name + "=" + c.dep.output.short_path for c in d.direct_crates.to_list()] link_search_flags += ["-Ldependency={}".format(_dirname(c.output.short_path)) for c in d.transitive_crates.to_list()] + # Gets the paths to the folders containing the standard library (or libcore) + rust_lib_files = depset(transitive = [toolchain.rust_lib.files, toolchain.rustc_lib.files]) + rust_lib_paths = depset([file.short_path for file in rust_lib_files.to_list()]).to_list() + rust_lib_dirs = depset([file.rsplit("/", 1)[0] for file in rust_lib_paths]).to_list() + + # Tell Rustc where to find the standard library + link_search_flags.extend(["-L ${{pwd}}/{}".format(lib) for lib in rust_lib_dirs]) + sysroot = find_sysroot(toolchain, short_path = True) if sysroot: link_search_flags.append("--sysroot=${{pwd}}/{}".format(sysroot)) From b01eae760f9420c52ef082e897bb2305a129c86c Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 10:53:47 -0700 Subject: [PATCH 15/19] ld lib path? --- rust/private/rustdoc_test.bzl | 12 +++++++++--- util/launcher/launcher.bzl | 12 ++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 049cc0f01e..2bcd86f3ae 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -143,9 +143,10 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): rust_lib_files = depset(transitive = [toolchain.rust_lib.files, toolchain.rustc_lib.files]) rust_lib_paths = depset([file.short_path for file in rust_lib_files.to_list()]).to_list() rust_lib_dirs = depset([file.rsplit("/", 1)[0] for file in rust_lib_paths]).to_list() + rust_lib_dirs = ["${{pwd}}/{}".format(lib) for lib in rust_lib_dirs] # Tell Rustc where to find the standard library - link_search_flags.extend(["-L ${{pwd}}/{}".format(lib) for lib in rust_lib_dirs]) + link_search_flags.extend(["-L {}".format(lib) for lib in rust_lib_dirs]) sysroot = find_sysroot(toolchain, short_path = True) if sysroot: @@ -170,8 +171,11 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): flags = link_search_flags + link_flags + edition_flags + # Start with the default shell env, which contains any --action_env + # settings passed in on the command line. + env = dict(ctx.configuration.default_shell_env) + # Build a set of environment variables to use for the test - env = {} toolchain_tools = [] cc_toolchain, feature_configuration = find_cc_toolchain(ctx) cc_env = get_cc_compile_env(cc_toolchain, feature_configuration) @@ -197,7 +201,9 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): if cc_toolchain.sysroot: env["SYSROOT"] = cc_toolchain.sysroot - env["SYSROOT"] = "${{pwd}}/{}".format(sysroot) + # env["SYSROOT"] = "${{pwd}}/{}".format(sysroot) + env["LD_LIBRARY_PATH"] = env.get("LD_LIBRARY_PATH", "") + ":".join(rust_lib_dirs) + env["DYLD_LIBRARY_PATH"] = env.get("DYLD_LIBRARY_PATH", "") + ":".join(rust_lib_dirs) return flags, env, toolchain_tools rust_doc_test = rule( diff --git a/util/launcher/launcher.bzl b/util/launcher/launcher.bzl index d359fc7af0..b56943213b 100644 --- a/util/launcher/launcher.bzl +++ b/util/launcher/launcher.bzl @@ -85,12 +85,12 @@ def _merge_providers(ctx, providers, launcher, launcher_files, executable = None ) # buildifier: disable=print - print(ctx.label, default_info.default_runfiles.merge( - # The original executable is now also considered a runfile - ctx.runfiles(files = launcher_files + [ - executable or default_info.files_to_run.executable, - ]), - ).files) + # print(ctx.label, default_info.default_runfiles.merge( + # # The original executable is now also considered a runfile + # ctx.runfiles(files = launcher_files + [ + # executable or default_info.files_to_run.executable, + # ]), + # ).files) providers.extend([ DefaultInfo( From 174fdb53193d468b90bfd85a7b11b2d1c30b5ade Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 11:14:39 -0700 Subject: [PATCH 16/19] cleaning? --- rust/private/rustdoc_test.bzl | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 2bcd86f3ae..dc3e5901ed 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -139,15 +139,6 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): link_flags += ["--extern=" + c.name + "=" + c.dep.output.short_path for c in d.direct_crates.to_list()] link_search_flags += ["-Ldependency={}".format(_dirname(c.output.short_path)) for c in d.transitive_crates.to_list()] - # Gets the paths to the folders containing the standard library (or libcore) - rust_lib_files = depset(transitive = [toolchain.rust_lib.files, toolchain.rustc_lib.files]) - rust_lib_paths = depset([file.short_path for file in rust_lib_files.to_list()]).to_list() - rust_lib_dirs = depset([file.rsplit("/", 1)[0] for file in rust_lib_paths]).to_list() - rust_lib_dirs = ["${{pwd}}/{}".format(lib) for lib in rust_lib_dirs] - - # Tell Rustc where to find the standard library - link_search_flags.extend(["-L {}".format(lib) for lib in rust_lib_dirs]) - sysroot = find_sysroot(toolchain, short_path = True) if sysroot: link_search_flags.append("--sysroot=${{pwd}}/{}".format(sysroot)) @@ -201,6 +192,11 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): if cc_toolchain.sysroot: env["SYSROOT"] = cc_toolchain.sysroot + # Gets the paths to the folders containing the standard library (or libcore) + rust_lib_files = depset(transitive = [toolchain.rust_lib.files, toolchain.rustc_lib.files]) + rust_lib_paths = depset([file.short_path for file in rust_lib_files.to_list()]).to_list() + rust_lib_dirs = depset([file.rsplit("/", 1)[0] for file in rust_lib_paths]).to_list() + rust_lib_dirs = ["${{pwd}}/{}".format(lib) for lib in rust_lib_dirs] # env["SYSROOT"] = "${{pwd}}/{}".format(sysroot) env["LD_LIBRARY_PATH"] = env.get("LD_LIBRARY_PATH", "") + ":".join(rust_lib_dirs) env["DYLD_LIBRARY_PATH"] = env.get("DYLD_LIBRARY_PATH", "") + ":".join(rust_lib_dirs) From cba555d82632360aa3ba19b093e14f01b9de4dce Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 11:19:09 -0700 Subject: [PATCH 17/19] rbe? --- rust/private/rustdoc_test.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index dc3e5901ed..8403640e94 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -183,12 +183,12 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): if cc_executable: env["CC"] = cc_executable ar_executable = cc_toolchain.ar_executable - if ar_executable: + # if ar_executable: # The default MacOS toolchain uses libtool as ar_executable not ar. # This doesn't work when used as $AR, so simply don't set it - tools will probably fall back to # /usr/bin/ar which is probably good enough. - if not ar_executable.endswith("libtool"): - env["AR"] = ar_executable + # if not ar_executable.endswith("libtool"): + # env["AR"] = ar_executable if cc_toolchain.sysroot: env["SYSROOT"] = cc_toolchain.sysroot From f3a1f2277cf878231f4ec863b37f6104b49bb38f Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 11:26:01 -0700 Subject: [PATCH 18/19] linker? --- rust/private/rustdoc_test.bzl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index 8403640e94..ae2a59d876 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -183,12 +183,13 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): if cc_executable: env["CC"] = cc_executable ar_executable = cc_toolchain.ar_executable - # if ar_executable: + if ar_executable: # The default MacOS toolchain uses libtool as ar_executable not ar. # This doesn't work when used as $AR, so simply don't set it - tools will probably fall back to # /usr/bin/ar which is probably good enough. - # if not ar_executable.endswith("libtool"): - # env["AR"] = ar_executable + if not ar_executable.endswith("libtool"): + env["AR"] = ar_executable + flags.extend(["-C", "linker={}".format(ar_executable)]) if cc_toolchain.sysroot: env["SYSROOT"] = cc_toolchain.sysroot From a71df5b53fee45bb68292d73552f3f6321e81765 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 10 Aug 2021 14:31:14 -0700 Subject: [PATCH 19/19] asdf --- rust/private/rustdoc_test.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl index ae2a59d876..c3f8ed5c28 100644 --- a/rust/private/rustdoc_test.bzl +++ b/rust/private/rustdoc_test.bzl @@ -170,6 +170,7 @@ def _build_rustdoc_flags(ctx, dep_info, crate_info, toolchain): toolchain_tools = [] cc_toolchain, feature_configuration = find_cc_toolchain(ctx) cc_env = get_cc_compile_env(cc_toolchain, feature_configuration) + print(cc_env) # MSVC requires INCLUDE to be set include = cc_env.get("INCLUDE")