MobileNativeFoundation / MobileNativeFoundation/rules_xcodeproj
Bug: Missing macOS execution constraints configure generator tools for Linux
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 626
- Forks
- 124
- PR merge metrics
- No merged PRs in 30d
Description
Description
With Linux execution platforms registered before macOS, the generated xcodeproj rule selects Linux for its default execution group. Its cfg = "exec" dependencies, including the rsync installed into the generated project, consequently target Linux even though the installer runs on macOS.
The generator rule and aspect created in xcodeproj/internal/xcodeproj_factory.bzl do not declare macOS execution constraints. Action-level no-remote/no-sandbox requirements do not constrain execution-platform resolution. Setting target_compatible_with = ["@platforms//os:macos"] on the public xcodeproj target also does not fix this: it constrains the runner's target platform, not the generated rule's execution platform.
There is another issue in the same ruleset: renamed_rsync, renamed_swiftc_stub, and renamed_import_indexstores independently select an execution platform, but their commands use BSD stat -f '%d' and macOS cp -c. They need macOS execution constraints too. With only the generator rule constrained, these genrules still run on Linux and emit stat: cannot read file system information for '%d': No such file or directory (the copy can nevertheless appear to succeed).
Reproduction steps
-
Use a macOS host with a working
xcodeprojtarget and macOS/Linux execution platforms and C/C++ toolchains, such as a mixed-platform remote-execution setup. -
Register Linux before macOS:
common --extra_execution_platforms=//platforms:linux_x86_64,//platforms:macos_arm64 -
Run
bazel run //:xcode.
In our workspace, the unpatched generator configures rsync for Linux and fails in @@rsync+//:rounding_h:
cp bazel-out/haswell_x86_64-opt-exec/bin/external/rsync+/proto.h proto.h
# Execution platform: ...//platforms/linux:haswell_x86_64
external/rsync+/rsync.h:388:10: fatal error: sys/filio.h: No such file or directory
Forcing the execution-platform list to contain only macOS avoids the platform issue, but prevents unrelated actions from using Linux.
Expected behavior
Project generation and the macOS integration tools resolve to macOS while other actions remain free to use Linux. No global execution-platform override should be necessary.
Proposed resolution and validation
The patch below adds a non-dev platforms dependency and macOS execution constraints to the generator rule, its aspect (which invokes the Mach-O target-build-settings generator), and the three rename genrules.
With this patch and the separate rsync dependency fix described below, bazel run //:xcode successfully generates and installs the full project with Linux first in the execution-platform list. The installed rsync is a working Mach-O arm64 binary. Local transfers using LZ4 compression and each of xxh64, xxh3, and xxh128 checksums also passed byte-for-byte comparison.
Separate dependency prerequisite
The BCR rsync 3.4.2 package has an independent platform bug: rounding_h invokes the execution machine's system cc using a supplied macOS config.h, but declares no execution constraint. Even after the generator configures rsync for macOS, this genrule can independently select Linux. We constrained that probe to macOS in a separate local rsync patch to complete the end-to-end test. That fix belongs to rsync's BCR packaging, not the rules_xcodeproj patch below.
We also resolved an independent LZ4/xxHash symbol collision when linking rsync with LLD by applying LZ4's upstream XXH_NAMESPACE=LZ4_ compiler define only to LZ4 sources.
Versions
- rules_xcodeproj: 4.1.0 (the factory on current main has the same missing constraints)
- Bazel: 9.2.0
- Xcode: 27.0, build 27A266a
- Host: macOS arm64
- rules_apple: 5.1.0
- rules_swift: 4.1.0
- rsync: 3.4.2
Patch against rules_xcodeproj 4.1.0
Apply with patch -p1. This is the patch used by our local Bzlmod override.
diff --git a/MODULE.bazel b/MODULE.bazel
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -13,6 +13,7 @@ bazel_dep(
)
bazel_dep(name = "bazel_features", version = "1.46.0")
bazel_dep(name = "bazel_skylib", version = "1.9.0")
+bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "rules_cc", version = "0.2.17")
bazel_dep(
name = "rules_swift",
diff --git a/xcodeproj/internal/xcodeproj_factory.bzl b/xcodeproj/internal/xcodeproj_factory.bzl
--- a/xcodeproj/internal/xcodeproj_factory.bzl
+++ b/xcodeproj/internal/xcodeproj_factory.bzl
@@ -22,6 +22,8 @@ def _make_xcodeproj_aspect(
attr_aspects = ["*"],
attrs = attrs,
fragments = ["apple", "cpp", "objc"],
+ # The target build settings generator is a macOS executable.
+ exec_compatible_with = ["@platforms//os:macos"],
toolchains = use_cc_toolchain(),
)
@@ -39,6 +41,10 @@ def _make_xcodeproj_rule(
doc = "Creates an `.xcodeproj` file in the workspace when run.",
implementation = impl,
attrs = attrs | XCODEPROJ_TRANSITION_ATTRS,
+ # Generator tools and installed integration binaries must run on macOS.
+ # Constrain resolution before cfg = "exec" configures these dependencies;
+ # action execution requirements cannot select their target platform.
+ exec_compatible_with = ["@platforms//os:macos"],
executable = True,
)
diff --git a/xcodeproj/internal/bazel_integration_files/BUILD b/xcodeproj/internal/bazel_integration_files/BUILD
--- a/xcodeproj/internal/bazel_integration_files/BUILD
+++ b/xcodeproj/internal/bazel_integration_files/BUILD
@@ -91,6 +91,7 @@ genrule(
name = "renamed_import_indexstores",
srcs = ["//tools/import_indexstores:universal_import_indexstores"],
outs = ["import_indexstores"],
+ exec_compatible_with = ["@platforms//os:macos"],
# Make `import_indexstores` have the right name
cmd = """\
readonly output="$@"
@@ -111,6 +112,7 @@ genrule(
name = "renamed_swiftc_stub",
srcs = ["//tools/swiftc_stub:universal_swiftc_stub"],
outs = ["swiftc"],
+ exec_compatible_with = ["@platforms//os:macos"],
# Make `swiftc_stub` have the right name
cmd = """\
readonly output="$@"
@@ -131,6 +133,7 @@ genrule(
name = "renamed_rsync",
srcs = ["@rsync"],
outs = ["rsync"],
+ exec_compatible_with = ["@platforms//os:macos"],
# Make `rsync` have the right name
cmd = """\
readonly output="$@"
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with MODULE.bazel, xcodeproj/internal/xcodeproj_factory.bzl, and xcodeproj/internal/bazel_integration_files/BUILD, then reproduce with Linux listed before macOS using bazel run //:xcode. Review execution-platform selection for the generator, aspect, and three rename genrules. Done means project generation and macOS integration tools resolve to macOS while unrelated actions can still use Linux.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos
- Domain
- build-system, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100