PAYATHON 2026

能否在 Xcode 的 pre-action/build phase 中设置 build setting?

技术老齐

要为当前构建设置 COMPILATION_CACHE_REMOTE_SERVICE_PATH,应在 Xcode 读取构建配置之前生成路径,再通过 xcodebuild 参数或 .xcconfig 传入。在 scheme 的 pre-action 或 Run Script build phase 中执行 export,无法直接修改当前构建使用的这个值。

为什么 export 不生效

Xcode 会将 build settings 的值作为环境变量传给脚本。脚本中的 export 只影响当前 shell 及其子进程,无法反向修改父进程中的构建设置,也不会传给 Xcode 随后独立启动的编译任务。Apple 的构建系统文档说明,修改一个构建脚本中的环境变量,不会影响其他脚本。

这两个脚本位置各有限制:

  • Run Script build phase 执行时,构建系统已经读取了相关设置。即使把脚本移到 Compile Sources 前面,export 也无法写回 build settings。
  • pre-action 执行得更早,但仍在独立的脚本进程中运行,无法通过 export 修改 Xcode 的环境。“Provide build settings from” 只允许脚本读取所选 target 的设置,不支持反向写入。

shell 赋值时,= 两侧不能有空格。正确写法是:

export COMPILATION_CACHE_REMOTE_SERVICE_PATH="$(/usr/bin/my-tool connect)"

这段代码能将值传给脚本启动的子进程,但无法改变外层 Xcode 构建的设置。

使用 xcodebuild:先生成路径,再启动构建

如果每次构建都需要新路径,可以用包装脚本先获取路径,再启动构建:

#!/bin/sh
set -eu

socket_path="$(/usr/bin/my-tool connect)"

if [ -z "$socket_path" ]; then
    echo "error: my-tool returned an empty socket path" >&2
    exit 1
fi

exec xcodebuild \
    -project "MyApp.xcodeproj" \
    -scheme "MyApp" \
    -configuration Debug \
    "COMPILATION_CACHE_REMOTE_SERVICE_PATH=$socket_path" \
    build

将项目名和 scheme 名替换为实际值;使用 workspace 的项目则改用 -workspace。

通过 SETTING=value 显式传值,构建从开始时就能获得该设置。Apple 文档说明,通过 xcodebuild 命令行传入的 build settings 具有最高优先级。

命令行覆盖可能影响本次构建涉及的多个 target。如果只希望某个 target 使用该值,应在该 target 的配置中设置,避免使用统一的命令行覆盖。

在 Xcode 界面构建:提前生成 .xcconfig

如果要继续使用 Xcode 的 Build 按钮,可以在 Xcode 读取配置之前生成本地配置文件,例如 LocalCache.xcconfig:

COMPILATION_CACHE_REMOTE_SERVICE_PATH = /tmp/my-compilation-cache.sock

示例路径应替换为工具实际返回的值。

  1. 在外部准备脚本中运行 /usr/bin/my-tool connect,将返回路径写入 LocalCache.xcconfig。
  2. 在项目编辑器的 Info → Configurations 中,为目标 target 的相应配置关联该文件。
  3. 如果已经使用 .xcconfig,在原配置文件中引入它,保留现有配置:
#include "LocalCache.xcconfig"
  1. 检查 target 的 Build Settings,确认没有更高优先级的显式值覆盖该设置。

.xcconfig 支持设置赋值和文件包含,具体语法见 Apple 的配置文件格式说明。

不要在配置中直接写:

COMPILATION_CACHE_REMOTE_SERVICE_PATH = $(/usr/bin/my-tool connect)

.xcconfig 中的 $(...) 用于引用其他 build setting,不会执行 shell 命令。

在本次构建的 pre-action 中改写 .xcconfig,也不能保证本次构建会读取新值。结果取决于配置读取和缓存的时机,因此配置文件应在构建准备阶段之前生成。

希望每次按 Build 都自动连接怎么办

如果工具支持固定或可复用的 socket 路径,可以预先将路径配置到 target 中,让 pre-action 负责启动或连接服务。每次构建时只需保证服务可用,无须动态改写 build setting。

前提是工具确实支持稳定的监听路径。仅将 connect 输出的随机路径替换成固定字符串,不会让服务自动监听那个地址。

如果工具每次都必须生成不同路径,用包装脚本启动 xcodebuild 更容易保证执行顺序:先取得路径,再启动使用该路径的构建。

使用时还要检查什么

  • my-tool connect 的标准输出应只包含路径,诊断信息应写入标准错误,否则命令替换会把日志一起捕获。
  • 工具返回路径时,服务应已准备好接受连接,并在编译期间保持运行。路径存在不代表服务一定可用。
  • 生成 .xcconfig 时,需要处理配置文件语法中的特殊字符,不能直接套用 shell 的引号规则。
  • scheme 的 Run → Arguments → Environment Variables 配置用于应用运行时环境,不能替代编译阶段的 build settings。Apple 的相关说明也将其用途限定为应用运行时。
  • 这些方法解决的是值的传递问题。当前工具链是否采用 COMPILATION_CACHE_REMOTE_SERVICE_PATH,以及还需要哪些缓存配置,应以实际使用的 Xcode、编译器和缓存服务要求为准。

备注:内容仅供参考。