Xcode Cloud运行Swift Package Plugin时出现写入权限错误
问题分析与解决方案
核心差异:Build Command vs Prebuild Command的沙箱权限
你遇到的权限问题,根源在于**.buildCommand和.prebuildCommand在Xcode Cloud环境中的沙箱权限限制不同**:
.prebuildCommand在项目整体构建流程的最早期执行,沙箱限制宽松,允许写入pluginWorkDirectory,这也是你的swiftgen插件能正常工作的原因。.buildCommand绑定到单个目标的构建阶段执行,Xcode Cloud对该阶段的文件系统访问权限有更严格的约束,即使是插件工作目录,也可能因执行时机的沙箱策略导致写入失败。
解决方案一:切换为Prebuild Command
直接将你的.buildCommand替换为.prebuildCommand,对齐swiftgen插件的执行时机,即可解决权限问题。同时需要完善输入文件的声明(Xcode Cloud沙箱要求明确列出所有需要读取的文件,而非仅文件夹):
struct Main: BuildToolPlugin { func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { let inputFolder = target.directory.appending("Image") let output = context.pluginWorkDirectory.appending("GeneratedImageAssets.swift") // 明确列出输入文件夹下的所有文件,满足Xcode Cloud沙箱的访问要求 let inputFiles = try FileManager.default.contentsOfDirectory(atPath: inputFolder.string) .map { inputFolder.appending($0) } return [ .prebuildCommand( displayName: "Running ImageAssets parser", executable: try context.tool(named: "ImageAssetsParser").path, arguments: [inputFolder.string, output.string], environment: [:], inputFiles: inputFiles, outputFiles: [output], // 可选:强制每次构建都执行,避免增量构建缓存导致的问题 alwaysOutOfDate: true ) ] } }
解决方案二:完善Build Command的输入文件声明(如果必须保留Build Command)
如果你的业务逻辑必须使用.buildCommand,需要确保所有被工具读取的文件都被显式声明为inputFiles,Xcode Cloud的沙箱不会允许工具访问未声明的文件,这种读取权限的限制可能会被误报为写入权限错误:
// 修改原代码中的inputFiles部分 inputFiles: try FileManager.default.contentsOfDirectory(atPath: inputFolder.string).map { inputFolder.appending($0) },
同时,确认你的ImageAssetsParser可执行目标在Package.swift中配置正常,没有额外的权限限制:
executableTarget( name: "ImageAssetsParser", dependencies: [] )
额外检查点
- 确认
GeneratedImageAssets.swift已被正确关联到目标的源文件中(可通过插件的outputFiles自动告知Xcode,无需手动添加)。 - 检查Xcode Cloud构建计划,确保未禁用插件执行的相关选项。
内容的提问来源于stack exchange,提问作者Rico Crescenzio
相关产品推荐
相关产品推荐

