Skip to content

Commit 86ea594

Browse files
committed
Serialization: apply the SDK build version as part of the cache hash
The SDK build version is a decent heuristic for expected changes in the SDK. Any change in SDK, to clang headers in particular, can break references from cached swiftmodules. Track the SDK build version as part of the swiftmodule cache hash. This will ensure we rebuild from swiftinterfaces on SDK updates. rdar://122655978
1 parent 8bb6846 commit 86ea594

File tree

7 files changed

+108
-12
lines changed

7 files changed

+108
-12
lines changed

include/swift/AST/ModuleLoader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,15 @@ class ModuleInterfaceChecker {
209209
struct InterfaceSubContextDelegate {
210210
virtual std::error_code runInSubContext(StringRef moduleName,
211211
StringRef interfacePath,
212+
StringRef sdkPath,
212213
StringRef outputPath,
213214
SourceLoc diagLoc,
214215
llvm::function_ref<std::error_code(ASTContext&, ModuleDecl*,
215216
ArrayRef<StringRef>,
216217
ArrayRef<StringRef>, StringRef)> action) = 0;
217218
virtual std::error_code runInSubCompilerInstance(StringRef moduleName,
218219
StringRef interfacePath,
220+
StringRef sdkPath,
219221
StringRef outputPath,
220222
SourceLoc diagLoc,
221223
bool silenceErrors,

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,13 +693,15 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
693693

694694
std::error_code runInSubContext(StringRef moduleName,
695695
StringRef interfacePath,
696+
StringRef sdkPath,
696697
StringRef outputPath,
697698
SourceLoc diagLoc,
698699
llvm::function_ref<std::error_code(ASTContext&, ModuleDecl*,
699700
ArrayRef<StringRef>, ArrayRef<StringRef>,
700701
StringRef)> action) override;
701702
std::error_code runInSubCompilerInstance(StringRef moduleName,
702703
StringRef interfacePath,
704+
StringRef sdkPath,
703705
StringRef outputPath,
704706
SourceLoc diagLoc,
705707
bool silenceErrors,
@@ -710,9 +712,10 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
710712
/// includes a hash of relevant key data.
711713
StringRef computeCachedOutputPath(StringRef moduleName,
712714
StringRef UseInterfacePath,
715+
StringRef sdkPath,
713716
llvm::SmallString<256> &OutPath,
714717
StringRef &CacheHash);
715-
std::string getCacheHash(StringRef useInterfacePath);
718+
std::string getCacheHash(StringRef useInterfacePath, StringRef sdkPath);
716719
};
717720
}
718721

lib/Frontend/ModuleInterfaceBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ bool ImplicitModuleInterfaceBuilder::buildSwiftModuleInternal(
345345
}
346346

347347
SubError = (bool)subASTDelegate.runInSubCompilerInstance(
348-
moduleName, interfacePath, OutPath, diagnosticLoc,
348+
moduleName, interfacePath, sdkPath, OutPath, diagnosticLoc,
349349
silenceInterfaceDiagnostics,
350350
[&](SubCompilerInstanceInfo &info) {
351351
auto EBuilder = ExplicitModuleInterfaceBuilder(

lib/Frontend/ModuleInterfaceBuilder.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class ImplicitModuleInterfaceBuilder {
4141
DiagnosticEngine *diags;
4242
InterfaceSubContextDelegate &subASTDelegate;
4343
const StringRef interfacePath;
44+
const StringRef sdkPath;
4445
const StringRef moduleName;
4546
const StringRef moduleCachePath;
4647
const StringRef prebuiltCachePath;
@@ -84,15 +85,16 @@ class ImplicitModuleInterfaceBuilder {
8485
public:
8586
ImplicitModuleInterfaceBuilder(
8687
SourceManager &sourceMgr, DiagnosticEngine *diags,
87-
InterfaceSubContextDelegate &subASTDelegate, StringRef interfacePath,
88+
InterfaceSubContextDelegate &subASTDelegate,
89+
StringRef interfacePath, StringRef sdkPath,
8890
StringRef moduleName, StringRef moduleCachePath,
8991
StringRef backupInterfaceDir, StringRef prebuiltCachePath,
9092
StringRef ABIDescriptorPath, bool disableInterfaceFileLock = false,
9193
bool silenceInterfaceDiagnostics = false,
9294
SourceLoc diagnosticLoc = SourceLoc(),
9395
DependencyTracker *tracker = nullptr)
9496
: sourceMgr(sourceMgr), diags(diags), subASTDelegate(subASTDelegate),
95-
interfacePath(interfacePath), moduleName(moduleName),
97+
interfacePath(interfacePath), sdkPath(sdkPath), moduleName(moduleName),
9698
moduleCachePath(moduleCachePath), prebuiltCachePath(prebuiltCachePath),
9799
backupInterfaceDir(backupInterfaceDir),
98100
ABIDescriptorPath(ABIDescriptorPath),

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ class ModuleInterfaceLoaderImpl {
10641064
llvm::SmallString<256> cachedOutputPath;
10651065
StringRef CacheHash;
10661066
astDelegate.computeCachedOutputPath(moduleName, interfacePath,
1067+
ctx.SearchPathOpts.getSDKPath(),
10671068
cachedOutputPath, CacheHash);
10681069

10691070
// Try to find the right module for this interface, either alongside it,
@@ -1144,7 +1145,9 @@ class ModuleInterfaceLoaderImpl {
11441145
Identifier realName = ctx.getRealModuleName(ctx.getIdentifier(moduleName));
11451146
ImplicitModuleInterfaceBuilder builder(
11461147
ctx.SourceMgr, diagsToUse,
1147-
astDelegate, interfacePath, realName.str(), cacheDir,
1148+
astDelegate, interfacePath,
1149+
ctx.SearchPathOpts.getSDKPath(),
1150+
realName.str(), cacheDir,
11481151
prebuiltCacheDir, backupInterfaceDir, StringRef(),
11491152
Opts.disableInterfaceLock,
11501153
ctx.IgnoreAdjacentModules, diagnosticLoc,
@@ -1177,7 +1180,9 @@ class ModuleInterfaceLoaderImpl {
11771180
// Set up a builder if we need to build the module. It'll also set up
11781181
// the genericSubInvocation we'll need to use to compute the cache paths.
11791182
ImplicitModuleInterfaceBuilder fallbackBuilder(
1180-
ctx.SourceMgr, &ctx.Diags, astDelegate, backupPath, moduleName, cacheDir,
1183+
ctx.SourceMgr, &ctx.Diags, astDelegate, backupPath,
1184+
ctx.SearchPathOpts.getSDKPath(),
1185+
moduleName, cacheDir,
11811186
prebuiltCacheDir, backupInterfaceDir, StringRef(),
11821187
Opts.disableInterfaceLock,
11831188
ctx.IgnoreAdjacentModules, diagnosticLoc,
@@ -1390,6 +1395,7 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface(
13901395
SerializeDependencyHashes, TrackSystemDependencies,
13911396
RequireOSSAModules, RequireNCGenerics);
13921397
ImplicitModuleInterfaceBuilder builder(SourceMgr, &Diags, astDelegate, InPath,
1398+
SearchPathOpts.getSDKPath(),
13931399
ModuleName, CacheDir, PrebuiltCacheDir,
13941400
BackupInterfaceDir, ABIOutputPath,
13951401
LoaderOpts.disableInterfaceLock,
@@ -1409,6 +1415,7 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface(
14091415
assert(failed);
14101416
assert(!backInPath.empty());
14111417
ImplicitModuleInterfaceBuilder backupBuilder(SourceMgr, &Diags, astDelegate, backInPath,
1418+
SearchPathOpts.getSDKPath(),
14121419
ModuleName, CacheDir, PrebuiltCacheDir,
14131420
BackupInterfaceDir, ABIOutputPath,
14141421
LoaderOpts.disableInterfaceLock,
@@ -1865,13 +1872,14 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
18651872
StringRef InterfaceSubContextDelegateImpl::computeCachedOutputPath(
18661873
StringRef moduleName,
18671874
StringRef useInterfacePath,
1875+
StringRef sdkPath,
18681876
llvm::SmallString<256> &OutPath,
18691877
StringRef &CacheHash) {
18701878
OutPath = genericSubInvocation.getClangModuleCachePath();
18711879
llvm::sys::path::append(OutPath, moduleName);
18721880
OutPath.append("-");
18731881
auto hashStart = OutPath.size();
1874-
OutPath.append(getCacheHash(useInterfacePath));
1882+
OutPath.append(getCacheHash(useInterfacePath, sdkPath));
18751883
CacheHash = OutPath.str().substr(hashStart);
18761884
OutPath.append(".");
18771885
auto OutExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
@@ -1890,9 +1898,11 @@ StringRef InterfaceSubContextDelegateImpl::computeCachedOutputPath(
18901898
/// with dead entries -- when other factors change, such as the contents of
18911899
/// the .swiftinterface input or its dependencies.
18921900
std::string
1893-
InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) {
1901+
InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath,
1902+
StringRef sdkPath) {
18941903
auto normalizedTargetTriple =
18951904
getTargetSpecificModuleTriple(genericSubInvocation.getLangOptions().Target);
1905+
std::string sdkBuildVersion = getSDKBuildVersion(sdkPath);
18961906

18971907
llvm::hash_code H = hash_combine(
18981908
// Start with the compiler version (which will be either tag names or
@@ -1918,6 +1928,10 @@ InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) {
19181928
// include it.
19191929
genericSubInvocation.getSDKPath(),
19201930

1931+
// The SDK build version may identify differences in headers
1932+
// that affects references serialized in the cached file.
1933+
sdkBuildVersion,
1934+
19211935
// Whether or not we're tracking system dependencies affects the
19221936
// invalidation behavior of this cache item.
19231937
genericSubInvocation.getFrontendOptions().shouldTrackSystemDependencies(),
@@ -1934,11 +1948,12 @@ InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) {
19341948
std::error_code
19351949
InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName,
19361950
StringRef interfacePath,
1951+
StringRef sdkPath,
19371952
StringRef outputPath,
19381953
SourceLoc diagLoc,
19391954
llvm::function_ref<std::error_code(ASTContext&, ModuleDecl*, ArrayRef<StringRef>,
19401955
ArrayRef<StringRef>, StringRef)> action) {
1941-
return runInSubCompilerInstance(moduleName, interfacePath, outputPath,
1956+
return runInSubCompilerInstance(moduleName, interfacePath, sdkPath, outputPath,
19421957
diagLoc, /*silenceErrors=*/false,
19431958
[&](SubCompilerInstanceInfo &info){
19441959
return action(info.Instance->getASTContext(),
@@ -1952,6 +1967,7 @@ InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName,
19521967
std::error_code
19531968
InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
19541969
StringRef interfacePath,
1970+
StringRef sdkPath,
19551971
StringRef outputPath,
19561972
SourceLoc diagLoc,
19571973
bool silenceErrors,
@@ -1981,8 +1997,8 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
19811997
// Calculate output path of the module.
19821998
llvm::SmallString<256> buffer;
19831999
StringRef CacheHash;
1984-
auto hashedOutput = computeCachedOutputPath(moduleName, interfacePath, buffer,
1985-
CacheHash);
2000+
auto hashedOutput = computeCachedOutputPath(moduleName, interfacePath,
2001+
sdkPath, buffer, CacheHash);
19862002
// If no specific output path is given, use the hashed output path.
19872003
if (outputPath.empty()) {
19882004
outputPath = hashedOutput;

lib/Serialization/ScanningLoaders.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,13 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
154154
// name for the module, which includes an appropriate hash.
155155
auto newExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
156156
auto realModuleName = Ctx.getRealModuleName(moduleName);
157+
StringRef sdkPath = Ctx.SearchPathOpts.getSDKPath();
157158
llvm::SmallString<32> modulePath = realModuleName.str();
158159
llvm::sys::path::replace_extension(modulePath, newExt);
159160
llvm::Optional<ModuleDependencyInfo> Result;
160161
std::error_code code = astDelegate.runInSubContext(
161-
realModuleName.str(), moduleInterfacePath.str(), StringRef(), SourceLoc(),
162+
realModuleName.str(), moduleInterfacePath.str(), sdkPath,
163+
StringRef(), SourceLoc(),
162164
[&](ASTContext &Ctx, ModuleDecl *mainMod, ArrayRef<StringRef> BaseArgs,
163165
ArrayRef<StringRef> PCMArgs, StringRef Hash) {
164166
assert(mainMod);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/// ProductBuildVersion of the SDK is tracked as part of the module cache hash.
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %empty-directory(%t/ModuleCache)
5+
// RUN: %empty-directory(%t/sdk/System/Library/CoreServices/)
6+
// RUN: split-file %s %t
7+
8+
/// Setup an "old" SDK.
9+
// RUN: cp %t/SystemVersion.plist.old %t/sdk/System/Library/CoreServices/SystemVersion.plist
10+
11+
/// Build Lib against the old SDK.
12+
// RUN: %target-swift-frontend -emit-module -sdk %t/sdk %t/Lib.swift \
13+
// RUN: -enable-library-evolution -swift-version 5 \
14+
// RUN: -emit-module-path %t/Lib.swiftmodule \
15+
// RUN: -emit-module-interface-path %t/Lib.swiftinterface
16+
17+
/// Baseline check, we should read the adjacent swiftmodule.
18+
// RUN: %target-swift-frontend -typecheck -verify -sdk %t/sdk -I %t \
19+
// RUN: %t/Client_NoRebuild.swift \
20+
// RUN: -Rmodule-interface-rebuild -module-cache-path %t/ModuleCache
21+
22+
/// Keep only the swiftinterface.
23+
// RUN: rm %t/Lib.swiftmodule
24+
25+
/// Build client, which should trigger a build from swiftinterface.
26+
// RUN: %target-swift-frontend -typecheck -verify -sdk %t/sdk -I %t \
27+
// RUN: %t/Client.swift \
28+
// RUN: -Rmodule-interface-rebuild -module-cache-path %t/ModuleCache
29+
30+
/// Update SDK.
31+
// RUN: cp %t/SystemVersion.plist.new %t/sdk/System/Library/CoreServices/SystemVersion.plist
32+
33+
/// Build client, which should trigger a build from swiftinterface.
34+
// RUN: %target-swift-frontend -typecheck -verify -sdk %t/sdk -I %t \
35+
// RUN: %t/Client.swift \
36+
// RUN: -Rmodule-interface-rebuild -module-cache-path %t/ModuleCache
37+
38+
/// Baseline check, we should reused the newly cached swiftmodule.
39+
// RUN: %target-swift-frontend -typecheck -verify -sdk %t/sdk -I %t \
40+
// RUN: %t/Client_NoRebuild.swift \
41+
// RUN: -Rmodule-interface-rebuild -module-cache-path %t/ModuleCache
42+
43+
//--- SystemVersion.plist.old
44+
<?xml version="1.0" encoding="UTF-8"?>
45+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
46+
<plist version="1.0">
47+
<dict>
48+
<key>ProductBuildVersion</key>
49+
<string>10A100</string>
50+
</dict>
51+
</plist>
52+
53+
//--- SystemVersion.plist.new
54+
<?xml version="1.0" encoding="UTF-8"?>
55+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
56+
<plist version="1.0">
57+
<dict>
58+
<key>ProductBuildVersion</key>
59+
<string>10A200</string>
60+
</dict>
61+
</plist>
62+
63+
//--- Lib.swift
64+
public func foo() {}
65+
66+
//--- Client.swift
67+
import Lib // expected-remark {{rebuilding module 'Lib' from interface}}
68+
69+
//--- Client_NoRebuild.swift
70+
import Lib
71+

0 commit comments

Comments
 (0)