diff --git a/test/layering_check/BUILD b/test/layering_check/BUILD index bf187861..739ce405 100644 --- a/test/layering_check/BUILD +++ b/test/layering_check/BUILD @@ -1,5 +1,6 @@ load("@bazel_skylib//rules:build_test.bzl", "build_test") load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test", "objc_library") +load("//test/rules:action_command_line_test.bzl", "action_command_line_test") package(features = ["layering_check"]) @@ -37,6 +38,74 @@ cc_test( ], ) +# From Clang 14 on, -std=c++20 switches the driver to C++20 modules +# semantics: including a header a module map covers *non-textually* becomes +# "module 'cxx20_modular' is needed but has not been provided" -- unless the +# toolchain passes -fno-cxx-modules (//toolchain:no_cxx_modules_flags, gated +# on use_module_maps). wrapped_clang's generated map and the per-target maps +# Bazel writes are all-textual and immune, but the system module map of a +# hermetic toolchain driving this configuration is not. +cc_library( + name = "cxx20_non_textual_module_map", + srcs = ["modular.cpp"], + hdrs = ["modular.h"], + additional_compiler_inputs = ["cxx20.modulemap"], + copts = [ + "-std=c++20", + "-fmodule-map-file=$(execpath cxx20.modulemap)", + ], + # use_module_maps alone, without layering_check: strict-decluse would + # (correctly) reject the include, since nothing declares a dependency on + # the map's module. The fix is gated on use_module_maps, not on + # layering_check itself. + features = [ + "-layering_check", + "use_module_maps", + ], +) + +build_test( + name = "cxx20_non_textual_module_map_test", + targets = [":cxx20_non_textual_module_map"], +) + +# The flag is emitted exactly when use_module_maps is enabled: by itself, by +# way of layering_check, and never without. Note the build test above cannot +# fail under Xcode's clang, which does not switch to C++20 modules semantics +# the way upstream Clang 14+ does -- these assert the flag so the fix is +# visible under the tools this repo tests with. +action_command_line_test( + name = "no_cxx_modules_flags_from_module_maps_test", + expected_argv = [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c", + ], + mnemonic = "CppCompile", + tags = ["requires_rules_based_toolchain"], + target_under_test = ":cxx20_non_textual_module_map", +) + +action_command_line_test( + name = "no_cxx_modules_flags_from_layering_check_test", + expected_argv = [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c", + ], + mnemonic = "CppCompile", + tags = ["requires_rules_based_toolchain"], + target_under_test = ":good_layering_check", +) + +action_command_line_test( + name = "no_cxx_modules_flags_off_without_module_maps_test", + mnemonic = "CppCompile", + not_expected_argv = ["-fno-cxx-modules"], + tags = ["requires_rules_based_toolchain"], + target_under_test = ":disabled_bad_layering_check", +) + objc_library( name = "bad_layering_check_objc", srcs = ["c.m"], diff --git a/test/layering_check/cxx20.modulemap b/test/layering_check/cxx20.modulemap new file mode 100644 index 00000000..547410bd --- /dev/null +++ b/test/layering_check/cxx20.modulemap @@ -0,0 +1,7 @@ +// A module map whose header is *not* textual, like the umbrella-directory +// system module maps a hermetic toolchain generates for its own headers -- +// unlike the all-textual maps wrapped_clang injects and Bazel writes per +// target, which C++20 modules semantics leave alone. +module "cxx20_modular" [system] { + header "modular.h" +} diff --git a/test/layering_check/modular.cpp b/test/layering_check/modular.cpp new file mode 100644 index 00000000..d1c1f905 --- /dev/null +++ b/test/layering_check/modular.cpp @@ -0,0 +1,3 @@ +#include "modular.h" + +int uses_modular() { return from_modular_header(); } diff --git a/test/layering_check/modular.h b/test/layering_check/modular.h new file mode 100644 index 00000000..5948dfb7 --- /dev/null +++ b/test/layering_check/modular.h @@ -0,0 +1,6 @@ +#ifndef TEST_LAYERING_CHECK_MODULAR_H_ +#define TEST_LAYERING_CHECK_MODULAR_H_ + +inline int from_modular_header() { return 20; } + +#endif // TEST_LAYERING_CHECK_MODULAR_H_ diff --git a/test/test_data/toolchain_configs/darwin_arm64.json b/test/test_data/toolchain_configs/darwin_arm64.json index b401f864..c8a93ae9 100644 --- a/test/test_data/toolchain_configs/darwin_arm64.json +++ b/test/test_data/toolchain_configs/darwin_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/darwin_arm64e.json b/test/test_data/toolchain_configs/darwin_arm64e.json index f073502f..82f0dc28 100644 --- a/test/test_data/toolchain_configs/darwin_arm64e.json +++ b/test/test_data/toolchain_configs/darwin_arm64e.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/darwin_x86_64.json b/test/test_data/toolchain_configs/darwin_x86_64.json index 4fcedc33..a86c7a94 100644 --- a/test/test_data/toolchain_configs/darwin_x86_64.json +++ b/test/test_data/toolchain_configs/darwin_x86_64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/ios_arm64.json b/test/test_data/toolchain_configs/ios_arm64.json index 29699372..860ad019 100644 --- a/test/test_data/toolchain_configs/ios_arm64.json +++ b/test/test_data/toolchain_configs/ios_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/ios_arm64e.json b/test/test_data/toolchain_configs/ios_arm64e.json index 7ad56f13..427ace79 100644 --- a/test/test_data/toolchain_configs/ios_arm64e.json +++ b/test/test_data/toolchain_configs/ios_arm64e.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/ios_sim_arm64.json b/test/test_data/toolchain_configs/ios_sim_arm64.json index a867db2a..2f885c52 100644 --- a/test/test_data/toolchain_configs/ios_sim_arm64.json +++ b/test/test_data/toolchain_configs/ios_sim_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/ios_x86_64.json b/test/test_data/toolchain_configs/ios_x86_64.json index 74fb08cf..6f2eec73 100644 --- a/test/test_data/toolchain_configs/ios_x86_64.json +++ b/test/test_data/toolchain_configs/ios_x86_64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/linux_x86_64.json b/test/test_data/toolchain_configs/linux_x86_64.json index 9685a4e2..86b29de6 100644 --- a/test/test_data/toolchain_configs/linux_x86_64.json +++ b/test/test_data/toolchain_configs/linux_x86_64.json @@ -1073,6 +1073,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/tvos_arm64.json b/test/test_data/toolchain_configs/tvos_arm64.json index 83ee4efa..49e92e99 100644 --- a/test/test_data/toolchain_configs/tvos_arm64.json +++ b/test/test_data/toolchain_configs/tvos_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/tvos_sim_arm64.json b/test/test_data/toolchain_configs/tvos_sim_arm64.json index c628bc18..e3e2ecd9 100644 --- a/test/test_data/toolchain_configs/tvos_sim_arm64.json +++ b/test/test_data/toolchain_configs/tvos_sim_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/tvos_x86_64.json b/test/test_data/toolchain_configs/tvos_x86_64.json index 7e66c770..5624a7fa 100644 --- a/test/test_data/toolchain_configs/tvos_x86_64.json +++ b/test/test_data/toolchain_configs/tvos_x86_64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/visionos_arm64.json b/test/test_data/toolchain_configs/visionos_arm64.json index 7a64ab0e..147d7534 100644 --- a/test/test_data/toolchain_configs/visionos_arm64.json +++ b/test/test_data/toolchain_configs/visionos_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/visionos_sim_arm64.json b/test/test_data/toolchain_configs/visionos_sim_arm64.json index a6e40f9d..77a3516f 100644 --- a/test/test_data/toolchain_configs/visionos_sim_arm64.json +++ b/test/test_data/toolchain_configs/visionos_sim_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/watchos_arm64.json b/test/test_data/toolchain_configs/watchos_arm64.json index 5f48484f..d65c014e 100644 --- a/test/test_data/toolchain_configs/watchos_arm64.json +++ b/test/test_data/toolchain_configs/watchos_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/watchos_arm64_32.json b/test/test_data/toolchain_configs/watchos_arm64_32.json index cf82ed5b..fbdf4def 100644 --- a/test/test_data/toolchain_configs/watchos_arm64_32.json +++ b/test/test_data/toolchain_configs/watchos_arm64_32.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/watchos_device_arm64.json b/test/test_data/toolchain_configs/watchos_device_arm64.json index 1ca524ad..b9512f82 100644 --- a/test/test_data/toolchain_configs/watchos_device_arm64.json +++ b/test/test_data/toolchain_configs/watchos_device_arm64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/watchos_device_arm64e.json b/test/test_data/toolchain_configs/watchos_device_arm64e.json index 336b7020..a08b86db 100644 --- a/test/test_data/toolchain_configs/watchos_device_arm64e.json +++ b/test/test_data/toolchain_configs/watchos_device_arm64e.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/test/test_data/toolchain_configs/watchos_x86_64.json b/test/test_data/toolchain_configs/watchos_x86_64.json index 2e994c83..fa7fd7e4 100644 --- a/test/test_data/toolchain_configs/watchos_x86_64.json +++ b/test/test_data/toolchain_configs/watchos_x86_64.json @@ -1006,6 +1006,45 @@ "type_name": "flag_set", "with_features": [] }, + { + "actions": [ + "c++-compile", + "c++-header-parsing", + "c++-module-codegen", + "c++-module-compile", + "clif-match", + "linkstamp-compile", + "lto-backend", + "objc++-compile" + ], + "flag_groups": [ + { + "expand_if_available": null, + "expand_if_equal": null, + "expand_if_false": null, + "expand_if_not_available": null, + "expand_if_true": null, + "flag_groups": [], + "flags": [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c" + ], + "iterate_over": null, + "type_name": "flag_group" + } + ], + "type_name": "flag_set", + "with_features": [ + { + "features": [ + "use_module_maps" + ], + "not_features": [], + "type_name": "with_feature_set" + } + ] + }, { "actions": [ "assemble", diff --git a/toolchain/BUILD b/toolchain/BUILD index 4b7e3754..e9100019 100644 --- a/toolchain/BUILD +++ b/toolchain/BUILD @@ -183,6 +183,7 @@ cc_args_list( name = "default_compile_flags", args = [ ":objcpp_default_flags", + ":no_cxx_modules_flags", "//toolchain/sanitizers:no_asan_compile_flags", ":always_compile_flags", ":fastbuild_compile_flags", @@ -191,6 +192,21 @@ cc_args_list( ], ) +# Bazel's layering_check is built on Clang module maps, which -std=c++20 +# breaks: from Clang 14 on the driver switches to C++20 modules semantics +# unless told otherwise, and Bazel does not support C++20 modules yet. +# https://github.com/llvm/llvm-project/commit/0556138624edf48621dd49a463dbe12e7101f17d +cc_args( + name = "no_cxx_modules_flags", + actions = ["@rules_cc//cc/toolchains/actions:cpp_compile_actions"], + args = [ + "-Xclang", + "-fno-cxx-modules", + "-Wno-module-import-in-extern-c", + ], + requires_any_of = ["@rules_cc//cc/toolchains/args/layering_check:use_module_maps"], +) + cc_args( name = "objcpp_default_flags", actions = ["@rules_cc//cc/toolchains/actions:objcpp_compile"], @@ -306,7 +322,10 @@ cc_args( dynamic_toolchain_info( name = "dynamic_toolchain_info", - visibility = ["//:__subpackages__"], + # The `cc_toolchain` macro references this from inside a select() on + # //configs:apple, so an external consumer of the macro that targets an + # Apple platform needs to be able to see it. + visibility = ["//visibility:public"], ) xcode_execution_info( diff --git a/toolchain/cc_toolchain.bzl b/toolchain/cc_toolchain.bzl index 1dd536da..0098370b 100644 --- a/toolchain/cc_toolchain.bzl +++ b/toolchain/cc_toolchain.bzl @@ -13,7 +13,14 @@ def cc_toolchain( module_map, sysroot_feature, supports_header_parsing, - tool_map): + tool_map, + flags_from_env = True, + llvm_version = None, + extra_enabled_features = None, + extra_known_features = None, + extra_include_directories = None, + dynamic_runtime_lib = None, + static_runtime_lib = None): """Defines a C/C++ toolchain with Apple defaults on Apple platforms. Args: @@ -22,14 +29,48 @@ def cc_toolchain( module_map: Module map artifact for modular builds. supports_header_parsing: Whether header parsing actions are supported. sysroot_feature: The enabled feature that supplies the toolchain's sysroot. - tool_map: The `cc_tool_map` that supplies the toolchain's tools. + tool_map: The `cc_tool_map` that supplies the toolchain's tools. On + Apple platforms some of the toolchain's args are not compiler flags + but part of `wrapped_clang`'s protocol -- the `__BAZEL_*` path + placeholders, and the sentinel args `STRIP_DEBUG_SYMBOLS`, + `LINKED_BINARY=...` and `DSYM_HINT_DSYM_PATH=...` that stand for + work the tool does around the compiler. A `tool_map` that does not + drive `wrapped_clang` itself has to supply a tool that resolves the + placeholders and acts on the sentinels the same way. + flags_from_env: Whether to append the flags read from `BAZEL_COPTS`, + `BAZEL_CONLYOPTS`, `BAZEL_CXXOPTS` and `BAZEL_LINKOPTS`. Defaults to + True. Note that `BAZEL_CXXOPTS` defaults to `-std=c++17`, so a + toolchain that sets its own C++ standard has to turn this off -- + the environment is read once per build, so it also cannot differ + between two toolchains in the same workspace. + llvm_version: The LLVM version of the tools in `tool_map`, e.g. + "17.0.6", when they come from a plain LLVM distribution rather + than from Xcode. Link flags that a distribution's `ld64.lld` only + accepts from some LLVM version on are dropped for the versions + before it; None (the default) means Xcode's tools, which accept + them all. + extra_enabled_features: A `cc_feature_set` of extra features to enable. + extra_known_features: A `cc_feature_set` of extra features to make known. + extra_include_directories: A `cc_args` of extra include directories. + dynamic_runtime_lib: Passed through to `cc_toolchain`. The dynamic + library to link when `static_link_cpp_runtimes` is enabled. + static_runtime_lib: Passed through to `cc_toolchain`. """ + + # -no_warn_duplicate_libraries and -reproducible are accepted by Xcode's + # ld64 and by ld64.lld from LLVM 19 on; older ld64.lld rejects arguments + # it does not know. + linker_takes_apple_flags = (not llvm_version) or int(llvm_version.split(".")[0]) >= 19 + + extra_enabled_features = [extra_enabled_features] if extra_enabled_features else [] + extra_known_features = [extra_known_features] if extra_known_features else [] + extra_include_directories = [extra_include_directories] if extra_include_directories else [] _cc_toolchain( name = name, args = [ Label("@apple_support_toolchain_env//:include_directories_from_xcode"), Label("//toolchain:extra_include_directories"), - ] + select({ + ] + extra_include_directories + select({ Label("//configs:apple"): [Label("//toolchain:apple_env")], "//conditions:default": [], }), @@ -103,14 +144,18 @@ def cc_toolchain( Label("//toolchain:headerpad"), Label("@rules_cc//cc/toolchains/args/objc_arc_flags:feature"), Label("//toolchain:user_link_flags"), # TODO: Switch to upstream feature + ] + ([ Label("@apple_support_toolchain_env//:linkopts_from_env"), # TODO: Join with the copts below + ] if flags_from_env else []) + [ Label("//toolchain:default_required_flags"), Label("//toolchain:__apply_simulator_compiler_flags"), Label("//toolchain/sanitizers:asan_wrapper"), Label("//toolchain/sanitizers:tsan_wrapper"), Label("//toolchain/sanitizers:ubsan_wrapper"), Label("//toolchain/sanitizers:default_sanitizer_flags"), + ] + ([ Label("@apple_support_toolchain_env//:copts_from_env"), + ] if flags_from_env else []) + [ Label("//toolchain:default_link_flags"), ] + select({ Label("//toolchain:opt_mode"): [Label("//toolchain:dead_strip")], @@ -122,6 +167,7 @@ def cc_toolchain( Label("//toolchain:apply_implicit_frameworks"), Label("//toolchain:link_cocoa_wrapper"), Label("//toolchain:extra_enabled_features"), + ] + extra_enabled_features + [ Label("@rules_cc//cc/toolchains/args/compile_flags:user_compile_flags_feature"), # TODO: Switch to compile_flags:feature if ordering isn't an issue Label("//toolchain:unfiltered_compile_flags"), Label("@rules_cc//cc/toolchains/args/compiler_input_flags:feature"), @@ -130,13 +176,13 @@ def cc_toolchain( Label("@rules_cc//cc/toolchains/args/soname_flags:feature"), Label("//toolchain:suppress_warnings_wrapper"), Label("//toolchain:treat_warnings_as_errors_wrapper"), - ] + select({ + ] + (select({ Label("//configs:apple"): [ Label("//toolchain:no_warn_duplicate_libraries"), Label("//toolchain:reproducible_linker_flag"), ], "//conditions:default": [], - }) + [ + }) if linker_takes_apple_flags else []) + [ Label("//toolchain:external_include_paths_wrapper"), ] + select({ Label("//configs:apple"): [ @@ -169,6 +215,7 @@ def cc_toolchain( Label("//toolchain/pgo:autofdo"), Label("//toolchain/pgo:fdo_optimize"), Label("@apple_support_toolchain_env//:off_by_default_layering_check_known_features"), + ] + extra_known_features + [ Label("//toolchain:extra_known_features"), Label("@rules_cc//cc/toolchains/args/layering_check:use_module_maps"), # TODO: https://github.com/bazelbuild/rules_cc/pull/657 ] + select({ @@ -184,6 +231,8 @@ def cc_toolchain( Label("//configs:apple"): [Label("//toolchain:stack_frame_variable")], "//conditions:default": [], }), + dynamic_runtime_lib = dynamic_runtime_lib, + static_runtime_lib = static_runtime_lib, module_map = module_map, supports_header_parsing = supports_header_parsing, supports_param_files = True,