From c42a955330fb475cb3e6768692b052ece6af9ac0 Mon Sep 17 00:00:00 2001 From: Rob Amos Date: Thu, 18 Jun 2020 16:25:13 +1000 Subject: [PATCH] Disabled the xcodebuild-wide BUILD_LIBRARY_FOR_DISTRIBUTION setting in favour of target-specific ones --- Sources/CreateXCFramework/Command.swift | 17 ++- Sources/CreateXCFramework/PackageInfo.swift | 6 + .../CreateXCFramework/ProjectGenerator.swift | 104 ++++++++++++++++-- Sources/CreateXCFramework/XcodeBuilder.swift | 1 - 4 files changed, 115 insertions(+), 13 deletions(-) diff --git a/Sources/CreateXCFramework/Command.swift b/Sources/CreateXCFramework/Command.swift index 4a44def..7ccca33 100644 --- a/Sources/CreateXCFramework/Command.swift +++ b/Sources/CreateXCFramework/Command.swift @@ -50,17 +50,28 @@ struct Command: ParsableCommand { let platforms = try package.supportedPlatforms() // get what we're building + try generator.writeXcconfig() let project = try generator.generate() - + // printing packages? if self.options.listProducts { package.printAllProducts(project: project) Darwin.exit(0) } - + + // get valid packages and their SDKs let productNames = try package.validProductNames(project: project) - let sdks = platforms.flatMap { $0.sdks } + + // 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 + } + + // save the project + try project.save(to: generator.projectPath) + // start building let builder = XcodeBuilder(project: project, projectPath: generator.projectPath, package: package, options: self.options) diff --git a/Sources/CreateXCFramework/PackageInfo.swift b/Sources/CreateXCFramework/PackageInfo.swift index 8409f02..1feb808 100644 --- a/Sources/CreateXCFramework/PackageInfo.swift +++ b/Sources/CreateXCFramework/PackageInfo.swift @@ -25,6 +25,12 @@ struct PackageInfo { .appendingPathComponent("swift-create-xcframework") .absoluteURL } + + var distributionBuildXcconfig: Foundation.URL { + return self.projectBuildDirectory + .appendingPathComponent("Distribution.xcconfig") + .absoluteURL + } // TODO: Map diagnostics to swift-log let diagnostics = DiagnosticsEngine() diff --git a/Sources/CreateXCFramework/ProjectGenerator.swift b/Sources/CreateXCFramework/ProjectGenerator.swift index 1ac6479..0b53a9f 100644 --- a/Sources/CreateXCFramework/ProjectGenerator.swift +++ b/Sources/CreateXCFramework/ProjectGenerator.swift @@ -7,6 +7,7 @@ import Foundation import TSCBasic +import TSCUtility import Xcodeproj struct ProjectGenerator { @@ -31,22 +32,107 @@ struct ProjectGenerator { } // MARK: - Generation - + + /// Writes out the Xcconfig file + func writeXcconfig () throws { + try open(AbsolutePath(self.package.distributionBuildXcconfig.path)) { stream in + stream ( + """ + BUILD_LIBRARY_FOR_DISTRIBUTION=YES + """ + ) + } + } + + /// Generate an Xcode project. + /// + /// This is basically a copy of Xcodeproj.generate() + /// func generate () throws -> Xcode.Project { let path = self.projectPath try makeDirectories(path) - - return try Xcodeproj.generate ( - projectName: self.package.package.name, + + // Generate the contents of project.xcodeproj (inside the .xcodeproj). + let project = try pbxproj ( xcodeprojPath: path, graph: self.package.graph, - options: XcodeprojOptions(addExtraFiles: false), + extraDirs: [], + extraFiles: [], + options: XcodeprojOptions(xcconfigOverrides: AbsolutePath(self.package.distributionBuildXcconfig.path)), diagnostics: self.package.diagnostics ) + + return project } - - private func createDirectory (at path: URL) throws { - guard FileManager.default.fileExists(atPath: path.path) == false else { return } - try FileManager.default.createDirectory(at: path, withIntermediateDirectories: true, attributes: nil) +} + + +// MARK: - Saving Xcode Projects + +extension Xcode.Project { + + 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 + // its string description. + let str = "// !$*UTF8*$!\n" + self.generatePlist().description + stream(str) + } + + for target in self.frameworkTargets { + ///// For framework targets, generate target.c99Name_Info.plist files in the + ///// directory that Xcode project is generated + let name = "\(target.name.spm_mangledToC99ExtendedIdentifier())_Info.plist" + try open(path.appending(RelativePath(name))) { print in + print(""" + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + + """) + } + } } } + +/// Writes the contents to the file specified. +/// +/// This method doesn't rewrite the file in case the new and old contents of +/// file are same. +fileprivate func open(_ path: AbsolutePath, body: ((String) -> Void) throws -> Void) throws { + let stream = BufferedOutputByteStream() + try body { line in + stream <<< line + stream <<< "\n" + } + // If the file exists with the identical contents, we don't need to rewrite it. + // + // This avoids unnecessarily triggering Xcode reloads of the project file. + if let contents = try? localFileSystem.readFileContents(path), contents == stream.bytes { + return + } + + // Write the real file. + try localFileSystem.writeFileContents(path, bytes: stream.bytes) +} diff --git a/Sources/CreateXCFramework/XcodeBuilder.swift b/Sources/CreateXCFramework/XcodeBuilder.swift index 2eba666..a414498 100644 --- a/Sources/CreateXCFramework/XcodeBuilder.swift +++ b/Sources/CreateXCFramework/XcodeBuilder.swift @@ -98,7 +98,6 @@ struct XcodeBuilder { "-project", self.path.pathString, "-configuration", self.options.configuration.xcodeConfigurationName, "-sdk", sdk.sdkName, - "BUILD_LIBRARY_FOR_DISTRIBUTION=YES", "BUILD_DIR=\(self.buildDirectory.path)" ]