哪些工具支持编辑 project.pbxproj 文件?
Posted
技术标签:
【中文标题】哪些工具支持编辑 project.pbxproj 文件?【英文标题】:What tools support editing project.pbxproj files? 【发布时间】:2015-08-21 06:16:53 【问题描述】:我想使用命令行直接编辑project.pbxproj
(用于 CI 服务器脚本)
什么工具可以让我做到这一点?
我以前用PlistBuddy
编辑输出Info.plist
;但是,我真正想做的是编辑这个用户定义的字段,它在多个地方使用,我真的不想在每个 plist 位置寻找它
【问题讨论】:
嗨。你能解释一下你想编辑.pbxproj
文件的内容吗?
用户定义字段
您可以尝试使用*.xcconfig
文件,加上user defined fields
可以从cmd 行重新定义。这是来自teamcity CI
的构建步骤:xcodebuild -project 'MyApp.xcodeproj' -scheme 'MyAppStaticTeamcity' -configuration 'Debug' -sdk 'iphoneos' GCC_PREPROCESSOR_DEFINITIONS='$GCC_PREPROCESSOR_DEFINITIONS NS_BLOCK_ASSERTIONS=1 MY_LOG_LEVEL=2' clean build
@Mozilla 实际上,我没有意识到您可以传入预处理器标志。如果我只想传入一个随机字段,这会直接起作用吗,比如"USER_DEFINED_VARIABLE=$hi"
??
也许你走错路了。如果您有一个经常更改的参数,在* .plist
中作为设置执行它会更容易。替换* .plist
中的值比编辑项目文件或传递用户定义字段容易得多(请参阅plistbuddy
)。在我的项目中,我将设置 server_address
放在 *.plist
中。
【参考方案1】:
project.pbxproj
也是一个old-style ASCII property list 文件。所以你可以使用/usr/libexec/PlistBuddy
来编辑它。
像这样打印一些用户定义键的值,
# Get the key A83311AA20DA4A80004B8C0E in your project.pbxproj
# LZD_NOTIFICATION_SERVICE_BUNDLE_ID is defined by me,
# Replace key paths with your own.
/usr/libexec/PlistBuddy -c 'print :objects:A83311AA20DA4A80004B8C0E:buildSettings:LZD_NOTIFICATION_SERVICE_BUNDLE_ID' LAAppAdapter.xcodeproj/project.pbxproj
这样设置它的值,
/usr/libexec/PlistBuddy -c 'set :objects:A83311AA20DA4A80004B8C0E:buildSettings:LZD_NOTIFICATION_SERVICE_BUNDLE_ID com.dawnsong.notification-service' LAAppAdapter.xcodeproj/project.pbxproj
更新:PlistBuddy
将自动将project.pbxproj
转换为 xml 格式的 plist 文件,因为 macOS Catalina 或更早版本。请考虑将设置项移到xcconfig
文件中,因为xcconfig
比project.pbxproj
更小更简单,使用perl
脚本编辑时不易出错。
【讨论】:
谢谢。很有帮助。这是 IMO 的正确答案。 用project.pbxproj
打印值似乎工作正常,但是当我使用set
命令时,整个project.pbxproj 被转换为XML .plist 文件,Xcode 无法再读取。
@sachadso 我认为PlistBuddy
的-x
选项成为默认选项。这是strange。
Apple Doc 说,“因为您不能以旧式 (OpenStep) 格式保存属性列表,所以此方法唯一有效的格式参数是 NSPropertyListXMLFormat_v1_0 和 NSPropertyListBinaryFormat_v1_0”。我认为它解释了为什么以及会发生什么
@sachadso 没有找到解决方案,所以我停止尝试弄乱 .pbxproj 文件。【参考方案2】:
我知道这个问题已经回答了一段时间,但由于最初的问题是关于支持操作 .pbxproj
文件的工具,而且许多其他人可能正在寻找相同的信息,所以我就是这样做的。我花了很长时间才弄清楚这一点,因为当我开始尝试这个时,我对 Xcode 非常不熟悉,所以我希望这可以为其他人节省我不得不投入的悲伤时间。
您可以使用plutil
命令将.pbxproj
文件从旧的.plist
格式转换为您可以更轻松地操作的XML 或JSON 格式。我正在使用 JSON。为此,只需运行:
plutil -convert json project.pbxproj
这将转换project.pbxproj
的格式,但请注意 - 与常识相反 - 输出不会是另一个具有 JSON 扩展名的文件,例如 project.json
。将会发生的事情是 project.pbxproj
将被转换为 JSON 格式,但保留它的神秘 .pbxproj
扩展名。因此,即使文件的格式已更改,Xcode 仍会拾取它并以新的 JSON 格式使用它。
然后,您可以使用您选择的任何 JSON 操作工具轻松更改 project.pbxproj
。我在 Groovy 脚本中使用了 Groovy 的 JsonSlurper
类。
注意 我也探索了 XML 选项,但我发现 XML 格式的 project.pbxproj
文件解析起来很麻烦。元素未正确嵌套以允许轻松遍历树。它的困扰:
<key>someKey</key>
<dict>
<!--More elements which provide configuration for the key above-->
</dict>
所以它本质上是位置性的。您必须查找与您要操作的设置相对应的key
元素,然后跳转到紧随其后的dict
元素。这意味着您必须将每个 XML 元素的子元素挂载到一个数组中,以便对它们进行索引。
【讨论】:
很好的解释。谢谢你分享这个。它为我节省了大量时间,也可能为其他许多人节省时间。 没问题@TheiosDev,你介意投票给我的答案吗?提前致谢。 将 pbxproj 文件转换为 JSON 对我不起作用。 Xcode 10 说文件已损坏,转换后无法打开。 @PaulSlocum 你试过升级plutil
命令吗?您可能正在使用旧的 plutil
版本,它无法处理由 Xcode 10+ 生成的 .pbxproj
格式,我使用的是 Brew。我刚试过brew outdated
,得到了这个libplist (1.12) < 2.0.0_1
。我查了一下,找到了here。遗憾的是,plutil
中没有-v
或--version
选项,但brew upgrade libplist
会为您提供最新版本或说Error: libplist 2.0.0_1 already installed
。
哇,我不知道 Xcode 可以支持这个。谢谢!【参考方案3】:
这里有 3 个实现 .pbxproj 文件编辑的开源工具:
https://github.com/CocoaPods/Xcodeproj(基于 Ruby) https://github.com/apache/cordova-node-xcode(基于 NodeJS) https://github.com/kronenthaler/mod-pbxproj(基于 Python)就个人而言,我使用基于 NodeJS 的工具获得了最好的体验。到目前为止,它已经可靠地满足了我们的所有需求。
下面列出了一个示例 javascript 文件 update-project.js
,它设置开发人员团队 ID、应用程序权利、将 GoogleService-Info.plist
文件添加到项目并将其作为构建目标的一部分进行检查。以此为灵感,根据您的需要调整脚本及其路径:
const fs = require('fs')
const xcode = require('xcode')
if (process.argv.length !== 3)
console.error("Please pass the development team ID as the first argument")
process.exit(1)
const developmentTeamId = process.argv[2]
const path = 'ios/App/App.xcodeproj/project.pbxproj'
const project = xcode.project(path)
project.parse(error =>
const targetKey = project.findTargetKey('App')
const appGroupKey = project.findPBXGroupKey(path: 'App')
project.addBuildProperty('CODE_SIGN_ENTITLEMENTS', 'App/App.entitlements')
project.addBuildProperty('DEVELOPMENT_TEAM', developmentTeamId)
project.addFile('App.entitlements', appGroupKey)
project.removeFile('GoogleService-Info.plist', appGroupKey)
const f = project.addFile('GoogleService-Info.plist', appGroupKey, target: targetKey)
f.uuid = project.generateUuid()
project.addToPbxBuildFileSection(f)
project.addToPbxResourcesBuildPhase(f)
fs.writeFileSync(path, project.writeSync())
)
上面的脚本可以用
执行yarn run update-project <arguments...>
假设update-project
注册在package.json
:
...,
"scripts":
...
"update-project": "node update-project.js"
,
...
【讨论】:
以上是关于哪些工具支持编辑 project.pbxproj 文件?的主要内容,如果未能解决你的问题,请参考以下文章
我应该忽略 xcodeproject/project.pbxproj 文件吗?
project.pbxproj 始终在 git 中标记为已修改
文件的 project.pbxproj 散列 - 使用啥散列以及如何使用?
升级本机反应时如何解决“project.pbxproj”文件中的冲突?