diff --git a/proto/swift_proto_library.bzl b/proto/swift_proto_library.bzl index 5da66e26b..dd0a35408 100644 --- a/proto/swift_proto_library.bzl +++ b/proto/swift_proto_library.bzl @@ -74,12 +74,18 @@ def _swift_proto_library_impl(ctx): direct_swift_proto_cc_info = direct_providers.direct_swift_proto_cc_info direct_swift_info = direct_providers.direct_swift_info direct_swift_proto_info = direct_providers.direct_swift_proto_info + direct_stats_files = getattr( + direct_output_group_info, + "swift_stats", + depset(), + ).to_list() direct_files = compact( [module.swift.swiftdoc for module in direct_swift_info.direct_modules] + [module.swift.swiftinterface for module in direct_swift_info.direct_modules] + [module.swift.private_swiftinterface for module in direct_swift_info.direct_modules] + [module.swift.swiftmodule for module in direct_swift_info.direct_modules] + - [module.swift.swiftsourceinfo for module in direct_swift_info.direct_modules], + [module.swift.swiftsourceinfo for module in direct_swift_info.direct_modules] + + direct_stats_files, ) return [ diff --git a/proto/swift_proto_library_group.bzl b/proto/swift_proto_library_group.bzl index 15515b0e8..313696995 100644 --- a/proto/swift_proto_library_group.bzl +++ b/proto/swift_proto_library_group.bzl @@ -104,12 +104,18 @@ def _swift_proto_library_group_impl(ctx): direct_swift_proto_cc_info = proto_target[SwiftProtoCcInfo] direct_swift_info = proto_target[SwiftInfo] direct_swift_proto_info = proto_target[SwiftProtoInfo] + direct_stats_files = getattr( + direct_output_group_info, + "swift_stats", + depset(), + ).to_list() direct_files = compact( [module.swift.swiftdoc for module in direct_swift_info.direct_modules] + [module.swift.swiftinterface for module in direct_swift_info.direct_modules] + [module.swift.private_swiftinterface for module in direct_swift_info.direct_modules] + [module.swift.swiftmodule for module in direct_swift_info.direct_modules] + - [module.swift.swiftsourceinfo for module in direct_swift_info.direct_modules], + [module.swift.swiftsourceinfo for module in direct_swift_info.direct_modules] + + direct_stats_files, ) return [ diff --git a/swift/internal/compiling.bzl b/swift/internal/compiling.bzl index 96cec8aef..b768eb4c5 100644 --- a/swift/internal/compiling.bzl +++ b/swift/internal/compiling.bzl @@ -42,6 +42,7 @@ load( "SWIFT_FEATURE_EMIT_BC", "SWIFT_FEATURE_EMIT_C_MODULE", "SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE", + "SWIFT_FEATURE_EMIT_STATS", "SWIFT_FEATURE_EMIT_SWIFTDOC", "SWIFT_FEATURE_EMIT_SWIFTINTERFACE", "SWIFT_FEATURE_ENABLE_EMBEDDED", @@ -567,6 +568,9 @@ def compile( represents the location where macro expansion files were written (only in debug/fastbuild and only when the toolchain supports macros). + + * `stats_directory`: A directory-type `File` that represents the + location where Swift compilation statistics were written. """ toolchains = gather_toolchains( swift_toolchain = swift_toolchain, @@ -658,6 +662,7 @@ def compile( if split_derived_file_generation: all_compile_outputs = compact([ compile_outputs.indexstore_directory, + compile_outputs.stats_directory, ]) + compile_outputs.object_files + compile_outputs.const_values_files all_derived_outputs = compact([ # The `.swiftmodule` file is explicitly listed as the first output @@ -686,6 +691,7 @@ def compile( compile_outputs.generated_header_file, compile_outputs.indexstore_directory, compile_outputs.macro_expansion_directory, + compile_outputs.stats_directory, ]) + compile_outputs.object_files + compile_outputs.const_values_files all_derived_outputs = [] @@ -960,6 +966,7 @@ to use swift_common.compile(include_dev_srch_paths = ...) instead.\ const_values_files = compile_outputs.const_values_files, indexstore_directory = compile_outputs.indexstore_directory, macro_expansion_directory = compile_outputs.macro_expansion_directory, + stats_directory = compile_outputs.stats_directory, ), swift_info = SwiftInfo( modules = [module_context], @@ -1523,6 +1530,16 @@ def _declare_compile_outputs( indexstore_directory = None include_index_unit_paths = False + if is_feature_enabled( + feature_configuration = feature_configuration, + feature_name = SWIFT_FEATURE_EMIT_STATS, + ): + stats_directory = actions.declare_directory( + "{}.swift-stats".format(target_name), + ) + else: + stats_directory = None + if not output_nature.emits_multiple_objects: # If we're emitting a single object, we don't use an object map; we just # declare the output file that the compiler will generate and there are @@ -1607,6 +1624,7 @@ def _declare_compile_outputs( object_files = object_files, output_file_map = output_file_map, derived_files_output_file_map = derived_files_output_file_map, + stats_directory = stats_directory, swiftdoc_file = swiftdoc_file, swiftinterface_file = swiftinterface_file, swiftmodule_file = swiftmodule_file, diff --git a/swift/internal/feature_names.bzl b/swift/internal/feature_names.bzl index f1ee4610e..72b6e841d 100644 --- a/swift/internal/feature_names.bzl +++ b/swift/internal/feature_names.bzl @@ -415,6 +415,10 @@ SWIFT_FEATURE_SUPPRESS_WARNINGS = "swift.suppress_warnings" # Pass -warnings-as-errors to the compiler. SWIFT_FEATURE_TREAT_WARNINGS_AS_ERRORS = "swift.treat_warnings_as_errors" +# If enabled, Swift compilation actions emit unified compilation statistics into +# a declared output directory. +SWIFT_FEATURE_EMIT_STATS = "swift.emit_stats" + # A feature that adds target_name in output path to support building # multiple frameworks with different target name, but same module name. SWIFT_FEATURE_ADD_TARGET_NAME_TO_OUTPUT = "swift.add_target_name_to_output" diff --git a/swift/internal/output_groups.bzl b/swift/internal/output_groups.bzl index 6f23f17e8..fde8f6e59 100644 --- a/swift/internal/output_groups.bzl +++ b/swift/internal/output_groups.bzl @@ -39,6 +39,7 @@ def supplemental_compilation_output_groups( const_values_files = [] indexstore_files = list(additional_indexstore_files) macro_expansions_files = [] + stats_files = [] for outputs in supplemental_outputs: if outputs.ast_files: @@ -49,6 +50,9 @@ def supplemental_compilation_output_groups( indexstore_files.append(outputs.indexstore_directory) if outputs.macro_expansion_directory: macro_expansions_files.append(outputs.macro_expansion_directory) + stats_directory = getattr(outputs, "stats_directory", None) + if stats_directory: + stats_files.append(stats_directory) output_groups = {} if ast_files: @@ -59,4 +63,6 @@ def supplemental_compilation_output_groups( output_groups["swift_index_store"] = depset(indexstore_files) if macro_expansions_files: output_groups["macro_expansions"] = depset(macro_expansions_files) + if stats_files: + output_groups["swift_stats"] = depset(stats_files) return output_groups diff --git a/swift/swift_binary.bzl b/swift/swift_binary.bzl index 0538c3db0..ec69e2940 100644 --- a/swift/swift_binary.bzl +++ b/swift/swift_binary.bzl @@ -43,6 +43,7 @@ load( ) load( "//swift/internal:utils.bzl", + "compact", "expand_locations", "get_providers", "include_developer_search_paths", @@ -88,6 +89,7 @@ def _swift_binary_impl(ctx): output_groups = {} module_contexts = [] additional_linking_contexts = [] + default_compile_outputs = [] # If the binary has sources, compile those first and collect the outputs to # be passed to the linker. @@ -134,6 +136,9 @@ def _swift_binary_impl(ctx): output_groups = supplemental_compilation_output_groups( supplemental_outputs, ) + default_compile_outputs = compact([ + supplemental_outputs.stats_directory, + ]) else: compile_result = None entry_point_function_name = None @@ -196,7 +201,9 @@ def _swift_binary_impl(ctx): DefaultInfo( executable = linking_outputs.executable, files = depset( - [linking_outputs.executable] + additional_debug_outputs, + [linking_outputs.executable] + + additional_debug_outputs + + default_compile_outputs, ), runfiles = ctx.runfiles( collect_data = True, diff --git a/swift/swift_compiler_plugin.bzl b/swift/swift_compiler_plugin.bzl index 83239f656..394fafc06 100644 --- a/swift/swift_compiler_plugin.bzl +++ b/swift/swift_compiler_plugin.bzl @@ -49,6 +49,7 @@ load( ) load( "//swift/internal:utils.bzl", + "compact", "expand_locations", "get_providers", ) @@ -112,6 +113,9 @@ def _swift_compiler_plugin_impl(ctx): module_contexts.append(module_context) compilation_outputs = compile_result.compilation_outputs supplemental_outputs = compile_result.supplemental_outputs + default_compile_outputs = compact([ + supplemental_outputs.stats_directory, + ]) # Apply the optional debugging outputs extension if the toolchain defines # one. @@ -189,7 +193,9 @@ def _swift_compiler_plugin_impl(ctx): DefaultInfo( executable = binary_linking_outputs.executable, files = depset( - [binary_linking_outputs.executable] + additional_debug_outputs, + [binary_linking_outputs.executable] + + additional_debug_outputs + + default_compile_outputs, ), runfiles = ctx.runfiles( collect_data = True, diff --git a/swift/swift_library.bzl b/swift/swift_library.bzl index 24ade7444..05a79f3f8 100644 --- a/swift/swift_library.bzl +++ b/swift/swift_library.bzl @@ -256,6 +256,7 @@ def _swift_library_impl(ctx): module_context.swift.private_swiftinterface, module_context.swift.swiftmodule, module_context.swift.swiftsourceinfo, + supplemental_outputs.stats_directory, linking_output.library_to_link.static_library, linking_output.library_to_link.pic_static_library, ]) diff --git a/swift/swift_test.bzl b/swift/swift_test.bzl index 1b4603983..9fa5b6820 100644 --- a/swift/swift_test.bzl +++ b/swift/swift_test.bzl @@ -50,6 +50,7 @@ load( ) load( "//swift/internal:utils.bzl", + "compact", "expand_locations", "get_providers", "include_developer_search_paths", @@ -496,12 +497,18 @@ def _swift_test_impl(ctx): {"TEST_BINARIES_FOR_LLVM_COV": linking_outputs.executable.short_path}, expanded_env.get_expanded_env(ctx, {}), ) + default_compile_outputs = compact([ + getattr(outputs, "stats_directory", None) + for outputs in all_supplemental_outputs + ]) return [ DefaultInfo( executable = linking_outputs.executable, files = depset( - [linking_outputs.executable] + additional_debug_outputs, + [linking_outputs.executable] + + additional_debug_outputs + + default_compile_outputs, ), runfiles = ctx.runfiles( collect_data = True, diff --git a/swift/toolchains/config/compile_config.bzl b/swift/toolchains/config/compile_config.bzl index 4a1433fe2..2c821a344 100644 --- a/swift/toolchains/config/compile_config.bzl +++ b/swift/toolchains/config/compile_config.bzl @@ -51,6 +51,7 @@ load( "SWIFT_FEATURE_EMIT_BC", "SWIFT_FEATURE_EMIT_C_MODULE", "SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE", + "SWIFT_FEATURE_EMIT_STATS", "SWIFT_FEATURE_EMIT_SWIFTDOC", "SWIFT_FEATURE_EMIT_SWIFTINTERFACE", "SWIFT_FEATURE_ENABLE_BARE_SLASH_REGEX", @@ -283,6 +284,13 @@ def compile_action_configs( configurators = [_constant_value_extraction_configurator], ), + # Configure compiler statistics output. + ActionConfigInfo( + actions = [SWIFT_ACTION_COMPILE], + configurators = [_stats_output_configurator], + features = [SWIFT_FEATURE_EMIT_STATS], + ), + # Link Time Optimization (LTO). ActionConfigInfo( actions = all_compile_action_names(), @@ -2398,6 +2406,14 @@ def _constant_value_extraction_configurator(prerequisites, args): inputs = [prerequisites.const_gather_protocols_file], ) +def _stats_output_configurator(prerequisites, args): + """Adds flags related to Swift compile statistics output.""" + args.add( + "-Xwrapped-swift=-stats-output-dir={}".format( + prerequisites.stats_directory.path, + ), + ) + def _upcoming_and_experimental_features_configurator(prerequisites, args): """Adds upcoming and experimental features to the command line.""" args.add_all( diff --git a/test/BUILD b/test/BUILD index 3e0a78ddc..c5f30a16b 100644 --- a/test/BUILD +++ b/test/BUILD @@ -25,6 +25,7 @@ load(":private_deps_tests.bzl", "private_deps_test_suite") load(":private_swiftinterface_tests.bzl", "private_swiftinterface_test_suite") load(":runtime_deps_tests.bzl", "runtime_deps_test_suite") load(":split_derived_files_tests.bzl", "split_derived_files_test_suite") +load(":stats_output_tests.bzl", "stats_output_test_suite") load(":swift_binary_linking_tests.bzl", "swift_binary_linking_test_suite") load(":swift_through_non_swift_tests.bzl", "swift_through_non_swift_test_suite") load(":swift_toolchain_tests.bzl", "swift_toolchain_test_suite") @@ -75,6 +76,8 @@ private_deps_test_suite(name = "private_deps") split_derived_files_test_suite(name = "split_derived_files") +stats_output_test_suite(name = "stats_output") + swift_binary_linking_test_suite(name = "swift_binary_rules") swift_through_non_swift_test_suite(name = "swift_through_non_swift") diff --git a/test/stats_output_tests.bzl b/test/stats_output_tests.bzl new file mode 100644 index 000000000..908d44388 --- /dev/null +++ b/test/stats_output_tests.bzl @@ -0,0 +1,87 @@ +"""Tests for `swift.emit_stats`.""" + +load( + "//test/rules:action_command_line_test.bzl", + "action_command_line_test", + "make_action_command_line_test_rule", +) +load( + "//test/rules:provider_test.bzl", + "make_provider_test_rule", +) + +stats_output_command_line_test = make_action_command_line_test_rule( + config_settings = { + "//command_line_option:features": [ + "swift.emit_stats", + ], + }, +) + +stats_output_provider_test = make_provider_test_rule( + config_settings = { + "//command_line_option:features": [ + "swift.emit_stats", + ], + }, +) + +def stats_output_test_suite(name, tags = []): + """Test suite for Swift stats output. + + Args: + name: The base name to be used in targets created by this macro. + tags: Additional tags to apply to each test. + """ + all_tags = [name] + tags + + action_command_line_test( + name = "{}_disabled_by_default".format(name), + mnemonic = "SwiftCompile", + not_expected_argv = [ + "-stats-output-dir", + ], + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + stats_output_command_line_test( + name = "{}_command_line".format(name), + expected_argv = [ + "-Xwrapped-swift=-stats-output-dir=$(BIN_DIR)/test/fixtures/debug_settings/simple.swift-stats", + ], + mnemonic = "SwiftCompile", + not_expected_argv = [ + "-trace-stats-events", + ], + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + stats_output_provider_test( + name = "{}_default_files".format(name), + expected_files = [ + "test/fixtures/debug_settings/simple.swift-stats", + "*", + ], + field = "files", + provider = "DefaultInfo", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + stats_output_provider_test( + name = "{}_output_group".format(name), + expected_files = [ + "test/fixtures/debug_settings/simple.swift-stats", + ], + field = "swift_stats", + provider = "OutputGroupInfo", + tags = all_tags, + target_under_test = "//test/fixtures/debug_settings:simple", + ) + + native.test_suite( + name = name, + tags = all_tags, + ) diff --git a/tools/common/bazel_substitutions.cc b/tools/common/bazel_substitutions.cc index b862e43ed..2b68993a7 100644 --- a/tools/common/bazel_substitutions.cc +++ b/tools/common/bazel_substitutions.cc @@ -69,9 +69,10 @@ std::string GetToolchainPath() { char* toolchain_id = getenv("TOOLCHAINS"); std::ostringstream output_stream; - int exit_code = - RunSubProcess({"/usr/bin/xcrun", "--find", "clang"}, - /*env=*/nullptr, &output_stream, /*stdout_to_stderr=*/true); + int exit_code = RunSubProcess({"/usr/bin/xcrun", "--find", "clang"}, + /*env=*/nullptr, &output_stream, + /*stdout_to_stderr=*/true, + /*print_timestamps=*/false); if (exit_code != 0) { std::cerr << output_stream.str() << "Error: `TOOLCHAINS=" << toolchain_id << "xcrun --find clang` failed with error code " << exit_code diff --git a/tools/common/process.cc b/tools/common/process.cc index 75737f79a..899d854ee 100644 --- a/tools/common/process.cc +++ b/tools/common/process.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,40 @@ extern char** environ; } #endif +namespace { + +std::string FormatLocalTime() { + std::time_t now = std::time(nullptr); + + std::tm local_time; +#if defined(_WIN32) + localtime_s(&local_time, &now); +#else + localtime_r(&now, &local_time); +#endif + + char time_buffer[9]; + std::strftime(time_buffer, sizeof(time_buffer), "%H:%M:%S", &local_time); + return time_buffer; +} + +} // namespace + +void PrintWorkerTimestamp(std::ostream* stderr_stream, const char* event) { + (*stderr_stream) << "rules_swift_worker " << event << " " << FormatLocalTime() + << "\n"; +} + +void PrintWorkerTimestamp(std::ostream* stderr_stream, const char* event, + const std::vector& args) { + (*stderr_stream) << "rules_swift_worker " << event << " " + << FormatLocalTime(); + if (!args.empty()) { + (*stderr_stream) << " " << args[0]; + } + (*stderr_stream) << "\n"; +} + std::map GetCurrentEnvironment() { std::map result; char** envp = environ; @@ -201,7 +236,8 @@ std::string GetCommandLine(const std::vector& arguments) { int RunSubProcess(const std::vector& args, std::map* env, - std::ostream* stderr_stream, bool stdout_to_stderr) { + std::ostream* stderr_stream, bool stdout_to_stderr, + bool print_timestamps) { std::error_code ec; std::unique_ptr redirector = WindowsIORedirector::Create(stdout_to_stderr, ec); @@ -212,6 +248,9 @@ int RunSubProcess(const std::vector& args, } PROCESS_INFORMATION piProcess = {0}; + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "exec", args); + } if (!CreateProcessA(NULL, GetCommandLine(args).data(), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &redirector->siStartInfo, &piProcess)) { @@ -230,6 +269,9 @@ int RunSubProcess(const std::vector& args, (*stderr_stream) << "wait for process failure (error " << dwLastError << ")\n"; CloseHandle(piProcess.hProcess); + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "after-exec", args); + } return dwLastError; } @@ -239,10 +281,16 @@ int RunSubProcess(const std::vector& args, (*stderr_stream) << "unable to get exit code (error " << dwLastError << ")\n"; CloseHandle(piProcess.hProcess); + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "after-exec", args); + } return dwLastError; } CloseHandle(piProcess.hProcess); + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "after-exec", args); + } return dwExitCode; } @@ -365,7 +413,8 @@ std::vector ConvertToCArgs(const std::vector& args) { int RunSubProcess(const std::vector& args, std::map* env, - std::ostream* stderr_stream, bool stdout_to_stderr) { + std::ostream* stderr_stream, bool stdout_to_stderr, + bool print_timestamps) { std::vector exec_argv = ConvertToCArgs(args); // Set up a pipe to redirect stderr from the child process so that we can @@ -398,6 +447,9 @@ int RunSubProcess(const std::vector& args, } pid_t pid; + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "exec", args); + } int status = posix_spawn(&pid, args[0].c_str(), redirector->PosixSpawnFileActions(), nullptr, exec_argv.data(), envp); @@ -422,22 +474,39 @@ int RunSubProcess(const std::vector& args, if (wait_status < 0) { (*stderr_stream) << "error: waiting on child process '" << args[0] << "'. " << strerror(errno) << "\n"; + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "after-exec", args); + } return wait_status; } if (WIFEXITED(status)) { - return WEXITSTATUS(status); + int exit_code = WEXITSTATUS(status); + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "after-exec", args); + } + return exit_code; } if (WIFSIGNALED(status)) { - return WTERMSIG(status); + int signal = WTERMSIG(status); + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "after-exec", args); + } + return signal; } // Unhandled case, if we hit this we should handle it above. + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "after-exec", args); + } return 42; } else { (*stderr_stream) << "error: forking process failed '" << args[0] << "'. " << strerror(status) << "\n"; + if (print_timestamps) { + PrintWorkerTimestamp(stderr_stream, "after-exec", args); + } return status; } } diff --git a/tools/common/process.h b/tools/common/process.h index 487f31106..54da7b31b 100644 --- a/tools/common/process.h +++ b/tools/common/process.h @@ -16,6 +16,7 @@ #define BUILD_BAZEL_RULES_SWIFT_TOOLS_WRAPPERS_PROCESS_H #include +#include #include #include @@ -25,7 +26,13 @@ // code of the spawned process. int RunSubProcess(const std::vector& args, std::map* env, - std::ostream* stderr_stream, bool stdout_to_stderr = false); + std::ostream* stderr_stream, bool stdout_to_stderr = false, + bool print_timestamps = true); + +// Prints a temporary worker timestamp diagnostic to the given stderr stream. +void PrintWorkerTimestamp(std::ostream* stderr_stream, const char* event); +void PrintWorkerTimestamp(std::ostream* stderr_stream, const char* event, + const std::vector& args); // Returns a hash map containing the current process's environment. std::map GetCurrentEnvironment(); diff --git a/tools/worker/BUILD b/tools/worker/BUILD index f5ec8e632..5da4429c0 100644 --- a/tools/worker/BUILD +++ b/tools/worker/BUILD @@ -26,6 +26,7 @@ cc_library( deps = [ ":swift_runner", ":worker_protocol", + "//tools/common:process", "//tools/common:temp_file", ], ) @@ -48,6 +49,7 @@ cc_library( }), deps = [ ":swift_runner", + "//tools/common:process", ], ) @@ -159,6 +161,7 @@ cc_binary( deps = [ ":compile_with_worker", ":compile_without_worker", + "//tools/common:process", "@bazel_tools//tools/cpp/runfiles", ], ) diff --git a/tools/worker/compile_without_worker.cc b/tools/worker/compile_without_worker.cc index 1870095df..fc275a159 100644 --- a/tools/worker/compile_without_worker.cc +++ b/tools/worker/compile_without_worker.cc @@ -18,10 +18,13 @@ #include #include +#include "tools/common/process.h" #include "tools/worker/swift_runner.h" int CompileWithoutWorker(const std::vector& args, std::string index_import_path) { + std::ostream* stderr_stream = &std::cerr; + PrintWorkerTimestamp(stderr_stream, "main"); return SwiftRunner(args, index_import_path) - .Run(&std::cerr, /*stdout_to_stderr=*/false); + .Run(stderr_stream, /*stdout_to_stderr=*/false); } diff --git a/tools/worker/pcm_hermetic_runner.cc b/tools/worker/pcm_hermetic_runner.cc index 2ee0b119c..6fc8d5262 100644 --- a/tools/worker/pcm_hermetic_runner.cc +++ b/tools/worker/pcm_hermetic_runner.cc @@ -54,8 +54,11 @@ int CaptureFrontendCommand(const std::vector& args, driver_args.push_back("-###"); std::stringstream sink; + PrintWorkerTimestamp(stderr_stream, "exec", driver_args); int rc = RunSubProcess(driver_args, /*env=*/nullptr, &sink, - /*stdout_to_stderr=*/true); + /*stdout_to_stderr=*/true, + /*print_timestamps=*/false); + PrintWorkerTimestamp(stderr_stream, "after-exec", driver_args); *captured = sink.str(); if (rc != 0) { (*stderr_stream) << "error: hermetic-pcm: swiftc -### exited " << rc diff --git a/tools/worker/swift_runner.cc b/tools/worker/swift_runner.cc index 6fcd73e3a..ed8ea92d9 100644 --- a/tools/worker/swift_runner.cc +++ b/tools/worker/swift_runner.cc @@ -592,6 +592,11 @@ bool SwiftRunner::ProcessArgument( job_env_["TEMPDIR"] = new_arg; job_env_.erase("TMPDIR"); #endif + } else if (StripPrefix("-stats-output-dir=", new_arg)) { + changed = true; + std::filesystem::create_directories(new_arg); + consumer("-stats-output-dir"); + consumer(new_arg); } else if (new_arg == "-ephemeral-module-cache") { // Create a temporary directory to hold the module cache, which will be // deleted after compilation is finished. diff --git a/tools/worker/work_processor.cc b/tools/worker/work_processor.cc index df6021c84..5f7cee283 100644 --- a/tools/worker/work_processor.cc +++ b/tools/worker/work_processor.cc @@ -26,6 +26,7 @@ #include #include +#include "tools/common/process.h" #include "tools/common/temp_file.h" #include "tools/worker/output_file_map.h" #include "tools/worker/swift_runner.h" @@ -209,6 +210,7 @@ void WorkProcessor::ProcessWorkRequest( params_file_stream.close(); std::ostringstream stderr_stream; + PrintWorkerTimestamp(&stderr_stream, "main"); if (is_incremental) { std::set dir_paths; diff --git a/tools/worker/worker_main.cc b/tools/worker/worker_main.cc index c3a8ec35c..c5f58674c 100644 --- a/tools/worker/worker_main.cc +++ b/tools/worker/worker_main.cc @@ -13,7 +13,6 @@ // limitations under the License. #include -#include #include #include