[llvm] r349096 - [gn build] Add infrastructure to create symlinks and use it to create lld's symlinks

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 13 16:16:33 PST 2018


Author: nico
Date: Thu Dec 13 16:16:33 2018
New Revision: 349096

URL: http://llvm.org/viewvc/llvm-project?rev=349096&view=rev
Log:
[gn build] Add infrastructure to create symlinks and use it to create lld's symlinks

This is slightly involved, see the comments in the code.

The GN build now builds a functional lld!

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

Added:
    llvm/trunk/utils/gn/build/symlink_or_copy.gni
    llvm/trunk/utils/gn/build/symlink_or_copy.py
Modified:
    llvm/trunk/utils/gn/secondary/BUILD.gn
    llvm/trunk/utils/gn/secondary/lld/tools/lld/BUILD.gn

Added: llvm/trunk/utils/gn/build/symlink_or_copy.gni
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/gn/build/symlink_or_copy.gni?rev=349096&view=auto
==============================================================================
--- llvm/trunk/utils/gn/build/symlink_or_copy.gni (added)
+++ llvm/trunk/utils/gn/build/symlink_or_copy.gni Thu Dec 13 16:16:33 2018
@@ -0,0 +1,24 @@
+# Creates a symlink (or, on Windows, copies).
+# Args:
+#   source: Path to link to.
+#   output: Where to create the symlink.
+template("symlink_or_copy") {
+  action(target_name) {
+    forward_variables_from(invoker, [ "deps" ])
+
+    # Make a stamp file the output to work around
+    # https://github.com/ninja-build/ninja/issues/1186
+    stamp =
+        "$target_gen_dir/" + get_path_info(invoker.output, "file") + ".stamp"
+    outputs = [
+      stamp,
+    ]
+    script = "//llvm/utils/gn/build/symlink_or_copy.py"
+    args = [
+      "--stamp",
+      rebase_path(stamp, root_out_dir),
+      invoker.source,
+      rebase_path(invoker.output, root_out_dir),
+    ]
+  }
+}

Added: llvm/trunk/utils/gn/build/symlink_or_copy.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/gn/build/symlink_or_copy.py?rev=349096&view=auto
==============================================================================
--- llvm/trunk/utils/gn/build/symlink_or_copy.py (added)
+++ llvm/trunk/utils/gn/build/symlink_or_copy.py Thu Dec 13 16:16:33 2018
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+"""Symlinks, or on Windows copies, an existing file to a second location.
+
+Overwrites the target location if it exists.
+Updates the mtime on a stamp file when done."""
+
+import argparse
+import errno
+import os
+import sys
+
+
+def main():
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('--stamp', required=True,
+                        help='name of a file whose mtime is updated on run')
+    parser.add_argument('source')
+    parser.add_argument('output')
+    args = parser.parse_args()
+
+    # FIXME: This should not check the host platform but the target platform
+    # (which needs to be passed in as an arg), for cross builds.
+    if sys.platform != 'win32':
+        try:
+            os.symlink(args.source, args.output)
+        except OSError as e:
+            if e.errno == errno.EEXIST:
+                os.remove(args.output)
+                os.symlink(args.source, args.output)
+            else:
+                raise
+    else:
+        import shutil
+        output = args.output + ".exe"
+        source = args.source + ".exe"
+        shutil.copyfile(os.path.join(os.path.dirname(output), source), output)
+
+    open(args.stamp, 'w') # Update mtime on stamp file.
+
+
+if __name__ == '__main__':
+    sys.exit(main())

Modified: llvm/trunk/utils/gn/secondary/BUILD.gn
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/gn/secondary/BUILD.gn?rev=349096&r1=349095&r2=349096&view=diff
==============================================================================
--- llvm/trunk/utils/gn/secondary/BUILD.gn (original)
+++ llvm/trunk/utils/gn/secondary/BUILD.gn Thu Dec 13 16:16:33 2018
@@ -1,11 +1,40 @@
 group("default") {
   deps = [
-    "//lld/tools/lld",
+    ":lld",
     "//llvm/tools/llc",
     "//llvm/tools/llvm-undname",
   ]
 }
 
+# Symlink handling.
+# On POSIX, symlinks to the target can be created before the target exist,
+# and the target can depend on the symlink targets, so that building the
+# target ensures the symlinks exist.
+# However, symlinks didn't exist on Windows until recently, so there the
+# binary needs to be copied -- which requires it to exist. So the symlink step
+# needs to run after the target that creates the binary.
+# In the cmake build, this is done via a "postbuild" on the target, which just
+# tacks on "&& copy out.exe out2.exe" to the link command.
+# GN doesn't have a way to express postbuild commands.  It could probably be
+# emulated by having the link command in the toolchain be a wrapper script that
+# reads a ".symlinks" file next to the target, and have an action write that
+# and make the target depend on that, but then every single link has to use the
+# wrapper (unless we do further acrobatics to use a different toolchain for
+# targets that need symlinks) even though most links don't need symlinks.
+# Instead, have a top-level target for each target that needs symlinks, and
+# make that depend on the symlinks. Then the symlinks can depend on the
+# executable.  This has the effect that `ninja lld` builds lld and then creates
+# symlinks (via this target), while `ninja bin/lld` only builds lld and doesn't
+# update symlinks (in particular, on Windows it doesn't copy the new lld to its
+# new locations); also `ninja lld-link` will build lld and copy it (on Windows)
+# to lld-link, but it won't copy it to ld.lld.
+# That seems simpler, more explicit, and good enough.
+group("lld") {
+  deps = [
+    "//lld/tools/lld:symlinks",
+  ]
+}
+
 # A pool called "console" in the root BUILD.gn is magic and represents ninja's
 # built-in console pool. (Requires a GN with `gn --version` >= 552353.)
 pool("console") {

Modified: llvm/trunk/utils/gn/secondary/lld/tools/lld/BUILD.gn
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/gn/secondary/lld/tools/lld/BUILD.gn?rev=349096&r1=349095&r2=349096&view=diff
==============================================================================
--- llvm/trunk/utils/gn/secondary/lld/tools/lld/BUILD.gn (original)
+++ llvm/trunk/utils/gn/secondary/lld/tools/lld/BUILD.gn Thu Dec 13 16:16:33 2018
@@ -1,4 +1,28 @@
-# FIXME: Set up symlinks pointing to lld.
+import("//llvm/utils/gn/build/symlink_or_copy.gni")
+
+symlinks = [
+  "lld-link",
+  "ld.lld",
+  "ld64.lld",
+  "wasm-ld",
+]
+foreach(target, symlinks) {
+  symlink_or_copy(target) {
+    deps = [
+      ":lld",
+    ]
+    source = "lld"
+    output = "$root_out_dir/bin/$target"
+  }
+}
+
+# //:lld depends on this symlink target, see comment in //BUILD.gn.
+group("symlinks") {
+  deps = []
+  foreach(target, symlinks) {
+    deps += [ ":$target" ]
+  }
+}
 
 executable("lld") {
   configs += [ "//llvm/utils/gn/build:lld_code" ]




More information about the llvm-commits mailing list