Merge pull request #10159 from akyrtzi/persistent-pch-diag-file-4.0
[4.0][driver] For the persistent bridging PCH job action, make sure to pass a serialized diagnostics path in the PCH output directory
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 016c650..1ba47f8 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -35,6 +35,7 @@
#include "swift/Option/SanitizerOptions.h"
#include "swift/Parse/Lexer.h"
#include "swift/Config.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
@@ -1831,7 +1832,8 @@
static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
types::ID outputType, const OutputInfo &OI,
- const TypeToPathMap *outputMap) {
+ const TypeToPathMap *outputMap,
+ StringRef outputPath = StringRef()) {
StringRef outputMapPath;
if (outputMap) {
auto iter = outputMap->find(outputType);
@@ -1842,6 +1844,8 @@
if (!outputMapPath.empty()) {
// Prefer a path from the OutputMap.
output.setAdditionalOutputForType(outputType, outputMapPath);
+ } else if (!outputPath.empty()) {
+ output.setAdditionalOutputForType(outputType, outputPath);
} else {
// Put the auxiliary output file next to the primary output file.
llvm::SmallString<128> path;
@@ -1861,6 +1865,58 @@
}
}
+static void addDiagFileOutputForPersistentPCHAction(Compilation &C,
+ const GeneratePCHJobAction *JA,
+ CommandOutput &output,
+ const OutputInfo &OI,
+ const TypeToPathMap *outputMap,
+ DiagnosticEngine &diags) {
+ assert(JA->isPersistentPCH());
+
+ // For a persistent PCH we don't use an output, the frontend determines
+ // the filename to use for the PCH. For the diagnostics file, try to
+ // determine an invocation-specific path inside the directory where the
+ // PCH is going to be written, and fallback to a temporary file if we
+ // cannot determine such a path.
+
+ StringRef pchOutDir = JA->getPersistentPCHDir();
+ StringRef headerPath = output.getBaseInput(JA->getInputIndex());
+ StringRef stem = llvm::sys::path::stem(headerPath);
+ StringRef suffix = types::getTypeTempSuffix(types::TY_SerializedDiagnostics);
+ SmallString<256> outPathBuf;
+
+ if (const Arg *A = C.getArgs().getLastArg(options::OPT_emit_module_path)) {
+ // The module file path is unique for a specific module and architecture
+ // (it won't be concurrently written to) so we can use the path as hash
+ // for determining the filename to use for the diagnostic file.
+ StringRef ModuleOutPath = A->getValue();
+ outPathBuf = pchOutDir;
+ llvm::sys::path::append(outPathBuf, stem);
+ outPathBuf += '-';
+ auto code = llvm::hash_value(ModuleOutPath);
+ outPathBuf += llvm::APInt(64, code).toString(36, /*Signed=*/false);
+ llvm::sys::path::replace_extension(outPathBuf, suffix);
+ }
+
+ if (outPathBuf.empty()) {
+ // Fallback to creating a temporary file.
+ std::error_code EC =
+ llvm::sys::fs::createTemporaryFile(stem, suffix, outPathBuf);
+ if (EC) {
+ diags.diagnose(SourceLoc(),
+ diag::error_unable_to_make_temporary_file,
+ EC.message());
+ return;
+ }
+ C.addTemporaryFile(outPathBuf.str());
+ }
+
+ if (!outPathBuf.empty()) {
+ addAuxiliaryOutput(C, output, types::TY_SerializedDiagnostics, OI,
+ outputMap, outPathBuf.str());
+ }
+}
+
/// If the file at \p input has not been modified since the last build (i.e. its
/// mtime has not changed), adjust the Job's condition accordingly.
static void
@@ -2095,8 +2151,14 @@
if (isa<CompileJobAction>(JA) || isa<GeneratePCHJobAction>(JA)) {
// Choose the serialized diagnostics output path.
if (C.getArgs().hasArg(options::OPT_serialize_diagnostics)) {
- addAuxiliaryOutput(C, *Output, types::TY_SerializedDiagnostics, OI,
- OutputMap);
+ auto pchJA = dyn_cast<GeneratePCHJobAction>(JA);
+ if (pchJA && pchJA->isPersistentPCH()) {
+ addDiagFileOutputForPersistentPCHAction(C, pchJA, *Output, OI,
+ OutputMap, Diags);
+ } else {
+ addAuxiliaryOutput(C, *Output, types::TY_SerializedDiagnostics, OI,
+ OutputMap);
+ }
// Remove any existing diagnostics files so that clients can detect their
// presence to determine if a command was run.
diff --git a/test/Driver/bridging-pch.swift b/test/Driver/bridging-pch.swift
index 467126f..36fa159 100644
--- a/test/Driver/bridging-pch.swift
+++ b/test/Driver/bridging-pch.swift
@@ -42,6 +42,12 @@
// PERSISTENT-YESPCHJOB: {{.*}}swift -frontend {{.*}} -emit-pch -pch-output-dir {{.*}}/pch
// PERSISTENT-YESPCHJOB: {{.*}}swift -frontend {{.*}} -import-objc-header {{.*}}bridging-header.h -pch-output-dir {{.*}}/pch -pch-disable-validation
+// RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch -serialize-diagnostics %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-YESPCHJOB-DIAG1
+// PERSISTENT-YESPCHJOB-DIAG1: {{.*}}swift -frontend {{.*}} -serialize-diagnostics-path {{.*}}bridging-header-{{.*}}.dia {{.*}} -emit-pch -pch-output-dir {{.*}}/pch
+
+// RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch-out-dir -serialize-diagnostics %s -emit-module -emit-module-path /module-path-dir 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-YESPCHJOB-DIAG2
+// PERSISTENT-YESPCHJOB-DIAG2: {{.*}}swift -frontend {{.*}} -serialize-diagnostics-path {{.*}}/pch-out-dir/bridging-header-{{.*}}.dia {{.*}} -emit-pch -pch-output-dir {{.*}}/pch-out-dir
+
// RUN: %swiftc_driver -typecheck -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch -parseable-output -driver-skip-execution %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-OUTPUT
// PERSISTENT-OUTPUT-NOT: "outputs": [