Skip to content

Commit 2d78cae

Browse files
author
Karim Alweheshy
committed
improve toolchain
1 parent 4e1ef38 commit 2d78cae

File tree

5 files changed

+78
-36
lines changed

5 files changed

+78
-36
lines changed

test/internal/custom_toolchain/BUILD

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ filegroup(
1212
custom_toolchain(
1313
name = "test_toolchain",
1414
overrides = {
15-
# Key is a label target, value is the tool name
1615
":test_swiftc": "swiftc",
1716
},
1817
toolchain_name = "TestCustomToolchain",

test/internal/custom_toolchain/custom_toolchain_test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ if [[ ! -f "$TOOLCHAIN_DIR/ToolchainInfo.plist" ]]; then
2020
fi
2121

2222
# Check for correct identifiers in the plist
23-
if ! grep -q "BazelRulesXcodeProj" "$TOOLCHAIN_DIR/ToolchainInfo.plist"; then
24-
echo "ERROR: ToolchainInfo.plist doesn't contain BazelRulesXcodeProj"
23+
if ! grep -q "TestCustomToolchain" "$TOOLCHAIN_DIR/ToolchainInfo.plist"; then
24+
echo "ERROR: ToolchainInfo.plist doesn't contain TestCustomToolchain"
2525
exit 1
2626
fi
2727

xcodeproj/internal/custom_toolchain.bzl

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Implementation of the `custom_toolchain` rule."""
22

3+
load("//xcodeproj/internal:providers.bzl", "ToolchainInfo")
4+
35
def _get_xcode_product_version(*, xcode_config):
46
raw_version = str(xcode_config.xcode_version())
57
if not raw_version:
@@ -21,31 +23,39 @@ def _custom_toolchain_impl(ctx):
2123
)
2224

2325
toolchain_name_base = ctx.attr.toolchain_name
24-
toolchain_dir = ctx.actions.declare_directory(
25-
toolchain_name_base + "{}".format(xcode_version) + ".xctoolchain",
26-
)
26+
toolchain_id = "com.rules_xcodeproj.{}.{}".format(toolchain_name_base, xcode_version)
27+
full_toolchain_name = "{}{}".format(toolchain_name_base, xcode_version)
28+
toolchain_dir = ctx.actions.declare_directory(full_toolchain_name + ".xctoolchain")
2729

2830
resolved_overrides = {}
2931
override_files = []
3032

31-
for tool_target, tool_name in ctx.attr.overrides.items():
32-
files = tool_target.files.to_list()
33+
# Process tools from comma-separated list
34+
for stub_target, tools_str in ctx.attr.overrides.items():
35+
files = stub_target.files.to_list()
3336
if not files:
34-
fail("ERROR: Override for '{}' does not produce any files!".format(tool_name))
37+
fail("ERROR: Override stub does not produce any files!")
3538

3639
if len(files) > 1:
37-
fail("ERROR: Override for '{}' produces multiple files ({}). Each override must have exactly one file.".format(
38-
tool_name,
40+
fail("ERROR: Override stub produces multiple files ({}). Each stub must have exactly one file.".format(
3941
len(files),
4042
))
4143

42-
override_file = files[0]
43-
override_files.append(override_file)
44-
resolved_overrides[tool_name] = override_file.path
44+
stub_file = files[0]
45+
if stub_file not in override_files:
46+
override_files.append(stub_file)
47+
48+
# Split comma-separated list of tool names
49+
tool_names = [name.strip() for name in tools_str.split(",")]
50+
51+
# Add an entry for each tool name
52+
for tool_name in tool_names:
53+
if tool_name: # Skip empty names
54+
resolved_overrides[tool_name] = stub_file.path
4555

4656
overrides_list = " ".join(["{}={}".format(k, v) for k, v in resolved_overrides.items()])
4757

48-
script_file = ctx.actions.declare_file(toolchain_name_base + "_setup.sh")
58+
script_file = ctx.actions.declare_file(full_toolchain_name + "_setup.sh")
4959

5060
ctx.actions.expand_template(
5161
template = ctx.file._symlink_template,
@@ -54,7 +64,8 @@ def _custom_toolchain_impl(ctx):
5464
substitutions = {
5565
"%overrides_list%": overrides_list,
5666
"%toolchain_dir%": toolchain_dir.path,
57-
"%toolchain_name_base%": toolchain_name_base,
67+
"%toolchain_id%": toolchain_id,
68+
"%toolchain_name_base%": full_toolchain_name,
5869
"%xcode_version%": xcode_version,
5970
},
6071
)
@@ -74,21 +85,28 @@ def _custom_toolchain_impl(ctx):
7485
use_default_shell_env = True,
7586
)
7687

77-
# Create runfiles with the override files and script file
7888
runfiles = ctx.runfiles(files = override_files + [script_file])
7989

80-
return [DefaultInfo(
81-
files = depset([toolchain_dir]),
82-
runfiles = runfiles,
83-
)]
90+
toolchain_provider = ToolchainInfo(
91+
name = full_toolchain_name,
92+
identifier = toolchain_id,
93+
)
94+
95+
return [
96+
DefaultInfo(
97+
files = depset([toolchain_dir]),
98+
runfiles = runfiles,
99+
),
100+
toolchain_provider,
101+
]
84102

85103
custom_toolchain = rule(
86104
implementation = _custom_toolchain_impl,
87105
attrs = {
88106
"overrides": attr.label_keyed_string_dict(
89107
allow_files = True,
90-
mandatory = False,
91-
default = {},
108+
mandatory = True,
109+
doc = "Map from stub target to comma-separated list of tool names that should use that stub",
92110
),
93111
"toolchain_name": attr.string(mandatory = True),
94112
"_symlink_template": attr.label(

xcodeproj/internal/providers.bzl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@ XcodeProjRunnerOutputInfo = provider(
1515
"runner": "The xcodeproj runner.",
1616
},
1717
)
18+
19+
ToolchainInfo = provider(
20+
doc = "Information about the custom toolchain",
21+
fields = {
22+
"identifier": "The bundle identifier of the toolchain",
23+
"name": "The full name of the toolchain",
24+
},
25+
)

xcodeproj/internal/templates/custom_toolchain_symlink.sh

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
set -e
2+
set -euo pipefail
33

44
# Define constants within the script
55
TOOLCHAIN_NAME_BASE="%toolchain_name_base%"
@@ -17,6 +17,10 @@ BUILT_TOOLCHAIN_PATH="$PWD/$TOOLCHAIN_DIR"
1717

1818
mkdir -p "$TOOLCHAIN_DIR"
1919

20+
# Parse overrides into a file for safer processing
21+
OVERRIDES_FILE=$(mktemp)
22+
echo "%overrides_list%" > "$OVERRIDES_FILE"
23+
2024
# Process all files from the default toolchain
2125
find "$DEFAULT_TOOLCHAIN" -type f -o -type l | while read -r file; do
2226
base_name="$(basename "$file")"
@@ -30,27 +34,40 @@ find "$DEFAULT_TOOLCHAIN" -type f -o -type l | while read -r file; do
3034
# Ensure parent directory exists
3135
mkdir -p "$TOOLCHAIN_DIR/$(dirname "$rel_path")"
3236

33-
# Process overrides
37+
# Check if this file has an override
3438
override_found=false
35-
while IFS='=' read -r key value; do
36-
if [[ "$key" == "$base_name" ]]; then
37-
value="$PWD/$value"
38-
cp "$value" "$TOOLCHAIN_DIR/$rel_path"
39-
# Make executable if original is executable
40-
if [[ -x "$file" ]]; then
41-
chmod +x "$TOOLCHAIN_DIR/$rel_path"
42-
fi
39+
override_value=""
40+
41+
for override in $(cat "$OVERRIDES_FILE"); do
42+
KEY="${override%%=*}"
43+
VALUE="${override#*=}"
44+
45+
if [[ "$KEY" == "$base_name" ]]; then
46+
override_value="$VALUE"
4347
override_found=true
4448
break
4549
fi
46-
done <<< "%overrides_list%"
50+
done
4751

48-
# If no override found, symlink the original
49-
if [[ "$override_found" == "false" ]]; then
52+
# Apply the override or create symlink
53+
if [[ "$override_found" == "true" ]]; then
54+
# Make path absolute
55+
override_path="$PWD/$override_value"
56+
cp "$override_path" "$TOOLCHAIN_DIR/$rel_path"
57+
58+
# Make executable if original is executable
59+
if [[ -x "$file" ]]; then
60+
chmod +x "$TOOLCHAIN_DIR/$rel_path"
61+
fi
62+
else
63+
# If no override found, symlink the original
5064
ln -sf "$file" "$TOOLCHAIN_DIR/$rel_path"
5165
fi
5266
done
5367

68+
# Clean up
69+
rm -f "$OVERRIDES_FILE"
70+
5471
# Generate the ToolchainInfo.plist directly with Xcode version information
5572
cat > "$TOOLCHAIN_DIR/ToolchainInfo.plist" << EOF
5673
<?xml version="1.0" encoding="UTF-8"?>

0 commit comments

Comments
 (0)