Skip to content

Commit 0703615

Browse files
Add generator_bazel_env (#3310)
Allows setting environment variables that affect only the nested generator call, but not the Xcode based calls. An example use case is setting `tools/bazel` output affecting env variables (e.g. color or verbosity). --------- Signed-off-by: Brentley Jones <github@brentleyjones.com>
1 parent bf72498 commit 0703615

3 files changed

Lines changed: 58 additions & 11 deletions

File tree

docs/bazel.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,13 @@ load("@rules_xcodeproj//xcodeproj:xcodeproj.bzl", "xcodeproj")
5353
load("@rules_xcodeproj//xcodeproj/internal/docs:xcodeproj.bzl", "xcodeproj")
5454

5555
xcodeproj(*, <a href="#xcodeproj-name">name</a>, <a href="#xcodeproj-associated_extra_files">associated_extra_files</a>, <a href="#xcodeproj-bazel_path">bazel_path</a>, <a href="#xcodeproj-bazel_env">bazel_env</a>, <a href="#xcodeproj-config">config</a>,
56-
<a href="#xcodeproj-default_xcode_configuration">default_xcode_configuration</a>, <a href="#xcodeproj-extra_files">extra_files</a>, <a href="#xcodeproj-focused_targets">focused_targets</a>, <a href="#xcodeproj-import_index_build_indexstores">import_index_build_indexstores</a>,
57-
<a href="#xcodeproj-install_directory">install_directory</a>, <a href="#xcodeproj-ios_device_cpus">ios_device_cpus</a>, <a href="#xcodeproj-ios_simulator_cpus">ios_simulator_cpus</a>, <a href="#xcodeproj-minimum_xcode_version">minimum_xcode_version</a>, <a href="#xcodeproj-post_build">post_build</a>,
58-
<a href="#xcodeproj-pre_build">pre_build</a>, <a href="#xcodeproj-project_name">project_name</a>, <a href="#xcodeproj-project_options">project_options</a>, <a href="#xcodeproj-scheme_autogeneration_mode">scheme_autogeneration_mode</a>,
59-
<a href="#xcodeproj-scheme_autogeneration_config">scheme_autogeneration_config</a>, <a href="#xcodeproj-target_name_mode">target_name_mode</a>, <a href="#xcodeproj-top_level_targets">top_level_targets</a>, <a href="#xcodeproj-tvos_device_cpus">tvos_device_cpus</a>,
60-
<a href="#xcodeproj-tvos_simulator_cpus">tvos_simulator_cpus</a>, <a href="#xcodeproj-unfocused_targets">unfocused_targets</a>, <a href="#xcodeproj-visionos_device_cpus">visionos_device_cpus</a>, <a href="#xcodeproj-visionos_simulator_cpus">visionos_simulator_cpus</a>,
61-
<a href="#xcodeproj-watchos_device_cpus">watchos_device_cpus</a>, <a href="#xcodeproj-watchos_simulator_cpus">watchos_simulator_cpus</a>, <a href="#xcodeproj-xcode_configurations">xcode_configurations</a>, <a href="#xcodeproj-xcschemes">xcschemes</a>, <a href="#xcodeproj-kwargs">**kwargs</a>)
56+
<a href="#xcodeproj-default_xcode_configuration">default_xcode_configuration</a>, <a href="#xcodeproj-extra_files">extra_files</a>, <a href="#xcodeproj-focused_targets">focused_targets</a>, <a href="#xcodeproj-generator_bazel_env">generator_bazel_env</a>,
57+
<a href="#xcodeproj-import_index_build_indexstores">import_index_build_indexstores</a>, <a href="#xcodeproj-install_directory">install_directory</a>, <a href="#xcodeproj-ios_device_cpus">ios_device_cpus</a>, <a href="#xcodeproj-ios_simulator_cpus">ios_simulator_cpus</a>,
58+
<a href="#xcodeproj-minimum_xcode_version">minimum_xcode_version</a>, <a href="#xcodeproj-post_build">post_build</a>, <a href="#xcodeproj-pre_build">pre_build</a>, <a href="#xcodeproj-project_name">project_name</a>, <a href="#xcodeproj-project_options">project_options</a>,
59+
<a href="#xcodeproj-scheme_autogeneration_mode">scheme_autogeneration_mode</a>, <a href="#xcodeproj-scheme_autogeneration_config">scheme_autogeneration_config</a>, <a href="#xcodeproj-target_name_mode">target_name_mode</a>,
60+
<a href="#xcodeproj-top_level_targets">top_level_targets</a>, <a href="#xcodeproj-tvos_device_cpus">tvos_device_cpus</a>, <a href="#xcodeproj-tvos_simulator_cpus">tvos_simulator_cpus</a>, <a href="#xcodeproj-unfocused_targets">unfocused_targets</a>,
61+
<a href="#xcodeproj-visionos_device_cpus">visionos_device_cpus</a>, <a href="#xcodeproj-visionos_simulator_cpus">visionos_simulator_cpus</a>, <a href="#xcodeproj-watchos_device_cpus">watchos_device_cpus</a>, <a href="#xcodeproj-watchos_simulator_cpus">watchos_simulator_cpus</a>,
62+
<a href="#xcodeproj-xcode_configurations">xcode_configurations</a>, <a href="#xcodeproj-xcschemes">xcschemes</a>, <a href="#xcodeproj-kwargs">**kwargs</a>)
6263
</pre>
6364

6465
Creates an `.xcodeproj` file in the workspace when run.
@@ -97,6 +98,7 @@ xcodeproj(
9798
| <a id="xcodeproj-default_xcode_configuration"></a>default_xcode_configuration | Optional. The name of the the Xcode configuration to use when building, if not overridden by custom schemes.<br><br>If not set, the first Xcode configuration alphabetically will be used. Use [`xcode_configurations`](#xcodeproj-xcode_configurations) to adjust Xcode configurations. | `None` |
9899
| <a id="xcodeproj-extra_files"></a>extra_files | Optional. A `list` of extra `File`s to be added to the project. | `[]` |
99100
| <a id="xcodeproj-focused_targets"></a>focused_targets | Optional. A `list` of target labels as `string` values.<br><br>If specified, only these targets will be included in the generated project; all other targets will be excluded, as if they were listed explicitly in the `unfocused_targets` argument. The labels must match transitive dependencies of the targets specified in the `top_level_targets` argument. | `[]` |
101+
| <a id="xcodeproj-generator_bazel_env"></a>generator_bazel_env | Optional. A `dict` of environment variables to set when invoking `bazel_path` during project generation only.<br><br>This behaves the same as `bazel_env`, but only applies to the generated runner's Bazel invocations while generating the project. These values are not written into the generated `.xcodeproj`, and they do not apply to Bazel builds launched later from Xcode. | `{}` |
100102
| <a id="xcodeproj-import_index_build_indexstores"></a>import_index_build_indexstores | Optional. Whether to import the index stores generated by Index Build.<br><br>This is useful if you want to use the index stores generated by Index Build to speed up Xcode's indexing process. You may not want this enabled if the additional work (mainly disk IO) of importing the index stores is not worth it for your project. | `True` |
101103
| <a id="xcodeproj-install_directory"></a>install_directory | Optional. The directory where the generated project will be written to.<br><br>The path is relative to the workspace root.<br><br>Defaults to the directory that the `xcodeproj` target is declared in (e.g. if the `xcodeproj` target is declared in `//foo/bar:BUILD` then the default value is `"foo/bar"`). Use `""` to have the project generated in the workspace root. | `None` |
102104
| <a id="xcodeproj-ios_device_cpus"></a>ios_device_cpus | Optional. The value to use for `--ios_multi_cpus` when building the transitive dependencies of the targets specified in the `top_level_targets` argument with the `"device"` `target_environment`.<br><br>**Warning:** Changing this value will affect the Starlark transition hash of all transitive dependencies of the targets specified in the `top_level_targets` argument with the `"device"` `target_environment`, even if they aren't iOS targets. | `"arm64"` |

xcodeproj/internal/xcodeproj_runner.bzl

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ load(":collections.bzl", "uniq")
66
load(":execution_root.bzl", "write_execution_root_file")
77
load(":providers.bzl", "XcodeProjRunnerOutputInfo")
88

9+
# Null character is used to represent `None`, since `attr.string_dict`
10+
# requires non-`None` values.
11+
_NULL_BAZEL_ENV_VALUE = "\0"
12+
_NULL_BAZEL_ENV_VALUE_LITERAL = "\\0"
13+
914
def _process_extra_flags(*, attr, content, setting, config, config_suffix):
1015
extra_flags = getattr(attr, setting)[BuildSettingInfo].value
1116
if extra_flags:
@@ -272,6 +277,7 @@ def _write_runner(
272277
execution_root_file,
273278
extra_flags_bazelrc,
274279
extra_generator_flags,
280+
generator_bazel_env,
275281
generator_build_file,
276282
generator_defs_bzl,
277283
install_path,
@@ -286,8 +292,10 @@ def _write_runner(
286292
base_envs_values = []
287293
collect_statements = []
288294
for key, value in bazel_env.items():
289-
if value == "\0":
290-
base_def_env_values.append(' \\"{}\\": \\"\\\\0\\",'.format(key))
295+
if value == _NULL_BAZEL_ENV_VALUE:
296+
base_def_env_values.append(
297+
' \\"{}\\": \\"{}\\",'.format(key, _NULL_BAZEL_ENV_VALUE_LITERAL),
298+
)
291299
collect_statements.append("""\
292300
if [[ -n "${{{key}:-}}" ]]; then
293301
envs+=("{key}=${key}")
@@ -323,6 +331,25 @@ fi
323331
),
324332
))
325333

334+
for key, value in generator_bazel_env.items():
335+
if value == _NULL_BAZEL_ENV_VALUE:
336+
collect_statements.append("""\
337+
if [[ -n "${{{key}:-}}" ]]; then
338+
envs+=("{key}=${key}")
339+
fi
340+
""".format(key = key))
341+
else:
342+
base_envs_values.append(" \"{}={}\"".format(
343+
key,
344+
(
345+
value.replace(
346+
# Escape double quotes for bash
347+
"\"",
348+
"\\\"",
349+
)
350+
),
351+
))
352+
326353
collect_bazel_env = """\
327354
envs=(
328355
{base_envs_values}
@@ -439,6 +466,7 @@ def _xcodeproj_runner_impl(ctx):
439466
extra_generator_flags = (
440467
ctx.attr._extra_generator_flags[BuildSettingInfo].value
441468
),
469+
generator_bazel_env = ctx.attr.generator_bazel_env,
442470
generator_build_file = generator_build_file,
443471
generator_defs_bzl = generator_defs_bzl,
444472
install_path = install_path,
@@ -475,6 +503,7 @@ xcodeproj_runner = rule(
475503
"default_xcode_configuration": attr.string(),
476504
"focused_labels": attr.string_list(default = []),
477505
"generation_shard_count": attr.int(mandatory = True),
506+
"generator_bazel_env": attr.string_dict(mandatory = True),
478507
"import_index_build_indexstores": attr.bool(mandatory = True),
479508
"install_directory": attr.string(mandatory = True),
480509
"ios_device_cpus": attr.string(mandatory = True),

xcodeproj/xcodeproj.bzl

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ load(
1313
"xcscheme_labels",
1414
)
1515

16+
# Null character is used to represent `None`, since `attr.string_dict`
17+
# requires non-`None` values.
18+
_NULL_BAZEL_ENV_VALUE = "\0"
19+
1620
def _normalize_build_setting(flag):
1721
if flag.startswith("//command_line_option:"):
1822
return flag
@@ -31,6 +35,7 @@ def xcodeproj(
3135
default_xcode_configuration = None,
3236
extra_files = [],
3337
focused_targets = [],
38+
generator_bazel_env = {},
3439
import_index_build_indexstores = True,
3540
install_directory = None,
3641
ios_device_cpus = "arm64",
@@ -150,6 +155,13 @@ def xcodeproj(
150155
listed explicitly in the `unfocused_targets` argument. The labels
151156
must match transitive dependencies of the targets specified in the
152157
`top_level_targets` argument.
158+
generator_bazel_env: Optional. A `dict` of environment variables to
159+
set when invoking `bazel_path` during project generation only.
160+
161+
This behaves the same as `bazel_env`, but only applies to the
162+
generated runner's Bazel invocations while generating the project.
163+
These values are not written into the generated `.xcodeproj`, and
164+
they do not apply to Bazel builds launched later from Xcode.
153165
import_index_build_indexstores: Optional. Whether to import the index
154166
stores generated by Index Build.
155167
@@ -365,6 +377,7 @@ def xcodeproj(
365377
if not bazel_path:
366378
bazel_path = "bazel"
367379
bazel_env = dict(bazel_env) if bazel_env else {}
380+
generator_bazel_env = dict(generator_bazel_env) if generator_bazel_env else {}
368381
if "PATH" not in bazel_env:
369382
bazel_env["PATH"] = "/bin:/usr/bin"
370383
if "LANG" not in bazel_env:
@@ -386,11 +399,13 @@ def xcodeproj(
386399
bazel_env["BAZELISK_SKIP_WRAPPER"] = None
387400

388401
bazel_env = {
389-
# Null character is used to represent `None`, since `attr.string_dict`
390-
# requires non-`None` values.
391-
key: "\0" if value == None else value
402+
key: _NULL_BAZEL_ENV_VALUE if value == None else value
392403
for key, value in sorted(bazel_env.items())
393404
}
405+
generator_bazel_env = {
406+
key: _NULL_BAZEL_ENV_VALUE if value == None else value
407+
for key, value in sorted(generator_bazel_env.items())
408+
}
394409

395410
if default_xcode_configuration and default_xcode_configuration not in xcode_configurations:
396411
keys = sorted(xcode_configurations.keys())
@@ -530,6 +545,7 @@ for {configuration} ({new_keys}) do not match keys of other configurations \
530545
config = config,
531546
default_xcode_configuration = default_xcode_configuration,
532547
focused_labels = focused_labels,
548+
generator_bazel_env = generator_bazel_env,
533549
generation_shard_count = generation_shard_count,
534550
import_index_build_indexstores = import_index_build_indexstores,
535551
install_directory = install_directory,

0 commit comments

Comments
 (0)