Skip to content

Commit

Permalink
Unify cache locations and pruning strategies
Browse files Browse the repository at this point in the history
- Use the same cache path for all tools in the build.This is safe because it's versioned internally
- Wire up the cache pruning mechanism to generic task caching to ensure consistent behavior
- Improve test coverage of replay in incremental builds
  • Loading branch information
owenv committed Feb 11, 2025
1 parent 6f94303 commit 9647382
Show file tree
Hide file tree
Showing 18 changed files with 365 additions and 78 deletions.
12 changes: 6 additions & 6 deletions Sources/SWBApplePlatform/Specs/AssetCatalogCompiler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,17 @@ public final class ActoolCompilerSpec : GenericCompilerSpec, SpecIdentifierType,
(macro == BuiltinMacros.ASSETCATALOG_COMPILER_INPUTS) ? cbc.scope.table.namespace.parseLiteralStringList(assetSymbolInputs.map { $0.path.str }) : lookup(macro)
}

let cachingEnabled = cbc.scope.evaluate(BuiltinMacros.ENABLE_GENERIC_TASK_CACHING)
let action: (any PlannedTaskAction)?
if let deferredAction = delegate.taskActionCreationDelegate.createDeferredExecutionTaskActionIfRequested(userPreferences: cbc.producer.userPreferences) {
action = deferredAction
} else if cachingEnabled {
} else if cbc.scope.evaluate(BuiltinMacros.ENABLE_GENERIC_TASK_CACHING), let casOptions = try? CASOptions.create(cbc.scope, nil) {
action = delegate.taskActionCreationDelegate.createGenericCachingTaskAction(
enableCacheDebuggingRemarks: cbc.scope.evaluate(BuiltinMacros.GENERIC_TASK_CACHE_ENABLE_DIAGNOSTIC_REMARKS),
enableTaskSandboxEnforcement: !cbc.scope.evaluate(BuiltinMacros.DISABLE_TASK_SANDBOXING),
sandboxDirectory: cbc.scope.evaluate(BuiltinMacros.TEMP_SANDBOX_DIR),
extraSandboxSubdirectories: [],
developerDirectory: cbc.scope.evaluate(BuiltinMacros.DEVELOPER_DIR)
developerDirectory: cbc.scope.evaluate(BuiltinMacros.DEVELOPER_DIR),
casOptions: casOptions
)
} else {
action = nil
Expand Down Expand Up @@ -359,17 +359,17 @@ public final class ActoolCompilerSpec : GenericCompilerSpec, SpecIdentifierType,
var ruleInfo = defaultRuleInfo(cbc, delegate, lookup: lookup)
ruleInfo[0..<1] = ["CompileAssetCatalogVariant", variant.rawValue]

let cachingEnabled = cbc.scope.evaluate(BuiltinMacros.ENABLE_GENERIC_TASK_CACHING)
let action: (any PlannedTaskAction)?
if let deferredAction = delegate.taskActionCreationDelegate.createDeferredExecutionTaskActionIfRequested(userPreferences: cbc.producer.userPreferences) {
action = deferredAction
} else if cachingEnabled {
} else if cbc.scope.evaluate(BuiltinMacros.ENABLE_GENERIC_TASK_CACHING), let casOptions = try? CASOptions.create(cbc.scope, nil) {
action = delegate.taskActionCreationDelegate.createGenericCachingTaskAction(
enableCacheDebuggingRemarks: cbc.scope.evaluate(BuiltinMacros.GENERIC_TASK_CACHE_ENABLE_DIAGNOSTIC_REMARKS),
enableTaskSandboxEnforcement: !cbc.scope.evaluate(BuiltinMacros.DISABLE_TASK_SANDBOXING),
sandboxDirectory: cbc.scope.evaluate(BuiltinMacros.TEMP_SANDBOX_DIR),
extraSandboxSubdirectories: [Path("outputs/0/\(overrideDir.basename)")],
developerDirectory: cbc.scope.evaluate(BuiltinMacros.DEVELOPER_DIR)
developerDirectory: cbc.scope.evaluate(BuiltinMacros.DEVELOPER_DIR),
casOptions: casOptions
)
} else {
action = nil
Expand Down
5 changes: 3 additions & 2 deletions Sources/SWBApplePlatform/Specs/InterfaceBuilderCompiler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,14 @@ public final class IbtoolCompilerSpecStoryboard: IbtoolCompilerSpec, SpecIdentif
}

override public func createTaskAction(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) -> (any PlannedTaskAction)? {
if cbc.scope.evaluate(BuiltinMacros.ENABLE_GENERIC_TASK_CACHING) {
if cbc.scope.evaluate(BuiltinMacros.ENABLE_GENERIC_TASK_CACHING), let casOptions = try? CASOptions.create(cbc.scope, nil) {
return delegate.taskActionCreationDelegate.createGenericCachingTaskAction(
enableCacheDebuggingRemarks: cbc.scope.evaluate(BuiltinMacros.GENERIC_TASK_CACHE_ENABLE_DIAGNOSTIC_REMARKS),
enableTaskSandboxEnforcement: !cbc.scope.evaluate(BuiltinMacros.DISABLE_TASK_SANDBOXING),
sandboxDirectory: cbc.scope.evaluate(BuiltinMacros.TEMP_SANDBOX_DIR),
extraSandboxSubdirectories: [],
developerDirectory: cbc.scope.evaluate(BuiltinMacros.DEVELOPER_DIR))
developerDirectory: cbc.scope.evaluate(BuiltinMacros.DEVELOPER_DIR),
casOptions: casOptions)
} else {
return nil
}
Expand Down
20 changes: 18 additions & 2 deletions Sources/SWBApplePlatform/Specs/RealityAssetsCompilerSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,23 @@ package final class RealityAssetsCompilerSpec: GenericCompilerSpec, SpecIdentifi
inputs.append(delegate.createNode(usdaSchemaPath) as (any PlannedNode))
}

let cachingEnabled = cbc.scope.evaluate(BuiltinMacros.ENABLE_GENERIC_TASK_CACHING)
let action: (any PlannedTaskAction)?
let cachingEnabled: Bool
if cbc.scope.evaluate(BuiltinMacros.ENABLE_GENERIC_TASK_CACHING), let casOptions = try? CASOptions.create(cbc.scope, nil) {
action = delegate.taskActionCreationDelegate.createGenericCachingTaskAction(
enableCacheDebuggingRemarks: cbc.scope.evaluate(BuiltinMacros.GENERIC_TASK_CACHE_ENABLE_DIAGNOSTIC_REMARKS),
enableTaskSandboxEnforcement: !cbc.scope.evaluate(BuiltinMacros.DISABLE_TASK_SANDBOXING),
sandboxDirectory: cbc.scope.evaluate(BuiltinMacros.TEMP_SANDBOX_DIR),
extraSandboxSubdirectories: [],
developerDirectory: cbc.scope.evaluate(BuiltinMacros.DEVELOPER_DIR),
casOptions: casOptions
)
cachingEnabled = true
} else {
action = nil
cachingEnabled = false
}


let ruleInfo = ["RealityAssetsCompile", cbc.output.str]
delegate.createTask(type: self,
Expand All @@ -190,7 +206,7 @@ package final class RealityAssetsCompilerSpec: GenericCompilerSpec, SpecIdentifi
inputs: inputs,
outputs: outputs,
mustPrecede: [],
action: cachingEnabled ? delegate.taskActionCreationDelegate.createGenericCachingTaskAction(enableCacheDebuggingRemarks: cbc.scope.evaluate(BuiltinMacros.GENERIC_TASK_CACHE_ENABLE_DIAGNOSTIC_REMARKS), enableTaskSandboxEnforcement: !cbc.scope.evaluate(BuiltinMacros.DISABLE_TASK_SANDBOXING), sandboxDirectory: cbc.scope.evaluate(BuiltinMacros.TEMP_SANDBOX_DIR), extraSandboxSubdirectories: [], developerDirectory: cbc.scope.evaluate(BuiltinMacros.DEVELOPER_DIR)) : nil,
action: action,
execDescription: "Compile Reality Asset \(rkAssetsPath.basename)",
preparesForIndexing: true,
enableSandboxing: !cachingEnabled,
Expand Down
16 changes: 12 additions & 4 deletions Sources/SWBBuildSystem/BuildOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1339,15 +1339,23 @@ internal final class OperationSystemAdaptor: SWBLLBuild.BuildSystemDelegate, Act
self.buildOutputDelegate = buildOutputDelegate
self._progressStatistics = BuildOperation.ProgressStatistics(numCommandsLowerBound: operation.buildDescription.targetTaskCounts.values.reduce(0, { $0 + $1 }))
self.core = core
self.dynamicOperationContext = DynamicTaskOperationContext(core: core, definingTargetsByModuleName: operation.buildDescription.definingTargetsByModuleName, cas: Self.setupCAS(core: core, operation: operation))
let cas: ToolchainCAS?
do {
cas = try Self.setupCAS(core: core, operation: operation)
} catch {
buildOutputDelegate.error(error.localizedDescription)
cas = nil
}
self.dynamicOperationContext = DynamicTaskOperationContext(core: core, definingTargetsByModuleName: operation.buildDescription.definingTargetsByModuleName, cas: cas)
self.queue = SWBQueue(label: "SWBBuildSystem.OperationSystemAdaptor.queue", qos: operation.request.qos, autoreleaseFrequency: .workItem)
}

private static func setupCAS(core: Core, operation: BuildOperation) -> ToolchainCAS? {
private static func setupCAS(core: Core, operation: BuildOperation) throws -> ToolchainCAS? {
let settings = operation.requestContext.getCachedSettings(operation.request.parameters)
let cachePath = Path(settings.globalScope.evaluate(BuiltinMacros.COMPILATION_CACHE_CAS_PATH)).join("swiftbuild")
let casOptions = try CASOptions.create(settings.globalScope, nil)
guard let casPlugin = core.lookupCASPlugin() else { return nil }
guard let cas = try? casPlugin.createCAS(path: cachePath, options: [:]) else { return nil }
guard let cas = try? casPlugin.createCAS(path: casOptions.casPath, options: [:]) else { return nil }

return cas
}

Expand Down
33 changes: 32 additions & 1 deletion Sources/SWBCAS/Errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,43 @@
//
//===----------------------------------------------------------------------===//

public enum ToolchainCASPluginError: Error, Sendable {
public enum ToolchainCASPluginError: Error, Sendable, CustomStringConvertible {
case missingRequiredSymbol(String)
case settingCASOptionFailed(String?)
case casCreationFailed(String?)
case storeFailed(String?)
case loadFailed(String?)
case cacheInsertionFailed(String?)
case cacheLookupFailed(String?)
case casSizeOperationUnsupported
case casSizeOperationFailed(String?)
case casPruneOperationUnsupported
case casPruneOperationFailed(String?)

public var description: String {
switch self {
case .missingRequiredSymbol(let symbol):
"missing required symbol: \(symbol)"
case .settingCASOptionFailed(let detail):
"setting CAS option failed: \(detail ?? "unknown error")"
case .casCreationFailed(let detail):
"creating CAS failed: \(detail ?? "unknown error")"
case .storeFailed(let detail):
"CAS store failed: \(detail ?? "unknown error")"
case .loadFailed(let detail):
"CAS load failed: \(detail ?? "unknown error")"
case .cacheInsertionFailed(let detail):
"cache insert failed: \(detail ?? "unknown error")"
case .cacheLookupFailed(let detail):
"cache lookup failed: \(detail ?? "unknown error")"
case .casSizeOperationUnsupported:
"CAS does not support size lookup"
case .casSizeOperationFailed(let detail):
"CAS size operation failed: \(detail ?? "unknown error")"
case .casPruneOperationUnsupported:
"CAS does not support pruning"
case .casPruneOperationFailed(let detail):
"CAS prune operation failed: \(detail ?? "unknown error")"
}
}
}
55 changes: 55 additions & 0 deletions Sources/SWBCAS/ToolchainCASPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,61 @@ public final class ToolchainCAS: @unchecked Sendable, CASProtocol, ActionCachePr
})
}

public func getOnDiskSize() throws -> Int64 {
var error: UnsafeMutablePointer<CChar>? = nil
guard let llcas_cas_get_ondisk_size = api.llcas_cas_get_ondisk_size else {
throw ToolchainCASPluginError.casSizeOperationUnsupported
}
let result = llcas_cas_get_ondisk_size(cCas, &error)
switch result {
case -1:
throw ToolchainCASPluginError.casSizeOperationUnsupported
case -2:
if let error = error {
let detailedError = String(cString: error)
api.llcas_string_dispose(error)
throw ToolchainCASPluginError.casSizeOperationFailed(detailedError)
}
throw ToolchainCASPluginError.casSizeOperationFailed(nil)
default:
return result
}
}

public func setOnDiskSizeLimit(_ limit: Int64) throws {
var error: UnsafeMutablePointer<CChar>? = nil
guard let llcas_cas_set_ondisk_size_limit = api.llcas_cas_set_ondisk_size_limit else {
throw ToolchainCASPluginError.casSizeOperationUnsupported
}
if llcas_cas_set_ondisk_size_limit(cCas, limit, &error) {
if let error = error {
let detailedError = String(cString: error)
api.llcas_string_dispose(error)
throw ToolchainCASPluginError.casSizeOperationFailed(detailedError)
}
throw ToolchainCASPluginError.casSizeOperationFailed(nil)
}
}

public func prune() throws {
var error: UnsafeMutablePointer<CChar>? = nil
guard let llcas_cas_prune_ondisk_data = api.llcas_cas_prune_ondisk_data else {
throw ToolchainCASPluginError.casPruneOperationUnsupported
}
if llcas_cas_prune_ondisk_data(cCas, &error) {
if let error = error {
let detailedError = String(cString: error)
api.llcas_string_dispose(error)
throw ToolchainCASPluginError.casPruneOperationFailed(detailedError)
}
throw ToolchainCASPluginError.casPruneOperationFailed(nil)
}
}

public var supportsPruning: Bool {
api.llcas_cas_get_ondisk_size != nil && api.llcas_cas_set_ondisk_size_limit != nil && api.llcas_cas_prune_ondisk_data != nil
}

deinit {
api.llcas_cas_dispose(cCas)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SWBCore/PlannedTaskAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ public protocol TaskActionCreationDelegate
func createDeferredExecutionTaskAction() -> any PlannedTaskAction
func createEmbedSwiftStdLibTaskAction() -> any PlannedTaskAction
func createFileCopyTaskAction(_ context: FileCopyTaskActionContext) -> any PlannedTaskAction
func createGenericCachingTaskAction(enableCacheDebuggingRemarks: Bool, enableTaskSandboxEnforcement: Bool, sandboxDirectory: Path, extraSandboxSubdirectories: [Path], developerDirectory: Path) -> any PlannedTaskAction
func createGenericCachingTaskAction(enableCacheDebuggingRemarks: Bool, enableTaskSandboxEnforcement: Bool, sandboxDirectory: Path, extraSandboxSubdirectories: [Path], developerDirectory: Path, casOptions: CASOptions) -> any PlannedTaskAction
func createInfoPlistProcessorTaskAction(_ contextPath: Path) -> any PlannedTaskAction
func createMergeInfoPlistTaskAction() -> any PlannedTaskAction
func createLinkAssetCatalogTaskAction() -> any PlannedTaskAction
Expand Down
Loading

0 comments on commit 9647382

Please # to comment.