diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java index fa31f110a38fe2..5b3eb6a39db80f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java @@ -477,7 +477,9 @@ public boolean useDotdFile(Artifact sourceFile) { } public boolean dotdFilesEnabled() { - return cppSemantics.needsDotdInputPruning(configuration) && !shouldParseShowIncludes(); + return cppSemantics.needsDotdInputPruning(configuration) + && !shouldParseShowIncludes() + && !featureConfiguration.isEnabled(CppRuleClasses.NO_DOTD_FILE); } public boolean serializedDiagnosticsFilesEnabled() { diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java index ac0afec22e38eb..8281af947a7eff 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java @@ -383,6 +383,9 @@ public static ToolchainTypeRequirement ccToolchainTypeRequirement(RuleDefinition /** A string constant for /showIncludes parsing feature, should only be used for MSVC toolchain */ public static final String PARSE_SHOWINCLUDES = "parse_showincludes"; + /** A string constant for a feature that, if enabled, disables .d file handling. */ + public static final String NO_DOTD_FILE = "no_dotd_file"; + /* * A string constant for the fdo_instrument feature. */ diff --git a/tools/cpp/BUILD.windows.tpl b/tools/cpp/BUILD.windows.tpl index 1e7fbcc68c1431..7ac916c2237328 100644 --- a/tools/cpp/BUILD.windows.tpl +++ b/tools/cpp/BUILD.windows.tpl @@ -211,6 +211,7 @@ cc_toolchain_config( default_link_flags = ["/MACHINE:X64"], dbg_mode_debug_flag = "%{dbg_mode_debug_flag_x64}", fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag_x64}", + supports_parse_showincludes = %{msvc_parse_showincludes_x64}, ) toolchain( @@ -277,6 +278,7 @@ cc_toolchain_config( default_link_flags = ["/MACHINE:X86"], dbg_mode_debug_flag = "%{dbg_mode_debug_flag_x86}", fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag_x86}", + supports_parse_showincludes = %{msvc_parse_showincludes_x86}, ) toolchain( @@ -343,6 +345,7 @@ cc_toolchain_config( default_link_flags = ["/MACHINE:ARM"], dbg_mode_debug_flag = "%{dbg_mode_debug_flag_arm}", fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag_arm}", + supports_parse_showincludes = %{msvc_parse_showincludes_arm}, ) toolchain( @@ -409,6 +412,7 @@ cc_toolchain_config( default_link_flags = ["/MACHINE:ARM64"], dbg_mode_debug_flag = "%{dbg_mode_debug_flag_arm64}", fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag_arm64}", + supports_parse_showincludes = %{msvc_parse_showincludes_arm64}, ) toolchain( @@ -475,6 +479,7 @@ cc_toolchain_config( default_link_flags = ["/MACHINE:X64", "/DEFAULTLIB:clang_rt.builtins-x86_64.lib"], dbg_mode_debug_flag = "%{clang_cl_dbg_mode_debug_flag_x64}", fastbuild_mode_debug_flag = "%{clang_cl_fastbuild_mode_debug_flag_x64}", + supports_parse_showincludes = %{clang_cl_parse_showincludes_x64}, ) toolchain( @@ -542,6 +547,7 @@ cc_toolchain_config( default_link_flags = ["/MACHINE:ARM64"], dbg_mode_debug_flag = "%{clang_cl_dbg_mode_debug_flag_arm64}", fastbuild_mode_debug_flag = "%{clang_cl_fastbuild_mode_debug_flag_arm64}", + supports_parse_showincludes = %{clang_cl_parse_showincludes_arm64}, ) toolchain( diff --git a/tools/cpp/lib_cc_configure.bzl b/tools/cpp/lib_cc_configure.bzl index 40e4f4c79d1f6f..cedb5de1735f91 100644 --- a/tools/cpp/lib_cc_configure.bzl +++ b/tools/cpp/lib_cc_configure.bzl @@ -148,7 +148,8 @@ def execute( repository_ctx, command, environment = None, - expect_failure = False): + expect_failure = False, + expect_empty_output = False): """Execute a command, return stdout if succeed and throw an error if it fails. Doesn't %-escape the result!""" if environment: result = repository_ctx.execute(command, environment = environment) @@ -171,10 +172,15 @@ def execute( ), ) stripped_stdout = result.stdout.strip() - if not stripped_stdout: - auto_configure_fail( - "empty output from command %s, stderr: (%s)" % (command, result.stderr), - ) + if expect_empty_output != (not stripped_stdout): + if expect_empty_output: + auto_configure_fail( + "non-empty output from command %s, stdout: (%s), stderr: (%s)" % (command, result.stdout, result.stderr), + ) + else: + auto_configure_fail( + "empty output from command %s, stderr: (%s)" % (command, result.stderr), + ) return stripped_stdout def get_cpu_value(repository_ctx): diff --git a/tools/cpp/windows_cc_configure.bzl b/tools/cpp/windows_cc_configure.bzl index 760a8435f99a65..4c3e367b22b4f8 100644 --- a/tools/cpp/windows_cc_configure.bzl +++ b/tools/cpp/windows_cc_configure.bzl @@ -488,6 +488,28 @@ def _is_support_debug_fastlink(repository_ctx, linker): result = execute(repository_ctx, [linker], expect_failure = True) return result.find("/DEBUG[:{FASTLINK|FULL|NONE}]") != -1 +def _is_support_parse_showincludes(repository_ctx, cl, env): + repository_ctx.file( + "main.cpp", + "#include \"bazel_showincludes.h\"\nint main(){}\n", + ) + repository_ctx.file( + "bazel_showincludes.h", + "\n", + ) + result = execute( + repository_ctx, + [cl, "/nologo", "/showIncludes", "/c", "main.cpp", "/out", "main.exe", "/Fo", "main.obj"], + # Attempt to force English language. This may fail if the language pack isn't installed. + environment = env | {"VSLANG": "1033"}, + ) + for file in ["main.cpp", "bazel_showincludes.h", "main.exe", "main.obj"]: + execute(repository_ctx, ["cmd", "/C", "del", file], expect_empty_output = True) + return any([ + line.startswith("Note: including file:") and line.endswith("bazel_showincludes.h") + for line in result.split("\n") + ]) + def find_llvm_path(repository_ctx): """Find LLVM install path.""" @@ -635,6 +657,7 @@ def _get_msvc_vars(repository_ctx, paths, target_arch = "x64", msvc_vars_x64 = N "%{msvc_lib_path_" + target_arch + "}": "vc_installation_error_" + target_arch + ".bat", "%{dbg_mode_debug_flag_" + target_arch + "}": "/DEBUG", "%{fastbuild_mode_debug_flag_" + target_arch + "}": "/DEBUG", + "%{msvc_parse_showincludes_" + target_arch + "}": repr(False), } return msvc_vars @@ -679,6 +702,13 @@ def _get_msvc_vars(repository_ctx, paths, target_arch = "x64", msvc_vars_x64 = N support_debug_fastlink = _is_support_debug_fastlink(repository_ctx, build_tools["LINK"]) write_builtin_include_directory_paths(repository_ctx, "msvc", escaped_cxx_include_directories, file_suffix = "_msvc") + support_parse_showincludes = _is_support_parse_showincludes(repository_ctx, build_tools["CL"], env) + if not support_parse_showincludes: + auto_configure_warning(""" +Header pruning has been disabled since Bazel failed to recognize the output of /showIncludes. +This can result in unnecessary recompilation. +Fix this by installing the English language pack for the Visual Studio installation at {} and run 'bazel sync --configure'.""".format(vc_path)) + msvc_vars = { "%{msvc_env_tmp_" + target_arch + "}": escaped_tmp_dir, "%{msvc_env_include_" + target_arch + "}": escaped_include_paths, @@ -689,6 +719,7 @@ def _get_msvc_vars(repository_ctx, paths, target_arch = "x64", msvc_vars_x64 = N "%{msvc_ml_path_" + target_arch + "}": build_tools.get("ML", "msvc_arm_toolchain_does_not_support_ml"), "%{msvc_link_path_" + target_arch + "}": build_tools["LINK"], "%{msvc_lib_path_" + target_arch + "}": build_tools["LIB"], + "%{msvc_parse_showincludes_" + target_arch + "}": repr(support_parse_showincludes), "%{dbg_mode_debug_flag_" + target_arch + "}": "/DEBUG:FULL" if support_debug_fastlink else "/DEBUG", "%{fastbuild_mode_debug_flag_" + target_arch + "}": "/DEBUG:FASTLINK" if support_debug_fastlink else "/DEBUG", } @@ -738,6 +769,7 @@ def _get_clang_cl_vars(repository_ctx, paths, msvc_vars, target_arch): "%{clang_cl_dbg_mode_debug_flag_" + target_arch + "}": "/DEBUG", "%{clang_cl_fastbuild_mode_debug_flag_" + target_arch + "}": "/DEBUG", "%{clang_cl_cxx_builtin_include_directories_" + target_arch + "}": "", + "%{clang_cl_parse_showincludes_" + target_arch + "}": repr(False), } return clang_cl_vars @@ -765,6 +797,8 @@ def _get_clang_cl_vars(repository_ctx, paths, msvc_vars, target_arch): # LLVM's lld-link.exe doesn't support /DEBUG:FASTLINK. "%{clang_cl_dbg_mode_debug_flag_" + target_arch + "}": "/DEBUG", "%{clang_cl_fastbuild_mode_debug_flag_" + target_arch + "}": "/DEBUG", + # clang-cl always emits the English language version of the /showIncludes prefix. + "%{clang_cl_parse_showincludes_" + target_arch + "}": repr(True), } return clang_cl_vars diff --git a/tools/cpp/windows_cc_toolchain_config.bzl b/tools/cpp/windows_cc_toolchain_config.bzl index e2f464a6c8ae43..264adb8285e350 100644 --- a/tools/cpp/windows_cc_toolchain_config.bzl +++ b/tools/cpp/windows_cc_toolchain_config.bzl @@ -14,6 +14,7 @@ """A Starlark cc_toolchain configuration rule for Windows""" +load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") load( "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", "action_config", @@ -28,7 +29,6 @@ load( "variable_with_value", "with_feature_set", ) -load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") all_compile_actions = [ ACTION_NAMES.c_compile, @@ -187,7 +187,6 @@ def _impl(ctx): "compiler_output_flags", "nologo", "msvc_env", - "parse_showincludes", "user_compile_flags", "sysroot", ], @@ -202,7 +201,6 @@ def _impl(ctx): "default_compile_flags", "nologo", "msvc_env", - "parse_showincludes", "user_compile_flags", "sysroot", "unfiltered_compile_flags", @@ -217,7 +215,6 @@ def _impl(ctx): "compiler_output_flags", "nologo", "msvc_env", - "parse_showincludes", "user_compile_flags", "sysroot", ], @@ -788,6 +785,7 @@ def _impl(ctx): parse_showincludes_feature = feature( name = "parse_showincludes", + enabled = ctx.attr.supports_parse_showincludes, flag_sets = [ flag_set( actions = [ @@ -801,6 +799,27 @@ def _impl(ctx): flag_groups = [flag_group(flags = ["/showIncludes"])], ), ], + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ], + # Force English (and thus a consistent locale) output so that Bazel can parse + # the /showIncludes output without having to guess the encoding. + env_entries = [env_entry(key = "VSLANG", value = "1033")], + ), + ], + ) + + # MSVC does not emit .d files. + no_dotd_file_feature = feature( + name = "no_dotd_file", + enabled = True, ) treat_warnings_as_errors_feature = feature( @@ -1100,6 +1119,7 @@ def _impl(ctx): external_include_paths_feature, preprocessor_defines_feature, parse_showincludes_feature, + no_dotd_file_feature, generate_pdb_file_feature, shared_flag_feature, linkstamps_feature, @@ -1416,6 +1436,7 @@ cc_toolchain_config = rule( "dbg_mode_debug_flag": attr.string(), "fastbuild_mode_debug_flag": attr.string(), "tool_bin_path": attr.string(default = "not_found"), + "supports_parse_showincludes": attr.bool(), }, provides = [CcToolchainConfigInfo], )