1# This is a convenience wrapper to run a platform-specific version of GN with any provided flags 2# from the directory where the user ran Bazel. Without this, users would need to specify the 3# exact flavor of GN needed and use --run_under to change directories before running GN. 4# 5# For example: 6# bazelisk //bazel/external/gn -- format gn/sksl.gni 7# is the same as 8# gn format gn/sksl.gni 9# except it uses a hermetic version of gn instead of whatever is on the user's machine. Note the -- 10# to pass arguments to gn and not have Bazel try to understand them. 11py_binary( 12 name = "gn", 13 srcs = [":gn.py"], 14 data = [":gn_exe"], 15 # We can compile remotely, but because we are running the executable to modify files in 16 # the source tree, running it in a remote, sandboxed would have no effect locally. 17 tags = ["no-remote"], 18) 19 20_GN = """ 21import os 22import subprocess 23import sys 24 25# execpath returns the path to the given label from the exec path. 26# https://bazel.build/reference/be/make-variables#predefined_label_variables 27# We need to get the absolute path here because we want to run gn from the 28# location where the user invoked Bazel. 29gn_exe = os.path.abspath("$(execpath :gn_exe)") 30 31# https://bazel.build/docs/user-manual#running-executables 32# Note: Bazel eats single quotes, so we must use double quotes. 33os.chdir(os.environ["BUILD_WORKING_DIRECTORY"]) # path where user ran Bazel 34 35# Pass any other args along to GN, and stream any output to the user. 36result = subprocess.run([gn_exe] + sys.argv[1:], encoding="utf-8") 37sys.exit(result.returncode) 38""" 39 40genrule( 41 name = "create_gn_script", 42 outs = ["gn.py"], 43 cmd = "echo '%s' > $@" % _GN, 44 tools = [ 45 ":gn_exe", 46 ], 47) 48 49filegroup( 50 name = "gn_exe", 51 srcs = select({ 52 "//bazel/common_config_settings:linux_x64": ["@gn_linux_amd64//:gn"], 53 "//bazel/common_config_settings:mac_arm64": ["@gn_mac_arm64//:gn"], 54 "//bazel/common_config_settings:mac_x64": ["@gn_mac_amd64//:gn"], 55 }), 56) 57