Skip to content

Commit c8e594b

Browse files
authored
Add an option to opt-in to removal of make-style dependencies (#371)
This is off by default because the scanner based dependencies still have some gaps in coverage. There's also a new mode to verify the scanner based deps against the make-style ones
1 parent f05dee0 commit c8e594b

File tree

4 files changed

+103
-29
lines changed

4 files changed

+103
-29
lines changed

Sources/SWBCore/LibSwiftDriver/LibSwiftDriver.swift

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,27 @@ public final class SwiftModuleDependencyGraph: SwiftGlobalExplicitDependencyGrap
188188
let directDependencies = graph.mainModule.directDependencies ?? []
189189
let transitiveDependencies = Set(directDependencies + SWBUtil.transitiveClosure(directDependencies, successors: { moduleID in graph.modules[moduleID]?.directDependencies ?? [] }).0)
190190

191-
var headerDependencies: [String] = []
192-
headerDependencies.reserveCapacity(transitiveDependencies.count * 10)
191+
var fileDependencies: [String] = []
192+
fileDependencies.reserveCapacity(transitiveDependencies.count * 10)
193193
for dependencyID in transitiveDependencies {
194-
let sourceFiles = graph.modules[dependencyID]?.sourceFiles ?? []
195-
for sourceFile in sourceFiles {
196-
headerDependencies.append(sourceFile)
194+
guard let moduleInfo = graph.modules[dependencyID] else {
195+
continue
196+
}
197+
fileDependencies.append(contentsOf: moduleInfo.sourceFiles ?? [])
198+
switch moduleInfo.details {
199+
case .swift:
200+
break
201+
case .swiftPlaceholder:
202+
break
203+
case .swiftPrebuiltExternal(let details):
204+
if let modulePath = VirtualPath.lookup(details.compiledModulePath.path).absolutePath {
205+
fileDependencies.append(modulePath.pathString)
206+
}
207+
case .clang:
208+
break
197209
}
198210
}
199-
return headerDependencies
211+
return fileDependencies
200212
}
201213

202214
public func queryTransitiveDependencyModuleNames(for key: String) throws -> [String] {

Sources/SWBCore/Settings/BuiltinMacros.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ public final class BuiltinMacros {
996996
public static let SWIFT_ALLOW_INSTALL_OBJC_HEADER = BuiltinMacros.declareBooleanMacro("SWIFT_ALLOW_INSTALL_OBJC_HEADER")
997997
public static let __SWIFT_ALLOW_INSTALL_OBJC_HEADER_MESSAGE = BuiltinMacros.declareStringMacro("__SWIFT_ALLOW_INSTALL_OBJC_HEADER_MESSAGE")
998998
public static let SWIFT_COMPILATION_MODE = BuiltinMacros.declareStringMacro("SWIFT_COMPILATION_MODE")
999+
public static let SWIFT_DEPENDENCY_REGISTRATION_MODE = BuiltinMacros.declareEnumMacro("SWIFT_DEPENDENCY_REGISTRATION_MODE") as EnumMacroDeclaration<SwiftDependencyRegistrationMode>
9991000
public static let SWIFT_DEPLOYMENT_TARGET = BuiltinMacros.declareStringMacro("SWIFT_DEPLOYMENT_TARGET")
10001001
public static let SWIFT_DEVELOPMENT_TOOLCHAIN = BuiltinMacros.declareBooleanMacro("SWIFT_DEVELOPMENT_TOOLCHAIN")
10011002
public static let SWIFT_EMIT_LOC_STRINGS = BuiltinMacros.declareBooleanMacro("SWIFT_EMIT_LOC_STRINGS")
@@ -2157,6 +2158,7 @@ public final class BuiltinMacros {
21572158
SWIFT_ALLOW_INSTALL_OBJC_HEADER,
21582159
__SWIFT_ALLOW_INSTALL_OBJC_HEADER_MESSAGE,
21592160
SWIFT_COMPILATION_MODE,
2161+
SWIFT_DEPENDENCY_REGISTRATION_MODE,
21602162
SWIFT_DEPLOYMENT_TARGET,
21612163
SWIFT_DEVELOPMENT_TOOLCHAIN,
21622164
SWIFT_EMIT_LOC_STRINGS,
@@ -2622,6 +2624,14 @@ public enum SwiftEnableExplicitModulesSetting: String, Equatable, Hashable, Enum
26222624
case disabled = "NO"
26232625
}
26242626

2627+
public enum SwiftDependencyRegistrationMode: String, Equatable, Hashable, EnumerationMacroType {
2628+
public static let defaultValue: SwiftDependencyRegistrationMode = .makeStyleDependenciesSupplementedByScanner
2629+
2630+
case makeStyleDependenciesSupplementedByScanner = "make-style"
2631+
case swiftDependencyScannerOnly = "dependency-scanner"
2632+
case verifySwiftDependencyScanner = "verify-swift-dependency-scanner"
2633+
}
2634+
26252635
/// Enumeration macro type for tri-state boolean value of whether the user has enabled compilation caching builds, disabled, or not set.
26262636
public enum CompilationCachingSetting: String, Equatable, Hashable, EnumerationMacroType {
26272637
public static let defaultValue = CompilationCachingSetting.notset

Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,9 @@ public struct SwiftDriverPayload: Serializable, TaskPayload, Encodable {
348348
public let reportRequiredTargetDependencies: BooleanWarningLevel
349349
public let linkerResponseFilePath: Path?
350350
public let dependencyFilteringRootPath: Path?
351+
public let verifyScannerDependencies: Bool
351352

352-
internal init(uniqueID: String, compilerLocation: LibSwiftDriver.CompilerLocation, moduleName: String, tempDirPath: Path, explicitModulesTempDirPath: Path, variant: String, architecture: String, eagerCompilationEnabled: Bool, explicitModulesEnabled: Bool, commandLine: [String], ruleInfo: [String], isUsingWholeModuleOptimization: Bool, casOptions: CASOptions?, reportRequiredTargetDependencies: BooleanWarningLevel, linkerResponseFilePath: Path?, dependencyFilteringRootPath: Path?) {
353+
internal init(uniqueID: String, compilerLocation: LibSwiftDriver.CompilerLocation, moduleName: String, tempDirPath: Path, explicitModulesTempDirPath: Path, variant: String, architecture: String, eagerCompilationEnabled: Bool, explicitModulesEnabled: Bool, commandLine: [String], ruleInfo: [String], isUsingWholeModuleOptimization: Bool, casOptions: CASOptions?, reportRequiredTargetDependencies: BooleanWarningLevel, linkerResponseFilePath: Path?, dependencyFilteringRootPath: Path?, verifyScannerDependencies: Bool) {
353354
self.uniqueID = uniqueID
354355
self.compilerLocation = compilerLocation
355356
self.moduleName = moduleName
@@ -366,10 +367,11 @@ public struct SwiftDriverPayload: Serializable, TaskPayload, Encodable {
366367
self.reportRequiredTargetDependencies = reportRequiredTargetDependencies
367368
self.linkerResponseFilePath = linkerResponseFilePath
368369
self.dependencyFilteringRootPath = dependencyFilteringRootPath
370+
self.verifyScannerDependencies = verifyScannerDependencies
369371
}
370372

371373
public init(from deserializer: any Deserializer) throws {
372-
try deserializer.beginAggregate(16)
374+
try deserializer.beginAggregate(17)
373375
self.uniqueID = try deserializer.deserialize()
374376
self.compilerLocation = try deserializer.deserialize()
375377
self.moduleName = try deserializer.deserialize()
@@ -386,10 +388,11 @@ public struct SwiftDriverPayload: Serializable, TaskPayload, Encodable {
386388
self.reportRequiredTargetDependencies = try deserializer.deserialize()
387389
self.linkerResponseFilePath = try deserializer.deserialize()
388390
self.dependencyFilteringRootPath = try deserializer.deserialize()
391+
self.verifyScannerDependencies = try deserializer.deserialize()
389392
}
390393

391394
public func serialize<T>(to serializer: T) where T : Serializer {
392-
serializer.serializeAggregate(16) {
395+
serializer.serializeAggregate(17) {
393396
serializer.serialize(self.uniqueID)
394397
serializer.serialize(self.compilerLocation)
395398
serializer.serialize(self.moduleName)
@@ -406,6 +409,7 @@ public struct SwiftDriverPayload: Serializable, TaskPayload, Encodable {
406409
serializer.serialize(self.reportRequiredTargetDependencies)
407410
serializer.serialize(self.linkerResponseFilePath)
408411
serializer.serialize(self.dependencyFilteringRootPath)
412+
serializer.serialize(self.verifyScannerDependencies)
409413
}
410414
}
411415
}
@@ -1391,6 +1395,20 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
13911395
return buildSettingEnabled
13921396
}
13931397

1398+
func shouldEmitMakeStyleDependencies(_ producer: any CommandProducer, _ scope: MacroEvaluationScope, delegate: any TaskGenerationDelegate) async -> Bool {
1399+
guard await swiftExplicitModuleBuildEnabled(producer, scope, delegate) else {
1400+
return true
1401+
}
1402+
switch scope.evaluate(BuiltinMacros.SWIFT_DEPENDENCY_REGISTRATION_MODE) {
1403+
case .makeStyleDependenciesSupplementedByScanner:
1404+
return true
1405+
case .swiftDependencyScannerOnly:
1406+
return false
1407+
case .verifySwiftDependencyScanner:
1408+
return true
1409+
}
1410+
}
1411+
13941412
private func swiftCachingEnabled(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, _ moduleName: String, _ useIntegratedDriver: Bool, _ explicitModuleBuildEnabled: Bool, _ disabledPCHCompile: Bool) async -> Bool {
13951413
guard cbc.producer.supportsCompilationCaching else { return false }
13961414

@@ -1822,8 +1840,10 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
18221840
// Instruct the compiler to serialize diagnostics.
18231841
args.append("-serialize-diagnostics")
18241842

1825-
// Instruct the compiler to emit dependencies information.
1826-
args.append("-emit-dependencies")
1843+
if await shouldEmitMakeStyleDependencies(cbc.producer, cbc.scope, delegate: delegate) {
1844+
// Instruct the compiler to emit dependencies information.
1845+
args.append("-emit-dependencies")
1846+
}
18271847

18281848
// Generate the .swiftmodule from this compilation to a known location.
18291849
//
@@ -2200,7 +2220,10 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
22002220
}
22012221
})
22022222

2203-
let dependencyInfoPath: Path? = {
2223+
let dependencyInfoPath: Path? = await {
2224+
guard await shouldEmitMakeStyleDependencies(cbc.producer, cbc.scope, delegate: delegate) else {
2225+
return nil
2226+
}
22042227
// FIXME: Duplication with `SwiftCompilerSpec.computeOutputFileMapContents`
22052228
//
22062229
// FIXME: Can we simplify this to not require the full macro scope?
@@ -2307,9 +2330,6 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
23072330

23082331
// Rest compilation (defined before for transparent dependency handling
23092332
let eagerCompilationEnabled = eagerCompilationEnabled(args: args, scope: cbc.scope, compilationMode: compilationMode, isUsingWholeModuleOptimization: isUsingWholeModuleOptimization)
2310-
// FIXME: Duplication with `SwiftCompilerSpec.computeOutputFileMapContents`
2311-
let masterSwiftBaseName = cbc.scope.evaluate(BuiltinMacros.TARGET_NAME) + compilationMode.moduleBaseNameSuffix + "-master"
2312-
let emitModuleDependenciesFilePath = objectFileDir.join(masterSwiftBaseName + "-emit-module.d")
23132333
let compilationRequirementOutputs: [any PlannedNode]
23142334
let compilationOutputs: [any PlannedNode]
23152335
if eagerCompilationEnabled {
@@ -2321,8 +2341,17 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
23212341
compilationOutputs = [compilationFinishedNode]
23222342
}
23232343

2344+
let dependencyData: DependencyDataStyle?
2345+
if await shouldEmitMakeStyleDependencies(cbc.producer, cbc.scope, delegate: delegate) {
2346+
// FIXME: Duplication with `SwiftCompilerSpec.computeOutputFileMapContents`
2347+
let masterSwiftBaseName = cbc.scope.evaluate(BuiltinMacros.TARGET_NAME) + compilationMode.moduleBaseNameSuffix + "-master"
2348+
let emitModuleDependenciesFilePath = objectFileDir.join(masterSwiftBaseName + "-emit-module.d")
2349+
dependencyData = eagerCompilationEnabled ? .makefileIgnoringSubsequentOutputs(emitModuleDependenciesFilePath) : dependencyInfoPath.map(DependencyDataStyle.makefileIgnoringSubsequentOutputs)
2350+
} else {
2351+
dependencyData = nil
2352+
}
2353+
23242354
// Compilation Requirements
2325-
let dependencyData: DependencyDataStyle? = eagerCompilationEnabled ? .makefileIgnoringSubsequentOutputs(emitModuleDependenciesFilePath) : dependencyInfoPath.map(DependencyDataStyle.makefileIgnoringSubsequentOutputs)
23262355
delegate.createTask(type: self, dependencyData: dependencyData, payload: payload, ruleInfo: ruleInfo("SwiftDriver Compilation Requirements", targetName), additionalSignatureData: additionalSignatureData, commandLine: ["builtin-Swift-Compilation-Requirements", "--"] + args, environment: environmentBindings, workingDirectory: compilerWorkingDirectory(cbc), inputs: allInputsNodes, outputs: compilationRequirementOutputs, action: delegate.taskActionCreationDelegate.createSwiftCompilationRequirementTaskAction(), execDescription: archSpecificExecutionDescription(cbc.scope.namespace.parseString("Unblock downstream dependents of $PRODUCT_NAME"), cbc, delegate), preparesForIndexing: true, enableSandboxing: enableSandboxing, additionalTaskOrderingOptions: [.compilation, .compilationRequirement, .linkingRequirement, .blockedByTargetHeaders, .compilationForIndexableSourceFile], usesExecutionInputs: true, showInLog: true)
23272356

23282357
if case .compile = compilationMode {
@@ -2461,8 +2490,9 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
24612490
compilerLocation = .library(libSwiftScanPath: libSwiftScanPath)
24622491
#endif
24632492
let explicitModuleBuildEnabled = await swiftExplicitModuleBuildEnabled(cbc.producer, cbc.scope, delegate)
2493+
let verifyScannerDependencies = explicitModuleBuildEnabled && cbc.scope.evaluate(BuiltinMacros.SWIFT_DEPENDENCY_REGISTRATION_MODE) == .verifySwiftDependencyScanner
24642494

2465-
return SwiftDriverPayload(uniqueID: uniqueID, compilerLocation: compilerLocation, moduleName: scope.evaluate(BuiltinMacros.SWIFT_MODULE_NAME), tempDirPath: tempDirPath, explicitModulesTempDirPath: explicitModulesTempDirPath, variant: variant, architecture: arch, eagerCompilationEnabled: eagerCompilationEnabled(args: args, scope: scope, compilationMode: compilationMode, isUsingWholeModuleOptimization: isUsingWholeModuleOptimization), explicitModulesEnabled: explicitModuleBuildEnabled, commandLine: commandLine, ruleInfo: ruleInfo, isUsingWholeModuleOptimization: isUsingWholeModuleOptimization, casOptions: casOptions, reportRequiredTargetDependencies: scope.evaluate(BuiltinMacros.DIAGNOSE_MISSING_TARGET_DEPENDENCIES), linkerResponseFilePath: linkerResponseFilePath, dependencyFilteringRootPath: cbc.producer.sdk?.path)
2495+
return SwiftDriverPayload(uniqueID: uniqueID, compilerLocation: compilerLocation, moduleName: scope.evaluate(BuiltinMacros.SWIFT_MODULE_NAME), tempDirPath: tempDirPath, explicitModulesTempDirPath: explicitModulesTempDirPath, variant: variant, architecture: arch, eagerCompilationEnabled: eagerCompilationEnabled(args: args, scope: scope, compilationMode: compilationMode, isUsingWholeModuleOptimization: isUsingWholeModuleOptimization), explicitModulesEnabled: explicitModuleBuildEnabled, commandLine: commandLine, ruleInfo: ruleInfo, isUsingWholeModuleOptimization: isUsingWholeModuleOptimization, casOptions: casOptions, reportRequiredTargetDependencies: scope.evaluate(BuiltinMacros.DIAGNOSE_MISSING_TARGET_DEPENDENCIES), linkerResponseFilePath: linkerResponseFilePath, dependencyFilteringRootPath: cbc.producer.sdk?.path, verifyScannerDependencies: verifyScannerDependencies)
24662496
}
24672497

24682498
func constructSwiftResponseFileTask(path: Path) {
@@ -3048,9 +3078,11 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
30483078
let diagnosticsFilePath = objectFileDir.join(objectFilePrefix + ".dia")
30493079
fileMapEntry.diagnostics = diagnosticsFilePath.str
30503080

3051-
// The dependencies file, used to discover implicit dependencies. This file will be in Makefile format.
3052-
let dependenciesFilePath = objectFileDir.join(objectFilePrefix + ".d")
3053-
fileMapEntry.dependencies = dependenciesFilePath.str
3081+
if await shouldEmitMakeStyleDependencies(cbc.producer, cbc.scope, delegate: delegate) {
3082+
// The dependencies file, used to discover implicit dependencies. This file will be in Makefile format.
3083+
let dependenciesFilePath = objectFileDir.join(objectFilePrefix + ".d")
3084+
fileMapEntry.dependencies = dependenciesFilePath.str
3085+
}
30543086

30553087
// The file used by Swift to manage intermodule dependencies.
30563088
let swiftDependenciesFilePath = objectFileDir.join(objectFilePrefix + ".swiftdeps")
@@ -3085,9 +3117,11 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
30853117
let emitModuleDiagnosticsFilePath = objectFileDir.join(masterSwiftBaseName + "-emit-module.dia")
30863118
fileMapEntry.emitModuleDiagnostics = emitModuleDiagnosticsFilePath.str
30873119

3088-
// The dependency file for emit-module jobs.
3089-
let emitModuleDependenciesFilePath = objectFileDir.join(masterSwiftBaseName + "-emit-module.d")
3090-
fileMapEntry.emitModuleDependencies = emitModuleDependenciesFilePath.str
3120+
if await shouldEmitMakeStyleDependencies(cbc.producer, cbc.scope, delegate: delegate) {
3121+
// The dependency file for emit-module jobs.
3122+
let emitModuleDependenciesFilePath = objectFileDir.join(masterSwiftBaseName + "-emit-module.d")
3123+
fileMapEntry.emitModuleDependencies = emitModuleDependenciesFilePath.str
3124+
}
30913125

30923126
// The PCH file path for generatePCH job.
30933127
let bridgingHeaderPCHPath = objectFileDir.join(masterSwiftBaseName + "-Bridging-header.pch")
@@ -3115,13 +3149,16 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
31153149
let emitModuleDiagnosticsFilePath = objectFileDir.join(masterSwiftBaseName + "-emit-module.dia")
31163150
fileMapEntry.emitModuleDiagnostics = emitModuleDiagnosticsFilePath.str
31173151

3118-
// The dependency file for emit-module jobs.
3119-
let emitModuleDependenciesFilePath = objectFileDir.join(masterSwiftBaseName + "-emit-module.d")
3120-
fileMapEntry.emitModuleDependencies = emitModuleDependenciesFilePath.str
3152+
if await shouldEmitMakeStyleDependencies(cbc.producer, cbc.scope, delegate: delegate) {
3153+
// The dependency file for emit-module jobs.
3154+
let emitModuleDependenciesFilePath = objectFileDir.join(masterSwiftBaseName + "-emit-module.d")
3155+
fileMapEntry.emitModuleDependencies = emitModuleDependenciesFilePath.str
31213156

3122-
// The dependencies file, used to discover implicit dependencies. This file will be in Makefile format.
3123-
let dependenciesFilePath = objectFileDir.join(masterSwiftBaseName + ".d")
3124-
fileMapEntry.dependencies = dependenciesFilePath.str
3157+
3158+
// The dependencies file, used to discover implicit dependencies. This file will be in Makefile format.
3159+
let dependenciesFilePath = objectFileDir.join(masterSwiftBaseName + ".d")
3160+
fileMapEntry.dependencies = dependenciesFilePath.str
3161+
}
31253162

31263163
// The file used by Swift to manage intermodule dependencies.
31273164
let swiftDependenciesFilePath = objectFileDir.join(masterSwiftBaseName + ".swiftdeps")

0 commit comments

Comments
 (0)