From 430934ab250564ae7fa42f89ec766bb2c5ba8dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?furby=E2=84=A2?= Date: Fri, 29 Nov 2024 21:33:45 -0700 Subject: [PATCH] Add reusable logic for checking whether in xcodebuild context. * Restores the async bundle command to be immutable again, instead of mutable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: furby™ --- .../swift-bundler/Bundler/DarwinBundler.swift | 7 +++++- .../XcodeBuildManager/XcodeBuildManager.swift | 17 +++++++++++++ .../swift-bundler/Commands/AsyncCommand.swift | 4 ++-- .../Commands/BundleCommand.swift | 24 ++++++------------- .../swift-bundler/Commands/RunCommand.swift | 2 +- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/Sources/swift-bundler/Bundler/DarwinBundler.swift b/Sources/swift-bundler/Bundler/DarwinBundler.swift index ad1dfd82..eb55d8f4 100644 --- a/Sources/swift-bundler/Bundler/DarwinBundler.swift +++ b/Sources/swift-bundler/Bundler/DarwinBundler.swift @@ -53,10 +53,15 @@ enum DarwinBundler: Bundler { return .failure(.missingDarwinPlatformVersion(context.platform)) } + // Whether a universal application binary (arm64 and x86_64) will be created. let universal = command.arguments.universal || command.arguments.architectures.count > 1 + + // Whether or not we are building with xcodebuild instead of swiftpm. + let isUsingXcodeBuild = XcodeBuildManager.isUsingXcodeBuild(for: command) + return .success( Context( - isXcodeBuild: command.builtWithXcode, + isXcodeBuild: command.builtWithXcode || isUsingXcodeBuild, universal: universal, standAlone: command.arguments.standAlone, platform: applePlatform, diff --git a/Sources/swift-bundler/Bundler/XcodeBuildManager/XcodeBuildManager.swift b/Sources/swift-bundler/Bundler/XcodeBuildManager/XcodeBuildManager.swift index 257e560d..12c8c222 100644 --- a/Sources/swift-bundler/Bundler/XcodeBuildManager/XcodeBuildManager.swift +++ b/Sources/swift-bundler/Bundler/XcodeBuildManager/XcodeBuildManager.swift @@ -149,4 +149,21 @@ enum XcodeBuildManager { ) } } + + /// Whether or not the bundle command utilizes xcodebuild instead of swiftpm. + /// - Parameters: + /// - command: The subcommand for creating app bundles for a package. + /// - Returns: Whether or not xcodebuild is invoked instead of swiftpm. + static func isUsingXcodeBuild(for command: BundleCommand) -> Bool { + var forceUsingXcodeBuild = command.arguments.xcodebuild + // For all apple platforms (not including macOS), we generate xcode + // support, because macOS cannot cross-compile for any of the other + // darwin platforms like it can with linux, and thus we need to use + // xcodebuild to build for these platforms (ex. visionOS, iOS, etc) + if forceUsingXcodeBuild || ![Platform.linux, Platform.macOS].contains(command.arguments.platform) { + forceUsingXcodeBuild = true + } + + return command.arguments.noXcodebuild ? !command.arguments.noXcodebuild : forceUsingXcodeBuild + } } diff --git a/Sources/swift-bundler/Commands/AsyncCommand.swift b/Sources/swift-bundler/Commands/AsyncCommand.swift index 654bf949..d447bc9e 100644 --- a/Sources/swift-bundler/Commands/AsyncCommand.swift +++ b/Sources/swift-bundler/Commands/AsyncCommand.swift @@ -7,7 +7,7 @@ protocol AsyncCommand: AsyncParsableCommand { func wrappedValidate() throws /// Implement this instead of `run()` to get custom Swift Bundler error handling. - mutating func wrappedRun() async throws + func wrappedRun() async throws } extension AsyncCommand { @@ -15,7 +15,7 @@ extension AsyncCommand { } extension AsyncCommand { - mutating func run() async { + func run() async { do { try await wrappedRun() } catch { diff --git a/Sources/swift-bundler/Commands/BundleCommand.swift b/Sources/swift-bundler/Commands/BundleCommand.swift index 8b90702b..337cf531 100644 --- a/Sources/swift-bundler/Commands/BundleCommand.swift +++ b/Sources/swift-bundler/Commands/BundleCommand.swift @@ -187,7 +187,7 @@ struct BundleCommand: AsyncCommand { return architectures } - mutating func wrappedRun() async throws { + func wrappedRun() async throws { _ = try await doBundling() } @@ -196,7 +196,7 @@ struct BundleCommand: AsyncCommand { /// `RunCommand` to figure out where the output bundle will end up even /// when the user instructs it to skip bundling. /// - Returns: A description of the structure of the bundler's output. - mutating func doBundling(dryRun: Bool = false) async throws -> BundlerOutputStructure { + func doBundling(dryRun: Bool = false) async throws -> BundlerOutputStructure { // Time execution so that we can report it to the user. let (elapsed, bundlerOutputStructure) = try await Stopwatch.time { // Load configuration @@ -220,20 +220,10 @@ struct BundleCommand: AsyncCommand { // Get relevant configuration let architectures = getArchitectures(platform: arguments.platform) - var forceUsingXcodeBuild = arguments.xcodebuild - // For all apple platforms (not including macOS), we generate xcode - // support, because macOS cannot cross-compile for any of the other - // darwin platforms like it can with linux, and thus we need to use - // xcodebuild to build for these platforms (ex. visionOS, iOS, etc) - if forceUsingXcodeBuild || ![Platform.linux, Platform.macOS].contains(arguments.platform) { - forceUsingXcodeBuild = true - } - forceUsingXcodeBuild = arguments.noXcodebuild ? !arguments.noXcodebuild : forceUsingXcodeBuild - - if forceUsingXcodeBuild { - // If building with xcodebuild, be sure to set that here. - self.builtWithXcode = true + // Whether or not we are building with xcodebuild instead of swiftpm. + let isUsingXcodeBuild = XcodeBuildManager.isUsingXcodeBuild(for: self) + if isUsingXcodeBuild { // Terminate the program if the project is an Xcodeproj based project. let xcodeprojs = try FileManager.default.contentsOfDirectory( at: packageDirectory, @@ -276,7 +266,7 @@ struct BundleCommand: AsyncCommand { // Get build output directory let productsDirectory: URL - if !forceUsingXcodeBuild { + if !isUsingXcodeBuild { productsDirectory = try arguments.productsDirectory ?? SwiftPackageManager.getProductsDirectory(buildContext).unwrap() } else { @@ -303,7 +293,7 @@ struct BundleCommand: AsyncCommand { // Create build job let build: () -> Result = { - if forceUsingXcodeBuild { + if isUsingXcodeBuild { XcodeBuildManager.build( product: appConfiguration.product, buildContext: buildContext diff --git a/Sources/swift-bundler/Commands/RunCommand.swift b/Sources/swift-bundler/Commands/RunCommand.swift index 50d7a5ec..f6fceac9 100644 --- a/Sources/swift-bundler/Commands/RunCommand.swift +++ b/Sources/swift-bundler/Commands/RunCommand.swift @@ -89,7 +89,7 @@ struct RunCommand: AsyncCommand { simulatorSearchTerm: simulatorSearchTerm ) - var bundleCommand = BundleCommand( + let bundleCommand = BundleCommand( arguments: _arguments, skipBuild: false, builtWithXcode: false,