feat(MiniProject): searchable Stadt-Rundlauf runner TUI

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>
This commit is contained in:
cediackermann 2026-06-29 12:05:50 +02:00
parent 0bc8137078
commit 7903970f08
No known key found for this signature in database
34 changed files with 3475 additions and 0 deletions

View file

@ -0,0 +1,39 @@
load("@rules_swift//swift:swift.bzl", "swift_binary")
swift_binary(
name = "StadtRundlauf",
srcs = ["main.swift"],
data = glob(["data/*.txt"]),
visibility = ["//visibility:public"],
deps = ["@swifttui//:SwiftTUI"],
)
# BEGIN GENERATED XCODEPROJ
load("@rules_xcodeproj//xcodeproj:defs.bzl", "top_level_target", "xcodeproj")
filegroup(
name = "xcodeproj_extra_files",
srcs = glob(
["**/*"],
exclude = [
"BUILD.bazel",
"BUILD",
"**/*.xcodeproj/**",
"**/.*",
"**/.*/**",
],
allow_empty = True,
),
visibility = ["//visibility:public"],
)
xcodeproj(
name = "xcodeproj",
project_name = "MiniProject",
tags = ["manual"],
extra_files = [":xcodeproj_extra_files"],
top_level_targets = [
"//m323/Sources/MiniProject:StadtRundlauf",
],
)
# END GENERATED XCODEPROJ

View file

@ -0,0 +1,856 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 60;
objects = {
FF0100000000000000000004 /* Generate Bazel Dependencies */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Generate Bazel Dependencies";
outputFileListPaths = (
"$(INTERNAL_DIR)/generated.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"$BAZEL_INTEGRATION_DIR/generate_bazel_dependencies.sh\"\n";
showEnvVarsInLog = 0;
};
FF0100000000000000000005 /* Create swift_debug_settings.py */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(BAZEL_INTEGRATION_DIR)/$(CONFIGURATION)-swift_debug_settings.py",
);
name = "Create swift_debug_settings.py";
outputPaths = (
"$(OBJROOT)/$(CONFIGURATION)/swift_debug_settings.py",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "perl -pe '\n # Replace \"__BAZEL_XCODE_DEVELOPER_DIR__\" with \"$(DEVELOPER_DIR)\"\n s/__BAZEL_XCODE_DEVELOPER_DIR__/\\$(DEVELOPER_DIR)/g;\n\n # Replace \"__BAZEL_XCODE_SDKROOT__\" with \"$(SDKROOT)\"\n s/__BAZEL_XCODE_SDKROOT__/\\$(SDKROOT)/g;\n\n # Replace build settings with their values\n s/\n \\$ # Match a dollar sign\n (\\()? # Optionally match an opening parenthesis and capture it\n ([a-zA-Z_]\\w*) # Match a variable name and capture it\n (?(1)\\)) # If an opening parenthesis was captured, match a closing parenthesis\n /$ENV{$2}/gx; # Replace the entire matched string with the value of the corresponding environment variable\n\n' \"$SCRIPT_INPUT_FILE_0\" > \"$SCRIPT_OUTPUT_FILE_0\"\n";
showEnvVarsInLog = 0;
};
FF0100000000000000000100 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BAZEL_PACKAGE_BIN_DIR = rules_xcodeproj;
CALCULATE_OUTPUT_GROUPS_SCRIPT = "$(BAZEL_INTEGRATION_DIR)/calculate_output_groups.py";
CC = "";
CXX = "";
INDEXING_SUPPORTED_PLATFORMS__ = "$(INDEXING_SUPPORTED_PLATFORMS__NO)";
INDEXING_SUPPORTED_PLATFORMS__NO = macosx;
INDEXING_SUPPORTED_PLATFORMS__YES = macosx;
INDEX_DISABLE_SCRIPT_EXECUTION = YES;
LD = "";
LDPLUSPLUS = "";
LIBTOOL = libtool;
SUPPORTED_PLATFORMS = "$(INDEXING_SUPPORTED_PLATFORMS__$(INDEX_ENABLE_BUILD_ARENA))";
SUPPORTS_MACCATALYST = YES;
SWIFT_EXEC = swiftc;
TAPI_EXEC = "";
TARGET_IDS_FILE = "$(BAZEL_OUT)/darwin_arm64-dbg/bin/external/rules_xcodeproj++rules_repos+rules_xcodeproj_generated/generator/m323/Sources/MiniProject/xcodeproj/xcodeproj_target_ids";
TARGET_NAME = BazelDependencies;
};
name = Debug;
};
FF0100000000000000000002 /* Build configuration list for PBXAggregateTarget "BazelDependencies" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FF0100000000000000000100 /* Debug */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
FF0100000000000000000001 /* BazelDependencies */ = {
isa = PBXAggregateTarget;
buildConfigurationList = FF0100000000000000000002 /* Build configuration list for PBXAggregateTarget "BazelDependencies" */;
buildPhases = (
FF0100000000000000000004 /* Generate Bazel Dependencies */,
FF0100000000000000000005 /* Create swift_debug_settings.py */,
);
dependencies = (
);
name = BazelDependencies;
productName = BazelDependencies;
};
FF0000000000000000000100 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS = NO;
BAZEL_CONFIG = rules_xcodeproj;
BAZEL_EXTERNAL = "$(BAZEL_OUTPUT_BASE)/external";
BAZEL_INTEGRATION_DIR = "$(INTERNAL_DIR)/bazel";
BAZEL_LLDB_INIT = "$(PROJECT_FILE_PATH)/rules_xcodeproj/bazel.lldbinit";
BAZEL_OUT = "$(PROJECT_DIR)/bazel-out";
BAZEL_OUTPUT_BASE = "$(_BAZEL_OUTPUT_BASE:standardizepath)";
BAZEL_WORKSPACE_ROOT = "$(SRCROOT)";
BUILD_DIR = "$(SYMROOT)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
BUILD_MARKER_FILE = "$(OBJROOT)/build_marker";
BUILD_WORKSPACE_DIRECTORY = "$(SRCROOT)";
CC = "$(BAZEL_INTEGRATION_DIR)/clang.sh";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_MODULES_AUTOLINK = NO;
CODE_SIGNING_ALLOWED = NO;
CODE_SIGN_STYLE = Manual;
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(BAZEL_PACKAGE_BIN_DIR)";
COPY_PHASE_STRIP = NO;
CXX = "$(BAZEL_INTEGRATION_DIR)/clang.sh";
DEBUG_INFORMATION_FORMAT = dwarf;
DSTROOT = "$(PROJECT_TEMP_DIR)";
ENABLE_DEBUG_DYLIB = NO;
ENABLE_DEFAULT_SEARCH_PATHS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_OPTIMIZATION_LEVEL = 0;
IMPORT_INDEX_BUILD_INDEXSTORES = YES;
INDEXING_PROJECT_DIR__ = "$(INDEXING_PROJECT_DIR__NO)";
INDEXING_PROJECT_DIR__NO = /Users/cediackermann/Library/Caches/bazel/_bazel_cediackermann/32ebb412f2c3c34f6a486c67eed584f9/rules_xcodeproj.noindex/build_output_base/execroot/_main;
INDEXING_PROJECT_DIR__YES = /Users/cediackermann/Library/Caches/bazel/_bazel_cediackermann/32ebb412f2c3c34f6a486c67eed584f9/rules_xcodeproj.noindex/indexbuild_output_base/execroot/_main;
INDEX_DATA_STORE_DIR = "$(INDEX_DATA_STORE_DIR)";
INDEX_FORCE_SCRIPT_EXECUTION = YES;
INDEX_IMPORT = "$(BAZEL_OUT)/darwin_arm64-opt-exec/bin/external/rules_xcodeproj++rules_repos+rules_xcodeproj_index_import/index-import";
INSTALL_PATH = "$(BAZEL_PACKAGE_BIN_DIR)/$(TARGET_NAME)/bin";
INTERNAL_DIR = "$(PROJECT_FILE_PATH)/rules_xcodeproj";
LD = "$(BAZEL_INTEGRATION_DIR)/ld";
LDPLUSPLUS = "$(BAZEL_INTEGRATION_DIR)/ld";
LD_DYLIB_INSTALL_NAME = "";
LD_OBJC_ABI_VERSION = "";
LD_RUNPATH_SEARCH_PATHS = "";
LEGACY_INDEX_IMPORT = "$(BAZEL_OUT)/darwin_arm64-opt-exec/bin/external/rules_xcodeproj++rules_repos+rules_xcodeproj_legacy_index_import/index-import";
LIBTOOL = "$(BAZEL_INTEGRATION_DIR)/libtool";
ONLY_ACTIVE_ARCH = YES;
PROJECT_DIR = /Users/cediackermann/Library/Caches/bazel/_bazel_cediackermann/32ebb412f2c3c34f6a486c67eed584f9/rules_xcodeproj.noindex/build_output_base/execroot/_main;
RESOLVED_REPOSITORIES = "\"./external/+http_archive+swifttui\" \"/Users/cediackermann/Library/Caches/bazel/_bazel_cediackermann/cache/repos/v1/contents/232e8b46dfa0c534358dfb71034ddfd32c5c6d6afb7bb7c3476b660b0b7d70e2/677a2cff-5ccc-47a7-98e4-ddce6cf76076\" \".\" \"/Users/cediackermann/Projects\"";
RULES_XCODEPROJ_BUILD_MODE = bazel;
SRCROOT = /Users/cediackermann/Projects;
SUPPORTS_MACCATALYST = NO;
SWIFT_EXEC = "$(BAZEL_INTEGRATION_DIR)/swiftc";
SWIFT_OBJC_INTERFACE_HEADER_NAME = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_USE_INTEGRATED_DRIVER = NO;
SWIFT_VERSION = 5.0;
TAPI_EXEC = /usr/bin/true;
TARGET_TEMP_DIR = "$(PROJECT_TEMP_DIR)/$(BAZEL_PACKAGE_BIN_DIR)/$(COMPILE_TARGET_NAME)";
USE_HEADERMAP = NO;
VALIDATE_WORKSPACE = NO;
_BAZEL_OUTPUT_BASE = "$(PROJECT_DIR)/../..";
};
name = Debug;
};
FF0000000000000000000002 /* Build configuration list for PBXProject */ = {
isa = XCConfigurationList;
buildConfigurations = (
FF0000000000000000000100 /* Debug */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
FF0000000000000000000001 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = FF0000000000000000000002 /* Build configuration list for PBXProject */;
compatibilityVersion = "Xcode 15.0";
developmentRegion = en;
hasScannedForEncodings = 0;
mainGroup = FF0000000000000000000003 /* /Users/cediackermann/Projects */;
productRefGroup = FF0000000000000000000004 /* Products */;
projectDirPath = /Users/cediackermann/Library/Caches/bazel/_bazel_cediackermann/32ebb412f2c3c34f6a486c67eed584f9/rules_xcodeproj.noindex/build_output_base/execroot/_main;
projectRoot = "";
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 9999;
LastUpgradeCheck = 9999;
TargetAttributes = {
FF0100000000000000000001 = {
CreatedOnToolsVersion = 26.6.0;
LastSwiftMigration = 9999;
};
0100FAB81B6F000000000001 = {
CreatedOnToolsVersion = 26.6.0;
LastSwiftMigration = 9999;
};
00004EB553A7000000000001 = {
CreatedOnToolsVersion = 26.6.0;
LastSwiftMigration = 9999;
};
};
};
knownRegions = (
en,
Base,
);
targets = (
FF0100000000000000000001 /* BazelDependencies */,
0100FAB81B6F000000000001 /* StadtRundlauf */,
00004EB553A7000000000001 /* SwiftTUI */,
);
};
00004EB553A7000000000003 /* Copy Bazel Outputs / Generate Bazel Dependencies (Index Build) */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Bazel Outputs / Generate Bazel Dependencies (Index Build)";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "set -euo pipefail\n\nif [[ \"$ACTION\" == \"indexbuild\" ]]; then\n cd \"$SRCROOT\"\n\n \"$BAZEL_INTEGRATION_DIR/generate_index_build_bazel_dependencies.sh\"\nelse\n \"$BAZEL_INTEGRATION_DIR/copy_outputs.sh\" \\\n \"_BazelForcedCompile_.swift\" \\\n \"\"\nfi\n";
showEnvVarsInLog = 0;
};
00004EB553A7000000000006 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
00FFC950564A0A8E85DE76AA /* Control.swift in Sources */,
00FFC927145F56EA91D8C9F9 /* Window.swift in Sources */,
00FF769EE4F24E03387EE327 /* Control+logTree.swift in Sources */,
00FF15120A8D075045D0C31A /* Node+logTree.swift in Sources */,
00FF02DFBDB02EF7CA6730AD /* log.swift in Sources */,
00FF5E51E93E85114A81C2ED /* AttributeScopes+SwiftTUIAttributes.swift in Sources */,
00FF9443A13020538EDF8602 /* Cell.swift in Sources */,
00FF29699AA621079339AEA2 /* CellAttributes.swift in Sources */,
00FF28471707BD8316B43410 /* Color.swift in Sources */,
00FFC77584E23F3984779346 /* Edges.swift in Sources */,
00FF38B4059491987FAEE965 /* Extended.swift in Sources */,
00FFDC2481C8A9ED7403DE2C /* Position.swift in Sources */,
00FF69CEE00F16C55B995EA3 /* Rect.swift in Sources */,
00FF40BBB288C62260CA76C3 /* EscapeSequence.swift in Sources */,
00FF79AAF9921EE12F892356 /* Layer.swift in Sources */,
00FF3A4B43C80D488C7CE32B /* LayerDrawing.swift in Sources */,
00FFF2E0DDE16A7D1010746B /* Renderer.swift in Sources */,
00FFDFD37AE54401B53A5ABB /* Size.swift in Sources */,
00FFB7DC9A3293ECE8393A58 /* Binding.swift in Sources */,
00FF4A4ABC004B5FF5637D01 /* Environment.swift in Sources */,
00FF3B45C9889ED370565846 /* ObservedObject.swift in Sources */,
00FF2C946200B58812B667DF /* State.swift in Sources */,
00FFEE3805EB06CFC8FC03C7 /* View+Environment.swift in Sources */,
00FF76C198B892A242BACBA0 /* View+ObservableObject.swift in Sources */,
00FF33C3B2D6D0317F653F20 /* View+State.swift in Sources */,
00FF49436AF208504407BD30 /* ASCII.swift in Sources */,
00FFF11402FCE9EA7A96512F /* Application.swift in Sources */,
00FF1F9002855C61CF31D72C /* ArrowKeyParser.swift in Sources */,
00FF1BC72723E836422B53B6 /* SwiftTUI.swift in Sources */,
00FF6E0FF588278BC1C0E96E /* ComposedView.swift in Sources */,
00FFC7BA845C5AB46EEDD9EC /* GenericView.swift in Sources */,
00FF24113C0B99C3349F0761 /* LayoutRootView.swift in Sources */,
00FF8259DABBDE007D9CA96C /* ModifierView.swift in Sources */,
00FFA88328D15EA01534CBB6 /* Node.swift in Sources */,
00FFB9C9BAB730C1E9019D6D /* PrimitiveView.swift in Sources */,
00FF0DE18E6C3150EE967582 /* View.swift in Sources */,
00FF0428EFF8BC4844DFEEF5 /* Weak.swift in Sources */,
00FFEE5BFF62FA2C9CE8512D /* WeakSet.swift in Sources */,
00FF7FEDD08A068D8D066266 /* Button.swift in Sources */,
00FF89E95841426E895D81E5 /* Color+View.swift in Sources */,
00FF65FFCD86BF306BEC3471 /* Divider.swift in Sources */,
00FFAC2EE02A2748301EB053 /* GeometryReader.swift in Sources */,
00FFF57F463FD5B6941F2333 /* ScrollView.swift in Sources */,
00FFCEF1BD7F380C94FAADB0 /* Spacer.swift in Sources */,
00FF23D86E413506C6F7DB25 /* Text.swift in Sources */,
00FF45B8E101B2B215011288 /* TextField.swift in Sources */,
00FFE75BB68A3EF17D60E39C /* EmptyView.swift in Sources */,
00FFAE6A70F1E1714BD84C61 /* ForEach.swift in Sources */,
00FFC6099114A3970F594B5A /* Group.swift in Sources */,
00FF86BDBAB1FB01FC69713C /* Background.swift in Sources */,
00FF0E0C217BCA513AA25E42 /* Bold.swift in Sources */,
00FF1F7CE9DEE5E71B7FD162 /* Border.swift in Sources */,
00FF17E30E5E434F1A61B03E /* FixedFrame.swift in Sources */,
00FF2570965BBE7BAABB7C8F /* FlexibleFrame.swift in Sources */,
00FF2E046DCFA53B787E8B14 /* ForegroundColor.swift in Sources */,
00FF159F585DA1FE891AC212 /* Italic.swift in Sources */,
00FFFD7F86C6332ACFE8E09A /* OnAppear.swift in Sources */,
00FF4600097791854D5254C8 /* Padding.swift in Sources */,
00FF7EBE80C2D2F703193AE2 /* SetEnvironment.swift in Sources */,
00FF187F7C193AE2DC5C0569 /* Strikethrough.swift in Sources */,
00FF377E17D813E1DF17B011 /* Underline.swift in Sources */,
00FFD84E8471C8E5126FC9E0 /* Optional+View.swift in Sources */,
00FF8C1E18A733FD0EE6B012 /* Alignment.swift in Sources */,
00FF0AA743B1E02D724F5F8C /* Axis.swift in Sources */,
00FF3907B1397417683BA7FC /* HStack.swift in Sources */,
00FF814531DF6F008282E112 /* VStack.swift in Sources */,
00FF5528E4594080E339FE5E /* ZStack.swift in Sources */,
00FFB8584ED0017DB11DE731 /* TupleView.swift in Sources */,
00FFB51099CAC91D5F78F022 /* ViewBuilder.swift in Sources */,
00FF8FA09DB2BD499064AC64 /* _ConditionalView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
00004EB553A7000000000100 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = arm64;
BAZEL_LABEL = "@@+http_archive+swifttui//:SwiftTUI";
BAZEL_OUTPUTS_PRODUCT = "bazel-out/darwin_arm64-dbg-ST-9a5aec5712f9/bin/external/+http_archive+swifttui/libSwiftTUI.a";
BAZEL_OUTPUTS_PRODUCT_BASENAME = libSwiftTUI.a;
BAZEL_PACKAGE_BIN_DIR = "bazel-out/darwin_arm64-dbg-ST-9a5aec5712f9/bin/external/+http_archive+swifttui";
BAZEL_TARGET_ID = "@@+http_archive+swifttui//:SwiftTUI darwin_arm64-dbg-ST-9a5aec5712f9";
COMPILE_TARGET_NAME = SwiftTUI;
MACOSX_DEPLOYMENT_TARGET = 26.5;
OTHER_SWIFT_FLAGS = "-Xcc -working-directory -Xcc $(PROJECT_DIR) -working-directory $(PROJECT_DIR) -enforce-exclusivity=checked -emit-const-values-path bazel-out/darwin_arm64-dbg-ST-9a5aec5712f9/bin/external/+http_archive+swifttui/SwiftTUI_objs/Sources/SwiftTUI/Controls/Control.swift.swiftconstvalues -DDEBUG -Onone -Xfrontend -internalize-at-link -enable-testing -disable-sandbox -file-compilation-dir . -Xcc -iquote -Xcc $(PROJECT_DIR) -Xcc -iquote -Xcc $(BAZEL_OUT)/darwin_arm64-dbg-ST-9a5aec5712f9/bin -Xfrontend -disable-clang-spi -enable-experimental-feature AccessLevelOnImport -static -Xcc -O0 -Xcc -DDEBUG=1 -Xcc -fstack-protector -Xcc -fstack-protector-all -Xfrontend -checked-async-objc-bridging=on";
PRODUCT_MODULE_NAME = SwiftTUI;
PRODUCT_NAME = SwiftTUI;
SDKROOT = macosx;
SUPPORTED_PLATFORMS = macosx;
SWIFT_ENABLE_EMIT_CONST_VALUES = NO;
TARGET_NAME = SwiftTUI;
};
name = Debug;
};
00004EB553A7000000000002 /* Build configuration list for PBXNativeTarget "SwiftTUI" */ = {
isa = XCConfigurationList;
buildConfigurations = (
00004EB553A7000000000100 /* Debug */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
00004EB553A70000000000FF /* libSwiftTUI.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSwiftTUI.a; sourceTree = BUILT_PRODUCTS_DIR; };
00004EB553A7000000000001 /* SwiftTUI */ = {
isa = PBXNativeTarget;
buildConfigurationList = 00004EB553A7000000000002 /* Build configuration list for PBXNativeTarget "SwiftTUI" */;
buildPhases = (
00004EB553A7000000000003 /* Copy Bazel Outputs / Generate Bazel Dependencies (Index Build) */,
00004EB553A7000000000006 /* Sources */,
);
buildRules = (
);
dependencies = (
00024EB553A7FF0001000000 /* PBXTargetDependency */,
);
name = SwiftTUI;
productName = SwiftTUI;
productType = "com.apple.product-type.library.static";
};
0100FAB81B6F000000000003 /* Copy Bazel Outputs / Generate Bazel Dependencies (Index Build) */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Bazel Outputs / Generate Bazel Dependencies (Index Build)";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "set -euo pipefail\n\nif [[ \"$ACTION\" == \"indexbuild\" ]]; then\n cd \"$SRCROOT\"\n\n \"$BAZEL_INTEGRATION_DIR/generate_index_build_bazel_dependencies.sh\"\nelse\n \"$BAZEL_INTEGRATION_DIR/copy_outputs.sh\" \\\n \"_BazelForcedCompile_.swift\" \\\n \"\"\nfi\n";
showEnvVarsInLog = 0;
};
0100FAB81B6F000000000005 /* Create Link Dependencies */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(LINK_PARAMS_FILE)",
);
name = "Create Link Dependencies";
outputPaths = (
"$(DERIVED_FILE_DIR)/link.params",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "set -euo pipefail\n\nif [[ \"${ENABLE_PREVIEWS:-}\" == \"YES\" ]]; then\nperl -pe 's/\\$(\\()?([a-zA-Z_]\\w*)(?(1)\\))/$ENV{$2}/g' \\\n \"$SCRIPT_INPUT_FILE_0\" > \"$SCRIPT_OUTPUT_FILE_0\"\nelse\n touch \"$SCRIPT_OUTPUT_FILE_0\"\nfi\n";
showEnvVarsInLog = 0;
};
0100FAB81B6F000000000006 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
01FF556AC73989CC680307A3 /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0100FAB81B6F000000000100 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = arm64;
BAZEL_LABEL = "@@//m323/Sources/MiniProject:StadtRundlauf";
BAZEL_OUTPUTS_PRODUCT = "bazel-out/darwin_arm64-dbg-ST-9a5aec5712f9/bin/m323/Sources/MiniProject/StadtRundlauf_codesigned";
BAZEL_OUTPUTS_PRODUCT_BASENAME = StadtRundlauf_codesigned;
BAZEL_PACKAGE_BIN_DIR = "bazel-out/darwin_arm64-dbg-ST-9a5aec5712f9/bin/m323/Sources/MiniProject";
BAZEL_TARGET_ID = "@@//m323/Sources/MiniProject:StadtRundlauf darwin_arm64-dbg-ST-9a5aec5712f9";
COMPILE_TARGET_NAME = StadtRundlauf;
EXECUTABLE_EXTENSION = "";
LINK_PARAMS_FILE = "$(BAZEL_OUT)/darwin_arm64-dbg-ST-9a5aec5712f9/bin/m323/Sources/MiniProject/StadtRundlauf.rules_xcodeproj.link.params";
MACOSX_DEPLOYMENT_TARGET = 26.5;
OTHER_LDFLAGS = "@$(DERIVED_FILE_DIR)/link.params";
OTHER_SWIFT_FLAGS = "-Xcc -working-directory -Xcc $(PROJECT_DIR) -working-directory $(PROJECT_DIR) -enforce-exclusivity=checked -emit-const-values-path bazel-out/darwin_arm64-dbg-ST-9a5aec5712f9/bin/m323/Sources/MiniProject/StadtRundlauf_objs/main.swift.swiftconstvalues -DDEBUG -Onone -Xfrontend -internalize-at-link -enable-testing -disable-sandbox -file-compilation-dir . -I$(BAZEL_OUT)/darwin_arm64-dbg-ST-9a5aec5712f9/bin/external/+http_archive+swifttui -Xcc -iquote -Xcc $(PROJECT_DIR) -Xcc -iquote -Xcc $(BAZEL_OUT)/darwin_arm64-dbg-ST-9a5aec5712f9/bin -Xfrontend -disable-clang-spi -enable-experimental-feature AccessLevelOnImport -Xfrontend -entry-point-function-name -Xfrontend m323_Sources_MiniProject_StadtRundlauf_main -Xcc -O0 -Xcc -DDEBUG=1 -Xcc -fstack-protector -Xcc -fstack-protector-all -Xfrontend -checked-async-objc-bridging=on";
PRODUCT_MODULE_NAME = m323_Sources_MiniProject_StadtRundlauf;
PRODUCT_NAME = StadtRundlauf;
SDKROOT = macosx;
SUPPORTED_PLATFORMS = macosx;
SWIFT_ENABLE_EMIT_CONST_VALUES = NO;
TARGET_NAME = StadtRundlauf;
};
name = Debug;
};
0100FAB81B6F000000000002 /* Build configuration list for PBXNativeTarget "StadtRundlauf" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0100FAB81B6F000000000100 /* Debug */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
0100FAB81B6F0000000000FF /* StadtRundlauf */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = StadtRundlauf; sourceTree = BUILT_PRODUCTS_DIR; };
0100FAB81B6F000000000001 /* StadtRundlauf */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0100FAB81B6F000000000002 /* Build configuration list for PBXNativeTarget "StadtRundlauf" */;
buildPhases = (
0100FAB81B6F000000000003 /* Copy Bazel Outputs / Generate Bazel Dependencies (Index Build) */,
0100FAB81B6F000000000005 /* Create Link Dependencies */,
0100FAB81B6F000000000006 /* Sources */,
);
buildRules = (
);
dependencies = (
0102FAB81B6FFF0001000000 /* PBXTargetDependency */,
);
name = StadtRundlauf;
productName = StadtRundlauf;
productReference = 0100FAB81B6F0000000000FF /* StadtRundlauf */;
productType = "com.apple.product-type.tool";
};
0101FAB81B6FFF0001000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = FF0000000000000000000001 /* Project object */;
proxyType = 1;
remoteGlobalIDString = FF0100000000000000000001;
remoteInfo = BazelDependencies;
};
0102FAB81B6FFF0001000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = BazelDependencies;
target = FF0100000000000000000001 /* BazelDependencies */;
targetProxy = 0101FAB81B6FFF0001000000 /* PBXContainerItemProxy */;
};
00014EB553A7FF0001000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = FF0000000000000000000001 /* Project object */;
proxyType = 1;
remoteGlobalIDString = FF0100000000000000000001;
remoteInfo = BazelDependencies;
};
00024EB553A7FF0001000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = BazelDependencies;
target = FF0100000000000000000001 /* BazelDependencies */;
targetProxy = 00014EB553A7FF0001000000 /* PBXContainerItemProxy */;
};
FF0000000000000000000003 /* /Users/cediackermann/Projects */ = {
isa = PBXGroup;
children = (
FE0B6A8C2E81F8461958AA13 /* m323 */,
FF0000000000000000000006 /* Bazel External Repositories */,
FF0000000000000000000004 /* Products */,
FF0000000000000000000005 /* Frameworks */,
);
path = /Users/cediackermann/Projects;
sourceTree = "<absolute>";
};
FE0256EB086C79D047D00FE0 /* ObservedObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservedObject.swift; sourceTree = "<group>"; };
FE04B709B3969540B2E9FBF6 /* GeometryReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeometryReader.swift; sourceTree = "<group>"; };
FE06B75F1D71891F3D634B95 /* log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = log.swift; sourceTree = "<group>"; };
FE0833F786CD2A2EF231EBE5 /* Strikethrough.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strikethrough.swift; sourceTree = "<group>"; };
FE0B6A8C2E81F8461958AA13 /* m323 */ = {
isa = PBXGroup;
children = (
FE33D36F2BFBBE20D6696EBB /* Sources */,
);
path = m323;
sourceTree = "<group>";
};
FE0FE8D7E60C3D79B2E83B9C /* ViewBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewBuilder.swift; sourceTree = "<group>"; };
FE1459FA19AD7E743575B55F /* Sources */ = {
isa = PBXGroup;
children = (
FEF05B9E4558F03213B7E607 /* SwiftTUI */,
);
path = Sources;
sourceTree = "<group>";
};
FE1D3E792C9AB2D0FEA7D0A2 /* ModifierView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModifierView.swift; sourceTree = "<group>"; };
FE1D5FAB1C88913D40911281 /* HStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HStack.swift; sourceTree = "<group>"; };
FE230A21685D7895A8803FF1 /* ScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollView.swift; sourceTree = "<group>"; };
FE235631F812A101E01AEAA5 /* Debug */ = {
isa = PBXGroup;
children = (
FE9EBAED75B41BFE5B66EF7B /* Control+logTree.swift */,
FE06B75F1D71891F3D634B95 /* log.swift */,
FE5C2DBA399E0612A054BE2E /* Node+logTree.swift */,
);
path = Debug;
sourceTree = "<group>";
};
FE24A664919669AC0926796A /* Binding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Binding.swift; sourceTree = "<group>"; };
FE25780E4212F6D462FB9149 /* SwiftTUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTUI.swift; sourceTree = "<group>"; };
FE28ED61A3E441791C892614 /* View+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+State.swift"; sourceTree = "<group>"; };
FE2F2B1FD47D4F1B77B16984 /* Control.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Control.swift; sourceTree = "<group>"; };
FE3348E7805B88D20C67D624 /* Underline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Underline.swift; sourceTree = "<group>"; };
FE335FCA49CCC6A3C60B53B5 /* Window.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Window.swift; sourceTree = "<group>"; };
FE33D36F2BFBBE20D6696EBB /* Sources */ = {
isa = PBXGroup;
children = (
FE8CD80AE6A7E8A5A94B63EF /* MiniProject */,
);
path = Sources;
sourceTree = "<group>";
};
FE359F43A055950CD2C4031A /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
FE36B7FB4825960CFD1EE9A0 /* ComposedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposedView.swift; sourceTree = "<group>"; };
FE39E81DC7BE1BDBF278368B /* SetEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetEnvironment.swift; sourceTree = "<group>"; };
FE3DF55F9C9C4BC3D6031FE4 /* FixedFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FixedFrame.swift; sourceTree = "<group>"; };
FE406681BF50D14C2B003EFA /* Padding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Padding.swift; sourceTree = "<group>"; };
FE47FE759AEAC5FE3B48E859 /* Rendering */ = {
isa = PBXGroup;
children = (
FE9FA50882B24965E3924A03 /* EscapeSequence.swift */,
FE59CDA3C4C23D3DCD619C36 /* Layer.swift */,
FE6C1FBF148386BCCB815946 /* LayerDrawing.swift */,
FEB6D73210F2E5F83E8C6A60 /* Renderer.swift */,
);
path = Rendering;
sourceTree = "<group>";
};
FE48F0B66A1921E14F62F077 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
FE4D287FEC68A8A72B76FA83 /* ViewGraph */ = {
isa = PBXGroup;
children = (
FE36B7FB4825960CFD1EE9A0 /* ComposedView.swift */,
FEAF08A52EEFA7CD8D7ACB91 /* GenericView.swift */,
FEEC8BA2E9A611FB242868D5 /* LayoutRootView.swift */,
FE1D3E792C9AB2D0FEA7D0A2 /* ModifierView.swift */,
FE955B7713691568C9113C22 /* Node.swift */,
FECDEC291E284E1243C69040 /* PrimitiveView.swift */,
FE97FC495C03EB6918A8AA5B /* View.swift */,
FE9FB11AE896BAE161926281 /* Weak.swift */,
FED14FCCEFFF6DEE187B47AF /* WeakSet.swift */,
);
path = ViewGraph;
sourceTree = "<group>";
};
FE4EC1526AFF23247D74D7E5 /* data */ = {
isa = PBXGroup;
children = (
FE720DFDDF5040A4048EB874 /* results.txt */,
FEBCFF654996A2FFA2F886E2 /* startList.txt */,
);
path = data;
sourceTree = "<group>";
};
FE50953DAFB8366A9E3C8D82 /* Views */ = {
isa = PBXGroup;
children = (
FE83C49A0278488FE260EB00 /* Controls */,
FEADBAABCB31677B191DFF6D /* Modifiers */,
FEAF3ED835721EE1EE7E90FD /* Stacks */,
FE7CE4A8C0BEDBFEB07D7052 /* _ConditionalView.swift */,
FE7E35A8870F6ECDB585186F /* EmptyView.swift */,
FE645B3378625EF192815274 /* ForEach.swift */,
FEF83A958022D95AB0510862 /* Group.swift */,
FE7B02AD81BAA59E17ABF025 /* Optional+View.swift */,
FE6E5D2B3020404DBED9B8FA /* TupleView.swift */,
FE0FE8D7E60C3D79B2E83B9C /* ViewBuilder.swift */,
);
path = Views;
sourceTree = "<group>";
};
FE565F9C1E240AF078068CC4 /* Bold.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bold.swift; sourceTree = "<group>"; };
FE56C3242B58455553442D0C /* Controls */ = {
isa = PBXGroup;
children = (
FE2F2B1FD47D4F1B77B16984 /* Control.swift */,
FE335FCA49CCC6A3C60B53B5 /* Window.swift */,
);
path = Controls;
sourceTree = "<group>";
};
FE56EC4E9A199BCE5A4F11A9 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
FE579D8399C4C1DCC8EED430 /* Italic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Italic.swift; sourceTree = "<group>"; };
FE59CDA3C4C23D3DCD619C36 /* Layer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Layer.swift; sourceTree = "<group>"; };
FE5C2DBA399E0612A054BE2E /* Node+logTree.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Node+logTree.swift"; sourceTree = "<group>"; };
FE645B3378625EF192815274 /* ForEach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForEach.swift; sourceTree = "<group>"; };
FE65E264CB4E0B80A1AFFB0C /* RunLoop */ = {
isa = PBXGroup;
children = (
FE48F0B66A1921E14F62F077 /* Application.swift */,
FEA362915EE372841E810442 /* ArrowKeyParser.swift */,
FE97AC026E7A91BD7F6FADDF /* ASCII.swift */,
);
path = RunLoop;
sourceTree = "<group>";
};
FE669B47061526964E8012FF /* Text.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Text.swift; sourceTree = "<group>"; };
FE6BA5124AB5DCB7C1C69060 /* OnAppear.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnAppear.swift; sourceTree = "<group>"; };
FE6C1FBF148386BCCB815946 /* LayerDrawing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayerDrawing.swift; sourceTree = "<group>"; };
FE6CB92FA70E5A7EE190EB1E /* FlexibleFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlexibleFrame.swift; sourceTree = "<group>"; };
FE6E5D2B3020404DBED9B8FA /* TupleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TupleView.swift; sourceTree = "<group>"; };
FE720DFDDF5040A4048EB874 /* results.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = results.txt; sourceTree = "<group>"; };
FE78B3B9FF062FE5A86D10CB /* Alignment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alignment.swift; sourceTree = "<group>"; };
FE7ADB44C83312F759326BC8 /* Rect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Rect.swift; sourceTree = "<group>"; };
FE7B02AD81BAA59E17ABF025 /* Optional+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+View.swift"; sourceTree = "<group>"; };
FE7CE4A8C0BEDBFEB07D7052 /* _ConditionalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _ConditionalView.swift; sourceTree = "<group>"; };
FE7E35A8870F6ECDB585186F /* EmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyView.swift; sourceTree = "<group>"; };
FE7E6DAF3716429D85DF1CB4 /* AttributeScopes+SwiftTUIAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttributeScopes+SwiftTUIAttributes.swift"; sourceTree = "<group>"; };
FE83C49A0278488FE260EB00 /* Controls */ = {
isa = PBXGroup;
children = (
FE56EC4E9A199BCE5A4F11A9 /* Button.swift */,
FE87BA54DCED0BC71F4DDCBC /* Color+View.swift */,
FE8F75BC675A850D30B1DFF7 /* Divider.swift */,
FE04B709B3969540B2E9FBF6 /* GeometryReader.swift */,
FE230A21685D7895A8803FF1 /* ScrollView.swift */,
FEFFB379E67528ADA003A9FF /* Spacer.swift */,
FE669B47061526964E8012FF /* Text.swift */,
FEFEB64A0F9ECD99B9D903B6 /* TextField.swift */,
);
path = Controls;
sourceTree = "<group>";
};
FE866088E045EAB828EAE645 /* Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Size.swift; sourceTree = "<group>"; };
FE87BA54DCED0BC71F4DDCBC /* Color+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+View.swift"; sourceTree = "<group>"; };
FE88BA287622CAA44EEFBB05 /* Cell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cell.swift; sourceTree = "<group>"; };
FE8A46FC66E9580571ECE3D7 /* VStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VStack.swift; sourceTree = "<group>"; };
FE8CD80AE6A7E8A5A94B63EF /* MiniProject */ = {
isa = PBXGroup;
children = (
FE4EC1526AFF23247D74D7E5 /* data */,
FE91213EB706159A32807EEC /* BUILD.bazel */,
FE359F43A055950CD2C4031A /* main.swift */,
);
path = MiniProject;
sourceTree = "<group>";
};
FE8F75BC675A850D30B1DFF7 /* Divider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Divider.swift; sourceTree = "<group>"; };
FE91213EB706159A32807EEC /* BUILD.bazel */ = {isa = PBXFileReference; explicitFileType = text.script.python; path = BUILD.bazel; sourceTree = "<group>"; };
FE91AD15BF6BBB472852849F /* Position.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Position.swift; sourceTree = "<group>"; };
FE94FB30E7CAB9941E04149F /* ForegroundColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForegroundColor.swift; sourceTree = "<group>"; };
FE955B7713691568C9113C22 /* Node.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = "<group>"; };
FE97AC026E7A91BD7F6FADDF /* ASCII.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASCII.swift; sourceTree = "<group>"; };
FE97FC495C03EB6918A8AA5B /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
FE981D88F74E1B0E237FF17A /* Extended.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extended.swift; sourceTree = "<group>"; };
FE9B6E8AD18CF510CC2C3174 /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
FE9EBAED75B41BFE5B66EF7B /* Control+logTree.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Control+logTree.swift"; sourceTree = "<group>"; };
FE9FA50882B24965E3924A03 /* EscapeSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EscapeSequence.swift; sourceTree = "<group>"; };
FE9FB11AE896BAE161926281 /* Weak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; };
FEA154E5D35B7BAA846E52FB /* Drawing */ = {
isa = PBXGroup;
children = (
FE47FE759AEAC5FE3B48E859 /* Rendering */,
FE7E6DAF3716429D85DF1CB4 /* AttributeScopes+SwiftTUIAttributes.swift */,
FE88BA287622CAA44EEFBB05 /* Cell.swift */,
FEB71BE6A8588DC0A820ED8E /* CellAttributes.swift */,
FE9B6E8AD18CF510CC2C3174 /* Color.swift */,
FED4C93198EC989AFB18C04D /* Edges.swift */,
FE981D88F74E1B0E237FF17A /* Extended.swift */,
FE91AD15BF6BBB472852849F /* Position.swift */,
FE7ADB44C83312F759326BC8 /* Rect.swift */,
FE866088E045EAB828EAE645 /* Size.swift */,
);
path = Drawing;
sourceTree = "<group>";
};
FEA171F995F100B4E80C25E3 /* View+ObservableObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+ObservableObject.swift"; sourceTree = "<group>"; };
FEA1CF9F8D2CA0B5F0D761B1 /* /Users/cediackermann/Library/Caches/bazel/_bazel_cediackermann/cache/repos/v1/contents/232e8b46dfa0c534358dfb71034ddfd32c5c6d6afb7bb7c3476b660b0b7d70e2/677a2cff-5ccc-47a7-98e4-ddce6cf76076 */ = {
isa = PBXGroup;
children = (
FE1459FA19AD7E743575B55F /* Sources */,
);
name = "+http_archive+swifttui";
path = "/Users/cediackermann/Library/Caches/bazel/_bazel_cediackermann/cache/repos/v1/contents/232e8b46dfa0c534358dfb71034ddfd32c5c6d6afb7bb7c3476b660b0b7d70e2/677a2cff-5ccc-47a7-98e4-ddce6cf76076";
sourceTree = "<absolute>";
};
FEA362915EE372841E810442 /* ArrowKeyParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowKeyParser.swift; sourceTree = "<group>"; };
FEADBAABCB31677B191DFF6D /* Modifiers */ = {
isa = PBXGroup;
children = (
FEF5075DC088803278713767 /* Background.swift */,
FE565F9C1E240AF078068CC4 /* Bold.swift */,
FEB681E54A115EA32E615BFB /* Border.swift */,
FE3DF55F9C9C4BC3D6031FE4 /* FixedFrame.swift */,
FE6CB92FA70E5A7EE190EB1E /* FlexibleFrame.swift */,
FE94FB30E7CAB9941E04149F /* ForegroundColor.swift */,
FE579D8399C4C1DCC8EED430 /* Italic.swift */,
FE6BA5124AB5DCB7C1C69060 /* OnAppear.swift */,
FE406681BF50D14C2B003EFA /* Padding.swift */,
FE39E81DC7BE1BDBF278368B /* SetEnvironment.swift */,
FE0833F786CD2A2EF231EBE5 /* Strikethrough.swift */,
FE3348E7805B88D20C67D624 /* Underline.swift */,
);
path = Modifiers;
sourceTree = "<group>";
};
FEAF08A52EEFA7CD8D7ACB91 /* GenericView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericView.swift; sourceTree = "<group>"; };
FEAF3ED835721EE1EE7E90FD /* Stacks */ = {
isa = PBXGroup;
children = (
FE78B3B9FF062FE5A86D10CB /* Alignment.swift */,
FED12C36473686FE93CB971C /* Axis.swift */,
FE1D5FAB1C88913D40911281 /* HStack.swift */,
FE8A46FC66E9580571ECE3D7 /* VStack.swift */,
FECF34CCEB582E63F618344C /* ZStack.swift */,
);
path = Stacks;
sourceTree = "<group>";
};
FEB681E54A115EA32E615BFB /* Border.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Border.swift; sourceTree = "<group>"; };
FEB6D73210F2E5F83E8C6A60 /* Renderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Renderer.swift; sourceTree = "<group>"; };
FEB71BE6A8588DC0A820ED8E /* CellAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellAttributes.swift; sourceTree = "<group>"; };
FEBCFF654996A2FFA2F886E2 /* startList.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = startList.txt; sourceTree = "<group>"; };
FEC2266FC2A8266E62E079AC /* PropertyWrappers */ = {
isa = PBXGroup;
children = (
FE24A664919669AC0926796A /* Binding.swift */,
FEC35B1294C0C3A5487073C1 /* Environment.swift */,
FE0256EB086C79D047D00FE0 /* ObservedObject.swift */,
FEEB3ECD861EEC2801B03652 /* State.swift */,
FEDEA3D2E3B24689EE2C2D07 /* View+Environment.swift */,
FEA171F995F100B4E80C25E3 /* View+ObservableObject.swift */,
FE28ED61A3E441791C892614 /* View+State.swift */,
);
path = PropertyWrappers;
sourceTree = "<group>";
};
FEC35B1294C0C3A5487073C1 /* Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = "<group>"; };
FECDEC291E284E1243C69040 /* PrimitiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimitiveView.swift; sourceTree = "<group>"; };
FECF34CCEB582E63F618344C /* ZStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZStack.swift; sourceTree = "<group>"; };
FED12C36473686FE93CB971C /* Axis.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Axis.swift; sourceTree = "<group>"; };
FED14FCCEFFF6DEE187B47AF /* WeakSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakSet.swift; sourceTree = "<group>"; };
FED4C93198EC989AFB18C04D /* Edges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Edges.swift; sourceTree = "<group>"; };
FEDEA3D2E3B24689EE2C2D07 /* View+Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Environment.swift"; sourceTree = "<group>"; };
FEEB3ECD861EEC2801B03652 /* State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = State.swift; sourceTree = "<group>"; };
FEEC8BA2E9A611FB242868D5 /* LayoutRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutRootView.swift; sourceTree = "<group>"; };
FEF05B9E4558F03213B7E607 /* SwiftTUI */ = {
isa = PBXGroup;
children = (
FE56C3242B58455553442D0C /* Controls */,
FE235631F812A101E01AEAA5 /* Debug */,
FEA154E5D35B7BAA846E52FB /* Drawing */,
FEC2266FC2A8266E62E079AC /* PropertyWrappers */,
FE65E264CB4E0B80A1AFFB0C /* RunLoop */,
FE4D287FEC68A8A72B76FA83 /* ViewGraph */,
FE50953DAFB8366A9E3C8D82 /* Views */,
FE25780E4212F6D462FB9149 /* SwiftTUI.swift */,
);
path = SwiftTUI;
sourceTree = "<group>";
};
FEF5075DC088803278713767 /* Background.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Background.swift; sourceTree = "<group>"; };
FEF83A958022D95AB0510862 /* Group.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Group.swift; sourceTree = "<group>"; };
FEFEB64A0F9ECD99B9D903B6 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
FEFFB379E67528ADA003A9FF /* Spacer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Spacer.swift; sourceTree = "<group>"; };
FF0000000000000000000006 /* Bazel External Repositories */ = {
isa = PBXGroup;
children = (
FEA1CF9F8D2CA0B5F0D761B1 /* /Users/cediackermann/Library/Caches/bazel/_bazel_cediackermann/cache/repos/v1/contents/232e8b46dfa0c534358dfb71034ddfd32c5c6d6afb7bb7c3476b660b0b7d70e2/677a2cff-5ccc-47a7-98e4-ddce6cf76076 */,
);
name = "Bazel External Repositories";
path = ../../external;
sourceTree = SOURCE_ROOT;
};
00FF02DFBDB02EF7CA6730AD /* log.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE06B75F1D71891F3D634B95 /* log.swift */; };
00FF0428EFF8BC4844DFEEF5 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE9FB11AE896BAE161926281 /* Weak.swift */; };
00FF0AA743B1E02D724F5F8C /* Axis.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED12C36473686FE93CB971C /* Axis.swift */; };
00FF0DE18E6C3150EE967582 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE97FC495C03EB6918A8AA5B /* View.swift */; };
00FF0E0C217BCA513AA25E42 /* Bold.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE565F9C1E240AF078068CC4 /* Bold.swift */; };
00FF15120A8D075045D0C31A /* Node+logTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE5C2DBA399E0612A054BE2E /* Node+logTree.swift */; };
00FF159F585DA1FE891AC212 /* Italic.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE579D8399C4C1DCC8EED430 /* Italic.swift */; };
00FF17E30E5E434F1A61B03E /* FixedFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE3DF55F9C9C4BC3D6031FE4 /* FixedFrame.swift */; };
00FF187F7C193AE2DC5C0569 /* Strikethrough.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE0833F786CD2A2EF231EBE5 /* Strikethrough.swift */; };
00FF1BC72723E836422B53B6 /* SwiftTUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE25780E4212F6D462FB9149 /* SwiftTUI.swift */; };
00FF1F7CE9DEE5E71B7FD162 /* Border.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEB681E54A115EA32E615BFB /* Border.swift */; };
00FF1F9002855C61CF31D72C /* ArrowKeyParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEA362915EE372841E810442 /* ArrowKeyParser.swift */; };
00FF23D86E413506C6F7DB25 /* Text.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE669B47061526964E8012FF /* Text.swift */; };
00FF24113C0B99C3349F0761 /* LayoutRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEC8BA2E9A611FB242868D5 /* LayoutRootView.swift */; };
00FF2570965BBE7BAABB7C8F /* FlexibleFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE6CB92FA70E5A7EE190EB1E /* FlexibleFrame.swift */; };
00FF28471707BD8316B43410 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE9B6E8AD18CF510CC2C3174 /* Color.swift */; };
00FF29699AA621079339AEA2 /* CellAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEB71BE6A8588DC0A820ED8E /* CellAttributes.swift */; };
00FF2C946200B58812B667DF /* State.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEB3ECD861EEC2801B03652 /* State.swift */; };
00FF2E046DCFA53B787E8B14 /* ForegroundColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE94FB30E7CAB9941E04149F /* ForegroundColor.swift */; };
00FF33C3B2D6D0317F653F20 /* View+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE28ED61A3E441791C892614 /* View+State.swift */; };
00FF377E17D813E1DF17B011 /* Underline.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE3348E7805B88D20C67D624 /* Underline.swift */; };
00FF38B4059491987FAEE965 /* Extended.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE981D88F74E1B0E237FF17A /* Extended.swift */; };
00FF3907B1397417683BA7FC /* HStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE1D5FAB1C88913D40911281 /* HStack.swift */; };
00FF3A4B43C80D488C7CE32B /* LayerDrawing.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE6C1FBF148386BCCB815946 /* LayerDrawing.swift */; };
00FF3B45C9889ED370565846 /* ObservedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE0256EB086C79D047D00FE0 /* ObservedObject.swift */; };
00FF40BBB288C62260CA76C3 /* EscapeSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE9FA50882B24965E3924A03 /* EscapeSequence.swift */; };
00FF45B8E101B2B215011288 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFEB64A0F9ECD99B9D903B6 /* TextField.swift */; };
00FF4600097791854D5254C8 /* Padding.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE406681BF50D14C2B003EFA /* Padding.swift */; };
00FF49436AF208504407BD30 /* ASCII.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE97AC026E7A91BD7F6FADDF /* ASCII.swift */; };
00FF4A4ABC004B5FF5637D01 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC35B1294C0C3A5487073C1 /* Environment.swift */; };
00FF5528E4594080E339FE5E /* ZStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = FECF34CCEB582E63F618344C /* ZStack.swift */; };
00FF5E51E93E85114A81C2ED /* AttributeScopes+SwiftTUIAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE7E6DAF3716429D85DF1CB4 /* AttributeScopes+SwiftTUIAttributes.swift */; };
00FF65FFCD86BF306BEC3471 /* Divider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8F75BC675A850D30B1DFF7 /* Divider.swift */; };
00FF69CEE00F16C55B995EA3 /* Rect.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE7ADB44C83312F759326BC8 /* Rect.swift */; };
00FF6E0FF588278BC1C0E96E /* ComposedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE36B7FB4825960CFD1EE9A0 /* ComposedView.swift */; };
00FF769EE4F24E03387EE327 /* Control+logTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE9EBAED75B41BFE5B66EF7B /* Control+logTree.swift */; };
00FF76C198B892A242BACBA0 /* View+ObservableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEA171F995F100B4E80C25E3 /* View+ObservableObject.swift */; };
00FF79AAF9921EE12F892356 /* Layer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE59CDA3C4C23D3DCD619C36 /* Layer.swift */; };
00FF7EBE80C2D2F703193AE2 /* SetEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE39E81DC7BE1BDBF278368B /* SetEnvironment.swift */; };
00FF7FEDD08A068D8D066266 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE56EC4E9A199BCE5A4F11A9 /* Button.swift */; };
00FF814531DF6F008282E112 /* VStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8A46FC66E9580571ECE3D7 /* VStack.swift */; };
00FF8259DABBDE007D9CA96C /* ModifierView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE1D3E792C9AB2D0FEA7D0A2 /* ModifierView.swift */; };
00FF86BDBAB1FB01FC69713C /* Background.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEF5075DC088803278713767 /* Background.swift */; };
00FF89E95841426E895D81E5 /* Color+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE87BA54DCED0BC71F4DDCBC /* Color+View.swift */; };
00FF8C1E18A733FD0EE6B012 /* Alignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE78B3B9FF062FE5A86D10CB /* Alignment.swift */; };
00FF8FA09DB2BD499064AC64 /* _ConditionalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE7CE4A8C0BEDBFEB07D7052 /* _ConditionalView.swift */; };
00FF9443A13020538EDF8602 /* Cell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE88BA287622CAA44EEFBB05 /* Cell.swift */; };
00FFA88328D15EA01534CBB6 /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE955B7713691568C9113C22 /* Node.swift */; };
00FFAC2EE02A2748301EB053 /* GeometryReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE04B709B3969540B2E9FBF6 /* GeometryReader.swift */; };
00FFAE6A70F1E1714BD84C61 /* ForEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE645B3378625EF192815274 /* ForEach.swift */; };
00FFB51099CAC91D5F78F022 /* ViewBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE0FE8D7E60C3D79B2E83B9C /* ViewBuilder.swift */; };
00FFB7DC9A3293ECE8393A58 /* Binding.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE24A664919669AC0926796A /* Binding.swift */; };
00FFB8584ED0017DB11DE731 /* TupleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE6E5D2B3020404DBED9B8FA /* TupleView.swift */; };
00FFB9C9BAB730C1E9019D6D /* PrimitiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FECDEC291E284E1243C69040 /* PrimitiveView.swift */; };
00FFC6099114A3970F594B5A /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEF83A958022D95AB0510862 /* Group.swift */; };
00FFC77584E23F3984779346 /* Edges.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED4C93198EC989AFB18C04D /* Edges.swift */; };
00FFC7BA845C5AB46EEDD9EC /* GenericView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEAF08A52EEFA7CD8D7ACB91 /* GenericView.swift */; };
00FFC927145F56EA91D8C9F9 /* Window.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE335FCA49CCC6A3C60B53B5 /* Window.swift */; };
00FFC950564A0A8E85DE76AA /* Control.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE2F2B1FD47D4F1B77B16984 /* Control.swift */; };
00FFCEF1BD7F380C94FAADB0 /* Spacer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFFB379E67528ADA003A9FF /* Spacer.swift */; };
00FFD84E8471C8E5126FC9E0 /* Optional+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE7B02AD81BAA59E17ABF025 /* Optional+View.swift */; };
00FFDC2481C8A9ED7403DE2C /* Position.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE91AD15BF6BBB472852849F /* Position.swift */; };
00FFDFD37AE54401B53A5ABB /* Size.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE866088E045EAB828EAE645 /* Size.swift */; };
00FFE75BB68A3EF17D60E39C /* EmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE7E35A8870F6ECDB585186F /* EmptyView.swift */; };
00FFEE3805EB06CFC8FC03C7 /* View+Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEDEA3D2E3B24689EE2C2D07 /* View+Environment.swift */; };
00FFEE5BFF62FA2C9CE8512D /* WeakSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED14FCCEFFF6DEE187B47AF /* WeakSet.swift */; };
00FFF11402FCE9EA7A96512F /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE48F0B66A1921E14F62F077 /* Application.swift */; };
00FFF2E0DDE16A7D1010746B /* Renderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEB6D73210F2E5F83E8C6A60 /* Renderer.swift */; };
00FFF57F463FD5B6941F2333 /* ScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE230A21685D7895A8803FF1 /* ScrollView.swift */; };
00FFFD7F86C6332ACFE8E09A /* OnAppear.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE6BA5124AB5DCB7C1C69060 /* OnAppear.swift */; };
01FF556AC73989CC680307A3 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE359F43A055950CD2C4031A /* main.swift */; };
FF0000000000000000000004 /* Products */ = {
isa = PBXGroup;
children = (
00004EB553A70000000000FF /* libSwiftTUI.a */,
0100FAB81B6F0000000000FF /* StadtRundlauf */,
);
name = Products;
sourceTree = "<group>";
};
FF0000000000000000000005 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
};
rootObject = FF0000000000000000000001 /* Project object */;
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>

View file

@ -0,0 +1,109 @@
#!/usr/bin/python3
"""An lldb module that registers a stop hook to set swift settings."""
import lldb
import re
# Order matters, it needs to be from the most nested to the least
_BUNDLE_EXTENSIONS = [
".framework",
".xctest",
".appex",
".bundle",
".app",
]
_TRIPLE_MATCH = re.compile(r"([^-]+-[^-]+)(-\D+)[^-]*(-.*)?")
_SETTINGS = {
"arm64-apple-macosx StadtRundlauf": {
"c": "-iquote$(PROJECT_DIR) -iquote$(BAZEL_OUT)/darwin_arm64-dbg-ST-9a5aec5712f9/bin -O0 -DDEBUG=1 -fstack-protector -fstack-protector-all",
"s": [
"$(BAZEL_OUT)/darwin_arm64-dbg-ST-9a5aec5712f9/bin/external/+http_archive+swifttui",
],
},
}
def __lldb_init_module(debugger, _internal_dict):
# Register the stop hook when this module is loaded in lldb
ci = debugger.GetCommandInterpreter()
res = lldb.SBCommandReturnObject()
ci.HandleCommand(
"target stop-hook add -P swift_debug_settings.StopHook",
res,
)
if not res.Succeeded():
print(f"""\
Failed to register Swift debug options stop hook:
{res.GetError()}
Please file a bug report here: \
https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md
""")
return
def _get_relative_executable_path(module):
for extension in _BUNDLE_EXTENSIONS:
prefix, _, suffix = module.rpartition(extension)
if prefix:
return prefix.split("/")[-1] + extension + suffix
return module.split("/")[-1]
class StopHook:
"An lldb stop hook class, that sets swift settings for the current module."
def __init__(self, _target, _extra_args, _internal_dict):
pass
def handle_stop(self, exe_ctx, _stream):
"Method that is called when the user stops in lldb."
module = exe_ctx.frame.module
if not module:
return
module_name = module.file.GetDirectory() + "/" + module.file.GetFilename()
versionless_triple = _TRIPLE_MATCH.sub(r"\1\2\3", module.GetTriple())
executable_path = _get_relative_executable_path(module_name)
key = f"{versionless_triple} {executable_path}"
settings = _SETTINGS.get(key)
if settings:
frameworks = " ".join([
f'"{path}"'
for path in settings.get("f", [])
])
if frameworks:
lldb.debugger.HandleCommand(
f"settings set -- target.swift-framework-search-paths {frameworks}",
)
else:
lldb.debugger.HandleCommand(
"settings clear target.swift-framework-search-paths",
)
includes = " ".join([
f'"{path}"'
for path in settings.get("s", [])
])
if includes:
lldb.debugger.HandleCommand(
f"settings set -- target.swift-module-search-paths {includes}",
)
else:
lldb.debugger.HandleCommand(
"settings clear target.swift-module-search-paths",
)
clang = settings.get("c")
if clang:
lldb.debugger.HandleCommand(
f"settings set -- target.swift-extra-clang-flags '{clang}'",
)
else:
lldb.debugger.HandleCommand(
"settings clear target.swift-extra-clang-flags",
)
return True

View file

@ -0,0 +1,25 @@
/*.app/Contents/Frameworks/libclang_rt.asan*.dylib
/*.app/Contents/Frameworks/libclang_rt.tsan*.dylib
/*.app/Contents/Frameworks/libclang_rt.ubsan*.dylib
/*.app/Contents/Frameworks/libXCTestBundleInject.dylib
/*.app/Contents/Frameworks/libXCTestSwiftSupport.dylib
/*.app/Contents/Frameworks/Testing.framework,
/*.app/Contents/Frameworks/XCTAutomationSupport.framework
/*.app/Contents/Frameworks/XCTest.framework
/*.app/Contents/Frameworks/XCTestCore.framework
/*.app/Contents/Frameworks/XCTestSupport.framework
/*.app/Contents/Frameworks/XCUIAutomation.framework
/*.app/Contents/Frameworks/XCUnit.framework
/*.app/Frameworks/libclang_rt.asan*.dylib
/*.app/Frameworks/libclang_rt.tsan*.dylib
/*.app/Frameworks/libclang_rt.ubsan*.dylib
/*.app/Frameworks/libXCTestBundleInject.dylib
/*.app/Frameworks/libXCTestSwiftSupport.dylib
/*.app/Frameworks/Testing.framework,
/*.app/Frameworks/XCTAutomationSupport.framework
/*.app/Frameworks/XCTest.framework
/*.app/Frameworks/XCTestCore.framework
/*.app/Frameworks/XCTestSupport.framework
/*.app/Frameworks/XCUIAutomation.framework
/*.app/Frameworks/XCUnit.framework
/*.app/PlugIns/*.xctest

View file

@ -0,0 +1,25 @@
/*.appex/Contents/Frameworks/libclang_rt.asan*.dylib
/*.appex/Contents/Frameworks/libclang_rt.tsan*.dylib
/*.appex/Contents/Frameworks/libclang_rt.ubsan*.dylib
/*.appex/Contents/Frameworks/libXCTestBundleInject.dylib
/*.appex/Contents/Frameworks/libXCTestSwiftSupport.dylib
/*.appex/Contents/Frameworks/Testing.framework,
/*.appex/Contents/Frameworks/XCTAutomationSupport.framework
/*.appex/Contents/Frameworks/XCTest.framework
/*.appex/Contents/Frameworks/XCTestCore.framework
/*.appex/Contents/Frameworks/XCTestSupport.framework
/*.appex/Contents/Frameworks/XCUIAutomation.framework
/*.appex/Contents/Frameworks/XCUnit.framework
/*.appex/Frameworks/libclang_rt.asan*.dylib
/*.appex/Frameworks/libclang_rt.tsan*.dylib
/*.appex/Frameworks/libclang_rt.ubsan*.dylib
/*.appex/Frameworks/libXCTestBundleInject.dylib
/*.appex/Frameworks/libXCTestSwiftSupport.dylib
/*.appex/Frameworks/Testing.framework,
/*.appex/Frameworks/XCTAutomationSupport.framework
/*.appex/Frameworks/XCTest.framework
/*.appex/Frameworks/XCTestCore.framework
/*.appex/Frameworks/XCTestSupport.framework
/*.appex/Frameworks/XCUIAutomation.framework
/*.appex/Frameworks/XCUnit.framework
/*.appex/PlugIns/*.xctest

View file

@ -0,0 +1,209 @@
# 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/Sources/MiniProject/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/Sources/MiniProject/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/Sources/MiniProject/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/Sources/MiniProject/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

View file

@ -0,0 +1,7 @@
# Generated by rules_xcodeproj. Do not edit.
envs=(
LANG=en_US.UTF-8
PATH=/bin:/usr/bin
BAZELISK_SKIP_WRAPPER=true
BAZEL_REAL=/Users/cediackermann/Library/Caches/bazelisk/downloads/sha256/2db883718453f0437a7bcb408e889dbf8539cdc4d61c8ebc3807a1a88d02ff08/bin/bazel
)

View file

@ -0,0 +1,435 @@
#!/usr/bin/python3
import datetime
import glob
import json
import os
import sys
import time
import traceback
# Ordered the same as we order platforms in the generated Xcode project, except
# macOS is last
_DEVICE_PLATFORMS = {
"iphoneos": None,
"appletvos": None,
"watchos": None,
"macosx": None,
}
_SIMULATOR_PLATFORMS = {
"iphonesimulator": None,
"appletvsimulator": None,
"watchsimulator": None,
"macosx": None,
}
def _wait_for_value(calculate_value, value_name):
wait_counter = 0
while True:
value = calculate_value()
if value:
break
if wait_counter == 0:
now = datetime.datetime.now().strftime('%H:%M:%S')
print(
f"note: ({now}) {value_name} not updated yet, waiting...",
file = sys.stderr,
flush = True,
)
if wait_counter == 10:
now = datetime.datetime.now().strftime('%H:%M:%S')
print(
f"""\
warning: ({now}) {value_name} still not updated after 10 seconds. If happens \
frequently, or the cache is never created, please file a bug report here: \
https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md""",
file = sys.stderr,
flush = True,
)
time.sleep(1)
wait_counter += 1
if wait_counter > 0:
now = datetime.datetime.now().strftime('%H:%M:%S')
print(
f"""\
note: ({now}) {value_name} updated after {wait_counter} seconds.""",
file = sys.stderr,
flush = True,
)
return value
def _get_build_request(
xcode_version,
objroot,
build_request_min_ctime):
if xcode_version < 1430:
# Before Xcode 14.3
def wait_for_description():
build_description_cache = max(
glob.iglob(
f"{objroot}/XCBuildData/BuildDescriptionCacheIndex-*",
),
key = os.path.getctime,
)
if (os.path.getctime(build_description_cache) >=
build_request_min_ctime):
return build_description_cache
return None
build_description_cache = (
_wait_for_value(wait_for_description, "BuildDescriptionCacheIndex")
)
with open(build_description_cache, 'rb') as f:
f.seek(-32, os.SEEK_END)
build_request_id = f.read().decode('ASCII')
build_request_file = (
f"{objroot}/XCBuildData/{build_request_id}-buildRequest.json"
)
def wait_for_build_request_file():
if os.path.exists(build_request_file):
with open(build_request_file, encoding = "utf-8") as f:
# Parse the build-request.json file
try:
return json.load(f)
except Exception as error:
print(
f"""\
error: Failed to parse '{build_request_file}':
{type(error).__name__}: {error}.
Please file a bug report here: \
https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md""",
file = sys.stderr,
)
exit(1)
return None
return _wait_for_value(
wait_for_build_request_file,
f"\"{build_request_file}\"",
)
def wait_for_build_request():
try:
xcbuilddata = max(
glob.iglob(f"{objroot}/XCBuildData/*.xcbuilddata"),
key = os.path.getctime,
)
if os.path.getctime(xcbuilddata) < build_request_min_ctime:
return None
except (ValueError, FileNotFoundError, OSError):
# ValueError: no .xcbuilddata files yet (empty glob)
# FileNotFoundError/OSError: TOCTOU race - file deleted between glob and getctime
return None
build_request_file = f"{xcbuilddata}/build-request.json"
if os.path.exists(build_request_file):
with open(build_request_file, encoding = "utf-8") as f:
# Parse the build-request.json file
try:
return json.load(f)
except Exception as error:
print(
f"""\
error: Failed to parse '{build_request_file}':
{type(error).__name__}: {error}.
Please file a bug report here: \
https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md""",
file = sys.stderr,
)
sys.exit(1)
return None
return _wait_for_value(
wait_for_build_request,
"newest 'buildRequest.json' file",
)
def _calculate_label_and_target_ids(
build_request,
guid_labels,
guid_target_ids):
# Xcode gets "stuck" in the `buildFiles` or `build` command for
# top-level targets, so we can't reliably change commands here. Leaving
# the code in place in case this is fixed in the future, or we want to
# do something similar in an XCBBuildService proxy.
#
# command = (
# build_request.get("_buildCommand2", {}).get("command", "build")
# )
command = "build"
parameters = build_request["parameters"]
platform = (
parameters["activeRunDestination"]["platform"]
)
configuration_name = parameters["configurationName"]
labels_and_target_ids = []
for target in build_request["configuredTargets"]:
label = guid_labels.get(target["guid"])
if not label:
# `BazelDependency` and the like
continue
full_target_target_ids = guid_target_ids[target["guid"]]
target_target_ids = (
full_target_target_ids.get(command) or
# Will only be `null` if `command == "buildFiles"` and there
# isn't a different compile target id
full_target_target_ids["build"]
)
target_ids = _select_target_ids(
target_target_ids[configuration_name],
platform,
)
for target_id in target_ids:
labels_and_target_ids.append((label, target_id))
if not labels_and_target_ids:
print(
"""\
error: Failed to determine labels and targets. Note, currently `.xcworkspace`s \
aren't supported. Please make sure you are opening the generated \
`.xcodeproj` file bundle directly. If you are, try using the "Clean Build \
Folder" command instead (⇧ ⌘ K). If you still get this error after that, then \
please file a bug report here: \
https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md""",
file = sys.stderr,
)
exit(1)
return labels_and_target_ids
def _calculate_guid_labels_and_target_ids(base_objroot):
pif_cache = f"{base_objroot}/XCBuildData/PIFCache"
project_cache = f"{pif_cache}/project"
target_cache = f"{pif_cache}/target"
# The PIF cache will only be created before the `SetSessionUserInfo`
# command, which normally happens when a project is opened. If Derived Data
# is cleared while the project is open
if not (os.path.exists(project_cache) and os.path.exists(target_cache)):
print(
f"""\
error: PIFCache ({pif_cache}) doesn't exist. If you manually cleared Derived \
Data, you need to close and re-open the project for the PIFCache to be created \
again. Using the "Clean Build Folder" command instead ( K) won't trigger \
this error. If this error still happens after re-opening the project, please \
file a bug report here: \
https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md""",
file = sys.stderr,
)
sys.exit(1)
project_pif = max(
glob.iglob(f"{project_cache}/*"),
key = os.path.getctime,
)
guid_payload_parent = f"{base_objroot}/guid_payload"
guid_payload_path = f"""\
{guid_payload_parent}/{os.path.basename(project_pif)}_v2.json"""
if os.path.exists(guid_payload_path):
with open(guid_payload_path, encoding = "utf-8") as f:
payload = json.load(f)
return payload["labels"], payload["targetIds"]
with open(project_pif, encoding = "utf-8") as f:
project_pif = json.load(f)
targets = project_pif["targets"]
guid_labels = {}
guid_target_ids = {}
for target_name in targets:
target_file = f"{target_cache}/{target_name}-json"
with open(target_file, encoding = "utf-8") as f:
target_pif = json.load(f)
label = None
build_target_ids = {}
compile_target_ids = {}
for configuration in target_pif["buildConfigurations"]:
config_build_target_ids = {"key": "BAZEL_TARGET_ID"}
config_compile_target_ids = {"key": "BAZEL_COMPILE_TARGET_IDS"}
for key, value in configuration["buildSettings"].items():
if key.startswith("BAZEL_TARGET_ID"):
# This uses a list in the case where the value isn't meant to
# be inherited. Otherwise, `$(BAZEL_TARGET_ID)` is used later
# in this processing to pull from an inherited setting.
if value == "$(BAZEL_TARGET_ID)":
target_ids = value
else:
# This is only a single value but the later parsing of
# these target ids assumes a list.
target_ids = [value]
config_build_target_ids[_platform_from_build_key(key)] = (
target_ids
)
elif key.startswith("BAZEL_COMPILE_TARGET_IDS"):
# This uses a list in the case where the value isn't meant to
# be inherited. Otherwise, `$(BAZEL_COMPILE_TARGET_IDS)` is
# used later in this processing to pull from an inherited
# setting.
if value == "$(BAZEL_COMPILE_TARGET_IDS)":
target_ids = "$(BAZEL_COMPILE_TARGET_IDS)"
else:
# Target identifiers contain a space but are space separated.
# Split on all spaces then rejoin across the identifier pairs.
target_ids = value.split(" ")
target_ids = [
" ".join(target_ids[i:i+2])
for i in range(0, len(target_ids), 2)
]
config_compile_target_ids[_platform_from_compile_key(key)] = (
target_ids
)
elif key == "BAZEL_LABEL":
label = value
configuration_name = configuration["name"]
build_target_ids[configuration_name] = config_build_target_ids
compile_target_ids[configuration_name] = config_compile_target_ids
if not label:
# `BazelDependency` and the like
continue
target_ids = {
"build": build_target_ids,
}
if len(compile_target_ids) > 1:
target_ids["buildFiles"] = compile_target_ids
guid = target_pif["guid"]
guid_labels[guid] = label
guid_target_ids[guid] = target_ids
os.makedirs(guid_payload_parent, exist_ok = True)
with open(guid_payload_path, "w", encoding = "utf-8") as f:
payload = {
"labels": guid_labels,
"targetIds": guid_target_ids,
}
json.dump(payload, f)
return guid_labels, guid_target_ids
def _platform_from_build_key(key):
if key.startswith("BAZEL_TARGET_ID[sdk="):
return key[20:-2]
return ""
def _platform_from_compile_key(key):
if key.startswith("BAZEL_COMPILE_TARGET_IDS[sdk="):
return key[29:-2]
return ""
def _select_target_ids(target_ids, platform):
key = target_ids["key"]
platforms = {platform: None}
# We need to try other similar platforms (i.e. other simulator platforms if
# `platform`` is for a simulator). This is to support schemes with targets
# of multiple platforms in them. Because `dict` is insertion ordered,
# `platform` will be checked first.
platforms.update(_similar_platforms(platform))
for platform in platforms:
platform_target_ids = target_ids.get(platform)
if platform_target_ids:
if platform_target_ids == f"$({key})":
return target_ids[""]
return platform_target_ids
return target_ids[""]
def _similar_platforms(platform):
if platform == "macosx" or "simulator" in platform:
return _SIMULATOR_PLATFORMS
return _DEVICE_PLATFORMS
def _main(
xcode_version,
objroot,
base_objroot,
marker_file,
prefixes_str):
if not os.path.exists(marker_file):
return
build_request_min_ctime = os.path.getctime(marker_file)
try:
xcode_version = int(xcode_version)
except ValueError:
print(
"""
warning: xcode_version was not an integer. Please file a bug report here: \
https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md
""",
file = sys.stderr,
)
xcode_version = 9999
prefixes = prefixes_str.split(",")
try:
build_request = _get_build_request(
xcode_version,
objroot,
build_request_min_ctime,
)
guid_labels, guid_target_ids = (
_calculate_guid_labels_and_target_ids(base_objroot)
)
except Exception:
print(
f"""\
error: Failed to calculate labels and target ids from PIFCache:
{traceback.format_exc()}
Please file a bug report here: \
https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/new?template=bug.md""",
file = sys.stderr,
)
sys.exit(1)
labels_and_target_ids = _calculate_label_and_target_ids(
build_request,
guid_labels,
guid_target_ids,
)
print("\n".join(
[
f"{label}\n{prefix} {id}"
for label, id in labels_and_target_ids
for prefix in prefixes
],
))
if __name__ == "__main__":
_main(
# XCODE_VERSION_ACTUAL
sys.argv[1],
# non_preview_objroot
sys.argv[2],
# base_objroot
sys.argv[3],
# build_marker_file
sys.argv[4],
# output_group_prefixes
sys.argv[5],
)

View file

@ -0,0 +1,29 @@
#!/bin/bash
set -euo pipefail
while test $# -gt 0
do
case $1 in
-MF)
shift
touch "$1"
;;
--serialize-diagnostics)
shift
cp "${BASH_SOURCE%/*}/cc.dia" "$1"
;;
*.o)
break
;;
-v)
# TODO: Make this work with custom toolchains
DEV_DIR_PREFIX=$(awk '{ sub(/.*-isysroot /, ""); sub(/.Contents\/Developer.*/, ""); print}' <<< "${@:1}")
clang="$DEV_DIR_PREFIX/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"
"$clang" "${@:1}"
break
;;
esac
shift
done

View file

@ -0,0 +1,74 @@
#!/bin/bash
set -euo pipefail
function patch_dsym() {
local dsym_name="$1"
shopt -s extglob
local binary_name="${dsym_name%.dSYM}"
binary_name="${binary_name%@(.app|.appex|.bundle|.dext|.kext|.framework|.pluginkit|.systemextension|.xctest|.xpc)}"
shopt +s extglob
local binary_path="${dsym_name}/Contents/Resources/DWARF/${binary_name}"
if [[ ! -f "$binary_path" ]]; then
echo "dSYM DWARF ${binary_path} does not exist." \
"Skip dSYM patch."
return 1
fi
local dwarf_uuid
dwarf_uuid=$(dwarfdump --uuid "${binary_path}" | cut -d ' ' -f 2)
if [[ -z "${dwarf_uuid// /}" ]]; then
echo "Failed to get dSYM uuid." \
"Skip dSYM patch."
return 1
fi
cat > "${dsym_name}/Contents/Resources/${dwarf_uuid}.plist" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<dict>
<key>DBGVersion</key>
<string>3</string>
<key>DBGSourcePathRemapping</key>
<dict>
<key>./bazel-out/</key>
<string>$BAZEL_OUT/</string>
<key>./external/</key>
<string>$BAZEL_EXTERNAL/</string>
<key>./</key>
<string>$SRCROOT/</string>
</dict>
</dict>
</plist>
EOF
}
readonly rsync="$BAZEL_INTEGRATION_DIR/rsync"
if [[ -n "${BAZEL_OUTPUTS_DSYM:-}" ]]; then
cd "${BAZEL_OUT%/*}"
# shellcheck disable=SC2046
"$rsync" \
--copy-links \
--recursive \
--times \
--archive \
--delete \
${exclude_list:+--exclude-from="$exclude_list"} \
--perms \
--chmod=u+w \
--out-format="%n%L" \
$(xargs -n1 <<< "$BAZEL_OUTPUTS_DSYM") \
"$TARGET_BUILD_DIR"
cd "${TARGET_BUILD_DIR}"
export -f patch_dsym
# shellcheck disable=SC2016
xargs -n1 sh -c 'patch_dsym $(basename "$1")' _ \
<<< "$BAZEL_OUTPUTS_DSYM"
fi

View file

@ -0,0 +1,104 @@
#!/bin/bash
set -euo pipefail
# readonly forced_swift_compile_file="$1"
readonly exclude_list="$2"
# # Touching this file on an error allows indexing to work better
# trap 'echo "private let touch = \"$(date +%s)\"" > "$DERIVED_FILE_DIR/$forced_swift_compile_file"' ERR
readonly test_frameworks=(
"libXCTestBundleInject.dylib"
"libXCTestSwiftSupport.dylib"
"IDEBundleInjection.framework"
"XCTAutomationSupport.framework"
"Testing.framework"
"XCTest.framework"
"XCTestCore.framework"
"XCTestSupport.framework"
"XCUIAutomation.framework"
"XCUnit.framework"
)
readonly rsync="$BAZEL_INTEGRATION_DIR/rsync"
if [[ "$ACTION" != indexbuild ]]; then
# Copy product
if [[ -n ${BAZEL_OUTPUTS_PRODUCT:-} ]]; then
cd "${BAZEL_OUTPUTS_PRODUCT%/*}"
if [[ -f "$BAZEL_OUTPUTS_PRODUCT_BASENAME" ]]; then
# Product is a binary, so symlink instead of rsync, to allow for Bazel-set
# rpaths to work
ln -sfh "$PWD/$BAZEL_OUTPUTS_PRODUCT_BASENAME" "$TARGET_BUILD_DIR/$PRODUCT_NAME"
else
# Product is a bundle
"$rsync" \
--copy-links \
--recursive \
--times \
--delete \
${exclude_list:+--exclude-from="$exclude_list"} \
--perms \
--chmod=u+w \
--out-format="%n%L" \
"$BAZEL_OUTPUTS_PRODUCT_BASENAME" \
"$TARGET_BUILD_DIR"
if [[ -n "${TEST_HOST:-}" ]]; then
# We need to re-sign test frameworks that Xcode placed into the test
# host un-signed
readonly test_host_app="${TEST_HOST%/*}"
# Only engage signing workflow if the test host is signed
if [[ -f "$test_host_app/embedded.mobileprovision" ]]; then
codesigning_authority=$(codesign -dvv "$TEST_HOST" 2>&1 >/dev/null | /usr/bin/sed -n -E 's/^Authority=(.*)/\1/p'| head -n 1)
for framework in "${test_frameworks[@]}"; do
framework="$test_host_app/Frameworks/$framework"
if [[ -e "$framework" ]]; then
codesign -f \
--preserve-metadata=identifier,entitlements,flags \
--timestamp=none \
--generate-entitlement-der \
-s "$codesigning_authority" \
"$framework"
fi
done
fi
fi
# Incremental installation can fail if an embedded bundle is recompiled but
# the Info.plist is not updated. This causes the delta bundle that Xcode
# actually installs to not have a bundle ID for the embedded bundle. We
# avoid this potential issue by always including the Info.plist in the delta
# bundle by touching them.
# Source: https://github.com/bazelbuild/tulsi/commit/27354027fada7aa3ec3139fd686f85cc5039c564
# TODO: Pass the exact list of files to touch to this script
readonly plugins_dir="$TARGET_BUILD_DIR/${PLUGINS_FOLDER_PATH:-}"
if [[ -d "$plugins_dir" ]]; then
find "$plugins_dir" -depth 2 -name "Info.plist" -exec touch {} \;
fi
# Xcode Previews has a hard time finding frameworks (`@rpath`) when using
# framework schemes, so let's symlink them into
# `$TARGET_BUILD_DIR` (since we modify `@rpath` to always include
# `@loader_path/SwiftUIPreviewsFrameworks`)
if [[ "${ENABLE_PREVIEWS:-}" == "YES" && \
-n "${PREVIEW_FRAMEWORK_PATHS:-}" ]]; then
mkdir -p "$TARGET_BUILD_DIR/$WRAPPER_NAME/SwiftUIPreviewsFrameworks"
cd "$TARGET_BUILD_DIR/$WRAPPER_NAME/SwiftUIPreviewsFrameworks"
# shellcheck disable=SC2016
xargs -n1 sh -c 'ln -shfF "$1" $(basename "$1")' _ \
<<< "$PREVIEW_FRAMEWORK_PATHS"
fi
fi
fi
fi
# TODO: https://github.com/MobileNativeFoundation/rules_xcodeproj/issues/402
# Copy diagnostics, and on a change
# `echo "private let touch = \"$(date +%s)\"" > $DERIVED_FILE_DIR/$forced_swift_compile_file"`
# See git blame for this comment for an example

View file

@ -0,0 +1,74 @@
#!/bin/bash
set -euo pipefail
readonly execution_root="$PROJECT_DIR"
readonly build_external="$execution_root/external"
{
# Set `CWD` to `$execution_root` so relative paths in binaries work
#
# This is needed because we use the `oso_prefix_is_pwd` feature, which makes the
# paths to archives relative to the exec root.
echo "platform settings -w \"$execution_root\""
# "Undo" `-debug-prefix-map` for breakpoints
#
# This needs to cause the files to match exactly what Xcode set for breakpoints,
# which is why we don't use `$execution_root` here. Xcode will set the path
# based on the way you opened a file. If you open a file via the Project
# navigator, or indexing (e.g. Jump to Definition), it will use the paths
# specified below.
# `bazel-out` when set from Project navigator or swiftsourcefile
echo "settings set target.source-map ./bazel-out/ \"$BAZEL_OUT\""
# `external` when set from Project navigator
echo "settings append target.source-map ./external/ \"$BAZEL_EXTERNAL\""
# `external` when set from swiftsourcefile
echo "settings append target.source-map ./external/ \"$build_external\""
if [[ "${BAZEL_SEPARATE_INDEXBUILD_OUTPUT_BASE:-}" == "YES" ]]; then
readonly output_base="${execution_root%/*/*}"
readonly workspace_name="${execution_root##*/}"
readonly index_execution_root="${output_base%/*}/indexbuild_output_base/execroot/$workspace_name"
readonly index_bazel_out="$index_execution_root/bazel-out"
readonly index_external="$index_execution_root/external"
mkdir -p "$index_bazel_out"
mkdir -p "$index_external"
# `bazel-out` when set from indexing opened file
echo "settings append target.source-map ./bazel-out/ \"$index_bazel_out\""
# `external` when set from indexing opened file
echo "settings append target.source-map ./external/ \"$index_external\""
fi
# Project files and locally resolved external repositories
#
# lldb seems to match breakpoints based on the second argument, using a simple
# prefix check that doesn't take into account the trailing slash. This means
# that we have to order the source-map settings so that the longest paths are
# first, otherwise an earlier setting can prevent a later setting from matching.
if [[ -n "${RESOLVED_REPOSITORIES:-}" ]]; then
# `external` for local repositories when set from Project navigator,
# and the project root
while IFS='' read -r x; do repos+=("$x"); done < <(xargs -n1 <<< "$RESOLVED_REPOSITORIES")
for (( i=0; i<${#repos[@]}; i+=2 )); do
prefix="${repos[$i]}"
path="${repos[$i+1]}"
echo "settings append target.source-map \"$prefix/\" \"$path\""
done
fi
# Import swift_debug_settings.py
#
# This Python module sets a stop hook, that when hit, sets the Swift debug
# settings (i.e. `target.swift-*``) for the module of the current frame. This
# fixes debugging when using `-serialize-debugging-options`.
echo "command script import \"$OBJROOT/$CONFIGURATION/swift_debug_settings.py\""
} > "$BAZEL_LLDB_INIT"

View file

@ -0,0 +1,2 @@
/*.framework/Modules/***
/*.framework/SwiftUIPreviewsFrameworks/***

View file

@ -0,0 +1,217 @@
#!/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

View file

@ -0,0 +1,76 @@
#!/bin/bash
set -euo pipefail
cd "$SRCROOT"
readonly config="${BAZEL_CONFIG}_indexbuild"
# Compiled outputs (i.e. swiftmodules) and generated inputs
output_groups=(
# Compile params
"bc $BAZEL_TARGET_ID"
# Indexstores and their filelist. Requesting indexstore directories triggers
# transitive Swift compilation (producing swiftmodules, indexstores, and
# generated headers) without linking, avoiding large product binaries. We use
# `--remote_download_regex` below to download the files we care
# about.
"bi $BAZEL_TARGET_ID"
)
indexstores_filelists=()
if [[ "$IMPORT_INDEX_BUILD_INDEXSTORES" == "YES" ]]; then
output_groups+=(
"index_import"
)
readonly targetid_regex='@{0,2}(.*)//(.*):(.*) ([^\ ]+)$'
if [[ "$BAZEL_TARGET_ID" =~ $targetid_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-bi.filelist"
indexstores_filelists+=("$filelist")
fi
readonly indexstores_regex='.*\.indexstore/.*|'
else
readonly indexstores_regex=''
fi
readonly build_pre_config_flags=(
# Include the following:
#
# - .indexstore directories to allow importing indexes
# - .swift{doc,module,sourceinfo} files for indexing
# - compilation input files (.cfg, .c, .C .cc, .cl, .cpp, .cu, .cxx, .c++,
# .def, .h, .H, .hh, .hpp, .hxx, .h++, .hmap, .ilc, .inc, .ipp, .tcc, .tlh,
# .tpp, .m, .modulemap, .mm, .pch, .swift, .yaml) for index compilation
#
# 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=${indexstores_regex}.*\.(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)$"
)
source "$BAZEL_INTEGRATION_DIR/bazel_build.sh"
# 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/}"
else
"$BAZEL_INTEGRATION_DIR/import_indexstores" \
"$PROJECT_DIR" \
"${indexstores_filelists[@]/#/$BAZEL_OUT/}"
fi
fi

View file

@ -0,0 +1,30 @@
#!/bin/bash
set -euo pipefail
passthrough_args=("${@:1}")
while test $# -gt 0
do
case $1 in
*_dependency_info.dat)
ld_version=$(ld -v 2>&1 | grep ^@)
printf "\0%s\0" "$ld_version" > "$1"
break
;;
-isysroot)
shift
# PATH/DEVELOPER_DIR isn't set when this is called, so we need to calculate
# the developer dir from the sysroot to invoke clang (used below)
developer_dir="${1/\/Platforms\/*/}"
;;
*.preview-thunk.dylib)
# Pass through for SwiftUI Preview thunk compilation
# TODO: Make this work with custom toolchains
exec "$developer_dir/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" "${passthrough_args[@]}"
;;
esac
shift
done

View file

@ -0,0 +1,21 @@
#!/bin/bash
set -euo pipefail
original_args=("$@")
while test $# -gt 0
do
case $1 in
-V)
# Xcode 15+ needs to know the version of libtool
exec libtool "${original_args[@]}"
;;
*_dependency_info.dat)
printf "\0 \0" > "$1"
break
;;
esac
shift
done

View file

@ -0,0 +1,124 @@
#!/usr/bin/python3
import os
import re
import subprocess
import sys
from typing import List
import signal
STRIP_COLOR_RE = re.compile(r"\x1b\[[0-9;]{1,}[A-Za-z]")
RELATIVE_DIAGNOSTICS_RE = re.compile(
r"""
^
(?P<loc>.+?:\d+(?::\d+)?:\s) # Capture location (e.g. "foo/bar:12:3: ")
(?:fatal\s)? # Dropping "fatal "
(?P<sev>(?:error|warning):\s) # Capture severity
(?P<msg>.*) # Capture the rest of the message
""",
re.VERBOSE,
)
def _uppercase_first_letter(s: str) -> str:
return s[:1].upper() + s[1:]
def _main(command: List[str]) -> None:
def _signal_handler(signum, frame):
"""Print signal information and ignore the signal."""
signal_name = signal.Signals(signum).name
print(f"\nReceived signal {signal_name} ({signum})\n", file=sys.stderr)
return
# Set up signal handler for SIGINT
signal.signal(signal.SIGINT, _signal_handler)
srcroot = os.getenv("SRCROOT")
if not srcroot:
sys.exit("SRCROOT environment variable must be set")
execution_root = os.getenv("PROJECT_DIR")
if not execution_root:
sys.exit("PROJECT_DIR environment variable must be set")
bazel_out_directory = os.getenv("BAZEL_OUT")
if not bazel_out_directory:
sys.exit("BAZEL_OUT environment variable must be set")
bazel_out_prefix = bazel_out_directory[:-len("/bazel-out")]
if not bazel_out_prefix.startswith("/"):
bazel_out_prefix = f"{srcroot}/{bazel_out_prefix}"
external_directory = os.getenv("BAZEL_EXTERNAL")
if not external_directory:
sys.exit("BAZEL_EXTERNAL environment variable must be set")
external_prefix = bazel_out_directory[:-len("/external")]
if not external_prefix.startswith("/"):
external_prefix = f"{srcroot}/{external_prefix}"
should_strip_color = os.getenv("COLOR_DIAGNOSTICS", default="YES") != "YES"
has_relative_diagnostic = False
def _replacement(match: re.Match) -> str:
message = f"""\
{match.group("loc")}{match.group("sev")}{_uppercase_first_letter(match.group("msg"))}\
"""
if message.startswith(execution_root):
# VFS overlays can make paths absolute, so make them relative again
message = message[(len(execution_root) + 1):]
if message.startswith("/"):
# If still an absolute path, don't add a prefix
return message
if message.startswith("bazel-out/"):
prefix = bazel_out_prefix
elif message.startswith("external/"):
prefix = external_prefix
else:
prefix = srcroot
return f"{prefix}/{message}"
process = subprocess.Popen(
command, bufsize=1, stderr=subprocess.PIPE, universal_newlines=True
)
assert process.stderr
def _process_log_line(line: str):
input_line = line.rstrip()
if should_strip_color:
input_line = STRIP_COLOR_RE.sub("", input_line)
if not input_line:
return
output_line = RELATIVE_DIAGNOSTICS_RE.sub(_replacement, input_line)
# Record if we have performed a relative diagnostic substitution.
if output_line != input_line:
nonlocal has_relative_diagnostic
has_relative_diagnostic = True
print(output_line, flush=True)
while process.poll() is None:
_process_log_line(process.stderr.readline())
for line in process.stderr:
_process_log_line(line)
# If the Bazel invocation failed and there was no formatted error found,
# print a nicer error message instead of a cryptic in Xcode:
# 'Command PhaseScriptExecution failed with a nonzero exit code'
if process.returncode != 0 and not has_relative_diagnostic:
print("error: The bazel build failed, please check the report navigator, "
"which may have more context about the failure.")
sys.exit(process.returncode)
if __name__ == "__main__":
_main(sys.argv[1:])

View file

@ -0,0 +1,27 @@
/*.app/Contents/Frameworks/libclang_rt.asan*.dylib
/*.app/Contents/Frameworks/libclang_rt.tsan*.dylib
/*.app/Contents/Frameworks/libclang_rt.ubsan*.dylib
/*.app/Contents/Frameworks/libXCTestBundleInject.dylib
/*.app/Contents/Frameworks/libXCTestSwiftSupport.dylib
/*.app/Contents/Frameworks/Testing.framework,
/*.app/Contents/Frameworks/XCTAutomationSupport.framework
/*.app/Contents/Frameworks/XCTest.framework
/*.app/Contents/Frameworks/XCTestCore.framework
/*.app/Contents/Frameworks/XCTestSupport.framework
/*.app/Contents/Frameworks/XCUIAutomation.framework
/*.app/Contents/Frameworks/XCUnit.framework
/*.app/Frameworks/libclang_rt.asan*.dylib
/*.app/Frameworks/libclang_rt.tsan*.dylib
/*.app/Frameworks/libclang_rt.ubsan*.dylib
/*.app/Frameworks/libXCTestBundleInject.dylib
/*.app/Frameworks/libXCTestSwiftSupport.dylib
/*.app/Frameworks/Testing.framework,
/*.app/Frameworks/XCTAutomationSupport.framework
/*.app/Frameworks/XCTest.framework
/*.app/Frameworks/XCTestCore.framework
/*.app/Frameworks/XCTestSupport.framework
/*.app/Frameworks/XCUIAutomation.framework
/*.app/Frameworks/XCUnit.framework
/*.app/PlugIns/***
/*.app/_WatchKitStub/***
/*.app/PlugIns/*.xctest

View file

@ -0,0 +1,139 @@
### `--config=rules_xcodeproj`
#
# Used directly when doing a normal build, but it is also the base config of all
# the `rules_xcodeproj_*` configs. Adjust this config if you want something to
# apply to all builds (which should be most settings).
common:rules_xcodeproj --verbose_failures
# Increase the default file digest cache size to 500k entries, as 50k (the
# default) is too small for large projects.
common:rules_xcodeproj --cache_computed_file_digests=500000
# We default to `dbg` since debugging is broken otherwise
common:rules_xcodeproj --compilation_mode=dbg
# Xcode builds shouldn't mess with the workspace's symlinks
common:rules_xcodeproj --experimental_convenience_symlinks=ignore
# Projects with large C/C++ target command-lines can fail to generate due
# without using params files. While the targets themselves might use params
# files, currently `Action.args` won't unless
# `--experimental_use_cpp_compile_action_args_params_file` is set.
# https://github.com/bazelbuild/bazel/issues/20746 would allow us to remove the
# need for this flag.
common:rules_xcodeproj --experimental_use_cpp_compile_action_args_params_file
# Not using `--define=apple.experimental.tree_artifact_outputs=1` is slow (we
# have to unzip an archive on each build). If this doesn't work for your
# project, you can set `--define=apple.experimental.tree_artifact_outputs=0`
# on `common:rules_xcodeproj` in your `.bazelrc` or `xcodeproj.bazelrc` file.
common:rules_xcodeproj --define=apple.experimental.tree_artifact_outputs=1
# Fix Test Issue navigation
common:rules_xcodeproj --features=apple.swizzle_absolute_xcttestsourcelocation
# `oso_prefix_is_pwd` removes absolute paths in debug info, which increases
# cache hit rates. We "undo" this in `bazel.lldbinit`, so debugging still works.
common:rules_xcodeproj --features=oso_prefix_is_pwd
# `relative_ast_path` uses relative paths when passing `--add_ast_path` to the
# linker, which increases cache hit rates. We "undo" this in `bazel.lldbinit`,
# so debugging still works.
common:rules_xcodeproj --features=relative_ast_path
# `swift.cacheable_swiftmodules` passes `-no-serialize-debugging-options` to
# `swiftc`, which fixes lldb crashes and increases cache hit rates. We "undo"
# this in `swift_debug_settings.py`, so debugging still works.
common:rules_xcodeproj --features=swift.cacheable_swiftmodules
# `swift.index-while-building` passes `-index-store-path` to `swiftc`, which
# generates index store data. We enable this globally, because we import indexes
# in Index Build as well. And even if we didn't, we would still want it enabled
# to get cache hits between normal and Index Build builds.
common:rules_xcodeproj --features=swift.index_while_building
common:rules_xcodeproj --features=swift.use_global_index_store
# Removes potentially large unneeded event from the BEP
common:rules_xcodeproj --nolegacy_important_outputs
# `--show_result=0` prevents showing the spec.json and intermediate `.xcodeproj`
# in the logs when generating, and all of the many outputs when building
common:rules_xcodeproj --show_result=0
# Disable sandboxing. Sandboxing on macOS is still very slow.
common:rules_xcodeproj --noworker_sandboxing
common:rules_xcodeproj --spawn_strategy=remote,worker,local
# Needed to download aspect output groups
build:rules_xcodeproj --remote_download_outputs=toplevel
### `--config=rules_xcodeproj_generator`
#
# Used when generating a project.
common:rules_xcodeproj_generator --config=rules_xcodeproj
### `--config=rules_xcodeproj_indexbuild`
#
# Used when doing an Index Build.
common:rules_xcodeproj_indexbuild --config=rules_xcodeproj
# Disable BES for Index Builds, as it runs a lot, and isn't user invoked
common:rules_xcodeproj_indexbuild --bes_backend= --bes_results_url=
### `--config=rules_xcodeproj_coverage`
#
# Used when doing building for code coverage.
common:rules_xcodeproj_coverage --config=rules_xcodeproj
# Enable features that allow for building for instrumentation.
#
# Of particular note are the (swift./)_coverage_prefix_map_absolute_sources_non_hermetic
# features, which remap the execroot during the build as the absolute, canonical path
# to the source root.
#
# This approach breaks remote caching when building for testing and codeCoverageEnabled
# is set to YES, but does not affect other builds (for running, or for testing without
# coverage).
common:rules_xcodeproj_coverage --features=coverage
common:rules_xcodeproj_coverage --features=llvm_coverage_map_format
common:rules_xcodeproj_coverage --features=_coverage_prefix_map_absolute_sources_non_hermetic
common:rules_xcodeproj_coverage --features=swift.coverage
common:rules_xcodeproj_coverage --features=swift._coverage_prefix_map_absolute_sources_non_hermetic
# Disable features that interfere with (swift./)_coverage_prefix_map_absolute_sources_non_hermetic
common:rules_xcodeproj_coverage --features=-coverage_prefix_map
common:rules_xcodeproj_coverage --features=-file_prefix_map
common:rules_xcodeproj_coverage --features=-swift.coverage_prefix_map
common:rules_xcodeproj_coverage --features=-swift.file_prefix_map
### `--config=rules_xcodeproj_swiftuipreviews`
#
# Used when doing a Xcode Previews build.
common:rules_xcodeproj_swiftuipreviews --config=rules_xcodeproj
# Allow frameworks to find framework dependencies when running a preview
# See `$PROJECT_FILE_PATH/rules_xcodeproj/bazel/copy_outputs.sh` for more info
common:rules_xcodeproj_swiftuipreviews --linkopt="-Wl,-rpath,@loader_path/SwiftUIPreviewsFrameworks"
# `swiftc` flags needed for SwiftUI Previews
common:rules_xcodeproj_swiftuipreviews --@@rules_swift+//swift:copt=-Xfrontend --@@rules_swift+//swift:copt=-enable-implicit-dynamic
common:rules_xcodeproj_swiftuipreviews --@@rules_swift+//swift:copt=-Xfrontend --@@rules_swift+//swift:copt=-enable-private-imports
common:rules_xcodeproj_swiftuipreviews --@@rules_swift+//swift:copt=-Xfrontend --@@rules_swift+//swift:copt=-enable-dynamic-replacement-chaining
### `--config=_rules_xcodeproj_build`
#
# Private implementation detail. Don't adjust this config, adjust
# `rules_xcodeproj` instead. This config exists solely to allow project-level
# configs to work correctly.
common:_rules_xcodeproj_build --config=rules_xcodeproj
### Project specific configs
# Import `xcodeproj.bazelrc` if it exists
try-import %workspace%/xcodeproj.bazelrc

View file

@ -0,0 +1,24 @@
/*.xctest/Contents/Frameworks/libclang_rt.asan*.dylib
/*.xctest/Contents/Frameworks/libclang_rt.tsan*.dylib
/*.xctest/Contents/Frameworks/libclang_rt.ubsan*.dylib
/*.xctest/Contents/Frameworks/libXCTestBundleInject.dylib
/*.xctest/Contents/Frameworks/libXCTestSwiftSupport.dylib
/*.xctest/Contents/Frameworks/Testing.framework,
/*.xctest/Contents/Frameworks/XCTAutomationSupport.framework
/*.xctest/Contents/Frameworks/XCTest.framework
/*.xctest/Contents/Frameworks/XCTestCore.framework
/*.xctest/Contents/Frameworks/XCTestSupport.framework
/*.xctest/Contents/Frameworks/XCUIAutomation.framework
/*.xctest/Contents/Frameworks/XCUnit.framework
/*.xctest/Frameworks/libclang_rt.asan*.dylib
/*.xctest/Frameworks/libclang_rt.tsan*.dylib
/*.xctest/Frameworks/libclang_rt.ubsan*.dylib
/*.xctest/Frameworks/libXCTestBundleInject.dylib
/*.xctest/Frameworks/libXCTestSwiftSupport.dylib
/*.xctest/Frameworks/Testing.framework,
/*.xctest/Frameworks/XCTAutomationSupport.framework
/*.xctest/Frameworks/XCTest.framework
/*.xctest/Frameworks/XCTestCore.framework
/*.xctest/Frameworks/XCTestSupport.framework
/*.xctest/Frameworks/XCUIAutomation.framework
/*.xctest/Frameworks/XCUnit.framework

View file

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "9999"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "NO">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Initialize Bazel Build Output Groups File"
scriptText = "mkdir -p &quot;${BUILD_MARKER_FILE%/*}&quot;&#10;touch &quot;$BUILD_MARKER_FILE&quot;&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0100FAB81B6F000000000001"
BuildableName = "StadtRundlauf"
BlueprintName = "StadtRundlauf"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Prepare BazelDependencies"
scriptText = "mkdir -p &quot;$PROJECT_DIR&quot;&#10;&#10;if [[ &quot;${ENABLE_ADDRESS_SANITIZER:-}&quot; == &quot;YES&quot; || \&#10; &quot;${ENABLE_THREAD_SANITIZER:-}&quot; == &quot;YES&quot; || \&#10; &quot;${ENABLE_UNDEFINED_BEHAVIOR_SANITIZER:-}&quot; == &quot;YES&quot; ]]&#10;then&#10; # TODO: Support custom toolchains once clang.sh supports them&#10; cd &quot;$INTERNAL_DIR&quot; || exit 1&#10; ln -shfF &quot;$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib&quot; lib&#10;fi&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0100FAB81B6F000000000001"
BuildableName = "StadtRundlauf"
BlueprintName = "StadtRundlauf"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "NO"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0100FAB81B6F000000000001"
BuildableName = "StadtRundlauf"
BlueprintName = "StadtRundlauf"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
disableMainThreadChecker = "YES"
disablePerformanceAntipatternChecker = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj/rules_xcodeproj/bazel.lldbinit"
disableMainThreadChecker = "YES"
disablePerformanceAntipatternChecker = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Update .lldbinit and copy dSYMs"
scriptText = "&quot;$BAZEL_INTEGRATION_DIR/create_lldbinit.sh&quot;&#10;&quot;$BAZEL_INTEGRATION_DIR/copy_dsyms.sh&quot;&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0100FAB81B6F000000000001"
BuildableName = "StadtRundlauf"
BlueprintName = "StadtRundlauf"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0100FAB81B6F000000000001"
BuildableName = "StadtRundlauf"
BlueprintName = "StadtRundlauf"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "BUILD_WORKING_DIRECTORY"
value = "$(BUILT_PRODUCTS_DIR)"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "BUILD_WORKSPACE_DIRECTORY"
value = "$(BUILD_WORKSPACE_DIRECTORY)"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Debug"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
customLLDBInitFile = "/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj/rules_xcodeproj/bazel.lldbinit"
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Update .lldbinit and copy dSYMs"
scriptText = "&quot;$BAZEL_INTEGRATION_DIR/create_lldbinit.sh&quot;&#10;&quot;$BAZEL_INTEGRATION_DIR/copy_dsyms.sh&quot;&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0100FAB81B6F000000000001"
BuildableName = "StadtRundlauf"
BlueprintName = "StadtRundlauf"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0100FAB81B6F000000000001"
BuildableName = "StadtRundlauf"
BlueprintName = "StadtRundlauf"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Debug"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "9999"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "NO">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Initialize Bazel Build Output Groups File"
scriptText = "mkdir -p &quot;${BUILD_MARKER_FILE%/*}&quot;&#10;touch &quot;$BUILD_MARKER_FILE&quot;&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00004EB553A7000000000001"
BuildableName = "libSwiftTUI.a"
BlueprintName = "SwiftTUI"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Prepare BazelDependencies"
scriptText = "mkdir -p &quot;$PROJECT_DIR&quot;&#10;&#10;if [[ &quot;${ENABLE_ADDRESS_SANITIZER:-}&quot; == &quot;YES&quot; || \&#10; &quot;${ENABLE_THREAD_SANITIZER:-}&quot; == &quot;YES&quot; || \&#10; &quot;${ENABLE_UNDEFINED_BEHAVIOR_SANITIZER:-}&quot; == &quot;YES&quot; ]]&#10;then&#10; # TODO: Support custom toolchains once clang.sh supports them&#10; cd &quot;$INTERNAL_DIR&quot; || exit 1&#10; ln -shfF &quot;$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain/usr/lib&quot; lib&#10;fi&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00004EB553A7000000000001"
BuildableName = "libSwiftTUI.a"
BlueprintName = "SwiftTUI"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "NO"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00004EB553A7000000000001"
BuildableName = "libSwiftTUI.a"
BlueprintName = "SwiftTUI"
ReferencedContainer = "container:/Users/cediackermann/Projects/m323/Sources/MiniProject/MiniProject.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "NO"
disableMainThreadChecker = "YES"
disablePerformanceAntipatternChecker = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
disableMainThreadChecker = "YES"
disablePerformanceAntipatternChecker = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Debug"
shouldUseLaunchSchemeArgsEnv = "NO"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Debug"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -0,0 +1,163 @@
23 14:30:36
14 14:31:29
15 14:32:14
27 14:32:54
1 14:32:59
12 14:33:04
28 14:33:12
24 14:33:18
26 14:34:38
2 14:34:59
5 14:35:48
6 14:36:41
8 14:36:51
21 14:37:00
81 14:37:28
7 14:38:01
69 14:38:21
4 14:38:36
13 14:38:39
62 14:38:49
29 14:38:52
87 14:39:19
51 14:39:22
84 14:39:27
86 14:39:53
90 14:40:02
65 14:40:09
71 14:40:16
3 14:40:29
58 14:40:34
92 14:41:10
93 14:41:20
64 14:41:22
85 14:41:25
22 14:42:22
70 14:42:41
94 14:44:03
63 14:44:07
91 14:44:47
61 14:44:54
53 14:44:59
57 14:45:19
55 14:45:36
52 14:45:42
88 14:45:48
56 14:46:03
54 14:47:44
66 14:51:11
83 14:51:52
176 15:15:15
165 15:16:44
163 15:16:47
174 15:17:09
171 15:17:32
183 15:18:08
177 15:18:14
146 15:18:24
167 15:19:13
162 15:19:15
132 15:19:35
164 15:20:22
101 15:20:34
133 15:20:57
140 15:21:05
169 15:21:09
137 15:21:14
134 15:21:19
115 15:22:04
123 15:22:06
103 15:22:26
166 15:23:10
145 15:23:18
118 15:23:24
114 15:23:28
139 15:23:35
173 15:23:49
143 15:23:54
141 15:24:03
131 15:24:19
116 15:24:22
170 15:24:28
119 15:24:32
175 15:24:34
178 15:24:37
107 15:25:06
104 15:25:08
142 15:25:21
168 15:25:27
181 15:25:28
180 15:26:19
122 15:26:20
113 15:26:22
109 15:26:28
102 15:26:31
161 15:27:21
138 15:27:36
135 15:27:38
111 15:27:51
121 15:27:53
144 15:29:17
105 15:29:35
172 15:30:15
179 15:30:30
120 15:33:13
182 15:33:23
110 15:33:31
117 15:34:42
106 15:34:56
112 15:35:21
262 16:15:44
261 16:15:45
236 16:15:49
254 16:16:28
232 16:17:14
270 16:17:16
239 16:17:58
257 16:18:16
240 16:18:34
268 16:18:59
269 16:19:13
243 16:19:25
224 16:19:36
213 16:19:40
255 16:19:53
238 16:20:00
259 16:20:03
202 16:20:10
209 16:20:23
265 16:20:24
221 16:21:00
230 16:21:03
260 16:21:30
253 16:21:57
205 16:22:17
225 16:22:23
226 16:23:11
235 16:23:17
207 16:23:22
216 16:23:35
229 16:23:56
258 16:24:01
267 16:24:07
234 16:24:08
233 16:25:36
252 16:26:08
263 16:26:11
227 16:26:42
208 16:26:44
212 16:26:53
242 16:27:37
211 16:27:41
241 16:27:56
204 16:28:26
222 16:28:59
201 16:29:07
223 16:30:25
214 16:30:58
210 16:31:12
256 16:31:20
206 16:35:58
203 16:39:01
231 16:39:32
228 16:41:12

View file

@ -0,0 +1,168 @@
1 1 Bruppacher 1
4 1 Lutz 2
7 1 Achermann
13 1 Amstein
22 1 Feusi 2
28 1 Bosshardt
52 1 Bloch
55 1 Doebeli
58 1 Meier R.
61 1 Ammann
64 1 Stauber
70 1 Bamberger
82 1 Wölfle 2
85 1 Bolz
88 1 Strausak
91 1 Oberholzer
94 1 Iten 2
103 2 Vogler
106 2 Bruppacher
109 2 Enz 1
112 2 Glogg 2
115 2 Vogt
118 2 Achermann
121 2 Tiefenauer
133 2 Weber
136 2 Felzmann 2
139 2 Hugentobler
142 2 Fehr
145 2 Gisler
163 2 Feusi
166 2 Temperli
169 2 Spillmann 1
172 2 Senft 2
175 2 Amschwand 2
178 2 Haupt
181 2 Merotto
202 3 Weinmann 1
205 3 Bloch
208 3 Lauener
211 3 Naef
214 3 Jost
223 3 Boegli
226 3 Inderbitzin 3
229 3 Ammann
232 3 Liebi
235 3 Boller 2
238 3 Camenzind
241 3 Trottmann 2
253 3 Togni
256 3 Zehnder
259 3 Brechbühl
262 3 Reolon 2
265 3 Künzler
268 3 Oberholzer
2 1 Bruppacher 2
5 1 Haas
8 1 Pfammatter
11 1 Gähwiler
14 1 Arnold
23 1 Temperli
26 1 Arnold
29 1 Merotto
53 1 Frei
56 1 Stauber
62 1 Le Pape
65 1 Donze
71 1 Murer
83 1 Leuch
86 1 Mattli
92 1 Kober
101 2 Hutter
104 2 Tobler 1
107 2 Lutz
110 2 Enz 2
113 2 Haas
116 2 Ender 1
119 2 Hirzel 1
122 2 Pfammatter
131 2 Gähwiler
134 2 Bucher
137 2 Hässig 1
140 2 Müller
143 2 Blaser 1
146 2 Bachmann
161 2 Stehli
164 2 Häuselmann
167 2 Trottmann 1
170 2 Spillmann 2
173 2 Stoll
176 2 Rebsamen
179 2 Gallmann
182 2 Bosshardt
203 3 Weinmann 2
206 3 Doebeli
209 3 Loosli 1
212 3 Heller
221 3 Winkler
224 3 Inderbitzin 1
227 3 Niggli 1
230 3 Leutenegger 1
233 3 Blust
236 3 Eckard
239 3 Müller
242 3 Brubpacher 1
254 3 Clavadetscher
257 3 Zeller 1
260 3 Jakob
263 3 Reolon 3
269 3 Kober
3 1 Lutz 1
6 1 Vogt
12 1 Bucher
15 1 Fehr
21 1 Feusi 1
24 1 Stoll
27 1 Spreng
51 1 Zehntner
54 1 Lauener
57 1 Bagattini
63 1 Liebi
66 1 Boller
69 1 Engler
81 1 Wölfle 1
84 1 Zehnder
87 1 Rütschi
90 1 Bernhard
93 1 Iten 1
102 2 Bochsler
105 2 Tobler 2
111 2 Glogg 1
114 2 Boller
117 2 Ender 2
120 2 Hirzel 2
123 2 Wietlisbach
132 2 Neuer
135 2 Felzmann 1
138 2 Hässig 2
141 2 Amstein
144 2 Blaser 2
162 2 Huber
165 2 Pongracz
168 2 Trottmann 2
171 2 Senft 1
174 2 Amschwand 1
177 2 Baumgartner
180 2 Huber
183 2 Spreng
201 3 Kohler
204 3 Zehntner
207 3 Frei
210 3 Loosli 2
213 3 Bagattini
216 3 Meier W.
222 3 Lauffer
225 3 Inderbitzin 2
228 3 Niggli 2
231 3 Leutenegger 2
234 3 Boller 1
237 3 Schneebeli
240 3 Trottmann 1
243 3 Brubpacher 2
252 3 Stalder
255 3 Leuch
258 3 Zeller 2
261 3 Reolon 1
264 3 Ehrismann
267 3 Wipf
270 3 Widmer

View file

@ -0,0 +1,213 @@
import Foundation
import SwiftTUI
// MARK: - Models
enum AgeGroup: Int, CustomStringConvertible, CaseIterable {
case junior = 1
case adult = 2
case senior = 3
var description: String {
switch self {
case .junior: return "Junior"
case .adult: return "Adult"
case .senior: return "Senior"
}
}
}
struct Runner {
let name: String
let ageGroup: AgeGroup
let time: String
let number: Int
}
enum SortKey: String, CaseIterable {
case name
case ageGroup
case time
case number
func sort(_ lhs: Runner, _ rhs: Runner) -> Bool {
switch self {
case .name: return lhs.name < rhs.name
case .ageGroup: return lhs.ageGroup.rawValue < rhs.ageGroup.rawValue
case .time: return lhs.time < rhs.time
case .number: return lhs.number < rhs.number
}
}
}
// MARK: - IO
func readFile(_ path: String) -> String {
(try? String(contentsOf: URL(fileURLWithPath: path), encoding: .utf8)) ?? ""
}
// MARK: - Parsing
func parseResults(_ content: String, separator: String) -> [Int: String] {
let pairs = content
.components(separatedBy: .newlines)
.compactMap { line -> (Int, String)? in
let cols = line.components(separatedBy: separator)
guard cols.count >= 2, let key = Int(cols[0]) else { return nil }
return (key, cols[1])
}
return Dictionary(pairs, uniquingKeysWith: { _, last in last })
}
func parseStarters(_ content: String, separator: String) -> [(nr: Int, ageGroup: Int, name: String)] {
content
.components(separatedBy: .newlines)
.compactMap { line in
let cols = line.components(separatedBy: separator)
guard cols.count >= 3, let nr = Int(cols[0]), let ageGroup = Int(cols[1])
else { return nil }
return (nr: nr, ageGroup: ageGroup, name: cols[2])
}
}
func assembleRunners(starters: [(nr: Int, ageGroup: Int, name: String)], results: [Int: String])
-> [Runner]
{
starters.compactMap { starter in
guard let time = results[starter.nr],
let group = AgeGroup(rawValue: starter.ageGroup)
else {
return nil
}
return Runner(name: starter.name, ageGroup: group, time: time, number: starter.nr)
}
}
func nonParticipants(starters: [(nr: Int, ageGroup: Int, name: String)], results: [Int: String])
-> [Runner]
{
starters.compactMap { starter in
guard results[starter.nr] == nil,
let group = AgeGroup(rawValue: starter.ageGroup)
else {
return nil
}
return Runner(name: starter.name, ageGroup: group, time: "DNS", number: starter.nr)
}
}
// MARK: - Transforms
func visibleRunners(
_ runners: [Runner],
query: String,
includedGroups: Set<AgeGroup>,
sortKey: SortKey
) -> [Runner] {
let needle = query.lowercased()
return runners
.filter { includedGroups.contains($0.ageGroup) }
.filter { needle.isEmpty || $0.name.lowercased().contains(needle) }
.sorted(by: sortKey.sort)
}
func toggling(_ groups: Set<AgeGroup>, _ group: AgeGroup) -> Set<AgeGroup> {
groups.contains(group) ? groups.subtracting([group]) : groups.union([group])
}
// MARK: - Formatting
func menuLabel(_ text: String, on: Bool) -> String {
on ? "[\(text)]" : " \(text) "
}
func formatRow(_ nr: String, _ name: String, _ group: String, _ time: String) -> String {
nr.padding(toLength: 6, withPad: " ", startingAt: 0)
+ name.padding(toLength: 22, withPad: " ", startingAt: 0)
+ group.padding(toLength: 9, withPad: " ", startingAt: 0)
+ time
}
// MARK: - Configuration
let resultsURL = "/Users/cediackermann/Projects/m323/Sources/MiniProject/data/results.txt"
let startListURL = "/Users/cediackermann/Projects/m323/Sources/MiniProject/data/startList.txt"
// MARK: - Entry Point
let results = parseResults(readFile(resultsURL), separator: "\t")
let starters = parseStarters(readFile(startListURL), separator: "\t")
let finished = assembleRunners(starters: starters, results: results)
let absent = nonParticipants(starters: starters, results: results)
Application(rootView: RunnerBrowser(finished: finished, absent: absent)).start()
// MARK: - TUI
struct RunnerBrowser: View {
let finished: [Runner]
let absent: [Runner]
@State private var query: String = ""
@State private var sortKey: SortKey = .number
@State private var includedGroups: Set<AgeGroup> = Set(AgeGroup.allCases)
@State private var showAbsent: Bool = false
private var source: [Runner] {
showAbsent ? absent : finished
}
private var visible: [Runner] {
visibleRunners(source, query: query, includedGroups: includedGroups, sortKey: sortKey)
}
var body: some View {
VStack(alignment: .leading) {
Text("Stadt-Rundlauf - \(visible.count)/\(source.count) runners")
.bold()
HStack {
Text("Show:")
Button(menuLabel("Finished", on: !showAbsent)) {
showAbsent = false
}
Button(menuLabel("Did not start", on: showAbsent)) {
showAbsent = true
}
}
HStack {
Text("Sort:")
ForEach(SortKey.allCases, id: \.rawValue) { key in
Button(menuLabel(key.rawValue, on: key == sortKey)) {
sortKey = key
}
}
}
HStack {
Text("Groups:")
ForEach(AgeGroup.allCases, id: \.rawValue) { group in
Button(menuLabel("\(group)", on: includedGroups.contains(group))) {
includedGroups = toggling(includedGroups, group)
}
}
}
TextField(placeholder: "Search by name…") { value in
query = value
}
Divider()
Text(formatRow("Nr", "Name", "Group", "Time")).bold()
ScrollView {
ForEach(visible, id: \.number) { runner in
Text(formatRow("#\(runner.number)", runner.name, "\(runner.ageGroup)", runner.time))
}
}
}
.padding()
}
}