@@ -10,10 +10,10 @@ def _get_xcode_product_version(*, xcode_config):
10
10
""" )
11
11
12
12
version_components = raw_version .split ("." )
13
- if len (version_components ) < 4 :
14
- # This will result in analysis cache misses, but it's better than
15
- # failing
16
- return raw_version
13
+ if len (version_components ) != 4 :
14
+ fail ( """ \
15
+ `xcode_config.xcode_version` returned an unexpected number of components: {}
16
+ """ . format ( len ( version_components )))
17
17
18
18
return version_components [3 ]
19
19
@@ -25,7 +25,10 @@ def _custom_toolchain_impl(ctx):
25
25
toolchain_name_base = ctx .attr .toolchain_name
26
26
toolchain_id = "com.rules_xcodeproj.{}.{}" .format (toolchain_name_base , xcode_version )
27
27
full_toolchain_name = "{}{}" .format (toolchain_name_base , xcode_version )
28
- toolchain_dir = ctx .actions .declare_directory (full_toolchain_name + ".xctoolchain" )
28
+
29
+ # Create two directories - one for symlinks, one for the final overridden toolchain
30
+ symlink_toolchain_dir = ctx .actions .declare_directory (full_toolchain_name + ".symlink.xctoolchain" )
31
+ final_toolchain_dir = ctx .actions .declare_directory (full_toolchain_name + ".xctoolchain" )
29
32
30
33
resolved_overrides = {}
31
34
override_files = []
@@ -53,29 +56,36 @@ def _custom_toolchain_impl(ctx):
53
56
if tool_name : # Skip empty names
54
57
resolved_overrides [tool_name ] = stub_file .path
55
58
59
+ # Instead of passing the full map of overrides, just pass the tool names
60
+ # This way, changes to the stubs don't trigger a rebuild
61
+ tool_names_list = " " .join (resolved_overrides .keys ())
62
+
56
63
overrides_list = " " .join (["{}={}" .format (k , v ) for k , v in resolved_overrides .items ()])
57
64
58
- script_file = ctx .actions .declare_file (full_toolchain_name + "_setup.sh" )
65
+ symlink_script_file = ctx .actions .declare_file (full_toolchain_name + "_symlink.sh" )
66
+ override_script_file = ctx .actions .declare_file (full_toolchain_name + "_override.sh" )
67
+ override_marker = ctx .actions .declare_file (full_toolchain_name + ".override.marker" )
59
68
69
+ # Create symlink script
60
70
ctx .actions .expand_template (
61
71
template = ctx .file ._symlink_template ,
62
- output = script_file ,
72
+ output = symlink_script_file ,
63
73
is_executable = True ,
64
74
substitutions = {
65
- "%overrides_list %" : overrides_list ,
66
- "%toolchain_dir%" : toolchain_dir .path ,
75
+ "%tool_names_list %" : tool_names_list ,
76
+ "%toolchain_dir%" : symlink_toolchain_dir .path ,
67
77
"%toolchain_id%" : toolchain_id ,
68
78
"%toolchain_name_base%" : full_toolchain_name ,
69
79
"%xcode_version%" : xcode_version ,
70
80
},
71
81
)
72
82
83
+ # First run the symlinking script to set up the toolchain
73
84
ctx .actions .run_shell (
74
- outputs = [toolchain_dir ],
75
- inputs = override_files ,
76
- tools = [script_file ],
77
- mnemonic = "CreateCustomToolchain" ,
78
- command = script_file .path ,
85
+ outputs = [symlink_toolchain_dir ],
86
+ tools = [symlink_script_file ],
87
+ mnemonic = "CreateSymlinkToolchain" ,
88
+ command = symlink_script_file .path ,
79
89
execution_requirements = {
80
90
"local" : "1" ,
81
91
"no-cache" : "1" ,
@@ -85,7 +95,36 @@ def _custom_toolchain_impl(ctx):
85
95
use_default_shell_env = True ,
86
96
)
87
97
88
- runfiles = ctx .runfiles (files = override_files + [script_file ])
98
+ if override_files :
99
+ ctx .actions .expand_template (
100
+ template = ctx .file ._override_template ,
101
+ output = override_script_file ,
102
+ is_executable = True ,
103
+ substitutions = {
104
+ "%final_toolchain_dir%" : final_toolchain_dir .path ,
105
+ "%marker_file%" : override_marker .path ,
106
+ "%overrides_list%" : overrides_list ,
107
+ "%symlink_toolchain_dir%" : symlink_toolchain_dir .path ,
108
+ "%tool_names_list%" : tool_names_list ,
109
+ },
110
+ )
111
+
112
+ ctx .actions .run_shell (
113
+ inputs = override_files + [symlink_toolchain_dir ],
114
+ outputs = [final_toolchain_dir , override_marker ],
115
+ tools = [override_script_file ],
116
+ mnemonic = "ApplyCustomToolchainOverrides" ,
117
+ command = override_script_file .path ,
118
+ execution_requirements = {
119
+ "local" : "1" ,
120
+ "no-cache" : "1" ,
121
+ "no-sandbox" : "1" ,
122
+ "requires-darwin" : "1" ,
123
+ },
124
+ use_default_shell_env = True ,
125
+ )
126
+
127
+ runfiles = ctx .runfiles (files = override_files + [symlink_script_file , override_script_file , override_marker ])
89
128
90
129
toolchain_provider = ToolchainInfo (
91
130
name = full_toolchain_name ,
@@ -94,7 +133,7 @@ def _custom_toolchain_impl(ctx):
94
133
95
134
return [
96
135
DefaultInfo (
97
- files = depset ([toolchain_dir ]),
136
+ files = depset ([final_toolchain_dir if override_files else symlink_toolchain_dir ]),
98
137
runfiles = runfiles ,
99
138
),
100
139
toolchain_provider ,
@@ -109,6 +148,10 @@ custom_toolchain = rule(
109
148
doc = "Map from stub target to comma-separated list of tool names that should use that stub" ,
110
149
),
111
150
"toolchain_name" : attr .string (mandatory = True ),
151
+ "_override_template" : attr .label (
152
+ allow_single_file = True ,
153
+ default = Label ("//xcodeproj/internal/templates:custom_toolchain_override.sh" ),
154
+ ),
112
155
"_symlink_template" : attr .label (
113
156
allow_single_file = True ,
114
157
default = Label ("//xcodeproj/internal/templates:custom_toolchain_symlink.sh" ),
0 commit comments