如何在Xcode中有条件地包含基于构建配置的文件?

时间:2022-09-11 16:30:59

I have an Xcode project with a large number of targets where I would like to include a settings bundle for apps built under the Ad-hoc and Debug configurations, but not under the Release configuration.

我有一个包含大量目标的Xcode项目,我想在其中包含在ad hoc和Debug配置下构建的应用程序的设置包,但不是在发布配置下。

Build Phases don't seem to allow for making themselves conditional on configuration (they can obviously be conditional on target, but doubling the number of targets in the project would make it completely unusable).

构建阶段似乎不允许将自己置于配置的条件下(它们显然可以基于目标,但项目中目标的数量增加一倍将使其完全不可用)。

That leaves writing a custom Build Rule. My plan is to exclude the Settings.bundle from all targets, and create a build rule that conditionally copies it into the product package, but applicable examples are really hard to find.

这就剩下编写自定义构建规则了。我的计划是排除设置。绑定所有目标,并创建一个构建规则,该规则有条件地将其复制到产品包中,但是很难找到适用的示例。

The build rule I've started has the Process setting set to "Source files with names matching:" and Settings.bundle as the name. The Using setting is "Custom script:".

我启动的构建规则将进程设置为“具有名称匹配的源文件:”和设置。包的名字。使用设置为“自定义脚本:”。

My custom script is as follows (with the caveat that my bash scripting is on a cargo cult level):

我的自定义脚本如下(请注意,我的bash脚本是在货物崇拜级别上的):

if [${CONFIGURATION} = 'Debug'] then
    cp -r ${INPUT_FILE_PATH} ${DERIVED_FILES_DIR}/.
fi

Finally, I have ${DERIVED_FILES_DIR}/Settings.bundle listed as an output file.

最后,我有$ { DERIVED_FILES_DIR } /设置。作为输出文件列出的包。

Since I'm here, it should be obvious that it's not working. My first question is whether there is somewhere I can view the output of the build rules as the execute to make sure that 1) it's actually being executed and that 2) I don't have a stupid syntax error somewhere.

既然我在这里,很明显它不工作了。我的第一个问题是,是否有什么地方可以把构建规则的输出看作是执行来确保1)它实际上正在被执行,而2)我在某个地方没有愚蠢的语法错误。

Also, what's the proper location (in the form of an environment variable) to copy the output to?

此外,将输出复制到的正确位置(以环境变量的形式)是什么?

6 个解决方案

#1


63  

I finally figured it out.

我终于想通了。

For each target for which you want to conditionally include the settings bundle, choose its Project from the source list, choose the target, and switch to the "Build Phases" tab.

对于需要有条件地包含settings bundle的每个目标,从源列表中选择其项目,选择目标,并切换到“构建阶段”选项卡。

Click the "Add Build Phase" button and choose "Add Run Script".

点击“添加构建阶段”按钮,选择“添加运行脚本”。

Then enter the following for the script:

然后输入以下脚本:

if [ "${CONFIGURATION}" == "Debug" ]; then
    cp -r "${PROJECT_DIR}/Settings.bundle" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app"
fi

#2


39  

I know this question has been answered already, and the answer was very helpful to me, but I wanted to throw my own modified solution out there as well.

我知道这个问题已经得到了回答,这个答案对我很有帮助,但我也想把我自己修改过的解决方案扔到外面去。

My requirement was to have different settings bundles for different build configurations, rather than just not including it at release. Assuming a simplistic approach of only Debug and Release configurations, here's how to do it:

我的要求是针对不同的构建配置拥有不同的设置包,而不是在发布时不包含它。假设一种简单的方法,只进行调试和发布配置,以下是如何做到的:

Start by adding 2 settings bundles to the project, named Settings-debug.bundle and Settings-release.bundle and then remove these files from the Copy Bundle Resources build phase. Next add a user defined build setting called SETTINGS_BUNDLE, which has different values for each configuration:

首先向项目添加两个设置包,命名为Settings-debug。包和Settings-release。捆绑,然后从复制捆绑资源构建阶段删除这些文件。接下来添加一个用户定义的构建设置SETTINGS_BUNDLE,每个配置都有不同的值:

Debug        ${PROJECT_DIR}/relative/path/to/Settings-debug.bundle
Release      ${PROJECT_DIR}/relative/path/to/Settings-release.bundle

Next add a run-script build phase (after Copy Bundle Resources) named Copy Settings Bundle with a modified version of the script in Frank's solution.

接下来,在Frank的解决方案中添加一个名为Copy Settings Bundle的运行脚本构建阶段(在Copy Bundle参考资料之后),该阶段使用修改后的脚本。

cp -r "${SETTINGS_BUNDLE}/" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle"

The difference here is that the copied bundle is always named Settings.bundle regardless of the source name.

这里的区别是复制的包总是命名为Settings。bundle,不管源名称。

You then need to add another build phase script to prevent code signing errors when the only changes are in the settings bundles. It forces the code signing step to occur on every build. This should run before the Compile Source Files build phase. I called mine Force Codesign.

然后,您需要添加另一个构建阶段脚本,以防止在设置包中只有更改时出现代码签名错误。它强制在每个构建上执行代码签名步骤。这应该在编译源文件构建阶段之前运行。我把我的部队叫做联合设计。

touch "${PROJECT_DIR}/relative/path/to/main.m"

#3


19  

For complied sources, there is a poorly documented user defined build setting that can be added. Files can be both excluded and included from compilation

对于已编译的源代码,可以添加一个文档较少的用户定义的构建设置。文件可以被排除在编译之外,也可以包含在编译中

Go to your target's Build Settings > Tap the + button > Add User-Defined Setting

进入目标的构建设置>点击+按钮>添加自定义设置

The key is either INCLUDED_SOURCE_FILE_NAMES or EXCLUDED_SOURCE_FILE_NAMES

密钥要么是INCLUDED_SOURCE_FILE_NAMES,要么是exclusive ded_source_file_names

The value is a space separated list of file paths

值是一个分隔的文件路径列表

See reference: http://lists.apple.com/archives/xcode-users/2009/Jun/msg00153.html

见参考:http://lists.apple.com/archives/xcode-users/2009/Jun/msg00153.html

#4


6  

Settings.bundle is always copied into destination area no matter whether Release or Debug configuration. So, maybe you need the following code:

设置。无论发布还是调试配置,bundle总是被复制到目标区域。所以,也许你需要以下代码:

if [ ${CONFIGURATION} == "Release" ]; then
    rm -rf ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle
fi

#5


3  

I am no shell script expert but I think you need space between the square brackets and the condition. Also, quoting the variables may help:

我不是shell脚本专家,但我认为您需要在方括号和条件之间留出空间。此外,引用变量可能会有帮助:

if [ "${CONFIGURATION}" = "Debug" ] then
    cp -r "${INPUT_FILE_PATH}" "${DERIVED_FILES_DIR}"/.
fi

As for the location, I use "$BUILT_PRODUCTS_DIR"/"$FULL_PRODUCT_NAME" for the root of my OS X app bundle.

至于位置,我使用“$BUILT_PRODUCTS_DIR”/“$FULL_PRODUCT_NAME”作为OS X应用程序包的根。

#6


1  

(Tested with Xcode 9.3)

(测试Xcode 9.3)

I can't find when Xcode included this feature but EXCLUDED_SOURCE_FILE_NAMES is now directly available in Build Settings > Build Options > Excluded Source File Names.

我找不到Xcode什么时候包含这个特性,但是现在在Build Settings > Build Options >中可以直接使用exclusive ded_source_file_name。

So you no longer need to create a User-Defined Setting.

因此,您不再需要创建用户定义的设置。

See below: 如何在Xcode中有条件地包含基于构建配置的文件?

见下文:

It will automatically add this line in your .pbxproj. 如何在Xcode中有条件地包含基于构建配置的文件?

它将自动在.pbxproj中添加这一行。

#1


63  

I finally figured it out.

我终于想通了。

For each target for which you want to conditionally include the settings bundle, choose its Project from the source list, choose the target, and switch to the "Build Phases" tab.

对于需要有条件地包含settings bundle的每个目标,从源列表中选择其项目,选择目标,并切换到“构建阶段”选项卡。

Click the "Add Build Phase" button and choose "Add Run Script".

点击“添加构建阶段”按钮,选择“添加运行脚本”。

Then enter the following for the script:

然后输入以下脚本:

if [ "${CONFIGURATION}" == "Debug" ]; then
    cp -r "${PROJECT_DIR}/Settings.bundle" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app"
fi

#2


39  

I know this question has been answered already, and the answer was very helpful to me, but I wanted to throw my own modified solution out there as well.

我知道这个问题已经得到了回答,这个答案对我很有帮助,但我也想把我自己修改过的解决方案扔到外面去。

My requirement was to have different settings bundles for different build configurations, rather than just not including it at release. Assuming a simplistic approach of only Debug and Release configurations, here's how to do it:

我的要求是针对不同的构建配置拥有不同的设置包,而不是在发布时不包含它。假设一种简单的方法,只进行调试和发布配置,以下是如何做到的:

Start by adding 2 settings bundles to the project, named Settings-debug.bundle and Settings-release.bundle and then remove these files from the Copy Bundle Resources build phase. Next add a user defined build setting called SETTINGS_BUNDLE, which has different values for each configuration:

首先向项目添加两个设置包,命名为Settings-debug。包和Settings-release。捆绑,然后从复制捆绑资源构建阶段删除这些文件。接下来添加一个用户定义的构建设置SETTINGS_BUNDLE,每个配置都有不同的值:

Debug        ${PROJECT_DIR}/relative/path/to/Settings-debug.bundle
Release      ${PROJECT_DIR}/relative/path/to/Settings-release.bundle

Next add a run-script build phase (after Copy Bundle Resources) named Copy Settings Bundle with a modified version of the script in Frank's solution.

接下来,在Frank的解决方案中添加一个名为Copy Settings Bundle的运行脚本构建阶段(在Copy Bundle参考资料之后),该阶段使用修改后的脚本。

cp -r "${SETTINGS_BUNDLE}/" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle"

The difference here is that the copied bundle is always named Settings.bundle regardless of the source name.

这里的区别是复制的包总是命名为Settings。bundle,不管源名称。

You then need to add another build phase script to prevent code signing errors when the only changes are in the settings bundles. It forces the code signing step to occur on every build. This should run before the Compile Source Files build phase. I called mine Force Codesign.

然后,您需要添加另一个构建阶段脚本,以防止在设置包中只有更改时出现代码签名错误。它强制在每个构建上执行代码签名步骤。这应该在编译源文件构建阶段之前运行。我把我的部队叫做联合设计。

touch "${PROJECT_DIR}/relative/path/to/main.m"

#3


19  

For complied sources, there is a poorly documented user defined build setting that can be added. Files can be both excluded and included from compilation

对于已编译的源代码,可以添加一个文档较少的用户定义的构建设置。文件可以被排除在编译之外,也可以包含在编译中

Go to your target's Build Settings > Tap the + button > Add User-Defined Setting

进入目标的构建设置>点击+按钮>添加自定义设置

The key is either INCLUDED_SOURCE_FILE_NAMES or EXCLUDED_SOURCE_FILE_NAMES

密钥要么是INCLUDED_SOURCE_FILE_NAMES,要么是exclusive ded_source_file_names

The value is a space separated list of file paths

值是一个分隔的文件路径列表

See reference: http://lists.apple.com/archives/xcode-users/2009/Jun/msg00153.html

见参考:http://lists.apple.com/archives/xcode-users/2009/Jun/msg00153.html

#4


6  

Settings.bundle is always copied into destination area no matter whether Release or Debug configuration. So, maybe you need the following code:

设置。无论发布还是调试配置,bundle总是被复制到目标区域。所以,也许你需要以下代码:

if [ ${CONFIGURATION} == "Release" ]; then
    rm -rf ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle
fi

#5


3  

I am no shell script expert but I think you need space between the square brackets and the condition. Also, quoting the variables may help:

我不是shell脚本专家,但我认为您需要在方括号和条件之间留出空间。此外,引用变量可能会有帮助:

if [ "${CONFIGURATION}" = "Debug" ] then
    cp -r "${INPUT_FILE_PATH}" "${DERIVED_FILES_DIR}"/.
fi

As for the location, I use "$BUILT_PRODUCTS_DIR"/"$FULL_PRODUCT_NAME" for the root of my OS X app bundle.

至于位置,我使用“$BUILT_PRODUCTS_DIR”/“$FULL_PRODUCT_NAME”作为OS X应用程序包的根。

#6


1  

(Tested with Xcode 9.3)

(测试Xcode 9.3)

I can't find when Xcode included this feature but EXCLUDED_SOURCE_FILE_NAMES is now directly available in Build Settings > Build Options > Excluded Source File Names.

我找不到Xcode什么时候包含这个特性,但是现在在Build Settings > Build Options >中可以直接使用exclusive ded_source_file_name。

So you no longer need to create a User-Defined Setting.

因此,您不再需要创建用户定义的设置。

See below: 如何在Xcode中有条件地包含基于构建配置的文件?

见下文:

It will automatically add this line in your .pbxproj. 如何在Xcode中有条件地包含基于构建配置的文件?

它将自动在.pbxproj中添加这一行。