Add Swift compilation flags to enable Clang's validate-per-build-session module behavior

Add '-validate-clang-modules-once' and '-clang-build-session-file' corresponding to Clang's '-fmodules-validate-once-per-build-session' and '-fbuild-session-file='. Ensure they are propagated to module interface build sub-invocations.

We require these to be first-class Swift options in order to ensure they are propagated to both: ClangImporter and implicit interface build compiler sub-invocations.

Compiler portion of rdar://105982120
This commit is contained in:
Artem Chikin
2023-02-28 10:50:09 -08:00
parent a64fc3b66d
commit 3ea5087e2f
9 changed files with 104 additions and 0 deletions

View File

@@ -221,6 +221,10 @@ ERROR(error_mode_requires_one_sil_multi_sib,none,
"this mode requires .sil for primary-file and only .sib for other inputs",
())
ERROR(error_clang_validate_once_requires_session_file,none,
"'-validate-clang-modules-once' also requires a '-clang-build-session-file' argument",
())
ERROR(error_no_output_filename_specified,none,
"an %0 filename was not specified for a mode which requires an "
"%0 filename", (StringRef))

View File

@@ -783,6 +783,14 @@ namespace swift {
/// Disable validating the persistent PCH.
bool PCHDisableValidation = false;
/// Don't verify input files for Clang modules if the module has been
/// successfully validated or loaded during this build session.
bool ValidateModulesOnce = false;
/// Use the last modification time of this file as the underlying Clang
/// build session timestamp.
std::string BuildSessionFilePath;
/// \see Mode
enum class Modes : uint8_t {
/// Set up Clang for importing modules into Swift and generating IR from

View File

@@ -550,6 +550,7 @@ private:
void
inheritOptionsForBuildingInterface(const SearchPathOptions &SearchPathOpts,
const LangOptions &LangOpts,
const ClangImporterOptions &clangImporterOpts,
bool suppressRemarks,
RequireOSSAModules_t requireOSSAModules);
bool extractSwiftInterfaceVersionAndArgs(CompilerInvocation &subInvocation,

View File

@@ -178,6 +178,15 @@ def no_strict_implicit_module_context :
Flags<[FrontendOption, HelpHidden]>,
HelpText<"Disable the strict forwarding of compilation context to downstream implicit module dependencies">;
def validate_clang_modules_once :
Flag<["-"], "validate-clang-modules-once">,
Flags<[FrontendOption]>,
HelpText<"Don't verify input files for Clang modules if the module has been successfully validated or loaded during this build session">;
def clang_build_session_file : Separate<["-"], "clang-build-session-file">,
Flags<[FrontendOption, ArgumentIsPath]>,
HelpText<"Use the last modification time of <file> as the underlying Clang build session timestamp">;
def disallow_forwarding_driver :
Flag<["-"], "disallow-use-new-driver">, Flags<[]>,
HelpText<"Disable using new swift-driver">;

View File

@@ -810,6 +810,11 @@ importer::addCommonInvocationArguments(
invocationArgStrs.push_back("-Xclang");
invocationArgStrs.push_back("-no-opaque-pointers");
if (importerOpts.ValidateModulesOnce) {
invocationArgStrs.push_back("-fmodules-validate-once-per-build-session");
invocationArgStrs.push_back("-fbuild-session-file=" + importerOpts.BuildSessionFilePath);
}
for (auto extraArg : importerOpts.ExtraArgs) {
invocationArgStrs.push_back(extraArg);
}

View File

@@ -1220,6 +1220,15 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
return HadError;
}
static bool ValidateModulesOnceOptions(const ClangImporterOptions &Opts,
DiagnosticEngine &Diags) {
if (Opts.ValidateModulesOnce && Opts.BuildSessionFilePath.empty()) {
Diags.diagnose(SourceLoc(), diag::error_clang_validate_once_requires_session_file);
return true;
}
return false;
}
static bool ParseClangImporterArgs(ClangImporterOptions &Opts,
ArgList &Args,
DiagnosticEngine &Diags,
@@ -1314,6 +1323,12 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts,
Opts.PCHDisableValidation |= Args.hasArg(OPT_pch_disable_validation);
}
Opts.ValidateModulesOnce |= Args.hasArg(OPT_validate_clang_modules_once);
if (auto *A = Args.getLastArg(OPT_clang_build_session_file))
Opts.BuildSessionFilePath = A->getValue();
if (ValidateModulesOnceOptions(Opts, Diags))
return true;
if (Args.hasFlag(options::OPT_warnings_as_errors,
options::OPT_no_warnings_as_errors, false))
Opts.ExtraArgs.push_back("-Werror");

View File

@@ -1448,6 +1448,7 @@ void ModuleInterfaceLoader::collectVisibleTopLevelModuleNames(
void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts,
const ClangImporterOptions &clangImporterOpts,
bool suppressRemarks, RequireOSSAModules_t RequireOSSAModules) {
GenericArgs.push_back("-frontend");
// Start with a genericSubInvocation that copies various state from our
@@ -1544,6 +1545,16 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
genericSubInvocation.getLangOptions().Features.insert(
Feature::LayoutPrespecialization);
}
// Validate Clang modules once perbuild session flags must be consistent
// across all module sub-invocations
if (clangImporterOpts.ValidateModulesOnce) {
genericSubInvocation.getClangImporterOptions().ValidateModulesOnce = true;
genericSubInvocation.getClangImporterOptions().BuildSessionFilePath = clangImporterOpts.BuildSessionFilePath;
GenericArgs.push_back("-validate-clang-modules-once");
GenericArgs.push_back("-clang-build-session-file");
GenericArgs.push_back(clangImporterOpts.BuildSessionFilePath);
}
}
bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs(
@@ -1586,6 +1597,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
: SM(SM), Diags(Diags), ArgSaver(Allocator) {
genericSubInvocation.setMainExecutablePath(LoaderOpts.mainExecutablePath);
inheritOptionsForBuildingInterface(searchPathOpts, langOpts,
clangImporterOpts,
Diags->getSuppressRemarks(),
requireOSSAModules);
// Configure front-end input.
@@ -1621,6 +1633,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
genericSubInvocation.getLangOptions().EnableAppExtensionRestrictions = true;
GenericArgs.push_back("-application-extension");
}
// Save the parent invocation's Target Triple
ParentInvocationTarget = langOpts.Target;

View File

@@ -0,0 +1,8 @@
// RUN: %empty-directory(%t)
// RUN: touch %t/Build.session
// RUN: %swift %s -typecheck -dump-clang-diagnostics -validate-clang-modules-once -clang-build-session-file %t/Build.session 2>&1 | %FileCheck %s
public func foo() {}
// CHECK: '-fmodules-validate-once-per-build-session'
// CHECK: '-fbuild-session-file=

View File

@@ -0,0 +1,41 @@
// This test ensures that the parent invocation's '-validate-clang-modules-once' flag is inherited when building dependency modules
// RUN: %empty-directory(%t)
// RUN: touch %t/Build.session
// RUN: %target-build-swift -module-name TestModule -module-link-name TestModule %S/Inputs/TestModule.swift -enable-library-evolution -emit-module-interface -o %t/TestModule.swiftmodule -swift-version 5 -Xfrontend -disable-implicit-concurrency-module-import -Xfrontend -disable-implicit-string-processing-module-import
// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I%t -validate-clang-modules-once -clang-build-session-file %t/Build.session -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import
// RUN: %FileCheck %s < %t/deps.json
import TestModule
// CHECK: "directDependencies": [
// CHECK-NEXT: {
// CHECK-DAG: "swift": "TestModule"
// CHECK-DAG: "swift": "Swift"
// CHECK-DAG: "swift": "SwiftOnoneSupport"
// CHECK: "swift": "TestModule"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "modulePath": "{{.*}}TestModule-{{.*}}.swiftmodule",
// CHECK-NEXT: "sourceFiles": [
// CHECK-NEXT: ],
// CHECK-NEXT: "directDependencies": [
// CHECK-NEXT: {
// CHECK-NEXT: "swift": "Swift"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "swift": "SwiftOnoneSupport"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "details": {
// CHECK-NEXT: "swift": {
// CHECK-NEXT: "moduleInterfacePath":
// CHECK-NEXT: "contextHash":
// CHECK-NEXT: "commandLine": [
// CHECK-NEXT: "-frontend",
// CHECK-NEXT: "-compile-module-from-interface",
// CHECK: "-validate-clang-modules-once",
// CHECK-NEXT: "-clang-build-session-file",
// CHECK-NEXT: "{{.*}}Build.session"