From 43b106e55f1bd675efb79a7ad7c6ec9e8374c2a9 Mon Sep 17 00:00:00 2001 From: Rob Amos Date: Wed, 1 Jul 2020 15:00:03 +1000 Subject: [PATCH] Added support for supplying an `--xcconfig` option that can be used to set project-wide build settings --- .../CreateXCFramework/Command+Options.swift | 3 ++ Sources/CreateXCFramework/Command.swift | 6 +-- Sources/CreateXCFramework/PackageInfo.swift | 17 ++++++- .../CreateXCFramework/ProjectGenerator.swift | 51 ++++++++++++++++--- action.js | 6 +++ action.yml | 3 ++ 6 files changed, 75 insertions(+), 11 deletions(-) diff --git a/Sources/CreateXCFramework/Command+Options.swift b/Sources/CreateXCFramework/Command+Options.swift index 737f8eb..c0a8fb5 100644 --- a/Sources/CreateXCFramework/Command+Options.swift +++ b/Sources/CreateXCFramework/Command+Options.swift @@ -30,6 +30,9 @@ extension Command { @Flag(help: "Prints the available products and targets") var listProducts: Bool + + @Option(help: "The path to a .xcconfig file that can be used to override Xcode build settings. Relative to the package path.") + var xcconfig: String? // MARK: - Output Options diff --git a/Sources/CreateXCFramework/Command.swift b/Sources/CreateXCFramework/Command.swift index a2344e3..770ecfd 100644 --- a/Sources/CreateXCFramework/Command.swift +++ b/Sources/CreateXCFramework/Command.swift @@ -50,7 +50,7 @@ struct Command: ParsableCommand { let platforms = try package.supportedPlatforms() // get what we're building - try generator.writeXcconfig() + try generator.writeDistributionXcconfig() let project = try generator.generate() // printing packages? @@ -65,9 +65,7 @@ struct Command: ParsableCommand { // we've applied the xcconfig to everything, but some dependencies (*cough* swift-nio) // have build errors, so we remove it from targets we're not building - for target in project.targets where productNames.contains(target.name) == false { - target.buildSettings.xcconfigFileRef = nil - } + try project.enableDistribution(targets: productNames, xcconfig: AbsolutePath(package.distributionBuildXcconfig.path).relative(to: AbsolutePath(package.rootDirectory.path))) // save the project try project.save(to: generator.projectPath) diff --git a/Sources/CreateXCFramework/PackageInfo.swift b/Sources/CreateXCFramework/PackageInfo.swift index 623a700..2e0bde5 100644 --- a/Sources/CreateXCFramework/PackageInfo.swift +++ b/Sources/CreateXCFramework/PackageInfo.swift @@ -32,7 +32,22 @@ struct PackageInfo { .appendingPathComponent("Distribution.xcconfig") .absoluteURL } - + + var overridesXcconfig: Foundation.URL? { + guard let path = self.options.xcconfig else { return nil } + + // absolute path + if path.hasPrefix("/") { + return Foundation.URL(fileURLWithPath: path) + + // strip current directory if thats where we are + } else if path.hasPrefix("./") { + return self.rootDirectory.appendingPathComponent(String(path[path.index(path.startIndex, offsetBy: 2)...])) + } + + return self.rootDirectory.appendingPathComponent(path) + } + // TODO: Map diagnostics to swift-log let diagnostics = DiagnosticsEngine() diff --git a/Sources/CreateXCFramework/ProjectGenerator.swift b/Sources/CreateXCFramework/ProjectGenerator.swift index b88ac46..6f266d0 100644 --- a/Sources/CreateXCFramework/ProjectGenerator.swift +++ b/Sources/CreateXCFramework/ProjectGenerator.swift @@ -15,7 +15,8 @@ struct ProjectGenerator { private enum Constants { static let `extension` = "xcodeproj" } - + + // MARK: - Properties let package: PackageInfo @@ -24,19 +25,32 @@ struct ProjectGenerator { let dir = AbsolutePath(self.package.projectBuildDirectory.path) return buildXcodeprojPath(outputDir: dir, projectName: self.package.package.name) } - + + // MARK: - Initialisation init (package: PackageInfo) { self.package = package } - + + // MARK: - Generation /// Writes out the Xcconfig file - func writeXcconfig () throws { + func writeDistributionXcconfig () throws { try makeDirectories(self.projectPath) - try open(AbsolutePath(self.package.distributionBuildXcconfig.path)) { stream in + + let path = AbsolutePath(self.package.distributionBuildXcconfig.path) + try open(path) { stream in + if let absolutePath = self.package.overridesXcconfig?.path { + stream ( + """ + #include "\(AbsolutePath(absolutePath).relative(to: AbsolutePath(path.dirname)).pathString)" + + """ + ) + } + stream ( """ BUILD_LIBRARY_FOR_DISTRIBUTION=YES @@ -59,12 +73,13 @@ struct ProjectGenerator { graph: self.package.graph, extraDirs: [], extraFiles: [], - options: XcodeprojOptions(xcconfigOverrides: AbsolutePath(self.package.distributionBuildXcconfig.path)), + options: XcodeprojOptions(xcconfigOverrides: (self.package.overridesXcconfig?.path).flatMap { AbsolutePath($0) }), diagnostics: self.package.diagnostics ) return project } + } @@ -72,6 +87,30 @@ struct ProjectGenerator { extension Xcode.Project { + /// This is the group that is normally created in Xcodeproj.xcodeProject() when you specify an xcconfigOverride + var configGroup: Xcode.Group { + let name = "Configs" + + if let group = self.mainGroup.subitems.lazy.compactMap({ $0 as? Xcode.Group }).first(where: { $0.name == name }) { + return group + } + + // doesn't exist - lets creat it + return self.mainGroup.addGroup(path: "", name: name) + } + + func enableDistribution (targets: [String], xcconfig: RelativePath) throws { + let group = self.configGroup + let ref = group.addFileReference ( + path: xcconfig.pathString, + name: xcconfig.basename + ) + + for target in self.targets where targets.contains(target.name) { + target.buildSettings.xcconfigFileRef = ref + } + } + func save (to path: AbsolutePath) throws { try open(path.appending(component: "project.pbxproj")) { stream in // Serialize the project model we created to a plist, and return diff --git a/action.js b/action.js index 7d01e81..c4dfabd 100644 --- a/action.js +++ b/action.js @@ -15,6 +15,7 @@ async function run () { let targets = core.getInput('target', { required: false }) let configuration = core.getInput('configuration', { required: false }) let platforms = core.getInput('platforms', { required: false }) + let xcconfig = core.getInput('xcconfig', { required: false }) // install mint if its not installed await installUsingBrewIfRequired("mint") @@ -34,6 +35,11 @@ async function run () { options.push(configuration) } + if (!!xcconfig) { + options.push('--xcconfig') + options.push(xcconfig) + } + if (!!platforms) { platforms .split(',') diff --git a/action.yml b/action.yml index ddc017a..3c016cb 100644 --- a/action.yml +++ b/action.yml @@ -12,6 +12,9 @@ inputs: description: "Build with a specific configuration ('debug' or 'release')" required: false default: release + xcconfig: + description: "The path to a .xcconfig file that can be used to override Xcode build settings. Relative to the package path." + required: false runs: using: node12