首页 > 解决方案 > 如何在 Swift 包管理器构建中运行脚本?

问题描述

我正在使用 Swift Package Manager (SPM) 将现有的 iOS 框架转换为模块;在一种情况下,我有一个位于原始框架版本的构建阶段的脚本,我需要在新的 Swift 包管理器构建过程中运行该脚本。

我已尝试将 Pre-action 脚本添加到相关模块的方案的构建部分(根据 Ben-xD 在https://forums.swift.org/t/how-to-run-a-build-的评论phase-script-when-building-a-standalone-swift-package-in-xcode/40117/8,尽管他后来的评论表明它不起作用)。我发现如果我直接构建模块,这种方法确实有效。但是,如果将模块构建为客户端应用程序或模块的依赖项(甚至作为其单元测试的依赖项),则该脚本似乎不会被调用。

我目前依靠 Package.swift 清单文件来管理所有模块设置,并在 Xcode 中使用它来构建和测试。

有没有办法将脚本作为 SPM 模块构建的一部分运行,以便它们能够可靠地运行,无论模块是直接构建还是作为依赖项间接构建?(可能可以添加到 Package.swift 文件中的东西?)

更新:我做了一些额外的搜索,发现了这个: https ://forums.swift.org/t/pitch-swiftpm-extensible-build-tools/44715/5 暗示这是不可能的,但可能在未来。在那之前,想知道是否有任何解决方法可以做一些简单的事情,比如获取一个作为 SPM 构建的一部分自动生成的文件,但在将其添加到包的资源包之前重命名它。

标签: iosswift-package-manager

解决方案


您可能想要尝试的是通过命令行执行您的脚本。此代码段可能对您有用:

import Foundation

extension Process {
    public func shell(command: String) -> String {
        launchPath = "/bin/bash"
        arguments = ["-c", command]
        
        let outputPipe = Pipe()
        standardOutput = outputPipe
        launch()
        
        let data = outputPipe.fileHandleForReading.readDataToEndOfFile()
        guard let outputData = String(data: data, encoding: String.Encoding.utf8) else { return "" }
        
        return outputData.characters.reduce("") { (result, value) in
            return result + String(value)
        }
    }
}


public func launch(command: String, arguments: [String]) -> String {
    let process = Process()
    let command = "\(command) \(arguments.joined(separator: " "))"
    return process.shell(command: command)
}

推荐阅读