diff --git a/Sources/Shared/Configuration.swift b/Sources/Shared/Configuration.swift index ac1dff466..5f68ac702 100644 --- a/Sources/Shared/Configuration.swift +++ b/Sources/Shared/Configuration.swift @@ -41,6 +41,9 @@ public final class Configuration { @Setting(key: "build_arguments", defaultValue: []) public var buildArguments: [String] + @Setting(key: "schemes_arguments", defaultValue: []) + public var schemesArguments: [String] + @Setting(key: "retain_assign_only_property_types", defaultValue: [], valueSanitizer: PropertyTypeSanitizer.sanitize) public var retainAssignOnlyPropertyTypes: [String] @@ -347,6 +350,8 @@ public final class Configuration { $cleanBuild.assign(value) case $buildArguments.key: $buildArguments.assign(value) + case $schemesArguments.key: + $schemesArguments.assign(value) case $relativeResults.key: $relativeResults.assign(value) case $retainCodableProperties.key: diff --git a/Sources/XcodeSupport/XcodeProject.swift b/Sources/XcodeSupport/XcodeProject.swift index 262e22e77..4e49d7c7e 100644 --- a/Sources/XcodeSupport/XcodeProject.swift +++ b/Sources/XcodeSupport/XcodeProject.swift @@ -105,8 +105,8 @@ final class XcodeProject: XcodeProjectlike { } } - func schemes() throws -> Set { - try xcodebuild.schemes(project: self) + func schemes(additionalArguments: [String]) throws -> Set { + try xcodebuild.schemes(project: self, additionalArguments: additionalArguments) } } diff --git a/Sources/XcodeSupport/XcodeProjectDriver.swift b/Sources/XcodeSupport/XcodeProjectDriver.swift index 7ffe51ea2..67a06b447 100644 --- a/Sources/XcodeSupport/XcodeProjectDriver.swift +++ b/Sources/XcodeSupport/XcodeProjectDriver.swift @@ -47,7 +47,9 @@ public final class XcodeProjectDriver { } // Ensure schemes exist within the project - let schemes = try project.schemes().filter { configuration.schemes.contains($0) } + let schemes = try project.schemes( + additionalArguments: configuration.schemesArguments + ).filter { configuration.schemes.contains($0) } let validSchemeNames = schemes.mapSet { $0 } if let scheme = Set(configuration.schemes).subtracting(validSchemeNames).first { diff --git a/Sources/XcodeSupport/XcodeProjectSetupGuide.swift b/Sources/XcodeSupport/XcodeProjectSetupGuide.swift index 6b3cc3564..b3ec0b134 100644 --- a/Sources/XcodeSupport/XcodeProjectSetupGuide.swift +++ b/Sources/XcodeSupport/XcodeProjectSetupGuide.swift @@ -43,7 +43,10 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide print(colorize("Select build targets to analyze:", .bold)) configuration.targets = select(multiple: targets, allowAll: true).selectedValues - let schemes = try filter(project.schemes(), project).map { $0 }.sorted() + let schemes = try filter( + project.schemes(additionalArguments: configuration.schemesArguments), + project + ).map { $0 }.sorted() print(colorize("\nSelect the schemes necessary to build your chosen targets:", .bold)) configuration.schemes = select(multiple: schemes, allowAll: false).selectedValues @@ -82,7 +85,11 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide private func getPodSchemes(in project: XcodeProjectlike) throws -> Set { let path = project.sourceRoot.appending("Pods/Pods.xcodeproj") guard path.exists else { return [] } - return try xcodebuild.schemes(type: "project", path: path.lexicallyNormalized().string) + return try xcodebuild.schemes( + type: "project", + path: path.lexicallyNormalized().string, + additionalArguments: configuration.schemesArguments + ) } private func filter(_ schemes: Set, _ project: XcodeProjectlike) throws -> [String] { diff --git a/Sources/XcodeSupport/XcodeProjectlike.swift b/Sources/XcodeSupport/XcodeProjectlike.swift index a82c4623b..34fa31537 100644 --- a/Sources/XcodeSupport/XcodeProjectlike.swift +++ b/Sources/XcodeSupport/XcodeProjectlike.swift @@ -10,7 +10,7 @@ protocol XcodeProjectlike: AnyObject { var name: String { get } var sourceRoot: FilePath { get } - func schemes() throws -> Set + func schemes(additionalArguments: [String]) throws -> Set } extension XcodeProjectlike { diff --git a/Sources/XcodeSupport/XcodeWorkspace.swift b/Sources/XcodeSupport/XcodeWorkspace.swift index 59cbdc3de..940e37a6a 100644 --- a/Sources/XcodeSupport/XcodeWorkspace.swift +++ b/Sources/XcodeSupport/XcodeWorkspace.swift @@ -42,8 +42,8 @@ final class XcodeWorkspace: XcodeProjectlike { } } - func schemes() throws -> Set { - try xcodebuild.schemes(project: self) + func schemes(additionalArguments: [String]) throws -> Set { + try xcodebuild.schemes(project: self, additionalArguments: additionalArguments) } // MARK: - Private diff --git a/Sources/XcodeSupport/Xcodebuild.swift b/Sources/XcodeSupport/Xcodebuild.swift index 588202e94..8e72b96fc 100644 --- a/Sources/XcodeSupport/Xcodebuild.swift +++ b/Sources/XcodeSupport/Xcodebuild.swift @@ -71,18 +71,36 @@ public final class Xcodebuild { return path } - func schemes(project: XcodeProjectlike) throws -> Set { - try schemes(type: project.type, path: project.path.lexicallyNormalized().string) + func schemes(project: XcodeProjectlike, additionalArguments: [String]) throws -> Set { + try schemes( + type: project.type, + path: project.path.lexicallyNormalized().string, + additionalArguments: additionalArguments + ) } - func schemes(type: String, path: String) throws -> Set { + func schemes(type: String, path: String, additionalArguments: [String]) throws -> Set { let args = [ "-\(type)", path, "-list", "-json" ] - let lines = try shell.exec(["xcodebuild"] + args, stderr: false).split(separator: "\n").map { String($0).trimmed } + var quotedArguments = additionalArguments + + for (i, arg) in additionalArguments.enumerated() { + if arg.hasPrefix("-"), + let value = additionalArguments[safe: i + 1], + !value.hasPrefix("-"), + !value.hasPrefix("\""), + !value.hasPrefix("\'") + { + quotedArguments[i + 1] = "\"\(value)\"" + } + } + + let xcodebuild = "xcodebuild \((args + quotedArguments).joined(separator: " "))" + let lines = try shell.exec(["/bin/sh", "-c", xcodebuild], stderr: false).split(separator: "\n").map { String($0).trimmed } // xcodebuild may output unrelated warnings, we need to strip them out otherwise // JSON parsing will fail. diff --git a/Tests/XcodeTests/XcodebuildTest.swift b/Tests/XcodeTests/XcodebuildTest.swift index fff8655df..a816e9780 100644 --- a/Tests/XcodeTests/XcodebuildTest.swift +++ b/Tests/XcodeTests/XcodebuildTest.swift @@ -36,7 +36,7 @@ class XcodebuildSchemesTest: XCTestCase { func testParseSchemes() { for output in XcodebuildListOutputs { shell.output = output - let schemes = try! xcodebuild.schemes(project: project) + let schemes = try! xcodebuild.schemes(project: project, additionalArguments: []) XCTAssertEqual(schemes, ["SchemeA", "SchemeB"]) } }