# This is a convenience wrapper to run a platform-specific version of GN with any provided flags # from the directory where the user ran Bazel. Without this, users would need to specify the # exact flavor of GN needed and use --run_under to change directories before running GN. # # For example: # bazelisk //bazel/external/gn -- format gn/sksl.gni # is the same as # gn format gn/sksl.gni # except it uses a hermetic version of gn instead of whatever is on the user's machine. Note the -- # to pass arguments to gn and not have Bazel try to understand them. py_binary( name = "gn", srcs = [":gn.py"], data = [":gn_exe"], # We can compile remotely, but because we are running the executable to modify files in # the source tree, running it in a remote, sandboxed would have no effect locally. tags = ["no-remote"], ) _GN = """ import os import subprocess import sys # rlocationpath returns the path to the given label from the runfiles path (which is the # parent directory, according to local experimentation). # https://bazel.build/reference/be/make-variables#predefined_label_variables # We need to get the absolute path here because we want to run gn from the # location where the user invoked Bazel. os.chdir("..") gn_exe = os.path.abspath("$(rlocationpath :gn_exe)") # https://bazel.build/docs/user-manual#running-executables # Note: Bazel eats single quotes, so we must use double quotes. os.chdir(os.environ["BUILD_WORKING_DIRECTORY"]) # path where user ran Bazel # Pass any other args along to GN, and stream any output to the user. result = subprocess.run([gn_exe] + sys.argv[1:], encoding="utf-8") sys.exit(result.returncode) """ genrule( name = "create_gn_script", outs = ["gn.py"], cmd = "echo '%s' > $@" % _GN, tools = [ ":gn_exe", ], ) filegroup( name = "gn_exe", srcs = select({ "//bazel/common_config_settings:linux_x64": ["@gn_linux_amd64//:gn"], "//bazel/common_config_settings:mac_arm64": ["@gn_mac_arm64//:gn"], "//bazel/common_config_settings:mac_x64": ["@gn_mac_amd64//:gn"], }), )