diff --git a/Package.resolved b/Package.resolved index f2b131ac..19f383d4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/tadija/AEXML.git", "state": { "branch": null, - "revision": "38f7d00b23ecd891e1ee656fa6aeebd6ba04ecc3", - "version": "4.6.1" + "revision": "db806756c989760b35108146381535aec231092b", + "version": "4.7.0" } }, { @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/kylef/PathKit.git", "state": { "branch": null, - "revision": "73f8e9dca9b7a3078cb79128217dc8f2e585a511", - "version": "1.0.0" + "revision": "3bfd2737b700b9a36565a8c94f4ad2b050a5e574", + "version": "1.0.1" } }, { @@ -24,8 +24,8 @@ "repositoryURL": "https://github.com/kylef/Spectre.git", "state": { "branch": null, - "revision": "f79d4ecbf8bc4e1579fbd86c3e1d652fb6876c53", - "version": "0.9.2" + "revision": "26cc5e9ae0947092c7139ef7ba612e34646086c7", + "version": "0.10.1" } }, { @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/tuist/XcodeProj.git", "state": { "branch": null, - "revision": "fae27b48bc14ff3fd9b02902e48c4665ce5a0793", - "version": "8.9.0" + "revision": "621eca8d091cc110a99adc23bb0d6618a65b4544", + "version": "9.13.0" } }, { diff --git a/Package.swift b/Package.swift index 00c88e43..14df8f46 100644 --- a/Package.swift +++ b/Package.swift @@ -7,7 +7,7 @@ import PackageDescription let package = Package( name: "XCRemoteCache", platforms: [ - .macOS(.v10_14), + .macOS(.v11), ], products: [ .executable(name: "xcprebuild", targets: ["xcprebuild"]), @@ -16,7 +16,7 @@ let package = Package( .package(url: "https://github.com/marmelroy/Zip.git", from: "2.1.2"), .package(url: "https://github.com/jpsim/Yams.git", from: "5.0.0"), .package(url: "https://github.com/apple/swift-argument-parser", from: "0.0.1"), - .package(url: "https://github.com/tuist/XcodeProj.git", from: "8.9.0"), + .package(url: "https://github.com/tuist/XcodeProj.git", from: "9.12.0"), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), ], targets: [ diff --git a/Sources/XCRemoteCache/Commands/Libtool/XCCreateUniversalBinary.swift b/Sources/XCRemoteCache/Commands/Libtool/XCCreateUniversalBinary.swift index b05117d8..6c61f3bc 100644 --- a/Sources/XCRemoteCache/Commands/Libtool/XCCreateUniversalBinary.swift +++ b/Sources/XCRemoteCache/Commands/Libtool/XCCreateUniversalBinary.swift @@ -47,11 +47,18 @@ class XCCreateUniversalBinary: XCLibtoolLogic { // TODO: find better (stable) technique to determine `$TARGET_TEMP_DIR` errorLog("\(firstInputURL.absoluteString)") - tempDir = firstInputURL + let environment = ProcessInfo.processInfo.environment + + if let targetTempDir = environment["TARGET_TEMP_DIR"], !targetTempDir.isEmpty { + tempDir = URL(fileURLWithPath: targetTempDir) + } else { + tempDir = firstInputURL .deletingLastPathComponent() .deletingLastPathComponent() .deletingLastPathComponent() .deletingLastPathComponent() + } + self.firstInputURL = firstInputURL self.toolName = toolName self.fallbackCommand = fallbackCommand diff --git a/Sources/XCRemoteCache/Commands/Prepare/CCWrapperBuilder.swift b/Sources/XCRemoteCache/Commands/Prepare/CCWrapperBuilder.swift index afa44280..5557f7e5 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/CCWrapperBuilder.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/CCWrapperBuilder.swift @@ -469,21 +469,10 @@ class TemplateBasedCCWrapperBuilder: CCWrapperBuilder { return execvp(clang_cmd, (char *const*) clang_args); } - // Verify all input arguments - if (dependency_file == NULL) { - fprintf(stderr, "error: missing %s input\\n", dependency_arg_name); - exit(1); - } - if (output_file == NULL) { - fprintf(stderr, "error: missing %s input\\n", output_arg_name); - exit(1); - } - if (input_file == NULL) { - fprintf(stderr, "error: missing input file\\n"); - exit(1); + if (dependency_file == NULL || output_file == NULL || input_file == NULL) { + return execvp(clang_cmd, (char *const*) clang_args); } - // Find tmp_dir #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers" diff --git a/Sources/XCRemoteCache/Commands/Prepare/Integrate/BuildSettingsIntegrateAppender.swift b/Sources/XCRemoteCache/Commands/Prepare/Integrate/BuildSettingsIntegrateAppender.swift index ec4f4b1c..7dd9554c 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/Integrate/BuildSettingsIntegrateAppender.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/Integrate/BuildSettingsIntegrateAppender.swift @@ -18,8 +18,7 @@ // under the License. import Foundation - -typealias BuildSettings = [String: Any] +import XcodeProj struct BuildSettingsIntegrateAppenderOption: OptionSet { let rawValue: Int @@ -62,6 +61,8 @@ class XcodeProjBuildSettingsIntegrateAppender: BuildSettingsIntegrateAppender { if options.contains(.disableSwiftDriverIntegration) { setBuildSetting(buildSettings: &result, key: "SWIFT_USE_INTEGRATED_DRIVER", value: "NO" ) } + setBuildSetting(buildSettings: &result, key: "ENABLE_DEBUG_DYLIB", value: "NO" ) + // When generating artifacts, no need to shell-out all compilation commands to our wrappers if case .consumer = mode { setBuildSetting(buildSettings: &result, key: "CC", value: wrappers.cc.path ) @@ -78,8 +79,8 @@ class XcodeProjBuildSettingsIntegrateAppender: BuildSettingsIntegrateAppender { setBuildSetting(buildSettings: &result, key: "LDPLUSPLUS", value: wrappers.ldplusplus.path ) } - let existingSwiftFlags = result["OTHER_SWIFT_FLAGS"] as? String - let existingCFlags = result["OTHER_CFLAGS"] as? String + let existingSwiftFlags = result["OTHER_SWIFT_FLAGS"]?.stringValue + let existingCFlags = result["OTHER_CFLAGS"]?.stringValue var swiftFlags = XcodeSettingsSwiftFlags(settingValue: existingSwiftFlags) var clangFlags = XcodeSettingsCFlags(settingValue: existingCFlags) @@ -102,14 +103,14 @@ class XcodeProjBuildSettingsIntegrateAppender: BuildSettingsIntegrateAppender { } private func setBuildSetting(buildSettings: inout BuildSettings, key: String, value: String?, excludedValue: String = "") { - buildSettings[key] = value + buildSettings[key] = value.map { .string($0) } guard value != nil else { // no need to exclude as the value will return } // Erase all overrides for a given sdk so a default toolchain is used for skippedSDK in sdksExclude { - buildSettings["\(key)[sdk=\(skippedSDK)]"] = excludedValue + buildSettings["\(key)[sdk=\(skippedSDK)]"] = .string(excludedValue) } } diff --git a/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift b/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift index 9713d1ff..a1f2661f 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/Integrate/XcodeProjIntegrate.swift @@ -216,7 +216,7 @@ struct XcodeProjIntegrate: Integrate { } } - try xcodeproj.write(path: outputPath) + try xcodeproj.writePBXProj(path: outputPath, override: true, outputSettings: PBXOutputSettings()) try lldbPatcher.enable() } diff --git a/Sources/XCRemoteCache/Commands/Prepare/Prepare.swift b/Sources/XCRemoteCache/Commands/Prepare/Prepare.swift index 78814c91..d34b359d 100644 --- a/Sources/XCRemoteCache/Commands/Prepare/Prepare.swift +++ b/Sources/XCRemoteCache/Commands/Prepare/Prepare.swift @@ -74,7 +74,7 @@ class Prepare: PrepareLogic { /// Finds the best commit with generated artifacts to use func prepare() throws -> PrepareResult { do { - guard fileAccessor.fileExists(atPath: PhaseCacheModeController.xcodeSelectLink.path) else { + guard (try? FileManager.default.destinationOfSymbolicLink(atPath: PhaseCacheModeController.xcodeSelectLink.path)) != nil else { throw PrepareError.missingXcodeSelectDirectory } diff --git a/Sources/XCRemoteCache/Commands/ProductBinaryCreator/XCCreateBinary.swift b/Sources/XCRemoteCache/Commands/ProductBinaryCreator/XCCreateBinary.swift index 26c44707..78b5980f 100644 --- a/Sources/XCRemoteCache/Commands/ProductBinaryCreator/XCCreateBinary.swift +++ b/Sources/XCRemoteCache/Commands/ProductBinaryCreator/XCCreateBinary.swift @@ -47,10 +47,17 @@ public class XCCreateBinary { self.dependencyInfo = URL(fileURLWithPath: dependencyInfo) // fileList is place in $TARGET_TEMP_DIR/Objects-normal/$ARCH/$TARGET_NAME.LinkFileList // TODO: find better (stable) technique to determine `$TARGET_TEMP_DIR` - tempDir = URL(fileURLWithPath: filelist) + let environment = ProcessInfo.processInfo.environment + + if let targetTempDir = environment["TARGET_TEMP_DIR"], !targetTempDir.isEmpty { + tempDir = URL(fileURLWithPath: targetTempDir) + } else { + tempDir = URL(fileURLWithPath: filelist) .deletingLastPathComponent() .deletingLastPathComponent() .deletingLastPathComponent() + } + self.fallbackCommand = fallbackCommand self.stepDescription = stepDescription } diff --git a/Sources/XCRemoteCache/Commands/Swiftc/SwiftcContext.swift b/Sources/XCRemoteCache/Commands/Swiftc/SwiftcContext.swift index 6cd89e08..5ff3b32e 100644 --- a/Sources/XCRemoteCache/Commands/Swiftc/SwiftcContext.swift +++ b/Sources/XCRemoteCache/Commands/Swiftc/SwiftcContext.swift @@ -107,11 +107,22 @@ public struct SwiftcContext { self.compilationFiles = compilationFiles // exampleWorkspaceFilePath has a format $TARGET_TEMP_DIR/Objects-normal/$ARCH/some.file // That may be subject to change for other Xcode versions - tempDir = URL(fileURLWithPath: exampleWorkspaceFilePath) + let environment = ProcessInfo.processInfo.environment + + if let targetTempDir = environment["TARGET_TEMP_DIR"], !targetTempDir.isEmpty { + tempDir = URL(fileURLWithPath: targetTempDir) + } else { + tempDir = URL(fileURLWithPath: exampleWorkspaceFilePath) .deletingLastPathComponent() .deletingLastPathComponent() .deletingLastPathComponent() - arch = URL(fileURLWithPath: exampleWorkspaceFilePath).deletingLastPathComponent().lastPathComponent + } + + if let archComponent = target.split(separator: "-").first, !archComponent.isEmpty { + arch = String(archComponent) + } else { + arch = URL(fileURLWithPath: exampleWorkspaceFilePath).deletingLastPathComponent().lastPathComponent + } let srcRoot: URL = URL(fileURLWithPath: config.sourceRoot) let remoteCommitLocation = URL(fileURLWithPath: config.remoteCommitFile, relativeTo: srcRoot) diff --git a/Sources/XCRemoteCache/Dependencies/CacheModeController.swift b/Sources/XCRemoteCache/Dependencies/CacheModeController.swift index 8768917d..7303bba9 100644 --- a/Sources/XCRemoteCache/Dependencies/CacheModeController.swift +++ b/Sources/XCRemoteCache/Dependencies/CacheModeController.swift @@ -41,7 +41,14 @@ protocol CacheModeController { class PhaseCacheModeController: CacheModeController { /// Path to the symbolic link that changes if other xcode is selected with `xcode-select -s` - static let xcodeSelectLink: URL = URL(fileURLWithPath: "/var/db/xcode_select_link") + static var xcodeSelectLink: URL { + let legacyPath = URL(fileURLWithPath: "/var/db/xcode_select_link") + let modernPath = URL(fileURLWithPath: "/var/select/developer_dir") + if (try? FileManager.default.destinationOfSymbolicLink(atPath: modernPath.path)) != nil { + return modernPath + } + return legacyPath + } private let mergeCommitFile: URL private let modeMarker: URL private let forceCached: Bool diff --git a/Tests/XCRemoteCacheTests/Commands/Prepare/Integrate/XcodeProjBuildSettingsIntegrateAppenderTests.swift b/Tests/XCRemoteCacheTests/Commands/Prepare/Integrate/XcodeProjBuildSettingsIntegrateAppenderTests.swift index 819323c7..d4c98808 100644 --- a/Tests/XCRemoteCacheTests/Commands/Prepare/Integrate/XcodeProjBuildSettingsIntegrateAppenderTests.swift +++ b/Tests/XCRemoteCacheTests/Commands/Prepare/Integrate/XcodeProjBuildSettingsIntegrateAppenderTests.swift @@ -18,6 +18,7 @@ // under the License. @testable import XCRemoteCache +import XcodeProj import XCTest class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { @@ -53,7 +54,7 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let resultURL = try XCTUnwrap(result["XCRC_FAKE_SRCROOT"] as? String) + let resultURL = try XCTUnwrap(result["XCRC_FAKE_SRCROOT"]?.stringValue) XCTAssertEqual(resultURL, fakeRootURL.path) } @@ -69,7 +70,7 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let resultURL: String = try XCTUnwrap(result["XCRC_FAKE_SRCROOT"] as? String) + let resultURL: String = try XCTUnwrap(result["XCRC_FAKE_SRCROOT"]?.stringValue) XCTAssertEqual(resultURL, fakeRootURL.path) } @@ -85,7 +86,7 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let ldPlusPlus: String = try XCTUnwrap(result["LDPLUSPLUS"] as? String) + let ldPlusPlus: String = try XCTUnwrap(result["LDPLUSPLUS"]?.stringValue) XCTAssertEqual(ldPlusPlus, binaries.ldplusplus.path) } @@ -100,7 +101,7 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let ldPlusPlusWatchOS: String = try XCTUnwrap(result["LDPLUSPLUS[sdk=watchOS*]"] as? String) + let ldPlusPlusWatchOS: String = try XCTUnwrap(result["LDPLUSPLUS[sdk=watchOS*]"]?.stringValue) XCTAssertEqual(ldPlusPlusWatchOS, "") } @@ -115,7 +116,7 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let libtoolWatchOS: String = try XCTUnwrap(result["LIBTOOL[sdk=watchOS*]"] as? String) + let libtoolWatchOS: String = try XCTUnwrap(result["LIBTOOL[sdk=watchOS*]"]?.stringValue) XCTAssertEqual(libtoolWatchOS, "libtool") } @@ -130,8 +131,8 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let ldPlusPlusWatchOS: String = try XCTUnwrap(result["LDPLUSPLUS[sdk=watchOS*]"] as? String) - let ldPlusPlusWatchSimulator: String = try XCTUnwrap(result["LDPLUSPLUS[sdk=watchsimulator*]"] as? String) + let ldPlusPlusWatchOS: String = try XCTUnwrap(result["LDPLUSPLUS[sdk=watchOS*]"]?.stringValue) + let ldPlusPlusWatchSimulator: String = try XCTUnwrap(result["LDPLUSPLUS[sdk=watchsimulator*]"]?.stringValue) XCTAssertEqual(ldPlusPlusWatchOS, "") XCTAssertEqual(ldPlusPlusWatchSimulator, "") @@ -147,8 +148,8 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let disabledWatchOS: String = try XCTUnwrap(result["XCRC_DISABLED[sdk=watchOS*]"] as? String) - let disabledWatchSimulator: String = try XCTUnwrap(result["XCRC_DISABLED[sdk=watchsimulator*]"] as? String) + let disabledWatchOS: String = try XCTUnwrap(result["XCRC_DISABLED[sdk=watchOS*]"]?.stringValue) + let disabledWatchSimulator: String = try XCTUnwrap(result["XCRC_DISABLED[sdk=watchsimulator*]"]?.stringValue) XCTAssertEqual(disabledWatchOS, "YES") XCTAssertEqual(disabledWatchSimulator, "YES") @@ -164,7 +165,7 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [.disableSwiftDriverIntegration] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let useSwiftIntegrationDriver: String = try XCTUnwrap(result["SWIFT_USE_INTEGRATED_DRIVER"] as? String) + let useSwiftIntegrationDriver: String = try XCTUnwrap(result["SWIFT_USE_INTEGRATED_DRIVER"]?.stringValue) XCTAssertEqual(useSwiftIntegrationDriver, "NO") } @@ -179,7 +180,7 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase { options: [] ) let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries) - let useSwiftIntegrationDriver: String? = result["SWIFT_USE_INTEGRATED_DRIVER"] as? String + let useSwiftIntegrationDriver: String? = result["SWIFT_USE_INTEGRATED_DRIVER"]?.stringValue XCTAssertNil(useSwiftIntegrationDriver) } diff --git a/Tests/XCRemoteCacheTests/Dependencies/PhaseCacheModeControllerTests.swift b/Tests/XCRemoteCacheTests/Dependencies/PhaseCacheModeControllerTests.swift index 2e08cee3..3b138221 100644 --- a/Tests/XCRemoteCacheTests/Dependencies/PhaseCacheModeControllerTests.swift +++ b/Tests/XCRemoteCacheTests/Dependencies/PhaseCacheModeControllerTests.swift @@ -101,7 +101,7 @@ class PhaseCacheModeControllerTests: FileXCTestCase { try modeController.enable(allowedInputFiles: [], dependencies: []) let allDeps = try dependenciesWriter.wroteDependencies.unwrap().values.flatMap { $0 } - XCTAssertTrue(allDeps.contains("/var/db/xcode_select_link")) + XCTAssertTrue(allDeps.contains(PhaseCacheModeController.xcodeSelectLink.path)) } func testDependsOnXcodeSelectLinkWhenDisabled() throws { @@ -122,7 +122,7 @@ class PhaseCacheModeControllerTests: FileXCTestCase { try modeController.disable() let allDeps = try dependenciesWriter.wroteDependencies.unwrap().values.flatMap { $0 } - XCTAssertTrue(allDeps.contains("/var/db/xcode_select_link")) + XCTAssertTrue(allDeps.contains(PhaseCacheModeController.xcodeSelectLink.path)) } func testForcedCachedPhaseFailToDisable() throws {