Skip to content
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

Set the same env vars as cargo both when invoking rustc and when invoking a cargo_build_script #661

Open
illicitonion opened this issue Mar 30, 2021 · 2 comments

Comments

@illicitonion
Copy link
Collaborator

Cargo sets this list of env vars when either invoking rustc, or cargo runing or cargo testing a binary. We should be setting them all when we invoke rustc.

Cargo additionally sets this list of env vars when running (not when compiling) a build script. We should be setting them all when we invoke a build script. We should also be setting all of the rustc env vars when we invoke a build script.

Currently we have two lists of env vars:

This list is used for when we invoke rustc:

def _get_rustc_env(ctx, toolchain):
"""Gathers rustc environment variables
Args:
ctx (ctx): The current target's rule context object
toolchain (rust_toolchain): The current target's rust toolchain context
Returns:
dict: Rustc environment variables
"""
version = ctx.attr.version if hasattr(ctx.attr, "version") else "0.0.0"
major, minor, patch = version.split(".", 2)
if "-" in patch:
patch, pre = patch.split("-", 1)
else:
pre = ""
return {
"CARGO_CFG_TARGET_ARCH": toolchain.target_arch,
"CARGO_CFG_TARGET_OS": toolchain.os,
"CARGO_PKG_AUTHORS": "",
"CARGO_PKG_DESCRIPTION": "",
"CARGO_PKG_HOMEPAGE": "",
"CARGO_PKG_NAME": ctx.label.name,
"CARGO_PKG_VERSION": version,
"CARGO_PKG_VERSION_MAJOR": major,
"CARGO_PKG_VERSION_MINOR": minor,
"CARGO_PKG_VERSION_PATCH": patch,
"CARGO_PKG_VERSION_PRE": pre,
}

This list is used when we invoke an already-compiled build-script (note that we use the above list when compiling the build script):

env = dict(ctx.configuration.default_shell_env)
env.update({
"CARGO_MANIFEST_DIR": manifest_dir,
"CARGO_PKG_NAME": crate_name,
"HOST": toolchain.exec_triple,
"OPT_LEVEL": compilation_mode_opt_level,
# This isn't exactly right, but Bazel doesn't have exact views of "debug" and "release", so...
"PROFILE": {"dbg": "debug", "fastbuild": "debug", "opt": "release"}.get(ctx.var["COMPILATION_MODE"], "unknown"),
"RUSTC": toolchain.rustc.path,
"TARGET": toolchain.target_triple,
# OUT_DIR is set by the runner itself, rather than on the action.
})
if ctx.attr.version:
version = ctx.attr.version.split("+")[0].split(".")
patch = version[2].split("-") if len(version) > 2 else [""]
env["CARGO_PKG_VERSION_MAJOR"] = version[0]
env["CARGO_PKG_VERSION_MINOR"] = version[1] if len(version) > 1 else ""
env["CARGO_PKG_VERSION_PATCH"] = patch[0]
env["CARGO_PKG_VERSION_PRE"] = patch[1] if len(patch) > 1 else ""
env["CARGO_PKG_VERSION"] = ctx.attr.version
# Pull in env vars which may be required for the cc_toolchain to work (e.g. on OSX, the SDK version).
# We hope that the linker env is sufficient for the whole cc_toolchain.
cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
_, _, linker_env = get_linker_and_args(ctx, cc_toolchain, feature_configuration, None)
env.update(**linker_env)
# MSVC requires INCLUDE to be set
cc_env = get_cc_compile_env(cc_toolchain, feature_configuration)
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:
env["AR"] = ar_executable
for f in ctx.attr.crate_features:
env["CARGO_FEATURE_" + name_to_crate_name(f).upper()] = "1"
env.update(expand_locations(
ctx,
ctx.attr.build_script_env,
getattr(ctx.attr, "data", []) +
getattr(ctx.attr, "compile_data", []),
))

Both of these lists are currently incomplete, as we've generally added stuff as-needed. Additionally, the rustc_env list contains some vars which should actually only be in the build_script list (e.g. CARGO_CFG_TARGET_ARCH and CARGO_CFG_TARGET_OS).

We should:

  1. Make the build script env vars be a superset of the rustc ones, by calling _get_rustc_env from _build_script_impl. This will both help keep the lists in sync, and avoid duplicating things like the processing of version numbers.
  2. Move any build_script-specific env vars out of _get_rustc_env
  3. (Optional): Add more env vars pro-actively, rather than reactively when someone finds some third-party code doesn't build.
@bbstilson
Copy link

bbstilson commented Feb 26, 2024

Related to:

Add more env vars pro-actively, rather than reactively when someone finds some third-party code doesn't build.

I've hit an issue compiling a sqlx query! macro as the CARGO env var is not set by rules_rust and is required by the macro

Any interim suggestions about how to get around this would be appreciated 🙂

@illicitonion
Copy link
Collaborator Author

$CARGO is definitely a tricky one. In the short term, you can probably add an annotation setting build_script_data to @rules_rust//rust/toolchain:current_cargo_files and setting build_script_env to {"CARGO": "$(execpath @rules_rust//rust/toolchain:current_cargo_files)"}. But in general, any time a build script tries to use cargo directly, it's likely to be doing something that won't be exactly compatible with how Bazel runs things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants