哪些工具支持编辑 project.pbxproj 个文件?
What tools support editing project.pbxproj files?
我想使用命令行直接编辑 project.pbxproj
(针对 CI 服务器脚本)
什么工具可以让我做到这一点?
我曾经使用PlistBuddy
编辑输出Info.plist
;然而,我真正想做的是编辑这个用户定义的字段,它在多个地方使用,我真的不想在每个 plist 位置寻找它
我知道这个问题已经回答了一段时间,但由于最初的问题是关于支持操作 .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
class。
注意 我也探索了 XML 选项,但我发现 XML 格式的 project.pbxproj
文件解析起来很麻烦。元素没有正确嵌套以允许轻松遍历树。它受到以下问题的困扰:
<key>someKey</key>
<dict>
<!--More elements which provide configuration for the key above-->
</dict>
所以它本质上是位置性的。您必须查找与您要操作的设置相对应的 key
元素,然后跳转到它之后的 dict
元素。这意味着您必须将每个 XML 元素的子元素装入一个数组中,以便为它们建立索引。
project.pbxproj
也是一个 old-style ASCII property list 文件。所以你可以使用/usr/libexec/PlistBuddy
来编辑它。
像这样打印一些 User-Defined 键的值,
# 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
UPDATE:PlistBuddy
会自动将 project.pbxproj
转换为 xml-format plist 文件,因为 macOS Catalina 或更早版本。请考虑将设置项移动到 xcconfig
文件而不是 ,因为 xcconfig
比 project.pbxproj
更小更简单,并且在编辑时不容易出错使用 perl
脚本.
这里有 3 个 open-source 实现 .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
(针对 CI 服务器脚本)
什么工具可以让我做到这一点?
我曾经使用PlistBuddy
编辑输出Info.plist
;然而,我真正想做的是编辑这个用户定义的字段,它在多个地方使用,我真的不想在每个 plist 位置寻找它
我知道这个问题已经回答了一段时间,但由于最初的问题是关于支持操作 .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
class。
注意 我也探索了 XML 选项,但我发现 XML 格式的 project.pbxproj
文件解析起来很麻烦。元素没有正确嵌套以允许轻松遍历树。它受到以下问题的困扰:
<key>someKey</key>
<dict>
<!--More elements which provide configuration for the key above-->
</dict>
所以它本质上是位置性的。您必须查找与您要操作的设置相对应的 key
元素,然后跳转到它之后的 dict
元素。这意味着您必须将每个 XML 元素的子元素装入一个数组中,以便为它们建立索引。
project.pbxproj
也是一个 old-style ASCII property list 文件。所以你可以使用/usr/libexec/PlistBuddy
来编辑它。
像这样打印一些 User-Defined 键的值,
# 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
UPDATE:PlistBuddy
会自动将 project.pbxproj
转换为 xml-format plist 文件,因为 macOS Catalina 或更早版本。请考虑将设置项移动到 xcconfig
文件而不是 ,因为 xcconfig
比 project.pbxproj
更小更简单,并且在编辑时不容易出错使用 perl
脚本.
这里有 3 个 open-source 实现 .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"
},
...
}