@@ -10,10 +10,10 @@ def _get_xcode_product_version(*, xcode_config):
1010""" )
1111
1212 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 )))
1717
1818 return version_components [3 ]
1919
@@ -25,7 +25,10 @@ def _custom_toolchain_impl(ctx):
2525 toolchain_name_base = ctx .attr .toolchain_name
2626 toolchain_id = "com.rules_xcodeproj.{}.{}" .format (toolchain_name_base , xcode_version )
2727 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" )
2932
3033 resolved_overrides = {}
3134 override_files = []
@@ -53,29 +56,36 @@ def _custom_toolchain_impl(ctx):
5356 if tool_name : # Skip empty names
5457 resolved_overrides [tool_name ] = stub_file .path
5558
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+
5663 overrides_list = " " .join (["{}={}" .format (k , v ) for k , v in resolved_overrides .items ()])
5764
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" )
5968
69+ # Create symlink script
6070 ctx .actions .expand_template (
6171 template = ctx .file ._symlink_template ,
62- output = script_file ,
72+ output = symlink_script_file ,
6373 is_executable = True ,
6474 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 ,
6777 "%toolchain_id%" : toolchain_id ,
6878 "%toolchain_name_base%" : full_toolchain_name ,
6979 "%xcode_version%" : xcode_version ,
7080 },
7181 )
7282
83+ # First run the symlinking script to set up the toolchain
7384 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 ,
7989 execution_requirements = {
8090 "local" : "1" ,
8191 "no-cache" : "1" ,
@@ -85,7 +95,36 @@ def _custom_toolchain_impl(ctx):
8595 use_default_shell_env = True ,
8696 )
8797
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 ])
89128
90129 toolchain_provider = ToolchainInfo (
91130 name = full_toolchain_name ,
@@ -94,7 +133,7 @@ def _custom_toolchain_impl(ctx):
94133
95134 return [
96135 DefaultInfo (
97- files = depset ([toolchain_dir ]),
136+ files = depset ([final_toolchain_dir if override_files else symlink_toolchain_dir ]),
98137 runfiles = runfiles ,
99138 ),
100139 toolchain_provider ,
@@ -109,6 +148,10 @@ custom_toolchain = rule(
109148 doc = "Map from stub target to comma-separated list of tool names that should use that stub" ,
110149 ),
111150 "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+ ),
112155 "_symlink_template" : attr .label (
113156 allow_single_file = True ,
114157 default = Label ("//xcodeproj/internal/templates:custom_toolchain_symlink.sh" ),
0 commit comments