limrun-xcode

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Remote Xcode build

远程Xcode构建

Build Apple projects on Limrun's remote Xcode, from any environment (Linux, Windows, macOS, VM, container).
lim xcode build
syncs your sources to a remote Xcode instance, builds there, and (when a simulator is attached) installs and relaunches the app. Never fall back to local Xcode, local simulators, or local build tools. Your job doesn't end at a green build: get the app running, verify it works, and iterate until the user is satisfied.
For driving the app once it's running (tap, type, element tree, screenshot, record), use the
limrun-ios-simulator
skill. For Bazel workspaces, use
limrun-xcode-bazel
instead of this skill.
在Limrun的远程Xcode环境中构建Apple项目,支持在任意环境(Linux、Windows、macOS、虚拟机、容器)中操作。
lim xcode build
会将你的源码同步到远程Xcode实例,在远程完成构建,并且(当连接模拟器时)自动安装并重启应用。无需依赖本地Xcode、本地模拟器或本地构建工具。你的工作不止于构建成功:要确保应用正常运行、验证功能可用,并持续迭代直到用户满意。
如需在应用运行后进行交互操作(点击、输入、查看元素树、截图、录屏),请使用**
limrun-ios-simulator
技能。针对Bazel工作区,请使用
limrun-xcode-bazel
**替代本技能。

Auth and CLI

认证与CLI

Install if needed:
npm install --global lim
. Auth is
lim login
or
LIM_API_KEY
(it may be set outside the project, so don't ask for it just because it's missing from
.env
or the shell). The CLI is the source of truth: the commands in this skill are verified, but if a flag errors or you need one not shown here, check
--help
instead of guessing:
bash
lim xcode --help
lim xcode build --help
如需安装请执行:
npm install --global lim
。认证方式为
lim login
或设置
LIM_API_KEY
(该密钥可能在项目外部配置,因此不要仅因
.env
或Shell中未设置就向用户索要)。CLI是权威参考:本技能中的命令均已验证,但如果某个参数报错或你需要此处未展示的参数,请查看
--help
而非自行猜测:
bash
lim xcode --help
lim xcode build --help

Build

构建

Instead of
xcodebuild
, build with:
bash
lim xcode build .
This creates or reuses the remembered Xcode target, syncs the current directory, and streams the build logs through stdout and stderr.
Use
--scheme
and
--workspace
if the project has multiple schemes or uses a workspace file:
bash
lim xcode build . --scheme MyApp --workspace MyApp.xcworkspace
Use
--configuration Debug
or
--configuration Release
for a specific Xcode configuration. If omitted, Limrun uses limbuild's project-type default:
Debug
for native Xcode builds,
Release
for React Native / Expo builds.
bash
lim xcode build . --configuration Debug
--dev-server-url
is only supported with
--configuration Debug
for React Native / Expo builds. It's a post-install launch URL: limbuild validates it is a parseable absolute URL, then opens it unchanged after installing on the attached simulator. Framework-specific skills construct the correct URL.
bash
lim xcode build . --configuration Debug --dev-server-url '<absolute-url>'
If the app launches without using the expected URL, open it explicitly to separate build/install issues from URL routing:
bash
lim ios open-url --id <ios-instance-id> '<absolute-url>'
替代
xcodebuild
,使用以下命令构建:
bash
lim xcode build .
该命令会创建或复用已保存的Xcode目标,同步当前目录内容,并通过stdout和stderr流式输出构建日志。
如果项目包含多个scheme或使用workspace文件,请使用
--scheme
--workspace
参数:
bash
lim xcode build . --scheme MyApp --workspace MyApp.xcworkspace
使用
--configuration Debug
--configuration Release
指定Xcode构建配置。若省略该参数,Limrun会使用limbuild的项目类型默认值:原生Xcode构建使用
Debug
,React Native/Expo构建使用
Release
bash
lim xcode build . --configuration Debug
--dev-server-url
仅在React Native/Expo构建搭配
--configuration Debug
时支持。它是安装后的启动URL:limbuild会验证其为可解析的绝对URL,随后在连接的模拟器上安装应用后直接打开该URL。框架专属技能会自动构造正确的URL。
bash
lim xcode build . --configuration Debug --dev-server-url '<absolute-url>'
如果应用未通过预期URL启动,请显式打开该URL,以区分构建/安装问题与URL路由问题:
bash
lim ios open-url --id <ios-instance-id> '<absolute-url>'

Generated Xcode projects (XcodeGen)

生成的Xcode项目(XcodeGen)

If the repo has a
project.yml
and the
.xcodeproj
is gitignored, do not run xcodegen locally and do not treat the missing project as an error. The remote sandbox generates the project from
project.yml
before building:
bash
lim xcode build .
The spec is found at the repo root or one directory down (like
ios/
), no flags needed. The project regenerates on every build, so
project.yml
edits take effect by just rebuilding. A committed or force-synced
.xcodeproj
always wins: the sandbox only generates when the sync didn't supply one.
If the repo's codegen produces gitignored inputs the build needs (a generated local Swift package, config-derived sources), run that step locally first and force-sync its output with
--include
:
bash
make generate   # or whatever the repo's codegen step is
lim xcode build . --include '^ios/GeneratedKit/'
--include
takes a regular expression like
--ignore
, not gitignore syntax. To reach files under a directory that is ignored as a whole, the pattern must also match the directory path itself, as above.
如果仓库包含
project.yml
.xcodeproj
被git忽略,请勿在本地运行xcodegen,也不要将缺失的项目视为错误。远程沙箱会在构建前从
project.yml
生成项目:
bash
lim xcode build .
配置文件会在仓库根目录或子目录(如
ios/
)中自动识别,无需额外参数。每次构建都会重新生成项目,因此修改
project.yml
后只需重新构建即可生效。如果同步时提供了已提交或强制同步的
.xcodeproj
,则优先使用该文件:仅当同步未提供项目文件时,沙箱才会生成项目。
如果仓库的代码生成步骤会生成构建所需的git忽略文件(如生成的本地Swift包、基于配置的源码),请先在本地执行该步骤,再使用
--include
强制同步输出文件:
bash
make generate   # 或仓库指定的代码生成步骤
lim xcode build . --include '^ios/GeneratedKit/'
--include
接受正则表达式(类似
--ignore
),而非gitignore语法。要同步被整体忽略的目录下的文件,模式必须同时匹配目录路径本身,如上例所示。

Run on a simulator

在模拟器上运行

lim xcode build
is build-and-install. Don't attach a simulator until the user needs to see or interact with the app. Check / attach:
bash
lim xcode get             # is a simulator already attached?
lim ios create --attach   # attach one (installs the last build immediately)
If the attach output includes a signed stream URL, share it with the user as a Markdown link, such as Live simulator.
When a simulator is attached, every successful
lim xcode build
automatically reinstalls and relaunches the app, no separate install step. To tap, type, read the element tree, screenshot, or record, switch to
limrun-ios-simulator
.
lim xcode build
兼具构建与安装功能。仅当用户需要查看或交互应用时再连接模拟器。检查/连接模拟器:
bash
lim xcode get             # 是否已连接模拟器?
lim ios create --attach   # 连接模拟器(立即安装上次构建的应用)
如果连接输出包含签名流URL,请将其作为Markdown链接分享给用户,例如:实时模拟器
当模拟器已连接时,每次成功执行
lim xcode build
都会自动重新安装并重启应用,无需单独执行安装步骤。如需点击、输入、查看元素树、截图或录屏,请切换至**
limrun-ios-simulator
**技能。

Signed device builds (IPA)

签名设备构建包(IPA)

To produce a signed IPA for real devices, build with
--sdk iphoneos
, pass the signing material, and upload the result to Asset Storage:
bash
lim xcode build . --sdk iphoneos --configuration Release \
  --certificate-p12 dist.p12 --certificate-password "$P12_PASSWORD" \
  --provisioning-profile app.mobileprovision \
  --upload myapp.ipa
The upload output includes a download URL for the signed IPA. A SUCCEEDED build means the signature already passed Apple's verifier on the server, so don't re-verify the IPA yourself unless the user asks. Invalid signing fails the build loudly instead of producing a broken artifact.
Use a p12 that includes its full CA chain, not just the leaf certificate. If needed, re-export it with the chain:
bash
openssl pkcs12 -export -inkey dist.key -in dist.pem -certfile wwdr.pem -out dist-chain.p12
Failure strings to recognize in the build output:
  • Unknown issuer hash
    : the p12 lacks its CA chain; re-export it with the chain as above.
  • code signature verification failed
    : the platform's post-sign check rejected the artifact. Not a problem in the user's code; retry, and report it if it persists.
  • p12 password errors:
    --certificate-password
    doesn't match the file; ask the user for the right password.
要生成用于真实设备的签名IPA,请使用
--sdk iphoneos
构建,传入签名材料,并将结果上传至资产存储:
bash
lim xcode build . --sdk iphoneos --configuration Release \
  --certificate-p12 dist.p12 --certificate-password "$P12_PASSWORD" \
  --provisioning-profile app.mobileprovision \
  --upload myapp.ipa
上传输出包含签名IPA的下载链接。构建成功意味着签名已通过服务器上Apple的验证,因此除非用户要求,否则无需自行重新验证IPA。无效签名会直接导致构建失败,不会生成损坏的产物。
请使用包含完整CA链的p12证书,而非仅叶子证书。如有需要,请重新导出包含CA链的证书:
bash
openssl pkcs12 -export -inkey dist.key -in dist.pem -certfile wwdr.pem -out dist-chain.p12
构建输出中需要识别的失败信息:
  • Unknown issuer hash
    :p12证书缺少CA链,请按照上述步骤重新导出包含CA链的证书。
  • code signature verification failed
    :平台签名后检查拒绝了产物。这不是用户代码的问题,请重试,若问题持续则上报。
  • p12密码错误:
    --certificate-password
    与文件不匹配,请向用户索要正确密码。

Ship to TestFlight

发布至TestFlight

To upload the signed IPA straight to TestFlight, pass
--upload-to-testflight
with the App Store Connect API key flags on a signed device build:
bash
lim xcode build . --sdk iphoneos --configuration Release \
  --certificate-p12 dist.p12 --certificate-password "$P12_PASSWORD" \
  --provisioning-profile app.mobileprovision \
  --upload-to-testflight --asc-key-id "$ASC_KEY_ID" --asc-issuer-id "$ASC_ISSUER_ID" \
  --asc-key AuthKey.p8
--upload-to-testflight
requires the signing flags,
--asc-key-id
, and
--asc-key
; passing asc flags without it is an error. Combine with
--upload <asset-name>
when the user also wants the IPA in Asset Storage.
Collect from the user (all three live in App Store Connect under Users and Access, Integrations tab, App Store Connect API):
  • --asc-key-id
    : the Key ID next to their API key. If they don't have one, point them at Team Keys with the Developer role: the least-privileged role that can upload builds. Creating team keys needs an Admin account.
  • --asc-issuer-id
    : the Issuer ID at the TOP of the Integrations page (a team value, not per-key). Omit this flag entirely for individual API keys.
  • --asc-key
    : path to the downloaded
    .p8
    file. Apple keeps no copy and the download link disappears after leaving the page; if the user lost it, they must generate a new key. Never commit the
    .p8
    or paste its content into files; pass a filesystem path.
After the upload, the build watches Apple's processing verdict for up to 120 seconds (
--asc-wait-timeout
, 0 skips, max 1800). Read the outcome from the final lines:
  • TestFlight: accepted by App Store Connect
    : done; the build appears in TestFlight once Apple finishes.
  • TestFlight: uploaded, still processing on Apple's side (upload <id>).
    : the exit code is 0 and the upload succeeded; Apple is still processing. Do NOT retry the build.
  • TestFlight upload failed: ...
    : exit code 1 with Apple's error text. The compile and signing succeeded; only the delivery failed.
Failure strings to recognize:
  • Apple text about the bundle version being already used: bump
    CFBundleVersion
    (Expo:
    expo.ios.buildNumber
    in app.json) and rebuild.
  • HTTP 401
    : key ID / issuer ID / .p8 mismatch, or a revoked key.
  • HTTP 403
    : the key's role cannot upload builds; it needs the Developer role or higher.
  • no App Store Connect app with bundle id
    : the app record doesn't exist; the user must create it in App Store Connect manually (the API cannot).
  • Build later stuck at "Missing Compliance" in TestFlight: the app doesn't answer the export-compliance question at build time. Set
    ITSAppUsesNonExemptEncryption
    to
    NO
    in Info.plist (Expo:
    expo.ios.config.usesNonExemptEncryption: false
    in app.json) and rebuild.
For hands-off delivery to testers, the app's internal TestFlight group must have automatic distribution enabled (create-only setting) and the compliance key above must be set; then no post-upload steps exist at all.
要将签名IPA直接上传至TestFlight,请在签名设备构建命令中添加
--upload-to-testflight
参数及App Store Connect API密钥相关参数:
bash
lim xcode build . --sdk iphoneos --configuration Release \
  --certificate-p12 dist.p12 --certificate-password "$P12_PASSWORD" \
  --provisioning-profile app.mobileprovision \
  --upload-to-testflight --asc-key-id "$ASC_KEY_ID" --asc-issuer-id "$ASC_ISSUER_ID" \
  --asc-key AuthKey.p8
--upload-to-testflight
需要签名参数、
--asc-key-id
--asc-key
;仅传入ASC参数但未指定该参数会报错。如果用户同时希望将IPA保存至资产存储,可以搭配
--upload <asset-name>
使用。
需向用户收集以下信息(全部可在App Store Connect的「用户与访问」-「集成」标签页的「App Store Connect API」中找到):
  • --asc-key-id
    :API密钥旁的密钥ID。如果用户没有密钥,请引导他们创建具有开发者角色的团队密钥:这是可上传构建包的最低权限角色。创建团队密钥需要管理员账号。
  • --asc-issuer-id
    :集成页面顶部的发行者ID(团队级别的值,而非每个密钥单独的ID)。对于个人API密钥,请完全省略该参数。
  • --asc-key
    :下载的
    .p8
    文件路径。Apple不会保留副本,离开页面后下载链接会消失;如果用户丢失了文件,必须重新生成密钥。请勿提交
    .p8
    文件或将其内容粘贴到其他文件中,请传入文件系统路径。
上传完成后,构建会等待Apple的处理结果最多120秒(可通过
--asc-wait-timeout
设置,0表示跳过,最大为1800)。最终结果可从最后几行输出中查看:
  • TestFlight: accepted by App Store Connect
    :完成;Apple处理完成后,构建包会出现在TestFlight中。
  • TestFlight: uploaded, still processing on Apple's side (upload <id>).
    :退出码为0,上传成功;Apple仍在处理中。请勿重试构建
  • TestFlight upload failed: ...
    :退出码为1,附带Apple的错误文本。编译和签名已成功,仅交付环节失败。
需要识别的失败信息:
  • Apple提示Bundle版本已被使用:修改
    CFBundleVersion
    (Expo项目:app.json中的
    expo.ios.buildNumber
    )并重新构建。
  • HTTP 401
    :密钥ID/发行者ID/.p8文件不匹配,或密钥已被撤销。
  • HTTP 403
    :密钥的角色无法上传构建包;需要开发者或更高权限角色。
  • no App Store Connect app with bundle id
    :应用记录不存在;用户必须在App Store Connect中手动创建应用(API无法创建)。
  • 构建包在TestFlight中卡在「缺失合规性」:应用在构建时未回答出口合规问题。在Info.plist中设置
    ITSAppUsesNonExemptEncryption
    NO
    (Expo项目:app.json中的
    expo.ios.config.usesNonExemptEncryption: false
    )并重新构建。
如需自动交付给测试人员,应用的内部TestFlight群组必须启用自动分发(仅创建时可设置),并且上述合规性参数已正确设置;之后无需任何上传后操作。

Preview builds

预览构建包

Only create a reusable preview asset when the user asks for a preview build or when you're opening a PR. Build and upload:
bash
ASSET_NAME="<bundle id / pr number / or any session identifier>.zip"
lim xcode build . --upload ${ASSET_NAME}
仅当用户要求生成预览构建包或你要提交PR时,才创建可复用的预览资产。构建并上传:
bash
ASSET_NAME="<bundle id / pr编号 / 或任意会话标识>.zip"
lim xcode build . --upload ${ASSET_NAME}

Debug preview build:

Debug预览构建包:

lim xcode build . --configuration Debug --upload ${ASSET_NAME}

Then construct the preview link and include it in your last message (and in the
PR, if you're opening one):
undefined
lim xcode build . --configuration Debug --upload ${ASSET_NAME}

然后构造预览链接,并将其包含在你的最后一条消息中(如果提交PR,也请包含在PR中):
undefined

Gotchas

注意事项

  • Build errors are your job to fix. If a build fails, read the error output, fix the code, and rebuild. Don't ask the user to fix build errors.
  • Instance ID for
    lim ios
    commands.
    They resolve the current instance from the git worktree of your cwd and can fail with
    No instance ID provided and no recent ios instance found
    . Get the ID from
    lim xcode get
    and pass
    --id <ios-instance-id>
    ; full recipe in limrun-ios-simulator's "Targeting the right instance" section.
  • Bundle ID discovery. If you don't know the bundle ID, check the Xcode project files or run
    lim ios list-apps
    after a successful build.
  • Auth errors on an authenticated command mean the session expired or
    LIM_API_KEY
    is wrong; ask the user to run
    lim login
    or provide a key.
  • Build settings are allowlisted. Only
    APP_CONFIG_*
    keys and
    SWIFT_ACTIVE_COMPILATION_CONDITIONS
    pass
    --build-setting
    ; anything else is rejected. Bump
    CURRENT_PROJECT_VERSION
    and friends in the Xcode project file instead.
  • Keep synced files small. A single ~2MB+ file can fail the client-side sync with ENOMEM before the build starts; compress large assets.
  • Symlinks sync when relative and in-root. A symlink whose target is an absolute path is skipped with a warning; recreate it with a relative target if the build needs it. A relative link escaping the synced folder fails the sync;
    --ignore
    it or sync from the repo root that contains the target.
  • Signing failures are loud and specific.
    Unknown issuer hash
    means the p12 lacks its CA chain, so re-export it with the chain;
    code signature verification failed
    means the platform's post-sign check rejected the artifact, which is not a code problem, so retry or report it.
  • 构建错误由你负责修复。如果构建失败,请读取错误输出、修复代码并重新构建。不要让用户修复构建错误。
  • lim ios
    命令的实例ID
    :这些命令会从当前工作目录的git工作树解析当前实例,可能会因
    No instance ID provided and no recent ios instance found
    而失败。可从
    lim xcode get
    获取ID,并传入
    --id <ios-instance-id>
    ;完整流程请查看limrun-ios-simulator技能中的「定位正确实例」部分。
  • Bundle ID查询:如果你不知道Bundle ID,请查看Xcode项目文件,或在构建成功后执行
    lim ios list-apps
    查询。
  • 认证错误:已认证的命令出现错误表示会话已过期或
    LIM_API_KEY
    不正确;请让用户执行
    lim login
    或提供正确密钥。
  • 构建设置白名单:仅
    APP_CONFIG_*
    键和
    SWIFT_ACTIVE_COMPILATION_CONDITIONS
    可通过
    --build-setting
    传递;其他设置会被拒绝。请在Xcode项目文件中修改
    CURRENT_PROJECT_VERSION
    等参数。
  • 保持同步文件体积较小:单个约2MB以上的文件可能会在构建开始前导致客户端同步因ENOMEM失败;请压缩大型资产。
  • 相对根目录的符号链接会被同步:目标为绝对路径的符号链接会被跳过并发出警告;如果构建需要,请重新创建为相对目标的符号链接。指向同步文件夹外部的相对链接会导致同步失败;请使用
    --ignore
    忽略它,或从包含目标的仓库根目录开始同步。
  • 签名失败会明确提示
    Unknown issuer hash
    表示p12证书缺少CA链,请重新导出包含CA链的证书;
    code signature verification failed
    表示平台签名后检查拒绝了产物,这不是代码问题,请重试或上报。