gn build: Add a template for calling write_cmake_config.py

No behavior change.

Differential Revision: https://reviews.llvm.org/D56487


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350905 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/utils/gn/TODO.txt b/utils/gn/TODO.txt
index 4051fe1..1588470 100644
--- a/utils/gn/TODO.txt
+++ b/utils/gn/TODO.txt
@@ -17,8 +17,6 @@
 - one-build-dir bootstrap builds using GN's toolchain feature
 
 - move clang_tablegen into lib/ for private files
-- add write_cmake_config() template, use it throughout where
-  write_cmake_config.py is called
 - add dead code stripping
 - move run_tablegen.py from build to tablegen folder
 - figure out why -Iclang/Support gets added so often
diff --git a/utils/gn/build/write_cmake_config.gni b/utils/gn/build/write_cmake_config.gni
new file mode 100644
index 0000000..0c89166
--- /dev/null
+++ b/utils/gn/build/write_cmake_config.gni
@@ -0,0 +1,54 @@
+# This file introduces a templates for calling write_cmake_config.py.
+#
+# write_cmake_config behaves like CMake's configure_file(), but runs at build
+# time, not at generator time.  See write_cmake_config.py for details.
+#
+# Parameters:
+#
+#   input (required) [string]
+#
+#   output (required) [string]
+#
+#   values (required) [list of strings]
+#       Each entry is a '='-separated key-value pair used for substitution.
+#
+# Example use:
+#
+#   write_cmake_config("attributes_compat_func_gen") {
+#     input = "Version.inc.in"
+#     output = "$root_gen_dir/clang/include/clang/Basic/Version.inc",
+#     values = [
+#       "CLANG_VERSION=$llvm_version",
+#     ]
+#   }
+
+template("write_cmake_config") {
+  assert(defined(invoker.input), "must set 'input' in $target_name")
+  assert(defined(invoker.output), "must set 'output' in $target_name")
+  assert(defined(invoker.values), "must set 'values' in $target_name")
+
+  action(target_name) {
+    script = "//llvm/utils/gn/build/write_cmake_config.py"
+
+    sources = [
+      invoker.input,
+    ]
+    outputs = [
+      invoker.output,
+    ]
+    args = [
+             "-o",
+             rebase_path(outputs[0], root_out_dir),
+             rebase_path(sources[0], root_out_dir),
+           ] + invoker.values
+
+    forward_variables_from(invoker,
+                           [
+                             "configs",
+                             "deps",
+                             "public_configs",
+                             "public_deps",
+                             "visibility",
+                           ])
+  }
+}
diff --git a/utils/gn/secondary/clang/include/clang/Basic/BUILD.gn b/utils/gn/secondary/clang/include/clang/Basic/BUILD.gn
index c064d12..7d67a2f 100644
--- a/utils/gn/secondary/clang/include/clang/Basic/BUILD.gn
+++ b/utils/gn/secondary/clang/include/clang/Basic/BUILD.gn
@@ -1,22 +1,13 @@
 import("//clang/utils/TableGen/clang_tablegen.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("//llvm/version.gni")
 
 # Version header.
 
-action("version") {
-  script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-  sources = [
-    "Version.inc.in",
-  ]
-  outputs = [
-    "$root_gen_dir/clang/include/clang/Basic/Version.inc",
-  ]
-  args = [
-    "-o",
-    rebase_path(outputs[0], root_out_dir),
-    rebase_path(sources[0], root_out_dir),
-
+write_cmake_config("version") {
+  input = "Version.inc.in"
+  output = "$target_gen_dir/Version.inc"
+  values = [
     "CLANG_VERSION=$llvm_version",
     "CLANG_VERSION_MAJOR=$llvm_version_major",
     "CLANG_VERSION_MINOR=$llvm_version_minor",
diff --git a/utils/gn/secondary/clang/include/clang/Config/BUILD.gn b/utils/gn/secondary/clang/include/clang/Config/BUILD.gn
index 0cb130e..a3c0d5a 100644
--- a/utils/gn/secondary/clang/include/clang/Config/BUILD.gn
+++ b/utils/gn/secondary/clang/include/clang/Config/BUILD.gn
@@ -1,6 +1,7 @@
 import("//clang/lib/ARCMigrate/enable.gni")
 import("//clang/lib/StaticAnalyzer/Frontend/enable.gni")
 import("//llvm/utils/gn/build/libs/xml/enable.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("//llvm/version.gni")
 
 config("Config_config") {
@@ -8,20 +9,10 @@
   include_dirs = [ "$target_gen_dir/clang/include" ]
 }
 
-action("Config") {
-  script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-  sources = [
-    "config.h.cmake",
-  ]
-  outputs = [
-    "$target_gen_dir/config.h",
-  ]
-  args = [
-    "-o",
-    rebase_path(outputs[0], root_out_dir),
-    rebase_path(sources[0], root_out_dir),
-
+write_cmake_config("Config") {
+  input = "config.h.cmake"
+  output = "$target_gen_dir/config.h"
+  values = [
     "BUG_REPORT_URL=https://bugs.llvm.org/",
     "CLANG_DEFAULT_LINKER=",
     "CLANG_DEFAULT_STD_C=",
@@ -47,36 +38,36 @@
   ]
 
   if (clang_enable_arcmt) {
-    args += [ "CLANG_ENABLE_ARCMT=1" ]
+    values += [ "CLANG_ENABLE_ARCMT=1" ]
   } else {
-    args += [ "CLANG_ENABLE_ARCMT=" ]
+    values += [ "CLANG_ENABLE_ARCMT=" ]
   }
 
   if (clang_enable_static_analyzer) {
-    args += [ "CLANG_ENABLE_STATIC_ANALYZER=1" ]
+    values += [ "CLANG_ENABLE_STATIC_ANALYZER=1" ]
   } else {
-    args += [ "CLANG_ENABLE_STATIC_ANALYZER=" ]
+    values += [ "CLANG_ENABLE_STATIC_ANALYZER=" ]
   }
 
   if (host_os != "win") {
-    args += [ "CLANG_HAVE_RLIMITS=1" ]
+    values += [ "CLANG_HAVE_RLIMITS=1" ]
   } else {
-    args += [ "CLANG_HAVE_RLIMITS=" ]
+    values += [ "CLANG_HAVE_RLIMITS=" ]
   }
 
   if (llvm_enable_libxml2) {
-    args += [ "CLANG_HAVE_LIBXML=1" ]
+    values += [ "CLANG_HAVE_LIBXML=1" ]
   } else {
-    args += [ "CLANG_HAVE_LIBXML=" ]
+    values += [ "CLANG_HAVE_LIBXML=" ]
   }
 
   if (host_os == "mac") {
     # FIXME: Hardcoding this isn't great, but assuming that the host ld version
     # has anything to do with the ld version where the built clang will run
     # isn't either. Probably want to make this a declare_args.
-    args += [ "HOST_LINK_VERSION=305" ]
+    values += [ "HOST_LINK_VERSION=305" ]
   } else {
-    args += [ "HOST_LINK_VERSION=" ]
+    values += [ "HOST_LINK_VERSION=" ]
   }
 
   # Let targets depending on this find the generated file.
diff --git a/utils/gn/secondary/clang/test/BUILD.gn b/utils/gn/secondary/clang/test/BUILD.gn
index 0d805bd..5929eec 100644
--- a/utils/gn/secondary/clang/test/BUILD.gn
+++ b/utils/gn/secondary/clang/test/BUILD.gn
@@ -3,24 +3,15 @@
 import("//llvm/lib/Target/targets.gni")
 import("//llvm/triples.gni")
 import("//llvm/utils/gn/build/libs/zlib/enable.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("clang_lit_site_cfg_files.gni")
 
 template("write_lit_config") {
-  action(target_name) {
-    script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-    sources = [
-      invoker.input,
-    ]
-    outputs = [
-      invoker.output,
-    ]
-    args = [
-      "-o",
-      rebase_path(outputs[0], root_out_dir),
-      rebase_path(sources[0], root_out_dir),
-
-      "LIT_SITE_CFG_IN_HEADER=## Autogenerated from ${sources[0]}, do not edit",
+  write_cmake_config(target_name) {
+    input = invoker.input
+    output = invoker.output
+    values = [
+      "LIT_SITE_CFG_IN_HEADER=## Autogenerated from $input, do not edit",
       "CLANG_BINARY_DIR=" +
           rebase_path(get_label_info("//clang", "target_out_dir")),
       "CLANG_SOURCE_DIR=" + rebase_path("//clang"),
@@ -34,11 +25,11 @@
     ]
     if (host_os == "win") {
       # See comment for Windows solink in llvm/utils/gn/build/toolchain/BUILD.gn
-      args += [ "SHLIBDIR=" + rebase_path("$root_out_dir/bin") ]
+      values += [ "SHLIBDIR=" + rebase_path("$root_out_dir/bin") ]
     } else {
-      args += [ "SHLIBDIR=" + rebase_path("$root_out_dir/lib") ]
+      values += [ "SHLIBDIR=" + rebase_path("$root_out_dir/lib") ]
     }
-    args += invoker.extra_args
+    values += invoker.extra_values
   }
 }
 
@@ -47,7 +38,7 @@
   input = "//clang/test/lit.site.cfg.py.in"
   output = clang_lit_site_cfg_file
 
-  extra_args = [
+  extra_values = [
     "CLANG_ANALYZER_WITH_Z3=",  # Must be empty, not 0.
     "CLANG_BUILD_EXAMPLES=0",
     "CLANG_DEFAULT_CXX_STDLIB=",  # Empty string means "default value" here.
@@ -69,35 +60,35 @@
   ]
 
   if (clang_enable_arcmt) {
-    extra_args += [ "CLANG_ENABLE_ARCMT=1" ]
+    extra_values += [ "CLANG_ENABLE_ARCMT=1" ]
   } else {
-    extra_args += [ "CLANG_ENABLE_ARCMT=0" ]
+    extra_values += [ "CLANG_ENABLE_ARCMT=0" ]
   }
 
   if (clang_enable_static_analyzer) {
-    extra_args += [ "CLANG_ENABLE_STATIC_ANALYZER=1" ]
+    extra_values += [ "CLANG_ENABLE_STATIC_ANALYZER=1" ]
   } else {
-    extra_args += [ "CLANG_ENABLE_STATIC_ANALYZER=0" ]
+    extra_values += [ "CLANG_ENABLE_STATIC_ANALYZER=0" ]
   }
 
   if (llvm_enable_zlib) {
-    extra_args += [ "HAVE_LIBZ=1" ]
+    extra_values += [ "HAVE_LIBZ=1" ]
   } else {
-    extra_args += [ "HAVE_LIBZ=0" ]  # Must be 0.
+    extra_values += [ "HAVE_LIBZ=0" ]  # Must be 0.
   }
 
   if (host_cpu == "x64") {
-    extra_args += [ "HOST_ARCH=x86_64" ]
+    extra_values += [ "HOST_ARCH=x86_64" ]
   } else {
     assert(false, "unimplemented host_cpu " + host_cpu)
   }
 
   if (host_os == "mac") {
-    extra_args += [ "LLVM_PLUGIN_EXT=.dylib" ]
+    extra_values += [ "LLVM_PLUGIN_EXT=.dylib" ]
   } else if (host_os == "win") {
-    extra_args += [ "LLVM_PLUGIN_EXT=.dll" ]
+    extra_values += [ "LLVM_PLUGIN_EXT=.dll" ]
   } else {
-    extra_args += [ "LLVM_PLUGIN_EXT=.so" ]
+    extra_values += [ "LLVM_PLUGIN_EXT=.so" ]
   }
 }
 
@@ -105,7 +96,7 @@
   # Fully-qualified instead of relative for LIT_SITE_CFG_IN_HEADER.
   input = "//clang/test/Unit/lit.site.cfg.py.in"
   output = clang_lit_unit_site_cfg_file
-  extra_args = [ "LLVM_BUILD_MODE=." ]
+  extra_values = [ "LLVM_BUILD_MODE=." ]
 }
 
 # This target should contain all dependencies of check-clang.
diff --git a/utils/gn/secondary/clang/tools/driver/BUILD.gn b/utils/gn/secondary/clang/tools/driver/BUILD.gn
index 0b51704..7324e04 100644
--- a/utils/gn/secondary/clang/tools/driver/BUILD.gn
+++ b/utils/gn/secondary/clang/tools/driver/BUILD.gn
@@ -1,4 +1,5 @@
 import("//llvm/utils/gn/build/symlink_or_copy.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("//llvm/version.gni")
 
 symlinks = [
@@ -35,20 +36,10 @@
 }
 
 if (host_os == "mac") {
-  action("write_info_plist") {
-    script = "//llvm/utils/gn/build/write_cmake_config.py"
-    sources = [
-      "Info.plist.in",
-    ]
-    outputs = [
-      "$target_gen_dir/Info.plist",
-    ]
-
-    args = [
-      "-o",
-      rebase_path(outputs[0], root_out_dir),
-      rebase_path(sources[0], root_out_dir),
-
+  write_cmake_config("write_info_plist") {
+    input = "Info.plist.in"
+    output = "$target_gen_dir/Info.plist"
+    values = [
       "TOOL_INFO_BUILD_VERSION=$llvm_version_major.$llvm_version_minor",
       "TOOL_INFO_NAME=clang",
       "TOOL_INFO_UTI=org.llvm.clang",
diff --git a/utils/gn/secondary/lld/include/lld/Common/BUILD.gn b/utils/gn/secondary/lld/include/lld/Common/BUILD.gn
index 5c7cd93..82a0923 100644
--- a/utils/gn/secondary/lld/include/lld/Common/BUILD.gn
+++ b/utils/gn/secondary/lld/include/lld/Common/BUILD.gn
@@ -1,19 +1,10 @@
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("//llvm/version.gni")
 
-action("version") {
-  script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-  sources = [
-    "Version.inc.in",
-  ]
-  outputs = [
-    "$target_gen_dir/Version.inc",
-  ]
-  args = [
-    "-o",
-    rebase_path(outputs[0], root_out_dir),
-    rebase_path(sources[0], root_out_dir),
-
+write_cmake_config("version") {
+  input = "Version.inc.in"
+  output = "$target_gen_dir/Version.inc"
+  values = [
     "LLD_VERSION=$llvm_version",
     "LLD_VERSION_MAJOR=$llvm_version_major",
     "LLD_VERSION_MINOR=$llvm_version_minor",
diff --git a/utils/gn/secondary/lld/test/BUILD.gn b/utils/gn/secondary/lld/test/BUILD.gn
index 166152c..6eb80c9 100644
--- a/utils/gn/secondary/lld/test/BUILD.gn
+++ b/utils/gn/secondary/lld/test/BUILD.gn
@@ -2,26 +2,16 @@
 import("//llvm/triples.gni")
 import("//llvm/utils/gn/build/libs/xml/enable.gni")
 import("//llvm/utils/gn/build/libs/zlib/enable.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("lld_lit_site_cfg_files.gni")
 
 # The bits common to writing lit.site.cfg.py.in and Unit/lit.site.cfg.py.in.
 template("write_lit_cfg") {
-  action(target_name) {
-    script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-    sources = [
-      invoker.input,
-    ]
-    outputs = [
-      invoker.output,
-    ]
-
-    args = [
-      "-o",
-      rebase_path(outputs[0], root_out_dir),
-      rebase_path(sources[0], root_out_dir),
-
-      "LIT_SITE_CFG_IN_HEADER=## Autogenerated from ${sources[0]}, do not edit",
+  write_cmake_config(target_name) {
+    input = invoker.input
+    output = invoker.output
+    values = [
+      "LIT_SITE_CFG_IN_HEADER=## Autogenerated from $input, do not edit",
       "LLD_BINARY_DIR=" +
           rebase_path(get_label_info("//lld", "target_out_dir")),
       "LLD_SOURCE_DIR=" + rebase_path("//lld"),
@@ -36,7 +26,7 @@
       "PYTHON_EXECUTABLE=$python_path",
       "TARGET_TRIPLE=$llvm_target_triple",
     ]
-    args += invoker.extra_args
+    values += invoker.extra_values
   }
 }
 
@@ -45,23 +35,23 @@
   input = "//lld/test/lit.site.cfg.py.in"
   output = lld_lit_site_cfg_file
 
-  extra_args = []
+  extra_values = []
   if (llvm_enable_dia_sdk) {
-    extra_args += [ "LLVM_ENABLE_DIA_SDK=1" ]
+    extra_values += [ "LLVM_ENABLE_DIA_SDK=1" ]
   } else {
-    extra_args += [ "LLVM_ENABLE_DIA_SDK=0" ]  # Must be 0.
+    extra_values += [ "LLVM_ENABLE_DIA_SDK=0" ]  # Must be 0.
   }
 
   if (llvm_enable_libxml2) {
-    extra_args += [ "LLVM_LIBXML2_ENABLED=1" ]
+    extra_values += [ "LLVM_LIBXML2_ENABLED=1" ]
   } else {
-    extra_args += [ "LLVM_LIBXML2_ENABLED=" ]  # Must be empty.
+    extra_values += [ "LLVM_LIBXML2_ENABLED=" ]  # Must be empty.
   }
 
   if (llvm_enable_zlib) {
-    extra_args += [ "HAVE_LIBZ=1" ]
+    extra_values += [ "HAVE_LIBZ=1" ]
   } else {
-    extra_args += [ "HAVE_LIBZ=0" ]  # Must be 0.
+    extra_values += [ "HAVE_LIBZ=0" ]  # Must be 0.
   }
 }
 
@@ -69,7 +59,7 @@
   # Fully-qualified instead of relative for LIT_SITE_CFG_IN_HEADER.
   input = "//lld/test/Unit/lit.site.cfg.py.in"
   output = lld_lit_unit_site_cfg_file
-  extra_args = [ "LLVM_BUILD_MODE=." ]
+  extra_values = [ "LLVM_BUILD_MODE=." ]
 }
 
 # This target should contain all dependencies of check-lld.
diff --git a/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn b/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
index 44ad0a0..41e1a31 100644
--- a/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
+++ b/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn
@@ -7,6 +7,7 @@
 import("//llvm/utils/gn/build/libs/xar/enable.gni")
 import("//llvm/utils/gn/build/libs/xml/enable.gni")
 import("//llvm/utils/gn/build/libs/zlib/enable.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("//llvm/version.gni")
 
 # Contains actions to create config.h, llvm-config.h, abi-breaking.h,
@@ -43,53 +44,32 @@
   llvm_enable_reverse_iteration = false
 }
 
-action("abi-breaking") {
-  script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-  sources = [
-    "abi-breaking.h.cmake",
-  ]
-  outputs = [
-    "$target_gen_dir/abi-breaking.h",
-  ]
-  args = [
-    "-o",
-    rebase_path(outputs[0], root_out_dir),
-
-    rebase_path(sources[0], root_out_dir),
-  ]
+write_cmake_config("abi-breaking") {
+  input = "abi-breaking.h.cmake"
+  output = "$target_gen_dir/abi-breaking.h"
+  values = []
 
   if (llvm_enable_abi_breaking_checks) {
-    args += [ "LLVM_ENABLE_ABI_BREAKING_CHECKS=1" ]
+    values += [ "LLVM_ENABLE_ABI_BREAKING_CHECKS=1" ]
   } else {
-    args += [ "LLVM_ENABLE_ABI_BREAKING_CHECKS=" ]
+    values += [ "LLVM_ENABLE_ABI_BREAKING_CHECKS=" ]
   }
 
   if (llvm_enable_reverse_iteration) {
-    args += [ "LLVM_ENABLE_REVERSE_ITERATION=1" ]
+    values += [ "LLVM_ENABLE_REVERSE_ITERATION=1" ]
   } else {
-    args += [ "LLVM_ENABLE_REVERSE_ITERATION=" ]
+    values += [ "LLVM_ENABLE_REVERSE_ITERATION=" ]
   }
 }
 
-action("config") {
-  script = "//llvm/utils/gn/build/write_cmake_config.py"
-
+write_cmake_config("config") {
   public_deps = [
     ":llvm-config",
   ]
 
-  sources = [
-    "config.h.cmake",
-  ]
-  outputs = [
-    "$target_gen_dir/config.h",
-  ]
-  args = [
-    "-o",
-    rebase_path(outputs[0], root_out_dir),
-    rebase_path(sources[0], root_out_dir),
-
+  input = "config.h.cmake"
+  output = "$target_gen_dir/config.h"
+  values = [
     "BUG_REPORT_URL=https://bugs.llvm.org/",
     "ENABLE_BACKTRACES=1",
     "ENABLE_CRASH_OVERRIDES=1",
@@ -149,7 +129,7 @@
   ]
 
   if (host_os == "linux") {
-    args += [
+    values += [
       "HAVE_FUTIMENS=1",
       "HAVE_LINK_H=1",
       "HAVE_LSEEK64=1",
@@ -161,7 +141,7 @@
       "HAVE_VALGRIND_VALGRIND_H=1",
     ]
   } else {
-    args += [
+    values += [
       "HAVE_FUTIMENS=",
       "HAVE_LINK_H=",
       "HAVE_LSEEK64=",
@@ -175,7 +155,7 @@
   }
 
   if (host_os == "mac") {
-    args += [
+    values += [
       "HAVE_CRASHREPORTER_INFO=1",
       "HAVE_DECL_ARC4RANDOM=1",
       "HAVE_DLADDR=1",
@@ -186,7 +166,7 @@
       "HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC=1",
     ]
   } else {
-    args += [
+    values += [
       "HAVE_CRASHREPORTER_INFO=",
       "HAVE_DECL_ARC4RANDOM=",
       "HAVE_DLADDR=",
@@ -199,7 +179,7 @@
   }
 
   if (host_os == "win") {
-    args += [
+    values += [
       "HAVE_BACKTRACE=",
       "HAVE_DECL_STRERROR_S=1",
       "HAVE_DLFCN_H=",
@@ -241,7 +221,7 @@
     ]
   } else {
     # POSIX-y system defaults.
-    args += [
+    values += [
       "HAVE_BACKTRACE=1",
       "HAVE_DECL_STRERROR_S=",
       "HAVE_DLFCN_H=1",
@@ -284,58 +264,48 @@
   }
 
   if (host_os == "linux") {
-    args += [ "LTDL_SHLIB_EXT=.so" ]
+    values += [ "LTDL_SHLIB_EXT=.so" ]
   } else if (host_os == "mac") {
-    args += [ "LTDL_SHLIB_EXT=.dylib" ]
+    values += [ "LTDL_SHLIB_EXT=.dylib" ]
   } else if (host_os == "win") {
-    args += [ "LTDL_SHLIB_EXT=.dll" ]
+    values += [ "LTDL_SHLIB_EXT=.dll" ]
   }
 
   if (llvm_enable_libedit) {
-    args += [ "HAVE_LIBEDIT=1" ]
+    values += [ "HAVE_LIBEDIT=1" ]
   } else {
-    args += [ "HAVE_LIBEDIT=" ]
+    values += [ "HAVE_LIBEDIT=" ]
   }
 
   if (llvm_enable_libxar) {
-    args += [ "HAVE_LIBXAR=1" ]
+    values += [ "HAVE_LIBXAR=1" ]
   } else {
-    args += [ "HAVE_LIBXAR=" ]
+    values += [ "HAVE_LIBXAR=" ]
   }
 
   if (llvm_enable_terminfo) {
-    args += [ "HAVE_TERMINFO=1" ]
+    values += [ "HAVE_TERMINFO=1" ]
   } else {
-    args += [ "HAVE_TERMINFO=" ]
+    values += [ "HAVE_TERMINFO=" ]
   }
 
   if (llvm_enable_zlib) {
-    args += [ "LLVM_ENABLE_ZLIB=1" ]
+    values += [ "LLVM_ENABLE_ZLIB=1" ]
   } else {
-    args += [ "LLVM_ENABLE_ZLIB=" ]
+    values += [ "LLVM_ENABLE_ZLIB=" ]
   }
 
   if (llvm_enable_libxml2) {
-    args += [ "LLVM_LIBXML2_ENABLED=1" ]
+    values += [ "LLVM_LIBXML2_ENABLED=1" ]
   } else {
-    args += [ "LLVM_LIBXML2_ENABLED=" ]
+    values += [ "LLVM_LIBXML2_ENABLED=" ]
   }
 }
 
-action("llvm-config") {
-  script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-  sources = [
-    "llvm-config.h.cmake",
-  ]
-  outputs = [
-    "$target_gen_dir/llvm-config.h",
-  ]
-  args = [
-    "-o",
-    rebase_path(outputs[0], root_out_dir),
-    rebase_path(sources[0], root_out_dir),
-
+write_cmake_config("llvm-config") {
+  input = "llvm-config.h.cmake"
+  output = "$target_gen_dir/llvm-config.h"
+  values = [
     "LLVM_ENABLE_DUMP=",
     "LINK_POLLY_INTO_TOOLS=",
     "LLVM_DEFAULT_TARGET_TRIPLE=$llvm_target_triple",
@@ -359,15 +329,15 @@
   ]
 
   if (host_os == "win") {
-    args += [ "LLVM_ON_UNIX=" ]
+    values += [ "LLVM_ON_UNIX=" ]
   } else {
-    args += [ "LLVM_ON_UNIX=1" ]
+    values += [ "LLVM_ON_UNIX=1" ]
   }
 
   if (llvm_enable_threads) {
-    args += [ "LLVM_ENABLE_THREADS=1" ]
+    values += [ "LLVM_ENABLE_THREADS=1" ]
   } else {
-    args += [ "LLVM_ENABLE_THREADS=" ]
+    values += [ "LLVM_ENABLE_THREADS=" ]
   }
 }
 
@@ -378,16 +348,10 @@
   assert(defined(invoker.key), "must set 'key' in $target_name")
   assert(defined(invoker.value), "must set 'value' in $target_name")
 
-  action(target_name) {
+  write_cmake_config(target_name) {
     visibility = [ ":write_target_def_files" ]
-    script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-    sources = [
-      "$target_name.in",
-    ]
-    outputs = [
-      "$target_gen_dir/$target_name",
-    ]
+    input = "$target_name.in"
+    output = "$target_gen_dir/$target_name"
 
     # Build something like
     # `LLVM_ENUM_ASM_PARSERS=LLVM_ASM_PARSER(ARM)\nLLVM_ASM_PARSER(X86)\n`. Note
@@ -397,10 +361,7 @@
     foreach(target, llvm_targets_to_build) {
       value = "$value${invoker.value}($target)\n"
     }
-    args = [
-      "-o",
-      rebase_path(outputs[0], root_out_dir),
-      rebase_path(sources[0], root_out_dir),
+    values = [
       "${invoker.key}=$value",
     ]
   }
diff --git a/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn b/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
index db2b972..16c18d4 100644
--- a/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
+++ b/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
@@ -81,8 +81,8 @@
     "WebAssemblyLowerEmscriptenEHSjLj.cpp",
     "WebAssemblyLowerGlobalDtors.cpp",
     "WebAssemblyMCInstLower.cpp",
-    "WebAssemblyMemIntrinsicResults.cpp",
     "WebAssemblyMachineFunctionInfo.cpp",
+    "WebAssemblyMemIntrinsicResults.cpp",
     "WebAssemblyOptimizeLiveIntervals.cpp",
     "WebAssemblyOptimizeReturned.cpp",
     "WebAssemblyPeephole.cpp",
diff --git a/utils/gn/secondary/llvm/test/BUILD.gn b/utils/gn/secondary/llvm/test/BUILD.gn
index 91f7a87..8a1d17c 100644
--- a/utils/gn/secondary/llvm/test/BUILD.gn
+++ b/utils/gn/secondary/llvm/test/BUILD.gn
@@ -6,24 +6,15 @@
 import("//llvm/utils/gn/build/libs/xar/enable.gni")
 import("//llvm/utils/gn/build/libs/xml/enable.gni")
 import("//llvm/utils/gn/build/libs/zlib/enable.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("llvm_lit_site_cfg_files.gni")
 
 template("write_lit_config") {
-  action(target_name) {
-    script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-    sources = [
-      invoker.input,
-    ]
-    outputs = [
-      invoker.output,
-    ]
-    args = [
-      "-o",
-      rebase_path(outputs[0], root_out_dir),
-      rebase_path(sources[0], root_out_dir),
-
-      "LIT_SITE_CFG_IN_HEADER=## Autogenerated from ${sources[0]}, do not edit",
+  write_cmake_config(target_name) {
+    input = invoker.input
+    output = invoker.output
+    values = [
+      "LIT_SITE_CFG_IN_HEADER=## Autogenerated from $input, do not edit",
       "ENABLE_SHARED=0",
       "LLVM_BINARY_DIR=" +
           rebase_path(get_label_info("//llvm", "target_out_dir")),
@@ -32,18 +23,18 @@
     ]
     if (host_os == "win") {
       # See comment for Windows solink in llvm/utils/gn/build/toolchain/BUILD.gn
-      args += [ "SHLIBDIR=" + rebase_path("$root_out_dir/bin") ]
+      values += [ "SHLIBDIR=" + rebase_path("$root_out_dir/bin") ]
     } else {
-      args += [ "SHLIBDIR=" + rebase_path("$root_out_dir/lib") ]
+      values += [ "SHLIBDIR=" + rebase_path("$root_out_dir/lib") ]
     }
-    args += invoker.extra_args
+    values += invoker.extra_values
   }
 }
 
 write_lit_config("lit_site_cfg") {
   input = "//llvm/test/lit.site.cfg.py.in"
   output = llvm_lit_site_cfg_file
-  extra_args = [
+  extra_values = [
     "BUILD_SHARED_LIBS=0",
 
     # Only used by the Go bindings tests, or if LLVM_USE_SANITIZER includes
@@ -88,25 +79,25 @@
   ]
 
   if (host_cpu == "x64") {
-    extra_args += [ "HOST_ARCH=x86_64" ]
+    extra_values += [ "HOST_ARCH=x86_64" ]
   } else {
     assert(false, "unimplemented host_cpu " + host_cpu)
   }
 
   if (host_os == "mac") {
-    extra_args += [
+    extra_values += [
       "EXEEXT=",
       "HOST_OS=Darwin",
       "SHLIBEXT=.dylib",
     ]
   } else if (host_os == "linux") {
-    extra_args += [
+    extra_values += [
       "EXEEXT=",
       "HOST_OS=Linux",
       "SHLIBEXT=.so",
     ]
   } else if (host_os == "win") {
-    extra_args += [
+    extra_values += [
       "EXEEXT=.exe",
       "HOST_OS=Windows",
       "SHLIBEXT=.dll",
@@ -119,57 +110,57 @@
     # so just claim that ld is gold on Linux.  The function also checks if
     # LLVMgold.so exists, but since that target isn't hooked up yet in the GN
     # build the LLVMgold.so tests currently don't run anywhere in the GN build.
-    extra_args += [ "GOLD_EXECUTABLE=ld" ]
+    extra_values += [ "GOLD_EXECUTABLE=ld" ]
   } else {
-    extra_args += [ "GOLD_EXECUTABLE=" ]
+    extra_values += [ "GOLD_EXECUTABLE=" ]
   }
   if (host_os == "mac") {
-    extra_args += [ "LD64_EXECUTABLE=ld" ]
+    extra_values += [ "LD64_EXECUTABLE=ld" ]
   } else {
-    extra_args += [ "LD64_EXECUTABLE=" ]
+    extra_values += [ "LD64_EXECUTABLE=" ]
   }
 
   if (llvm_enable_assertions) {
-    extra_args += [ "ENABLE_ASSERTIONS=1" ]
+    extra_values += [ "ENABLE_ASSERTIONS=1" ]
   } else {
-    extra_args += [ "ENABLE_ASSERTIONS=0" ]  # Must be 0.
+    extra_values += [ "ENABLE_ASSERTIONS=0" ]  # Must be 0.
   }
 
   if (llvm_enable_libxar) {
-    extra_args += [ "HAVE_LIBXAR=1" ]
+    extra_values += [ "HAVE_LIBXAR=1" ]
   } else {
-    extra_args += [ "HAVE_LIBXAR=0" ]  # Must be 0.
+    extra_values += [ "HAVE_LIBXAR=0" ]  # Must be 0.
   }
 
   if (llvm_enable_dia_sdk) {
-    extra_args += [ "LLVM_ENABLE_DIA_SDK=1" ]
+    extra_values += [ "LLVM_ENABLE_DIA_SDK=1" ]
   } else {
-    extra_args += [ "LLVM_ENABLE_DIA_SDK=0" ]  # Must be 0.
+    extra_values += [ "LLVM_ENABLE_DIA_SDK=0" ]  # Must be 0.
   }
 
   if (llvm_enable_libxml2) {
-    extra_args += [ "LLVM_LIBXML2_ENABLED=1" ]
+    extra_values += [ "LLVM_LIBXML2_ENABLED=1" ]
   } else {
-    extra_args += [ "LLVM_LIBXML2_ENABLED=" ]  # Must be empty.
+    extra_values += [ "LLVM_LIBXML2_ENABLED=" ]  # Must be empty.
   }
 
   if (llvm_enable_threads) {
-    extra_args += [ "LLVM_ENABLE_THREADS=1" ]
+    extra_values += [ "LLVM_ENABLE_THREADS=1" ]
   } else {
-    extra_args += [ "LLVM_ENABLE_THREADS=0" ]  # Must be 0.
+    extra_values += [ "LLVM_ENABLE_THREADS=0" ]  # Must be 0.
   }
 
   if (llvm_enable_zlib) {
-    extra_args += [ "HAVE_LIBZ=1" ]
+    extra_values += [ "HAVE_LIBZ=1" ]
   } else {
-    extra_args += [ "HAVE_LIBZ=0" ]  # Must be 0.
+    extra_values += [ "HAVE_LIBZ=0" ]  # Must be 0.
   }
 }
 
 write_lit_config("lit_unit_site_cfg") {
   input = "//llvm/test/Unit/lit.site.cfg.py.in"
   output = llvm_lit_unit_site_cfg_file
-  extra_args = [ "LLVM_BUILD_MODE=." ]
+  extra_values = [ "LLVM_BUILD_MODE=." ]
 }
 
 # This target should contain all dependencies of check-llvm.
diff --git a/utils/gn/secondary/llvm/tools/llvm-config/BUILD.gn b/utils/gn/secondary/llvm/tools/llvm-config/BUILD.gn
index ee5bb32..2f662e0 100644
--- a/utils/gn/secondary/llvm/tools/llvm-config/BUILD.gn
+++ b/utils/gn/secondary/llvm/tools/llvm-config/BUILD.gn
@@ -4,17 +4,12 @@
 import("//llvm/utils/gn/build/libs/terminfo/enable.gni")
 import("//llvm/utils/gn/build/libs/xml/enable.gni")
 import("//llvm/utils/gn/build/libs/zlib/enable.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 import("//llvm/version.gni")
 
-action("BuildVariables.inc") {
-  script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-  sources = [
-    "BuildVariables.inc.in",
-  ]
-  outputs = [
-    "$target_gen_dir/BuildVariables.inc",
-  ]
+write_cmake_config("BuildVariables.inc") {
+  input = "BuildVariables.inc.in"
+  output = "$target_gen_dir/BuildVariables.inc"
 
   if (is_debug) {
     build_mode = "debug"
@@ -68,11 +63,7 @@
     system_libs += " ${l}z${lib}"
   }
 
-  args = [
-    "-o",
-    rebase_path(outputs[0], root_out_dir),
-    rebase_path(sources[0], root_out_dir),
-
+  values = [
     "LLVM_SRC_ROOT=" + rebase_path("//llvm"),
     "LLVM_OBJ_ROOT=" + rebase_path(root_out_dir),
 
diff --git a/utils/gn/secondary/llvm/utils/llvm-lit/BUILD.gn b/utils/gn/secondary/llvm/utils/llvm-lit/BUILD.gn
index 9568cb6..fca5679 100644
--- a/utils/gn/secondary/llvm/utils/llvm-lit/BUILD.gn
+++ b/utils/gn/secondary/llvm/utils/llvm-lit/BUILD.gn
@@ -1,20 +1,15 @@
 import("//clang/test/clang_lit_site_cfg_files.gni")
 import("//lld/test/lld_lit_site_cfg_files.gni")
 import("//llvm/test/llvm_lit_site_cfg_files.gni")
+import("//llvm/utils/gn/build/write_cmake_config.gni")
 
-action("llvm-lit") {
-  script = "//llvm/utils/gn/build/write_cmake_config.py"
-
-  sources = [
-    "llvm-lit.in",
-  ]
-  outputs = [
-    "$root_out_dir/bin/llvm-lit",
-  ]
+write_cmake_config("llvm-lit") {
+  input = "llvm-lit.in"
+  output = "$root_out_dir/bin/llvm-lit"
 
   if (host_os == "win") {
     # llvm-lit needs suffix.py for multiprocess to find a main module.
-    outputs[0] = "${outputs[0]}.py"
+    output = "${output}.py"
   }
 
   # lit's lit/llvm/config.py shells out to llvm-config.
@@ -51,11 +46,7 @@
   config_map += "map_config('" + rebase_path("//llvm/test/Unit/lit.cfg.py") +
                 "', '" + rebase_path(llvm_lit_unit_site_cfg_file) + "')\n"
 
-  args = [
-    "-o",
-    rebase_path(outputs[0], root_out_dir),
-    rebase_path(sources[0], root_out_dir),
-
+  values = [
     "LLVM_SOURCE_DIR=" + rebase_path("//llvm"),
     "LLVM_BINARY_DIR=" +
         rebase_path(get_label_info("//llvm", "target_out_dir")),