diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5508a4b..6bc4e55 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,34 +13,15 @@ on: - '**/*.swift' jobs: - tests-xcode-13_0: - name: Test Builds - Xcode 13.0 - runs-on: macos-11.0 - env: - DEVELOPER_DIR: /Applications/Xcode_13.0.app/Contents/Developer - - steps: - - name: 🛒 Checkout - uses: actions/checkout@v2 + tests-macos12: + name: Test Builds - macOS 12 + runs-on: macos-12 + strategy: + matrix: + xcode: [ "13.1", "13.2.1", "13.3.1", "13.4.1" ] - - name: 🧱 Build - run: make build-release - - - name: 🚩 Checkout Vexil - uses: actions/checkout@v2 - with: - repository: unsignedapps/Vexil - ref: v1.2.2 - path: Vexil - - - name: 📦 Package Vexil - run: cd Vexil && ../.build/release/swift-create-xcframework --zip --zip-version 1.2.2 --platform ios --platform macos --platform tvos --platform watchos - - tests-xcode-12_5: - name: Test Builds - Xcode 12.5 - runs-on: macos-11.0 env: - DEVELOPER_DIR: /Applications/Xcode_12.5.1.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer steps: - name: 🛒 Checkout @@ -59,57 +40,15 @@ jobs: - name: 📦 Package Vexil run: cd Vexil && ../.build/release/swift-create-xcframework --zip --zip-version 1.2.2 --platform ios --platform macos --platform tvos --platform watchos - tests-xcode-12_4: - name: Test Builds - Xcode 12.4 + tests-macos11: + name: Test Builds - macOS 11 runs-on: macos-11.0 - env: - DEVELOPER_DIR: /Applications/Xcode_12.4.app/Contents/Developer - - steps: - - name: 🛒 Checkout - uses: actions/checkout@v2 - - - name: 🧱 Build - run: make build-release - - - name: 🚩 Checkout Vexil - uses: actions/checkout@v2 - with: - repository: unsignedapps/Vexil - ref: v1.2.2 - path: Vexil - - - name: 📦 Package Vexil - run: cd Vexil && ../.build/release/swift-create-xcframework --zip --zip-version 1.2.2 --platform ios --platform macos --platform tvos --platform watchos - - tests-xcode-12_3: - name: Test Builds - Xcode 12.3 - runs-on: macos-10.15 - env: - DEVELOPER_DIR: /Applications/Xcode_12.3.app/Contents/Developer - - steps: - - name: 🛒 Checkout - uses: actions/checkout@v2 - - - name: 🧱 Build - run: make build-release - - - name: 🚩 Checkout Vexil - uses: actions/checkout@v2 - with: - repository: unsignedapps/Vexil - ref: v1.2.2 - path: Vexil - - - name: 📦 Package Vexil - run: cd Vexil && ../.build/release/swift-create-xcframework --zip --zip-version 1.2.2 --platform ios --platform macos --platform tvos --platform watchos + strategy: + matrix: + xcode: [ "12.4", "12.5.1", "13.0", "13.1", "13.2" ] - tests-xcode-12_2: - name: Test Builds - Xcode 12.2 - runs-on: macos-10.15 env: - DEVELOPER_DIR: /Applications/Xcode_12.2.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer steps: - name: 🛒 Checkout diff --git a/Package.resolved b/Package.resolved index 6e60d66..836a1b4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,17 @@ "repositoryURL": "https://github.com/apple/swift-argument-parser.git", "state": { "branch": null, - "revision": "83b23d940471b313427da226196661856f6ba3e0", - "version": "0.4.4" + "revision": "e394bf350e38cb100b6bc4172834770ede1b7232", + "version": "1.0.3" + } + }, + { + "package": "swift-collections", + "repositoryURL": "https://github.com/apple/swift-collections.git", + "state": { + "branch": null, + "revision": "48254824bb4248676bf7ce56014ff57b142b77eb", + "version": "1.0.2" } }, { @@ -15,16 +24,16 @@ "repositoryURL": "https://github.com/apple/swift-crypto.git", "state": { "branch": null, - "revision": "3bea268b223651c4ab7b7b9ad62ef9b2d4143eb6", - "version": "1.1.6" + "revision": "ddb07e896a2a8af79512543b1c7eb9797f8898a5", + "version": "1.1.7" } }, { "package": "swift-driver", "repositoryURL": "https://github.com/apple/swift-driver.git", "state": { - "branch": "release/5.5", - "revision": "ba0ab62cfc3999fb47fcfa33f046677008d9b145", + "branch": "release/5.7", + "revision": "3d1af45a920fb1a4c3a1a3ca416fdd49dc8d48b3", "version": null } }, @@ -32,8 +41,8 @@ "package": "llbuild", "repositoryURL": "https://github.com/apple/swift-llbuild.git", "state": { - "branch": "release/5.5", - "revision": "b5d9b4a9995c05688ae5f3b87a0d7ac0dc45c6c6", + "branch": "release/5.7", + "revision": "e2c27ee7ae7bd82ba35e97bac3c453faa582afd9", "version": null } }, @@ -41,17 +50,26 @@ "package": "SwiftPM", "repositoryURL": "https://github.com/apple/swift-package-manager.git", "state": { - "branch": "release/5.5", - "revision": "96c347b1419e513291f07c988f3e995363d400ed", + "branch": "release/5.7", + "revision": "9f3157bfb7d5dc06cac36b4c86e441136067b7ce", "version": null } }, + { + "package": "swift-system", + "repositoryURL": "https://github.com/apple/swift-system.git", + "state": { + "branch": null, + "revision": "836bc4557b74fe6d2660218d56e3ce96aff76574", + "version": "1.1.1" + } + }, { "package": "swift-tools-support-core", "repositoryURL": "https://github.com/apple/swift-tools-support-core.git", "state": { - "branch": "release/5.5", - "revision": "1b21e2ce36891ed4f458421a83b5d9e886acd4cd", + "branch": "release/5.7", + "revision": "184eba382f6abbb362ffc02942d790ff35019ad4", "version": null } }, diff --git a/Package.swift b/Package.swift index a1439af..3caea99 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,19 @@ import PackageDescription let dependencies: [Package.Dependency] -#if swift(>=5.5) +#if swift(>=5.7) +dependencies = [ + .package(url: "https://github.com/apple/swift-argument-parser.git", .exact("1.0.3")), + .package(name: "SwiftPM", url: "https://github.com/apple/swift-package-manager.git", .branch("release/5.7")), + .package(url: "https://github.com/apple/swift-tools-support-core.git", .branch("release/5.7")), +] +#elseif swift(>=5.6) +dependencies = [ + .package(url: "https://github.com/apple/swift-argument-parser.git", .exact("1.0.3")), + .package(name: "SwiftPM", url: "https://github.com/apple/swift-package-manager.git", .branch("release/5.6")), + .package(url: "https://github.com/apple/swift-tools-support-core.git", .exact("0.2.5")) +] +#elseif swift(>=5.5) dependencies = [ .package(url: "https://github.com/apple/swift-argument-parser.git", .exact("0.4.4")), .package(name: "SwiftPM", url: "https://github.com/apple/swift-package-manager.git", .branch("release/5.5")), @@ -18,13 +30,22 @@ dependencies = [ ] #endif +let platforms: [SupportedPlatform] +#if swift(>=5.6) +platforms = [ + .macOS(.v11), +] +#else +platforms = [ + .macOS(.v10_15), +] +#endif + let package = Package( name: "swift-create-xcframework", // TODO: Add Linux / Windows support - platforms: [ - .macOS(.v10_15), - ], + platforms: platforms, products: [ .executable(name: "swift-create-xcframework", targets: [ "CreateXCFramework" ]), diff --git a/README.md b/README.md index 51ce9da..29b998a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # swift-create-xcframework +>[!IMPORTANT] +>This project is **unmaintained**. It is recommended that you use a fork like [segment-integrations/swift-create-xcframework](https://github.com/segment-integrations/swift-create-xcframework) that includes support for Xcode 15. + swift-create-xcframework is a very simple tool designed to wrap `xcodebuild` and the process of creating multiple frameworks for a Swift Package and merging them into a single XCFramework. On the 23rd of June 2020, Apple announced Xcode 12 and Swift 5.3 with support for Binary Targets. Though they provide a simplified way to [include Binary Frameworks in your packages][apple-docs], they did not provide a simple way to create your XCFrameworks, with only some [documentation for the long manual process][manual-docs]. swift-create-xcframework bridges that gap. diff --git a/Sources/CreateXCFramework/Command+Options.swift b/Sources/CreateXCFramework/Command+Options.swift index 4cf1fc8..238e46c 100644 --- a/Sources/CreateXCFramework/Command+Options.swift +++ b/Sources/CreateXCFramework/Command+Options.swift @@ -37,6 +37,9 @@ extension Command { @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? + @Flag(help: "Enables Library Evolution for the whole build stack. Normally we apply it only to the targets listed to be built to work around issues with projects that don't support it.") + var stackEvolution: Bool = false + @Option(help: ArgumentHelp("Arbitrary Xcode build settings that are passed directly to the `xcodebuild` invocation. Can be specified multiple times.", valueName: "NAME=VALUE")) var xcSetting: [BuildSetting] = [] diff --git a/Sources/CreateXCFramework/Command.swift b/Sources/CreateXCFramework/Command.swift index 299f04e..2805632 100644 --- a/Sources/CreateXCFramework/Command.swift +++ b/Sources/CreateXCFramework/Command.swift @@ -23,11 +23,11 @@ struct Command: ParsableCommand { """ Note that Swift Binary Frameworks (XCFramework) support is only available in Swift 5.1 or newer, and so it is only supported by recent versions of Xcode and the *OS SDKs. Likewise, - only Apple pplatforms are supported. + only Apple platforms are supported. Supported platforms: \(TargetPlatform.allCases.map({ $0.rawValue }).joined(separator: ", ")) """, - version: "1.4.0" + version: "2.3.0" ) @@ -77,7 +77,9 @@ 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 - try project.enableDistribution(targets: productNames, xcconfig: AbsolutePath(package.distributionBuildXcconfig.path).relative(to: AbsolutePath(package.rootDirectory.path))) + if self.options.stackEvolution == false { + 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 1547e69..8366881 100644 --- a/Sources/CreateXCFramework/PackageInfo.swift +++ b/Sources/CreateXCFramework/PackageInfo.swift @@ -6,11 +6,20 @@ // import ArgumentParser +#if swift(>=5.6) +import Basics +#endif import Build import Foundation +#if swift(>=5.6) +import PackageGraph +#endif import PackageLoading import PackageModel import SPMBuildCore +#if swift(>=5.6) +import TSCBasic +#endif import Workspace import Xcodeproj @@ -27,6 +36,10 @@ struct PackageInfo { .absoluteURL } + var hasDistributionBuildXcconfig: Bool { + self.overridesXcconfig != nil || self.options.stackEvolution == false + } + var distributionBuildXcconfig: Foundation.URL { return self.projectBuildDirectory .appendingPathComponent("Distribution.xcconfig") @@ -49,19 +62,24 @@ struct PackageInfo { } // TODO: Map diagnostics to swift-log +#if swift(>=5.6) + let observabilitySystem = ObservabilitySystem { _, diagnostics in + print("\(diagnostics.severity): \(diagnostics.message)") + } +#else let diagnostics = DiagnosticsEngine() +#endif let options: Command.Options -// let package: Package let graph: PackageGraph let manifest: Manifest - let toolchain: Toolchain + let toolchain: UserToolchain let workspace: Workspace // MARK: - Initialisation - init (options: Command.Options) throws { + init (options: Command.Options) throws { // swiftlint:disable:this function_body_length self.options = options self.rootDirectory = Foundation.URL(fileURLWithPath: options.packagePath, isDirectory: true).absoluteURL self.buildDirectory = self.rootDirectory.appendingPathComponent(options.buildPath, isDirectory: true).absoluteURL @@ -70,6 +88,14 @@ struct PackageInfo { self.toolchain = try UserToolchain(destination: try .hostDestination()) + #if swift(>=5.7) + let loader = ManifestLoader(toolchain: self.toolchain) + self.workspace = try Workspace(forRootPackage: root, customManifestLoader: loader) + #elseif swift(>=5.6) + let resources = ToolchainConfiguration(swiftCompilerPath: self.toolchain.swiftCompilerPath) + let loader = ManifestLoader(toolchain: resources) + self.workspace = try Workspace(forRootPackage: root, customManifestLoader: loader) + #else #if swift(>=5.5) let resources = try UserManifestResources(swiftCompiler: self.toolchain.swiftCompiler, swiftCompilerFlags: []) #else @@ -77,8 +103,20 @@ struct PackageInfo { #endif let loader = ManifestLoader(manifestResources: resources) self.workspace = Workspace.create(forRootPackage: root, manifestLoader: loader) - - #if swift(>=5.5) + #endif + + #if swift(>=5.6) + self.graph = try workspace.loadPackageGraph(rootPath: root, observabilityScope: self.observabilitySystem.topScope) + let workspace = self.workspace + let scope = observabilitySystem.topScope + self.manifest = try tsc_await { + workspace.loadRootManifest( + at: root, + observabilityScope: scope, + completion: $0 + ) + } + #elseif swift(>=5.5) self.graph = try self.workspace.loadPackageGraph(rootPath: root, diagnostics: self.diagnostics) let swiftCompiler = toolchain.swiftCompiler self.manifest = try tsc_await { @@ -161,7 +199,7 @@ struct PackageInfo { Invalid product/target name(s): \(invalidProducts.joined(separator: "\n ")) - Available \(self.manifest.name) products: + Available \(self.manifest.displayName) products: \(allLibraryProductNames.sorted().joined(separator: "\n ")) Additional available targets: @@ -180,7 +218,7 @@ struct PackageInfo { print ( """ - \nAvailable \(self.manifest.name) products: + \nAvailable \(self.manifest.displayName) products: \(allLibraryProductNames.sorted().joined(separator: "\n ")) Additional available targets: @@ -232,7 +270,7 @@ enum SupportedPlatforms { case packageValid (plan: [SupportedPlatform]) } -extension SupportedPlatform: Equatable, Comparable { +extension SupportedPlatform: Comparable { public static func == (lhs: SupportedPlatform, rhs: SupportedPlatform) -> Bool { return lhs.platform == rhs.platform && lhs.version == rhs.version } @@ -276,3 +314,11 @@ enum PackageValidationError: LocalizedError { } } } + +#if swift(<5.6) +extension Manifest { + var displayName: String { + name + } +} +#endif diff --git a/Sources/CreateXCFramework/Platforms.swift b/Sources/CreateXCFramework/Platforms.swift index 31ed138..b4c1dd5 100644 --- a/Sources/CreateXCFramework/Platforms.swift +++ b/Sources/CreateXCFramework/Platforms.swift @@ -60,7 +60,7 @@ enum TargetPlatform: String, ExpressibleByArgument, CaseIterable { case .macos: return [ SDK ( - destination: "platform=macOS", + destination: "generic/platform=macOS,name=Any Mac", archiveName: "macos.xcarchive", releaseFolder: "Release", buildSettings: nil @@ -70,7 +70,7 @@ enum TargetPlatform: String, ExpressibleByArgument, CaseIterable { case .maccatalyst: return [ SDK ( - destination: "platform=macOS,variant=Mac Catalyst", + destination: "generic/platform=macOS,variant=Mac Catalyst", archiveName: "maccatalyst.xcarchive", releaseFolder: "Release-maccatalyst", buildSettings: [ "SUPPORTS_MACCATALYST": "YES" ] diff --git a/Sources/CreateXCFramework/ProjectGenerator.swift b/Sources/CreateXCFramework/ProjectGenerator.swift index e4b404e..3e7189c 100644 --- a/Sources/CreateXCFramework/ProjectGenerator.swift +++ b/Sources/CreateXCFramework/ProjectGenerator.swift @@ -23,7 +23,11 @@ struct ProjectGenerator { var projectPath: AbsolutePath { let dir = AbsolutePath(self.package.projectBuildDirectory.path) - return buildXcodeprojPath(outputDir: dir, projectName: self.package.manifest.name) + #if swift(>=5.7) + return XcodeProject.makePath(outputDir: dir, projectName: self.package.manifest.displayName) + #else + return buildXcodeprojPath(outputDir: dir, projectName: self.package.manifest.displayName) + #endif } @@ -38,6 +42,10 @@ struct ProjectGenerator { /// Writes out the Xcconfig file func writeDistributionXcconfig () throws { + guard self.package.hasDistributionBuildXcconfig else { + return + } + try makeDirectories(self.projectPath) let path = AbsolutePath(self.package.distributionBuildXcconfig.path) @@ -56,14 +64,6 @@ struct ProjectGenerator { BUILD_LIBRARY_FOR_DISTRIBUTION=YES """ ) - - if package.options.platform.contains(.maccatalyst) { - stream ( - """ - SUPPORTS_MACCATALYST=YES - """ - ) - } } } @@ -76,6 +76,20 @@ struct ProjectGenerator { try makeDirectories(path) // Generate the contents of project.xcodeproj (inside the .xcodeproj). +#if swift(>=5.6) + let project = try pbxproj ( + xcodeprojPath: path, + graph: self.package.graph, + extraDirs: [], + extraFiles: [], + options: XcodeprojOptions ( + xcconfigOverrides: (self.package.overridesXcconfig?.path).flatMap { AbsolutePath($0) }, + useLegacySchemeGenerator: true + ), + fileSystem: localFileSystem, + observabilityScope: self.package.observabilitySystem.topScope + ) +#else let project = try pbxproj ( xcodeprojPath: path, graph: self.package.graph, @@ -87,6 +101,7 @@ struct ProjectGenerator { ), diagnostics: self.package.diagnostics ) +#endif return project } @@ -126,7 +141,11 @@ extension Xcode.Project { try open(path.appending(component: "project.pbxproj")) { stream in // Serialize the project model we created to a plist, and return // its string description. +#if swift(>=5.6) + let str = try "// !$*UTF8*$!\n" + self.generatePlist().description +#else let str = "// !$*UTF8*$!\n" + self.generatePlist().description +#endif stream(str) } diff --git a/Sources/CreateXCFramework/XcodeBuilder.swift b/Sources/CreateXCFramework/XcodeBuilder.swift index 6f6180d..a48b1e9 100644 --- a/Sources/CreateXCFramework/XcodeBuilder.swift +++ b/Sources/CreateXCFramework/XcodeBuilder.swift @@ -122,8 +122,13 @@ struct XcodeBuilder { } } + // enable evolution for the whole stack + if self.options.stackEvolution { + command.append("BUILD_LIBRARY_FOR_DISTRIBUTION=YES") + } + // add build settings provided in the invocation - options.xcSetting.forEach { setting in + self.options.xcSetting.forEach { setting in command.append("\(setting.name)=\(setting.value)") } diff --git a/Sources/CreateXCFramework/Zipper.swift b/Sources/CreateXCFramework/Zipper.swift index 81fe0f9..676c593 100644 --- a/Sources/CreateXCFramework/Zipper.swift +++ b/Sources/CreateXCFramework/Zipper.swift @@ -5,7 +5,13 @@ // Created by Rob Amos on 13/5/20. // +#if canImport(Basics) +import Basics +#endif import Foundation +#if swift(>=5.6) +import PackageGraph +#endif import PackageModel import TSCBasic import Workspace @@ -51,7 +57,13 @@ struct Zipper { } func checksum (file: Foundation.URL) throws -> Foundation.URL { +#if swift(>=5.7) + let sum = try checksum(forBinaryArtifactAt: AbsolutePath(file.path)) +#elseif swift(>=5.6) + let sum = try self.package.workspace.checksum(forBinaryArtifactAt: AbsolutePath(file.path)) +#else let sum = self.package.workspace.checksum(forBinaryArtifactAt: AbsolutePath(file.path), diagnostics: self.package.diagnostics) +#endif let checksumFile = file.deletingPathExtension().appendingPathExtension("sha256") try Data(sum.utf8).write(to: checksumFile) return checksumFile @@ -73,13 +85,22 @@ struct Zipper { // find the package that contains our target guard let packageRef = self.package.graph.packages.first(where: { $0.targets.contains(where: { $0.name == target }) }) else { return nil } +#if swift(>=5.6) guard - let dependency = self.package.workspace.state.dependencies[forNameOrIdentity: packageRef.name], + let dependency = self.package.workspace.state.dependencies[packageRef.identity], + case let .custom(version, _) = dependency.state + else { + return fallback.flatMap { "-" + $0 } + } +#else + guard + let dependency = self.package.workspace.state.dependencies[forNameOrIdentity: packageRef.packageName], case let .checkout(checkout) = dependency.state, let version = checkout.version else { return fallback.flatMap { "-" + $0 } } +#endif return "-" + version.description } @@ -90,4 +111,42 @@ struct Zipper { func clean (file: Foundation.URL) throws { try FileManager.default.removeItem(at: file) } + + #if swift(>=5.7) + private func checksum(forBinaryArtifactAt path: AbsolutePath) throws -> String { + let fileSystem = localFileSystem + let checksumAlgorithm = SHA256() + let archiver = ZipArchiver(fileSystem: fileSystem) + + // Validate the path has a supported extension. + guard let pathExtension = path.extension, archiver.supportedExtensions.contains(pathExtension) else { + let supportedExtensionList = archiver.supportedExtensions.joined(separator: ", ") + throw StringError("unexpected file type; supported extensions are: \(supportedExtensionList)") + } + + // Ensure that the path with the accepted extension is a file. + guard fileSystem.isFile(path) else { + throw StringError("file not found at path: \(path.pathString)") + } + + let contents = try fileSystem.readFileContents(path) + return checksumAlgorithm.hash(contents).hexadecimalRepresentation + } + #endif +} + +#if swift(>=5.6) +// Intentionally left blank +#elseif swift(>=5.5) +private extension ResolvedPackage { + var packageName: String { + self.manifestName + } +} +#else +private extension ResolvedPackage { + var packageName: String { + self.name + } } +#endif diff --git a/action.js b/action.js index 6622593..a03bc3e 100644 --- a/action.js +++ b/action.js @@ -4,12 +4,12 @@ const path = require('path') const artifact = require('././.action/artifact') const fs = require('fs') -const scxVersion = '2.0.0' +const scxVersion = 'v2.3.0' const outputPath = '.build/xcframework-zipfile.url' core.setCommandEcho(true) -async function run () { +async function run() { try { let packagePath = core.getInput('path', { required: false }) let targets = core.getInput('target', { required: false }) @@ -24,7 +24,7 @@ async function run () { await installUsingMintIfRequired('swift-create-xcframework', 'unsignedapps/swift-create-xcframework') // put together our options - var options = [ '--zip', '--github-action' ] + var options = ['--zip', '--github-action'] if (!!packagePath) { options.push('--package-path') options.push(packagePath) @@ -60,7 +60,7 @@ async function run () { }) } - await exec.exec('swift-create-xcframework', options) + await runUsingMint('swift-create-xcframework', options) let client = artifact.create() let files = fs.readFileSync(outputPath, { encoding: 'utf8' }) @@ -70,7 +70,7 @@ async function run () { for (var i = 0, c = files.length; i < c; i++) { let file = files[i] let name = path.basename(file) - await client.uploadArtifact(name, [ file ], path.dirname(file)) + await client.uploadArtifact(name, [file], path.dirname(file)) } } catch (error) { @@ -78,28 +78,32 @@ async function run () { } } -async function installUsingBrewIfRequired (package) { +async function installUsingBrewIfRequired(package) { if (await isInstalled(package)) { core.info(package + " is already installed.") } else { core.info("Installing " + package) - await exec.exec('brew', [ 'install', package ]) + await exec.exec('brew', ['install', package]) } } -async function installUsingMintIfRequired (command, package) { +async function installUsingMintIfRequired(command, package) { if (await isInstalled(command)) { core.info(command + " is already installed") } else { core.info("Installing " + package) - await exec.exec('mint', [ 'install', 'unsignedapps/swift-create-xcframework@' + scxVersion ]) + await exec.exec('mint', ['install', 'unsignedapps/swift-create-xcframework@' + scxVersion]) } } -async function isInstalled (command) { - return await exec.exec('which', [ command ], { silent: true, failOnStdErr: false, ignoreReturnCode: true }) == 0 +async function isInstalled(command) { + return await exec.exec('which', [command], { silent: true, failOnStdErr: false, ignoreReturnCode: true }) == 0 +} + +async function runUsingMint(command, options) { + await exec.exec('mint', ['run', command, ...options]) } run()