Skip to content

Commit de7ab4c

Browse files
committed
[Dependency Scanning] Disable validation of Swift dependency modules' existing pre-built candidate binary module files in the scanner, on a non-caching build.
As-is, this default interferes with the incremental build machinery which conservatively assumes that binary module dependencies must cause dependents to be re-built.
1 parent d9476aa commit de7ab4c

File tree

8 files changed

+25
-20
lines changed

8 files changed

+25
-20
lines changed

include/swift/AST/SearchPathOptions.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,9 @@ class SearchPathOptions {
532532
/// Specify the module loading behavior of the compilation.
533533
ModuleLoadingMode ModuleLoadMode = ModuleLoadingMode::PreferSerialized;
534534

535-
/// Legacy scanner search behavior.
536-
bool NoScannerModuleValidation = false;
535+
/// New scanner search behavior. Validate up-to-date existing Swift module
536+
/// dependencies in the scanner itself.
537+
bool ScannerModuleValidation = false;
537538

538539
/// Return all module search paths that (non-recursively) contain a file whose
539540
/// name is in \p Filenames.
@@ -583,7 +584,7 @@ class SearchPathOptions {
583584
hash_combine_range(RuntimeLibraryImportPaths.begin(),
584585
RuntimeLibraryImportPaths.end()),
585586
DisableModulesValidateSystemDependencies,
586-
NoScannerModuleValidation,
587+
ScannerModuleValidation,
587588
ModuleLoadMode);
588589
}
589590

include/swift/Option/FrontendOptions.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,8 @@ def disable_sending_args_and_results_with_region_isolation : Flag<["-"],
13571357
HelpText<"Disable sending args and results when region based isolation is enabled. Only enabled with asserts">,
13581358
Flags<[HelpHidden]>;
13591359

1360+
def scanner_module_validation: Flag<["-"], "scanner-module-validation">,
1361+
HelpText<"Validate binary modules in the dependency scanner">;
13601362
def no_scanner_module_validation: Flag<["-"], "no-scanner-module-validation">,
13611363
HelpText<"Do not validate binary modules in scanner and delegate the validation to swift-frontend">;
13621364
def module_load_mode: Separate<["-"], "module-load-mode">,

lib/Frontend/CompilerInvocation.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,6 +1967,7 @@ static bool validateSwiftModuleFileArgumentAndAdd(const std::string &swiftModule
19671967

19681968
static bool ParseSearchPathArgs(SearchPathOptions &Opts, ArgList &Args,
19691969
DiagnosticEngine &Diags,
1970+
const CASOptions &CASOpts,
19701971
StringRef workingDirectory) {
19711972
using namespace options;
19721973
namespace path = llvm::sys::path;
@@ -2104,8 +2105,10 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, ArgList &Args,
21042105
Opts.ScannerPrefixMapper.push_back(Opt.str());
21052106
}
21062107

2107-
Opts.NoScannerModuleValidation |=
2108-
Args.hasArg(OPT_no_scanner_module_validation);
2108+
// rdar://132340493 disable scanner-side validation for non-caching builds
2109+
Opts.ScannerModuleValidation |= Args.hasFlag(OPT_scanner_module_validation,
2110+
OPT_no_scanner_module_validation,
2111+
CASOpts.EnableCaching);
21092112

21102113
std::optional<std::string> forceModuleLoadingMode;
21112114
if (auto *A = Args.getLastArg(OPT_module_load_mode))
@@ -3494,7 +3497,7 @@ bool CompilerInvocation::parseArgs(
34943497
ParseSymbolGraphArgs(SymbolGraphOpts, ParsedArgs, Diags, LangOpts);
34953498

34963499
if (ParseSearchPathArgs(SearchPathOpts, ParsedArgs, Diags,
3497-
workingDirectory)) {
3500+
CASOpts, workingDirectory)) {
34983501
return true;
34993502
}
35003503

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,7 @@ ModuleInterfaceCheckerImpl::getCompiledModuleCandidatesForInterface(
14021402

14031403
auto validateModule = [&](StringRef modulePath) {
14041404
// Legacy behavior do not validate module.
1405-
if (Ctx.SearchPathOpts.NoScannerModuleValidation)
1405+
if (!Ctx.SearchPathOpts.ScannerModuleValidation)
14061406
return true;
14071407

14081408
// If we picked the other module already, no need to validate this one since
@@ -1919,8 +1919,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
19191919
searchPathOpts.PluginSearchOpts;
19201920

19211921
// Get module loading behavior options.
1922-
genericSubInvocation.getSearchPathOptions().NoScannerModuleValidation =
1923-
searchPathOpts.NoScannerModuleValidation;
1922+
genericSubInvocation.getSearchPathOptions().ScannerModuleValidation = searchPathOpts.ScannerModuleValidation;
19241923
genericSubInvocation.getSearchPathOptions().ModuleLoadMode =
19251924
searchPathOpts.ModuleLoadMode;
19261925

lib/Serialization/ScanningLoaders.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
156156
auto compiledCandidates =
157157
getCompiledCandidates(Ctx, realModuleName.str(), InPath);
158158
if (!compiledCandidates.empty() &&
159-
!Ctx.SearchPathOpts.NoScannerModuleValidation) {
159+
Ctx.SearchPathOpts.ScannerModuleValidation) {
160160
assert(compiledCandidates.size() == 1 &&
161161
"Should only have 1 candidate module");
162162
auto BinaryDep = scanModuleFile(compiledCandidates[0], isFramework,

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework,
454454
isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
455455
Ctx.SearchPathOpts.DeserializedPathRecoverer, loadedModuleFile);
456456

457-
if (!Ctx.SearchPathOpts.NoScannerModuleValidation) {
457+
if (Ctx.SearchPathOpts.ScannerModuleValidation) {
458458
// If failed to load, just ignore and return do not found.
459459
if (loadInfo.status != serialization::Status::Valid) {
460460
if (Ctx.LangOpts.EnableModuleLoadingRemarks)

test/ScanDependencies/compiled_swift_modules.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foo
1010

1111
// HAS_BINARY: "swiftPrebuiltExternal": "Foo"
1212

13-
// HAS_NO_COMPILED-NOT: "{{.*}}Foo.swiftmodule{{.*}}.swiftmodule"
13+
// HAS_NO_COMPILED-NOT: "compiledModulePath":{{.*}}"{{.*}}Foo.swiftmodule{{.*}}.swiftmodule"
1414

1515
// Step 1: build swift interface and swift module side by side
1616
// RUN: %target-swift-frontend -emit-module %t/Foo.swift -emit-module-path %t/Foo.swiftmodule/%target-swiftmodule-name -module-name Foo -emit-module-interface-path %t/Foo.swiftmodule/%target-swiftinterface-name
@@ -20,7 +20,7 @@ import Foo
2020
// RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_COMPILED
2121

2222
/// Check scanner picked binary dependency if not requesting raw scan output.
23-
// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d
23+
// RUN: %target-swift-frontend -scan-dependencies %s -scanner-module-validation -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d
2424
// RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_BINARY
2525

2626
// Step 3: remove the adjacent module.
@@ -38,7 +38,7 @@ import Foo
3838
// RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_COMPILED
3939

4040
/// Check scanner picked binary dependency if not requesting raw scan output.
41-
// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d -sdk %t -prebuilt-module-cache-path %t/ResourceDir/%target-sdk-name/prebuilt-modules
41+
// RUN: %target-swift-frontend -scan-dependencies %s -scanner-module-validation -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d -sdk %t -prebuilt-module-cache-path %t/ResourceDir/%target-sdk-name/prebuilt-modules
4242
// RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_BINARY
4343

4444
// Step 6: update the interface file from where the prebuilt module cache was built.

test/ScanDependencies/testable-dependencies.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// RUN: %t/A.swift
1818

1919
/// Import testable build, should use binary but no extra dependencies.
20-
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-serialized -module-name Test %t/main.swift \
20+
// RUN: %target-swift-frontend -scan-dependencies -scanner-module-validation -module-load-mode prefer-serialized -module-name Test %t/main.swift \
2121
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
2222
// RUN: -o %t/deps1.json -I %t/testable -swift-version 5 -Rmodule-loading
2323
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps1.json Test directDependencies | %FileCheck %s --check-prefix TEST1
@@ -26,15 +26,15 @@
2626
// EMPTY-NOT: B
2727

2828
/// Import regular build, should use binary.
29-
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-serialized -module-name Test %t/main.swift \
29+
// RUN: %target-swift-frontend -scan-dependencies -scanner-module-validation -module-load-mode prefer-serialized -module-name Test %t/main.swift \
3030
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
3131
// RUN: -o %t/deps2.json -I %t/regular -swift-version 5 -Rmodule-loading
3232
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps2.json Test directDependencies | %FileCheck %s --check-prefix TEST2
3333
// TEST2: "swiftPrebuiltExternal": "A"
3434
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps2.json swiftPrebuiltExternal:A directDependencies | %FileCheck %s --check-prefix EMPTY --allow-empty
3535

3636
/// Testable import testable build, should use binary, even interface is preferred.
37-
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/testable.swift \
37+
// RUN: %target-swift-frontend -scan-dependencies -scanner-module-validation -module-load-mode prefer-interface -module-name Test %t/testable.swift \
3838
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \
3939
// RUN: -o %t/deps3.json -I %t/testable -I %t/internal -swift-version 5 -Rmodule-loading
4040
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps3.json Test directDependencies | %FileCheck %s --check-prefix TEST3
@@ -43,21 +43,21 @@
4343
// TEST3-A: "swift": "B"
4444

4545
/// Testable import non-testable build without enable testing.
46-
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/testable.swift \
46+
// RUN: %target-swift-frontend -scan-dependencies -scanner-module-validation -module-load-mode prefer-interface -module-name Test %t/testable.swift \
4747
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
4848
// RUN: -o %t/deps4.json -I %t/regular -swift-version 5
4949
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps4.json Test directDependencies | %FileCheck %s --check-prefix TEST4
5050
// TEST4: "swiftPrebuiltExternal": "A"
5151
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps4.json swiftPrebuiltExternal:A directDependencies | %FileCheck %s --check-prefix EMPTY --allow-empty
5252

5353
/// Testable import non-testable build enable testing, still succeed since swift-frontend can provide a better diagnostics when the module is actually imported.
54-
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/testable.swift \
54+
// RUN: %target-swift-frontend -scan-dependencies -scanner-module-validation -module-load-mode prefer-interface -module-name Test %t/testable.swift \
5555
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \
5656
// RUN: -o %t/deps5.json -I %t/regular -swift-version 5 -Rmodule-loading
5757

5858
/// Regular import a testable module with no interface, don't load optional dependencies.
5959
// RUN: rm %t/testable/A.swiftinterface
60-
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/main.swift \
60+
// RUN: %target-swift-frontend -scan-dependencies -scanner-module-validation -module-load-mode prefer-interface -module-name Test %t/main.swift \
6161
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \
6262
// RUN: -o %t/deps6.json -I %t/testable -swift-version 5 -Rmodule-loading
6363
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps6.json Test directDependencies | %FileCheck %s --check-prefix TEST6

0 commit comments

Comments
 (0)