1- def _custom_toolchain_impl (ctx ):
2- toolchain_name_base = ctx .attr .toolchain_name
31
4- # Create a file to store Xcode version
5- xcode_version_file = ctx .actions .declare_file (toolchain_name_base + "_xcode_version.txt" )
2+ def _get_xcode_product_version (* , xcode_config ):
3+ raw_version = str (xcode_config .xcode_version ())
4+ if not raw_version :
5+ fail ("""\
6+ `xcode_config.xcode_version` was not set. This is a bazel bug. Try again.
7+ """ )
68
7- # Run xcodebuild to get the Xcode version
8- ctx .actions .run_shell (
9- outputs = [xcode_version_file ],
10- command = """
11- # Get Xcode version and clean it for use in filenames
12- xcodebuild -version | head -n 1 | sed 's/Xcode //' | tr -d '.' | tr ' ' '_' > {outfile}
13- """ .format (outfile = xcode_version_file .path ),
14- mnemonic = "GetXcodeVersion" ,
15- execution_requirements = {"no-sandbox" : "1" },
16- )
9+ version_components = raw_version .split ("." )
10+ if len (version_components ) < 4 :
11+ # This will result in analysis cache misses, but it's better than
12+ # failing
13+ return raw_version
1714
18- # Create a file to store the default toolchain path
19- default_toolchain_path_file = ctx .actions .declare_file (toolchain_name_base + "_default_toolchain_path.txt" )
15+ return version_components [3 ]
2016
21- # Run xcrun to get the default toolchain path
22- ctx .actions .run_shell (
23- outputs = [default_toolchain_path_file ],
24- command = "xcrun --find clang | sed 's|/usr/bin/clang$||' > {outfile}" .format (
25- outfile = default_toolchain_path_file .path
26- ),
27- mnemonic = "GetDefaultToolchainPath" ,
28- execution_requirements = {"no-sandbox" : "1" }, # Allow xcrun to access system paths
17+
18+ def _custom_toolchain_impl (ctx ):
19+ xcode_version = _get_xcode_product_version (
20+ xcode_config = ctx .attr ._xcode_config [apple_common .XcodeVersionConfig ],
2921 )
3022
31- # Declare the output directory for the toolchain
32- toolchain_dir = ctx .actions .declare_directory (toolchain_name_base + ".xctoolchain" )
23+ toolchain_name_base = ctx .attr .toolchain_name
24+ toolchain_dir = ctx .actions .declare_directory (
25+ toolchain_name_base + ".{}" .format (xcode_version ) + ".xctoolchain"
26+ )
3327
3428 resolved_overrides = {}
35- override_files = [] # Collect all override files to include in inputs
29+ override_files = []
3630
3731 for tool_target , tool_name in ctx .attr .overrides .items ():
38- # The key is the target (label), the value is the tool name (string)
3932 files = tool_target .files .to_list ()
4033 if not files :
4134 fail ("ERROR: Override for '{}' does not produce any files!" .format (tool_name ))
@@ -45,15 +38,13 @@ def _custom_toolchain_impl(ctx):
4538 tool_name , len (files )))
4639
4740 override_file = files [0 ]
48- override_files .append (override_file ) # Add to list of input files
41+ override_files .append (override_file )
4942 resolved_overrides [tool_name ] = override_file .path
5043
51- # Generate symlink creation commands dynamically, excluding plist files
5244 overrides_list = " " .join (["{}={}" .format (k , v ) for k , v in resolved_overrides .items ()])
5345
5446 script_file = ctx .actions .declare_file (toolchain_name_base + "_setup.sh" )
5547
56- # Use expand_template with simplified substitutions
5748 ctx .actions .expand_template (
5849 template = ctx .file ._symlink_template ,
5950 output = script_file ,
@@ -62,39 +53,49 @@ def _custom_toolchain_impl(ctx):
6253 "%toolchain_name_base%" : toolchain_name_base ,
6354 "%toolchain_dir%" : toolchain_dir .path ,
6455 "%overrides_list%" : overrides_list ,
65- "%default_toolchain_path_file%" : default_toolchain_path_file .path ,
66- "%xcode_version_file%" : xcode_version_file .path ,
56+ "%xcode_version%" : xcode_version ,
6757 },
6858 )
6959
70- # Run the generated shell script
7160 ctx .actions .run_shell (
72- outputs = [toolchain_dir ],
73- inputs = [default_toolchain_path_file , xcode_version_file ] + override_files ,
74- tools = [script_file ],
75- mnemonic = "SymlinkDefaultXcodeToolchain" ,
76- command = script_file .path ,
77- execution_requirements = {"no-sandbox" : "1" },
61+ outputs = [toolchain_dir ],
62+ inputs = override_files ,
63+ tools = [script_file ],
64+ mnemonic = "CreateCustomToolchain" ,
65+ command = script_file .path ,
66+ execution_requirements = {
67+ "no-sandbox" : "1" ,
68+ "no-cache" : "1" ,
69+ "local" : "1" ,
70+ "requires-darwin" : "1" ,
71+ },
72+ use_default_shell_env = True ,
7873 )
7974
8075 # Create runfiles with the override files and script file
81- runfiles = ctx .runfiles (files = override_files + [script_file , default_toolchain_path_file , xcode_version_file ])
76+ runfiles = ctx .runfiles (files = override_files + [script_file ])
8277
8378 return [DefaultInfo (
84- files = depset ([toolchain_dir ]),
85- runfiles = runfiles ,
79+ files = depset ([toolchain_dir ]),
80+ runfiles = runfiles ,
8681 )]
8782
8883custom_toolchain = rule (
89- implementation = _custom_toolchain_impl ,
90- attrs = {
91- "toolchain_name" : attr .string (mandatory = True ),
84+ implementation = _custom_toolchain_impl ,
85+ attrs = {
86+ "toolchain_name" : attr .string (mandatory = True ),
9287 "overrides" : attr .label_keyed_string_dict (
93- allow_files = True , mandatory = False , default = {}
88+ allow_files = True , mandatory = False , default = {}
9489 ),
9590 "_symlink_template" : attr .label (
96- allow_single_file = True ,
97- default = Label ("//xcodeproj/internal/templates:custom_toolchain_symlink.sh" ),
91+ allow_single_file = True ,
92+ default = Label ("//xcodeproj/internal/templates:custom_toolchain_symlink.sh" ),
93+ ),
94+ "_xcode_config" : attr .label (
95+ default = configuration_field (
96+ name = "xcode_config_label" ,
97+ fragment = "apple" ,
98+ ),
9899 ),
99100 },
100101)
0 commit comments