如何在 Xcode 中根据构建配置有条件地包含文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8496476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 04:11:38  来源:igfitidea点击:

How can I conditionally include a file based on build configuration in Xcode?

xcodebuild-rules

提问by Frank Schmitt

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.

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

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:".

我开始的构建规则将 Process 设置设置为“名称匹配的源文件:”和 Settings.bundle 作为名称。使用设置是“自定义脚本:”。

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.bundlelisted as an output file.

最后,我将其${DERIVED_FILES_DIR}/Settings.bundle列为输出文件。

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?

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

回答by Frank Schmitt

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.

对于您想要有条件地包含设置包的每个目标,从源列表中选择其项目,选择目标,然后切换到“构建阶段”选项卡。

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

回答by Ell Neal

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 Debugand Releaseconfigurations, here's how to do it:

我的要求是为不同的构建配置提供不同的设置包,而不是在发布时不包含它。假设只有DebugRelease配置的简单方法,这里是如何做到的:

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

加入2个设置捆绑项目,命名为启动Settings-debug.bundleSettings-release.bundle然后从删除这些文件复制包资源构建阶段。接下来添加一个名为 的用户定义的构建设置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 Bundlewith a modified version of the script in Frank's solution.

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

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

The difference here is that the copied bundle is always named Settings.bundleregardless 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 beforethe Compile Source Filesbuild phase. I called mine Force Codesign.

然后,您需要添加另一个构建阶段脚本,以防止在设置包中发生唯一更改时出现代码签名错误。它强制在每次构建时执行代码签名步骤。这应该运行之前编译源文件生成阶段。我叫我的Force Codesign

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

回答by Kyle Redfearn

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_NAMESor EXCLUDED_SOURCE_FILE_NAMES

关键是无论是INCLUDED_SOURCE_FILE_NAMESEXCLUDED_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

回答by Toldy

(Tested with Xcode 9.3)

(使用Xcode 9.3测试)

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

我找不到 Xcode 何时包含此功能,但EXCLUDED_SOURCE_FILE_NAMES现在可以直接在Build Settings > Build Options > Excluded Source File Names.

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

所以你不再需要创建一个User-Defined Setting.

See below: enter image description here

见下文: 在此处输入图片说明

It will automatically add this line in your .pbxproj. enter image description here

它会自动在您的.pbxproj. 在此处输入图片说明

回答by Allen

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

无论是 Release 还是 Debug 配置,Settings.bundle 总是被复制到目标区域。所以,也许你需要以下代码:

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

回答by Stephen Chu

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 应用程序包的根目录。