Add a SwiftTUI terminal app that lists race runners from the start list and results files, with an interactive menu to sort, filter by age group, toggle finishers vs. non-starters, and live-search by name. Parsing and transforms are written as pure functions over the file contents. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
217 lines
7.7 KiB
Bash
Executable file
217 lines
7.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
cd "$SRCROOT"
|
|
|
|
# Calculate Bazel `--output_groups`
|
|
|
|
if [ "$ACTION" == "indexbuild" ]; then
|
|
echo >&2 "error: \`BazelDependencies\` should not run during Index Build." \
|
|
"Please file a bug report here:" \
|
|
"https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md"
|
|
exit 1
|
|
else
|
|
if [[ "${ENABLE_PREVIEWS:-}" == "YES" ]]; then
|
|
# Compile params, products (i.e. bundles) and index store data, and link
|
|
# params
|
|
readonly output_group_prefixes="bc,bp,bl"
|
|
else
|
|
# Products (i.e. bundles) and index store data
|
|
readonly output_group_prefixes="bp"
|
|
fi
|
|
|
|
# In Xcode 14 the "Index" directory was renamed to "Index.noindex".
|
|
# `$INDEX_DATA_STORE_DIR` is set to `$OBJROOT/INDEX_DIR/DataStore`, so we can
|
|
# use it to determine the name of the directory regardless of Xcode version.
|
|
readonly index_dir="${INDEX_DATA_STORE_DIR%/*}"
|
|
readonly index_dir_name="${index_dir##*/}"
|
|
|
|
# Xcode doesn't adjust `$OBJROOT` in scheme action scripts when building for
|
|
# previews. So we need to look in the non-preview build directory for this file.
|
|
readonly non_preview_objroot="${OBJROOT/\/Intermediates.noindex\/Previews\/*//Intermediates.noindex}"
|
|
readonly base_objroot="${non_preview_objroot/\/$index_dir_name\/Build\/Intermediates.noindex//Build/Intermediates.noindex}"
|
|
readonly build_marker_file="$non_preview_objroot/build_marker"
|
|
|
|
# We need to read from `$output_groups_file` as soon as possible, as concurrent
|
|
# writes to it can happen during indexing, which breaks the off-by-one-by-design
|
|
# nature of it
|
|
IFS=$'\n' read -r -d '' -a labels_and_output_groups < \
|
|
<( "$CALCULATE_OUTPUT_GROUPS_SCRIPT" \
|
|
"$XCODE_VERSION_ACTUAL" \
|
|
"$non_preview_objroot" \
|
|
"$base_objroot" \
|
|
"$build_marker_file" \
|
|
$output_group_prefixes \
|
|
&& printf '\0' )
|
|
|
|
readonly outputgroup_regex='[^\ ]+ @{0,2}(.*)//(.*):(.*) ([^\ ]+)$'
|
|
|
|
raw_labels=()
|
|
raw_target_ids=()
|
|
output_groups=("index_import" "target_ids_list")
|
|
indexstores_filelists=()
|
|
for (( i=0; i<${#labels_and_output_groups[@]}; i+=2 )); do
|
|
raw_labels+=("${labels_and_output_groups[i]}")
|
|
|
|
output_group="${labels_and_output_groups[i+1]}"
|
|
raw_target_ids+=("${output_group#* }")
|
|
output_groups+=("$output_group")
|
|
|
|
output_type="${output_group%% *}"
|
|
|
|
if [[ "$output_type" == 'xi' || "$output_type" == 'bi' ]]; then
|
|
if [[ $output_group =~ $outputgroup_regex ]]; then
|
|
repo="${BASH_REMATCH[1]}"
|
|
if [[ "$repo" == "@" ]]; then
|
|
repo=""
|
|
fi
|
|
|
|
package="${BASH_REMATCH[2]}"
|
|
target="${BASH_REMATCH[3]}"
|
|
configuration="${BASH_REMATCH[4]}"
|
|
filelist="$configuration/bin/${repo:+"external/$repo/"}$package/$target-${output_type}.filelist"
|
|
|
|
indexstores_filelists+=("$filelist")
|
|
fi
|
|
fi
|
|
done
|
|
readonly indexstores_filelists
|
|
|
|
if [ "${#output_groups[@]}" -eq 1 ]; then
|
|
echo "BazelDependencies invoked without any output groups set." \
|
|
"Exiting early."
|
|
exit
|
|
else
|
|
labels=()
|
|
while IFS= read -r -d '' label; do
|
|
labels+=("$label")
|
|
done < <(printf "%s\0" "${raw_labels[@]}" | sort -uz)
|
|
|
|
target_ids=()
|
|
while IFS= read -r -d '' target_id; do
|
|
target_ids+=("$target_id")
|
|
done < <(printf "%s\0" "${raw_target_ids[@]}" | sort -uz)
|
|
fi
|
|
fi
|
|
|
|
# Build
|
|
|
|
build_pre_config_flags=(
|
|
# Include the following:
|
|
#
|
|
# - .indexstore directories to allow importing indexes
|
|
# - .swift{doc,sourceinfo} files for indexing
|
|
# - .a and .swiftmodule files for lldb
|
|
# - primary compilation input files (.c, .C, .cc, .cl, .cpp, .cu, .cxx, .c++,
|
|
# .m, .mm, .swift) for Xcode build input checking
|
|
# - files needed for Clang importer (headers, modulemaps, yaml files, etc.)
|
|
#
|
|
# This is brittle. If different file extensions are used for compilation
|
|
# inputs, they will need to be added to this list. Ideally we can stop doing
|
|
# this once Bazel adds support for a Remote Output Service.
|
|
"--remote_download_regex=.*\.indexstore/.*|.*\.(a|cfg|c|C|cc|cl|cpp|cu|cxx|c++|def|h|H|hh|hpp|hxx|h++|hmap|ilc|inc|inl|ipp|tcc|tlh|tli|tpp|m|modulemap|mm|pch|swift|swiftdoc|swiftmodule|swiftsourceinfo|yaml)$"
|
|
)
|
|
|
|
apply_sanitizers=1
|
|
if [ "$ACTION" == "indexbuild" ]; then
|
|
readonly config="${BAZEL_CONFIG}_indexbuild"
|
|
|
|
# Index Build doesn't need sanitizers
|
|
apply_sanitizers=0
|
|
elif [ "${ENABLE_PREVIEWS:-}" == "YES" ]; then
|
|
readonly config="${BAZEL_CONFIG}_swiftuipreviews"
|
|
elif [ "${CLANG_COVERAGE_MAPPING:-}" == YES ] && [ "${BAZEL_SUPPRESS_COVERAGE_BUILD:-}" != YES ]; then
|
|
# Code coverage build
|
|
#
|
|
# CLANG_COVERAGE_MAPPING is set to YES when the active scheme's test action has code coverage enabled. It is configured
|
|
# irrespective of the value of ENABLE_CODE_COVERAGE, and of whether the current build action is for testing or not.
|
|
#
|
|
# We would rather use ENABLE_CODE_COVERAGE here, but the value of that setting is often YES even when code coverage is not
|
|
# enabled in the active scheme.
|
|
readonly config="${BAZEL_CONFIG}_coverage"
|
|
|
|
echo "warning: Code coverage is enabled. In order to maintain compatibility with Xcode, the instrumented build is not hermetic. Remote cache performance will be affected." >&2
|
|
else
|
|
readonly config="_${BAZEL_CONFIG}_build"
|
|
fi
|
|
|
|
# Respect the "Continue building after errors" setting
|
|
continue_building_value="$(defaults read com.apple.dt.Xcode IDEBuildingContinueBuildingAfterErrors 2>/dev/null || echo 0)"
|
|
if [ "$continue_building_value" == "1" ]; then
|
|
build_pre_config_flags+=("--keep_going")
|
|
else
|
|
build_pre_config_flags+=("--nokeep_going")
|
|
fi
|
|
|
|
# Runtime Sanitizers
|
|
if [[ $apply_sanitizers -eq 1 ]]; then
|
|
if [ "${ENABLE_ADDRESS_SANITIZER:-}" == "YES" ]; then
|
|
build_pre_config_flags+=(
|
|
--copt=-fno-omit-frame-pointer
|
|
--copt=-fno-sanitize-recover=all
|
|
--copt=-fsanitize=address
|
|
--linkopt=-fsanitize=address
|
|
--@@rules_swift+//swift:copt=-sanitize=address
|
|
--copt=-Wno-macro-redefined
|
|
--copt=-D_FORTIFY_SOURCE=0
|
|
)
|
|
fi
|
|
if [ "${ENABLE_THREAD_SANITIZER:-}" == "YES" ]; then
|
|
build_pre_config_flags+=(
|
|
--copt=-fno-omit-frame-pointer
|
|
--copt=-fno-sanitize-recover=all
|
|
--copt=-fsanitize=thread
|
|
--linkopt=-fsanitize=thread
|
|
--@@rules_swift+//swift:copt=-sanitize=thread
|
|
)
|
|
fi
|
|
if [ "${ENABLE_UNDEFINED_BEHAVIOR_SANITIZER:-}" == "YES" ]; then
|
|
build_pre_config_flags+=(
|
|
--copt=-fno-omit-frame-pointer
|
|
--copt=-fno-sanitize-recover=all
|
|
--copt=-fsanitize=undefined
|
|
--linkopt=-fsanitize=undefined
|
|
)
|
|
fi
|
|
fi
|
|
readonly build_pre_config_flags
|
|
|
|
# `bazel_build.sh` sets `output_path`
|
|
source "$BAZEL_INTEGRATION_DIR/bazel_build.sh"
|
|
|
|
# Async actions
|
|
#
|
|
# For these commands to run in the background, both stdout and stderr need to be
|
|
# redirected, otherwise Xcode will block the run script.
|
|
|
|
readonly log_dir="$OBJROOT/rules_xcodeproj_logs"
|
|
mkdir -p "$log_dir"
|
|
|
|
# Report errors from previous async actions
|
|
shopt -s nullglob
|
|
for log in "$log_dir"/*.async.log; do
|
|
if [[ -s "$log" ]]; then
|
|
command=$(basename "${log%.async.log}")
|
|
echo "warning: Previous run of \"$command\" had output:" >&2
|
|
sed "s|^|warning: |" "$log" >&2
|
|
echo "warning: If you believe this is a bug, please file a report here:" \
|
|
"https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md" \
|
|
>&2
|
|
fi
|
|
done
|
|
|
|
# Import indexes
|
|
if [ -n "${indexstores_filelists:-}" ]; then
|
|
if [[ "${BAZEL_SEPARATE_INDEXBUILD_OUTPUT_BASE:-}" == "YES" ]]; then
|
|
"$BAZEL_INTEGRATION_DIR/import_indexstores" \
|
|
"$INDEXING_PROJECT_DIR__NO" \
|
|
"${indexstores_filelists[@]/#/$output_path/}" \
|
|
>"$log_dir/import_indexstores.async.log" 2>&1 &
|
|
else
|
|
"$BAZEL_INTEGRATION_DIR/import_indexstores" \
|
|
"$PROJECT_DIR" \
|
|
"${indexstores_filelists[@]/#/$BAZEL_OUT/}" \
|
|
>"$log_dir/import_indexstores.async.log" 2>&1 &
|
|
fi
|
|
fi
|