in Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift [135:222]
func run() throws {
let outputFile = output ?? projectURL
let projectRoot = projectURL.deletingLastPathComponent()
let projectPath = Path(projectURL.path)
let outputPath = Path(outputFile.path)
// Override all extra configs (default to 'user.rc', next to the main '.rcinfo' file)
let initialOverride = IntegrationCacheConfig(
recommendedCacheAddress: nil,
xcccFile: binaries.cc.path,
mode: mode
)
try storeRCOverride(initialOverride, configOverrideLocation: configOverride)
if case .consumer = mode {
// require successful preparation
do {
// Call xcprepare to probe if XCRemoteCache can be safely used
let args = ["--configuration"] + consumerEligibleConfigurations + ["--platform"] +
consumerEligiblePlatforms
let yamlString = try shellGetStdout(
binaries.prepare.path,
args: args,
inDir: projectRoot.path,
environment: nil
)
let decoder = YAMLDecoder()
let prepareResult = try decoder.decode(PrepareResult.self, from: yamlString, userInfo: [:])
guard case .preparedFor(_, recommendedCacheAddress: let remote) = prepareResult else {
throw XcodeProjIntegrateError.noArtifactsToReuse
}
// Override the configuration again to include recommended cache address provided by xcprepare
let finalOverride = IntegrationCacheConfig(
recommendedCacheAddress: remote,
xcccFile: binaries.cc.path,
mode: mode
)
try storeRCOverride(finalOverride, configOverrideLocation: configOverride)
} catch {
// integration cannot be done as `xccc` hasn't been generated
exit(1, "XCRemoteCache cannot be initialized with a consumer mode. Error: \(error).")
}
}
// modify .pbxproj
let xcodeproj = try XcodeProj(path: projectPath)
for target in xcodeproj.pbxproj.nativeTargets {
guard targetIncludeOracle.shouldInclude(identifier: target.name) else {
continue
}
guard let targetConfigurations = target.buildConfigurationList else {
fatalError("Missing buildConfigurationList. Cannot apply")
}
// Apply settings for only few configurations
let targetConfigurationsToIntegrate = targetConfigurations.buildConfigurations.filter {
configurationIncludeOracle.shouldInclude(identifier: $0.name)
}
guard !targetConfigurationsToIntegrate.isEmpty else {
// No need to append build phases if none of Configurations exist for that target
continue
}
for buildConfiguration in targetConfigurationsToIntegrate {
let initialSettings = buildConfiguration.buildSettings
let finalSettings = buildSettingsAppender.appendToBuildSettings(
buildSettings: initialSettings,
wrappers: binaries
)
buildConfiguration.buildSettings = finalSettings
}
addSharedBuildPhases(target: target, in: xcodeproj.pbxproj)
// Add producer build phase that marks given sha+configuration+platform as "ready to use"
if case .producer = mode, finalProducerTarget == target.name {
addFinalProducerBuildPhases(target: target, in: xcodeproj.pbxproj)
}
}
try xcodeproj.write(path: outputPath)
try lldbPatcher.enable()
}