diff --git a/cargo/private/cargo_build_script.bzl b/cargo/private/cargo_build_script.bzl index 12a2271cd9..fe1c2bcdd9 100644 --- a/cargo/private/cargo_build_script.bzl +++ b/cargo/private/cargo_build_script.bzl @@ -64,10 +64,11 @@ rather than going through this rule. executable = True, ) -def get_cc_compile_args_and_env(cc_toolchain, feature_configuration): +def get_cc_compile_args_and_env(ctx, cc_toolchain, feature_configuration): """Gather cc environment variables from the given `cc_toolchain` Args: + ctx (ctx): The current rule's context. cc_toolchain (cc_toolchain): The current rule's `cc_toolchain`. feature_configuration (FeatureConfiguration): Class used to construct command lines from CROSSTOOL features. @@ -77,24 +78,30 @@ def get_cc_compile_args_and_env(cc_toolchain, feature_configuration): - (sequence): A flattened list of CXX command line flags. - (dict): C environment variables to be set for this configuration. """ - compile_variables = cc_common.create_compile_variables( + c_compile_variables = cc_common.create_compile_variables( feature_configuration = feature_configuration, cc_toolchain = cc_toolchain, + user_compile_flags = ctx.fragments.cpp.copts + ctx.fragments.cpp.conlyopts, + ) + cxx_compile_variables = cc_common.create_compile_variables( + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + user_compile_flags = ctx.fragments.cpp.copts + ctx.fragments.cpp.cxxopts, ) cc_c_args = cc_common.get_memory_inefficient_command_line( feature_configuration = feature_configuration, action_name = ACTION_NAMES.c_compile, - variables = compile_variables, + variables = c_compile_variables, ) cc_cxx_args = cc_common.get_memory_inefficient_command_line( feature_configuration = feature_configuration, action_name = ACTION_NAMES.cpp_compile, - variables = compile_variables, + variables = cxx_compile_variables, ) cc_env = cc_common.get_environment_variables( feature_configuration = feature_configuration, action_name = ACTION_NAMES.c_compile, - variables = compile_variables, + variables = c_compile_variables, ) return cc_c_args, cc_cxx_args, cc_env @@ -523,7 +530,7 @@ def _cargo_build_script_impl(ctx): if cc_toolchain: # MSVC requires INCLUDE to be set - cc_c_args, cc_cxx_args, cc_env = get_cc_compile_args_and_env(cc_toolchain, feature_configuration) + cc_c_args, cc_cxx_args, cc_env = get_cc_compile_args_and_env(ctx, cc_toolchain, feature_configuration) include = cc_env.get("INCLUDE") if include: if toolchain.exec_triple.str.find("windows") > 0: diff --git a/cargo/tests/cargo_build_script/cc_args_and_env/BUILD.bazel b/cargo/tests/cargo_build_script/cc_args_and_env/BUILD.bazel index a2e39c9855..80a1fe5572 100644 --- a/cargo/tests/cargo_build_script/cc_args_and_env/BUILD.bazel +++ b/cargo/tests/cargo_build_script/cc_args_and_env/BUILD.bazel @@ -28,6 +28,7 @@ load( "sysroot_bazel_placeholder_test", "sysroot_next_absolute_test", "sysroot_relative_test", + "user_compile_flags_test", "xclang_isystem_absolute_test", "xclang_isystem_relative_test", ) @@ -91,3 +92,5 @@ direct_libs_relative_test(name = "direct_libs_relative_test") direct_libs_absolute_test(name = "direct_libs_absolute_test") direct_libs_as_flag_operand_test(name = "direct_libs_as_flag_operand_test") + +user_compile_flags_test(name = "user_compile_flags_test") diff --git a/cargo/tests/cargo_build_script/cc_args_and_env/cc_args_and_env_test.bzl b/cargo/tests/cargo_build_script/cc_args_and_env/cc_args_and_env_test.bzl index 2f492ea49d..d1e6826db5 100644 --- a/cargo/tests/cargo_build_script/cc_args_and_env/cc_args_and_env_test.bzl +++ b/cargo/tests/cargo_build_script/cc_args_and_env/cc_args_and_env_test.bzl @@ -23,6 +23,22 @@ _EXPECTED_CC_TOOLCHAIN_TOOLS = { def _test_cc_config_impl(ctx): features = [ + feature( + name = "user_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = ACTION_NAME_GROUPS.all_cc_compile_actions, + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ), feature( name = "default_compiler_flags", enabled = True, @@ -243,6 +259,13 @@ def _cc_args_and_env_analysis_test_impl(ctx): "error: expected '{}' to be in cargo {}: '{}'".format(flag, env_var, actual_flags), ) + for env_var, forbidden_flags in { + "CFLAGS": ctx.attr.forbidden_cflags, + "CXXFLAGS": ctx.attr.forbidden_cxxflags, + }.items(): + for flag in forbidden_flags: + asserts.false(env, flag in cargo_action.env[env_var].split(" "), "{} must not contain {}".format(env_var, flag)) + arflags = cargo_action.env["ARFLAGS"] asserts.equals( env, @@ -264,15 +287,19 @@ def _cc_args_and_env_analysis_test_impl(ctx): return analysistest.end(env) +_CC_ARGS_AND_ENV_TEST_ATTRS = { + "expected_cflags": attr.string_list(default = ["-Wall"]), + "expected_cxxflags": attr.string_list(default = ["-fno-rtti"]), + "expected_include": attr.string(default = ""), + "legacy_cc_toolchain": attr.bool(default = False), + "forbidden_cflags": attr.string_list(), + "forbidden_cxxflags": attr.string_list(), +} + cc_args_and_env_analysis_test = analysistest.make( impl = _cc_args_and_env_analysis_test_impl, doc = """An analysistest to examine the custom cargo flags of an cargo_build_script target.""", - attrs = { - "expected_cflags": attr.string_list(default = ["-Wall"]), - "expected_cxxflags": attr.string_list(default = ["-fno-rtti"]), - "expected_include": attr.string(default = ""), - "legacy_cc_toolchain": attr.bool(default = False), - }, + attrs = _CC_ARGS_AND_ENV_TEST_ATTRS, ) def cargo_build_script_with_extra_cc_compile_flags( @@ -771,3 +798,25 @@ def direct_libs_as_flag_operand_test(name): target_under_test = "%s/cargo_build_script" % name, expected_cflags = ["-imacros", "${pwd}/test/relative/libfoo.a", "-B", "${pwd}/test/relative/obj.o"], ) + +user_compile_flags_analysis_test = analysistest.make( + impl = _cc_args_and_env_analysis_test_impl, + attrs = _CC_ARGS_AND_ENV_TEST_ATTRS, + config_settings = { + "//command_line_option:copt": ["-DUSER_COMMON"], + "//command_line_option:conlyopt": ["-DUSER_C_ONLY"], + "//command_line_option:cxxopt": ["-DUSER_CXX_ONLY"], + }, +) + +def user_compile_flags_test(name): + """Check common and language-specific user flags in build script environments.""" + cargo_build_script_with_extra_cc_compile_flags(name = name + "/cargo_build_script") + user_compile_flags_analysis_test( + name = name, + target_under_test = name + "/cargo_build_script", + expected_cflags = ["-Wall", "-DUSER_COMMON", "-DUSER_C_ONLY"], + expected_cxxflags = ["-fno-rtti", "-DUSER_COMMON", "-DUSER_CXX_ONLY"], + forbidden_cflags = ["-DUSER_CXX_ONLY"], + forbidden_cxxflags = ["-DUSER_C_ONLY"], + )