m323/m323.xcodeproj/rules_xcodeproj/bazel/bazel_build.sh
cediackermann b1968074b6
build: generate per-package and aggregate Xcode projects
Add rules_xcodeproj targets to each package BUILD plus a root m323
project, with extra_files filegroups so the full source tree shows in
Xcode. Ignore Scala/Metals build dirs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 14:00:40 +02:00

209 lines
6.9 KiB
Bash
Executable file

# It is assumed that this file is `source`ed from another script, with the following variable set:
#
# - BAZEL_CONFIG
# - BAZEL_INTEGRATION_DIR
# - BAZEL_OUT
# - DEVELOPER_DIR
# - GENERATOR_LABEL
# - HOME
# - INTERNAL_DIR
# - OBJROOT
# - RULES_XCODEPROJ_BUILD_MODE
# - SRCROOT
# - TERM
# - USER
# - XCODE_PRODUCT_BUILD_VERSION
# - (optional) build_pre_config_flags
# - config
# - (optional) labels
# - output_groups
# - (optional) target_ids
output_groups_flag="--output_groups=$(IFS=, ; echo "${output_groups[*]}")"
readonly output_groups_flag
# Set `output_base`
# In `runner.sh` the generator has the build output base set inside of the outer
# bazel's output path (`bazel-out/`). So here we need to make our output base
# changes relative to that changed path.
readonly build_output_base="$BAZEL_OUTPUT_BASE"
if [[
"$ACTION" == "indexbuild" &&
"${BAZEL_SEPARATE_INDEXBUILD_OUTPUT_BASE:-}" == "YES"
]]; then
# We use a different output base for Index Build to prevent normal builds and
# indexing waiting on bazel locks from the other. We nest it inside of the
# normal output base directory so that it's not cleaned up when running
# `bazel clean`, but is when running `bazel clean --expunge`. This matches
# Xcode behavior of not cleaning the Index Build outputs by default.
readonly output_base="${build_output_base%/*}/indexbuild_output_base"
readonly workspace_name="${PROJECT_DIR##*/}"
readonly output_path="$output_base/execroot/$workspace_name/bazel-out"
# Use current path for "bazel-out/" and "external/"
# This fixes Index Build to use its version of generated and external files
readonly vfs_overlay_roots="{\"external-contents\": \"$output_path\",\"name\": \"$BAZEL_OUT\",\"type\": \"directory-remap\"},{\"external-contents\": \"$output_base/external\",\"name\": \"$BAZEL_EXTERNAL\",\"type\": \"directory-remap\"}"
else
readonly output_base="$build_output_base"
readonly output_path="$BAZEL_OUT"
readonly vfs_overlay_roots=""
fi
# Set `bazel_cmd` for calling `bazel`
bazelrcs=(
--noworkspace_rc
"--bazelrc=$BAZEL_INTEGRATION_DIR/xcodeproj.bazelrc"
)
if [[ -s ".bazelrc" ]]; then
bazelrcs+=("--bazelrc=.bazelrc")
fi
if [[ -s "$BAZEL_INTEGRATION_DIR/xcodeproj_extra_flags.bazelrc" ]]; then
bazelrcs+=("--bazelrc=$BAZEL_INTEGRATION_DIR/xcodeproj_extra_flags.bazelrc")
fi
readonly bazelrcs
readonly allowed_vars=(
"BUILD_WORKSPACE_DIRECTORY"
"DEVELOPER_DIR"
"HOME"
"HTTP_PROXY"
"http_proxy"
"HTTPS_PROXY"
"https_proxy"
"NO_PROXY"
"no_proxy"
"SSH_AUTH_SOCK"
"TERM"
"USER"
)
passthrough_env=()
for var in "${allowed_vars[@]}"; do
if [[ -n "${!var:-}" ]]; then
passthrough_env+=("$var=${!var}")
fi
done
source "$BAZEL_INTEGRATION_DIR/bazel_env.sh"
bazel_cmd=(
env -i
"${passthrough_env[@]}"
"${envs[@]}"
"/Users/cediackermann/Projects/tools/bazel"
# Restart bazel server if `DEVELOPER_DIR` changes to clear `developerDirCache`
"--host_jvm_args=-Xdock:name=$DEVELOPER_DIR"
"${bazelrcs[@]}"
--output_base "$output_base"
)
if [[
"$ACTION" == "indexbuild" &&
"${BAZEL_SEPARATE_INDEXBUILD_OUTPUT_BASE:-}" != "YES"
]]; then
# Allow normal builds to cancel Index Builds
bazel_cmd+=("--preemptible")
fi
readonly bazel_cmd
readonly base_pre_config_flags=(
# Be explicit about our desired Xcode version
"--xcode_version=$XCODE_PRODUCT_BUILD_VERSION"
# Set `DEVELOPER_DIR` in case a bazel wrapper filters it
"--repo_env=DEVELOPER_DIR=$DEVELOPER_DIR"
# Work around https://github.com/bazelbuild/bazel/issues/8902
# `USE_CLANG_CL` is only used on Windows, we set it here to cause Bazel to
# re-evaluate the cc_toolchain for a different Xcode version
"--repo_env=USE_CLANG_CL=$XCODE_PRODUCT_BUILD_VERSION"
"--repo_env=XCODE_VERSION=$XCODE_PRODUCT_BUILD_VERSION"
# Don't block the end of the build for BES upload (artifacts OR events)
"--bes_upload_mode=NOWAIT_FOR_UPLOAD_COMPLETE"
)
if [[ "${BAZEL_SEPARATE_INDEXBUILD_OUTPUT_BASE:-}" == "YES" ]]; then
# Create VFS overlay
cat > "$OBJROOT/bazel-out-overlay.yaml" <<EOF
{"case-sensitive": "false", "fallthrough": true, "roots": [$vfs_overlay_roots],"version": 0}
EOF
fi
# Custom Swift toolchains
if [[ -n "${TOOLCHAINS-}" ]]; then
# We remove all Metal toolchains from the list first
toolchains_array=($TOOLCHAINS)
filtered_toolchains=()
for tc in "${toolchains_array[@]}"; do
if [[ "$tc" != "com.apple.dt.toolchain.Metal"* ]]; then
filtered_toolchains+=("$tc")
fi
done
if [[ ${#filtered_toolchains[@]} -gt 0 ]]; then
toolchain="${filtered_toolchains[0]}"
if [[ "$toolchain" == "com.apple.dt.toolchain.XcodeDefault" ]]; then
unset toolchain
fi
fi
fi
# Build
echo "Starting Bazel build"
"$BAZEL_INTEGRATION_DIR/process_bazel_build_log.py" \
"${bazel_cmd[@]}" \
build \
"${base_pre_config_flags[@]}" \
${build_pre_config_flags:+"${build_pre_config_flags[@]}"} \
--config="$config" \
--color=yes \
${toolchain:+--action_env=TOOLCHAINS="$toolchain"} \
"$output_groups_flag" \
"@@rules_xcodeproj++rules_repos+rules_xcodeproj_generated//generator/m323/xcodeproj:xcodeproj" \
${labels:+"--build_metadata=PATTERN=${labels[*]}"} \
2>&1
# Verify that we actually built what we requested
if [[ -n "${target_ids:-}" ]]; then
if [[ ! -s "$PROJECT_DIR/bazel-out/darwin_arm64-dbg/bin/external/rules_xcodeproj++rules_repos+rules_xcodeproj_generated/generator/m323/xcodeproj/xcodeproj_target_ids" ]]; then
echo "error: \"$PROJECT_DIR/bazel-out/darwin_arm64-dbg/bin/external/rules_xcodeproj++rules_repos+rules_xcodeproj_generated/generator/m323/xcodeproj/xcodeproj_target_ids\" was not created. This can happen if" \
"you apply build-affecting flags to \"rules_xcodeproj_generator\" config, or" \
"with the \"--@rules_xcodeproj//xcodeproj:extra_generator_flags\" flag." \
"Please ensure that all build-affecting flags are moved to the" \
"\"rules_xcodeproj\" config or" \
"\"--@rules_xcodeproj//xcodeproj:extra_common_flags\" flag. If you are still" \
"getting this error after adjusting your setup and regenerating your project," \
"please file a bug report here:" \
"https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md" \
>&2
exit 1
fi
# We need to sort the inputs for `comm` to work on macOS 15.4+
diff_output=$(
comm -23 \
<(printf '%s\n' "${target_ids[@]}" | sort) \
<(sort "$PROJECT_DIR/bazel-out/darwin_arm64-dbg/bin/external/rules_xcodeproj++rules_repos+rules_xcodeproj_generated/generator/m323/xcodeproj/xcodeproj_target_ids")
)
if [ -n "$diff_output" ]; then
missing_target_ids=("${diff_output[@]}")
echo "error: There were some target IDs that weren't known to Bazel" \
"(e.g. \"${missing_target_ids[0]}\"). Please regenerate the project to fix" \
"this. If you are still getting this error after regenerating your project," \
"please file a bug report here:" \
"https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md" \
>&2
exit 1
fi
fi