Skip to content

Commit dc09d91

Browse files
Properly configure AR for the cargo_build_script rule
There were two issues with AR in the cargo_build_script rule: 1. ARFLAGS was not set. 2. For many toolchains, the ar tool was not properly configured. This change fixes both of those problems.
1 parent 76a0b8f commit dc09d91

File tree

3 files changed

+198
-15
lines changed

3 files changed

+198
-15
lines changed

cargo/private/cargo_build_script.bzl

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,10 @@ def get_cc_compile_args_and_env(cc_toolchain, feature_configuration):
130130
131131
Returns:
132132
tuple: A tuple of the following items:
133-
- (sequence): A flattened C command line flags for given action.
134-
- (sequence): A flattened CXX command line flags for given action.
135-
- (dict): C environment variables to be set for given action.
133+
- (sequence): A flattened list of C command line flags.
134+
- (sequence): A flattened list of CXX command line flags.
135+
- (sequence): A flattened list of AR command line flags.
136+
- (dict): C environment variables to be set for this configuration.
136137
"""
137138
compile_variables = cc_common.create_compile_variables(
138139
feature_configuration = feature_configuration,
@@ -148,12 +149,17 @@ def get_cc_compile_args_and_env(cc_toolchain, feature_configuration):
148149
action_name = ACTION_NAMES.cpp_compile,
149150
variables = compile_variables,
150151
)
152+
cc_ar_args = cc_common.get_memory_inefficient_command_line(
153+
feature_configuration = feature_configuration,
154+
action_name = ACTION_NAMES.cpp_link_static_library,
155+
variables = compile_variables,
156+
)
151157
cc_env = cc_common.get_environment_variables(
152158
feature_configuration = feature_configuration,
153159
action_name = ACTION_NAMES.c_compile,
154160
variables = compile_variables,
155161
)
156-
return cc_c_args, cc_cxx_args, cc_env
162+
return cc_c_args, cc_cxx_args, cc_ar_args, cc_env
157163

158164
def _pwd_flags_sysroot(args):
159165
"""Prefix execroot-relative paths of known arguments with ${pwd}.
@@ -423,7 +429,7 @@ def _cargo_build_script_impl(ctx):
423429
env["LDFLAGS"] = " ".join(_pwd_flags(link_args))
424430

425431
# MSVC requires INCLUDE to be set
426-
cc_c_args, cc_cxx_args, cc_env = get_cc_compile_args_and_env(cc_toolchain, feature_configuration)
432+
cc_c_args, cc_cxx_args, cc_ar_args, cc_env = get_cc_compile_args_and_env(cc_toolchain, feature_configuration)
427433
include = cc_env.get("INCLUDE")
428434
if include:
429435
env["INCLUDE"] = include
@@ -444,11 +450,17 @@ def _cargo_build_script_impl(ctx):
444450
action_name = ACTION_NAMES.cpp_link_static_library,
445451
)
446452

453+
# Many C/C++ toolchains are missing an action_config for AR because
454+
# one was never included in the unix_cc_toolchain_config.
455+
if not env["AR"]:
456+
env["AR"] = cc_toolchain.ar_executable
457+
447458
# Populate CFLAGS and CXXFLAGS that cc-rs relies on when building from source, in particular
448459
# to determine the deployment target when building for apple platforms (`macosx-version-min`
449460
# for example, itself derived from the `macos_minimum_os` Bazel argument).
450461
env["CFLAGS"] = " ".join(_pwd_flags(cc_c_args))
451462
env["CXXFLAGS"] = " ".join(_pwd_flags(cc_cxx_args))
463+
env["ARFLAGS"] = " ".join(_pwd_flags(cc_ar_args))
452464

453465
# Inform build scripts of rustc flags
454466
# https://github.com/rust-lang/cargo/issues/9600

test/cargo_build_script/cc_args_and_env/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
load(
22
"cc_args_and_env_test.bzl",
3+
"ar_flags_test",
34
"bindir_absolute_test",
45
"bindir_relative_test",
56
"fsanitize_ignorelist_absolute_test",
67
"fsanitize_ignorelist_relative_test",
78
"isystem_absolute_test",
89
"isystem_relative_test",
10+
"legacy_cc_toolchain_test",
911
"sysroot_absolute_test",
1012
"sysroot_next_absolute_test",
1113
"sysroot_relative_test",
@@ -28,3 +30,7 @@ bindir_absolute_test(name = "bindir_absolute_test")
2830
fsanitize_ignorelist_absolute_test(name = "fsanitize_ignorelist_absolute_test")
2931

3032
fsanitize_ignorelist_relative_test(name = "fsanitize_ignorelist_relative_test")
33+
34+
ar_flags_test(name = "ar_flags_test")
35+
36+
legacy_cc_toolchain_test(name = "legacy_cc_toolchain_test")

test/cargo_build_script/cc_args_and_env/cc_args_and_env_test.bzl

Lines changed: 175 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@ To verify the processed cargo cc_args, we use cc_args_and_env_analysis_test().
88
"""
99

1010
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
11-
load("@rules_cc//cc:action_names.bzl", "ACTION_NAME_GROUPS")
12-
load("@rules_cc//cc:cc_toolchain_config_lib.bzl", "feature", "flag_group", "flag_set")
11+
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES", "ACTION_NAME_GROUPS")
12+
load("@rules_cc//cc:cc_toolchain_config_lib.bzl", "action_config", "feature", "flag_group", "flag_set", "tool", "tool_path")
1313
load("@rules_cc//cc:defs.bzl", "cc_toolchain")
1414
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
1515
load("//cargo:defs.bzl", "cargo_build_script")
1616

17+
_EXPECTED_CC_TOOLCHAIN_TOOLS = {
18+
"AR": "/usr/fake/ar",
19+
"CC": "/usr/fake/gcc",
20+
"CXX": "/usr/fake/g++",
21+
}
22+
1723
def _test_cc_config_impl(ctx):
1824
features = [
1925
feature(
@@ -30,9 +36,96 @@ def _test_cc_config_impl(ctx):
3036
),
3137
],
3238
),
39+
feature(
40+
name = "default_cpp_flags",
41+
enabled = True,
42+
flag_sets = [
43+
flag_set(
44+
actions = ACTION_NAME_GROUPS.all_cpp_compile_actions,
45+
flag_groups = ([
46+
flag_group(
47+
flags = ctx.attr.extra_cxx_compile_flags,
48+
),
49+
]),
50+
),
51+
],
52+
),
53+
feature(
54+
name = "default_ar_flags",
55+
enabled = True,
56+
flag_sets = [
57+
flag_set(
58+
actions = [ACTION_NAMES.cpp_link_static_library],
59+
flag_groups = ([
60+
flag_group(
61+
flags = ctx.attr.extra_ar_flags,
62+
),
63+
]),
64+
),
65+
],
66+
),
3367
]
68+
69+
tool_paths = []
70+
action_configs = []
71+
if ctx.attr.legacy_cc_toolchain:
72+
tool_paths = [
73+
tool_path(
74+
name = "gcc",
75+
path = _EXPECTED_CC_TOOLCHAIN_TOOLS["CC"],
76+
),
77+
tool_path(
78+
name = "cpp",
79+
path = _EXPECTED_CC_TOOLCHAIN_TOOLS["CXX"],
80+
),
81+
tool_path(
82+
name = "ar",
83+
path = _EXPECTED_CC_TOOLCHAIN_TOOLS["AR"],
84+
),
85+
# These need to be set to something to create a toolchain, but
86+
# is not tested here.
87+
tool_path(
88+
name = "ld",
89+
path = "/usr/ignored/false",
90+
),
91+
tool_path(
92+
name = "nm",
93+
path = "/usr/ignored/false",
94+
),
95+
tool_path(
96+
name = "objdump",
97+
path = "/usr/ignored/false",
98+
),
99+
tool_path(
100+
name = "strip",
101+
path = "/usr/ignored/false",
102+
),
103+
]
104+
else:
105+
action_configs = (
106+
action_config(
107+
action_name = ACTION_NAMES.c_compile,
108+
tools = [
109+
tool(path = _EXPECTED_CC_TOOLCHAIN_TOOLS["CC"]),
110+
],
111+
),
112+
action_config(
113+
action_name = ACTION_NAMES.cpp_compile,
114+
tools = [
115+
tool(path = _EXPECTED_CC_TOOLCHAIN_TOOLS["CXX"]),
116+
],
117+
),
118+
action_config(
119+
action_name = ACTION_NAMES.cpp_link_static_library,
120+
tools = [
121+
tool(path = _EXPECTED_CC_TOOLCHAIN_TOOLS["AR"]),
122+
],
123+
),
124+
)
125+
34126
config_info = cc_common.create_cc_toolchain_config_info(
35127
ctx = ctx,
128+
action_configs = action_configs,
36129
toolchain_identifier = "test-cc-toolchain",
37130
host_system_name = "unknown",
38131
target_system_name = "unknown",
@@ -42,13 +135,17 @@ def _test_cc_config_impl(ctx):
42135
abi_version = "unknown",
43136
abi_libc_version = "unknown",
44137
features = features,
138+
tool_paths = tool_paths,
45139
)
46140
return config_info
47141

48142
test_cc_config = rule(
49143
implementation = _test_cc_config_impl,
50144
attrs = {
145+
"extra_ar_flags": attr.string_list(),
51146
"extra_cc_compile_flags": attr.string_list(),
147+
"extra_cxx_compile_flags": attr.string_list(),
148+
"legacy_cc_toolchain": attr.bool(default = False),
52149
},
53150
provides = [CcToolchainConfigInfo],
54151
)
@@ -84,27 +181,66 @@ def _cc_args_and_env_analysis_test_impl(ctx):
84181
env = analysistest.begin(ctx)
85182
tut = analysistest.target_under_test(env)
86183
cargo_action = tut[DepActionsInfo].actions[0]
87-
cflags = cargo_action.env["CFLAGS"].split(" ")
88-
for flag in ctx.attr.expected_cflags:
89-
asserts.true(
184+
185+
for env_var, expected_path in _EXPECTED_CC_TOOLCHAIN_TOOLS.items():
186+
if ctx.attr.legacy_cc_toolchain and env_var == "CXX":
187+
# When using the legacy tool_path toolchain configuration approach,
188+
# the CXX tool is forced to be the same as the the CC tool.
189+
# See: https://github.com/bazelbuild/bazel/blob/14840856986f21b54330e352b83d687825648889/src/main/starlark/builtins_bzl/common/cc/toolchain_config/legacy_features.bzl#L1296-L1304
190+
expected_path = _EXPECTED_CC_TOOLCHAIN_TOOLS["CC"]
191+
192+
actual_path = cargo_action.env.get(env_var)
193+
asserts.false(
194+
env,
195+
actual_path == None,
196+
"error: '{}' tool unset".format(env_var),
197+
)
198+
asserts.equals(
90199
env,
91-
flag in cflags,
92-
"error: expected '{}' to be in cargo CFLAGS: '{}'".format(flag, cflags),
200+
expected_path,
201+
actual_path,
202+
"error: '{}' tool path '{}' does not match expected '{}'".format(
203+
env_var,
204+
actual_path,
205+
expected_path,
206+
),
93207
)
94208

209+
_ENV_VAR_TO_EXPECTED_ARGS = {
210+
"ARFLAGS": ctx.attr.expected_arflags,
211+
"CFLAGS": ctx.attr.expected_cflags,
212+
"CXXFLAGS": ctx.attr.expected_cxxflags,
213+
}
214+
215+
for env_var, expected_flags in _ENV_VAR_TO_EXPECTED_ARGS.items():
216+
actual_flags = cargo_action.env[env_var].split(" ")
217+
for flag in expected_flags:
218+
asserts.true(
219+
env,
220+
flag in actual_flags,
221+
"error: expected '{}' to be in cargo {}: '{}'".format(flag, env_var, actual_flags),
222+
)
223+
95224
return analysistest.end(env)
96225

97226
cc_args_and_env_analysis_test = analysistest.make(
98227
impl = _cc_args_and_env_analysis_test_impl,
99228
doc = """An analysistest to examine the custom cargo flags of an cargo_build_script target.""",
100229
attrs = {
101-
"expected_cflags": attr.string_list(),
230+
"expected_arflags": attr.string_list(default = ["-x"]),
231+
"expected_cflags": attr.string_list(default = ["-Wall"]),
232+
"expected_cxxflags": attr.string_list(default = ["-fno-rtti"]),
233+
"legacy_cc_toolchain": attr.bool(default = False),
102234
},
103235
)
104236

105237
def cargo_build_script_with_extra_cc_compile_flags(
238+
*,
106239
name,
107-
extra_cc_compile_flags):
240+
extra_cc_compile_flags = ["-Wall"],
241+
extra_cxx_compile_flags = ["-fno-rtti"],
242+
extra_ar_flags = ["-x"],
243+
legacy_cc_toolchain = False):
108244
"""Produces a test cargo_build_script target that's set up to use a custom cc_toolchain with the extra_cc_compile_flags.
109245
110246
This is achieved by creating a cascade of targets:
@@ -115,12 +251,19 @@ def cargo_build_script_with_extra_cc_compile_flags(
115251
116252
Args:
117253
name: The name of the test target.
118-
extra_cc_compile_flags: Extra args for the cc_toolchain.
254+
extra_cc_compile_flags: Extra C/C++ args for the cc_toolchain.
255+
extra_cxx_compile_flags: Extra C++-specific args for the cc_toolchain.
256+
extra_ar_flags: Extra archiver args for the cc_toolchain.
257+
legacy_cc_toolchain: Enables legacy tool_path configuration of the cc
258+
cc toolchain.
119259
"""
120260

121261
test_cc_config(
122262
name = "%s/cc_toolchain_config" % name,
123263
extra_cc_compile_flags = extra_cc_compile_flags,
264+
extra_cxx_compile_flags = extra_cxx_compile_flags,
265+
extra_ar_flags = extra_ar_flags,
266+
legacy_cc_toolchain = legacy_cc_toolchain,
124267
)
125268
cc_toolchain(
126269
name = "%s/test_cc_toolchain_impl" % name,
@@ -250,3 +393,25 @@ def fsanitize_ignorelist_absolute_test(name):
250393
target_under_test = "%s/cargo_build_script" % name,
251394
expected_cflags = ["-fsanitize-ignorelist=/test/absolute/path"],
252395
)
396+
397+
def ar_flags_test(name):
398+
cargo_build_script_with_extra_cc_compile_flags(
399+
name = "%s/cargo_build_script" % name,
400+
extra_ar_flags = ["-static"],
401+
)
402+
cc_args_and_env_analysis_test(
403+
name = name,
404+
target_under_test = "%s/cargo_build_script" % name,
405+
expected_arflags = ["-static"],
406+
)
407+
408+
def legacy_cc_toolchain_test(name):
409+
cargo_build_script_with_extra_cc_compile_flags(
410+
name = "%s/cargo_build_script" % name,
411+
legacy_cc_toolchain = True,
412+
)
413+
cc_args_and_env_analysis_test(
414+
name = name,
415+
target_under_test = "%s/cargo_build_script" % name,
416+
legacy_cc_toolchain = True,
417+
)

0 commit comments

Comments
 (0)