[build] Fix integration with Zircon build when it uses Clang

The --strip-headers format (which is optimal for device storage use)
is incompatible with linking.  The Zircon build's `.so` files are in
this format when it builds with Clang-based variants rather than the
default "gcc" variant.  For C/C++ linking, the build system feeds
the right files (the `.so.debug` files) directly into the link step.
However, Rust and Go builds rely on -L... search paths and -l...
searches matching lib....so file names.  So this must be accomodated
in the directories set up by the build for -L... switches passed to
those compilers.

Bug: BLD-447 #comment Fixed --variant clang build
Test: fx set core.arm64 --variant clang && fx build
Change-Id: Ie7a030688b0a5f5fa19682a74238f7882189f865
diff --git a/build/config/fuchsia/BUILD.gn b/build/config/fuchsia/BUILD.gn
index 4641bd5..0595afb 100644
--- a/build/config/fuchsia/BUILD.gn
+++ b/build/config/fuchsia/BUILD.gn
@@ -177,6 +177,12 @@
   libs = rebase_path(read_file(api_file, "json"), ".", zircon_root_build_dir)
   assert(libs != [], "$api_file empty?")
   assert(libs == [ libs[0] ], "$api_file has multiple entries?")
+  link_file = libs[0]
+  if (get_path_info(link_file, "file") != "libfdio.so") {
+    link_file = rebase_path(link_file)
+    write_file("$target_gen_dir/libfdio.so", [ "INPUT($link_file)" ])
+    libs[0] = "$target_gen_dir/libfdio.so"
+  }
 }
 
 config("executable_config") {
diff --git a/build/go/go_build.gni b/build/go/go_build.gni
index 6f31f81..eb9926a 100644
--- a/build/go/go_build.gni
+++ b/build/go/go_build.gni
@@ -180,7 +180,7 @@
       ]
 
       foreach(target, zircon_legacy_targets) {
-        if (target.target_name == "zircon" || target.target_name == "fdio") {
+        if (target.target_name == "zircon") {
           _libs = target.libs
           lib = _libs[0]
           assert(_libs == [ lib ])
@@ -191,6 +191,13 @@
           ]
         }
       }
+
+      # See //build/config/fuchsia:fdio_config.
+      args += [
+        "--lib-dir",
+        rebase_path(get_label_info("//build/config/fuchsia:fdio_config",
+                                   "target_gen_dir")),
+      ]
     } else {
       args += [
         "--go-root",
diff --git a/build/zircon/zircon_library.gni b/build/zircon/zircon_library.gni
index 01cdce2..314548d 100644
--- a/build/zircon/zircon_library.gni
+++ b/build/zircon/zircon_library.gni
@@ -121,10 +121,23 @@
     }
 
     if (defined(invoker.libs)) {
+      # Rust targets use -L... -lfoo instead of explicit files.  So they
+      # need to collect the -L list via metadata, and directories on that
+      # list needs to hold exact names libfoo.so or libfoo.a for -lfoo.
       metadata = {
-        zircon_lib_dirs =
-            get_path_info(rebase_path(invoker.libs, "", zircon_root_build_dir),
-                          "dir")
+        zircon_lib_dirs = []
+        foreach(file, invoker.libs) {
+          if (get_path_info(file, "extension") == "so" ||
+              get_path_info(file, "extension") == "a") {
+            zircon_lib_dirs += [ rebase_path(get_path_info(file, "dir"),
+                                             "",
+                                             zircon_root_build_dir) ]
+          } else {
+            file = rebase_path(file, "", zircon_root_build_dir)
+            write_file("$target_gen_dir/lib$library.so", [ "INPUT($file)" ])
+            zircon_lib_dirs += [ rebase_path(target_gen_dir) ]
+          }
+        }
         if (defined(invoker.lib_dirs)) {
           zircon_lib_dirs +=
               rebase_path(invoker.lib_dirs, "", zircon_root_build_dir)
diff --git a/zircon/BUILD.gn b/zircon/BUILD.gn
index a28e129..3294a45 100644
--- a/zircon/BUILD.gn
+++ b/zircon/BUILD.gn
@@ -303,6 +303,7 @@
         ":asan-libs-$cpu",
       ]
       metadata = {
+        # //build/images/manifest.gni finds this by name and cpu.
         images = [
           {
             cpu = cpu
@@ -312,6 +313,12 @@
                                root_build_dir)
           },
         ]
+
+        # This prevents build_api_module("legacy-$cpu") from visiting the
+        # ASan incarnations of all the libraries.  The legacy build wants
+        # only the manifest of ASan shared libraries.  It wants the targets
+        # themselves only from the primary build.
+        legacy_barrier = []
       }
     }
   }
diff --git a/zircon/public/gn/BUILDCONFIG.gn b/zircon/public/gn/BUILDCONFIG.gn
index 07e42f1..8b888a9 100644
--- a/zircon/public/gn/BUILDCONFIG.gn
+++ b/zircon/public/gn/BUILDCONFIG.gn
@@ -376,19 +376,25 @@
       libfile = "$target_out_dir/$libfile"
       if (sdk == "static") {
         libs_file = "${libfile}.a"
+        link_file = libs_file
       } else {
         libs_file = "${libfile}.so"
+        debug_files += [ rebase_path("${libs_file}.debug", root_build_dir) ]
         install_files += [
           {
             source = rebase_path(libs_file, root_build_dir)
             dest = "dist/" + get_path_info(libs_file, "file")
           },
         ]
-        debug_files += [ rebase_path("${libs_file}.debug", root_build_dir) ]
+
+        # TODO(TC-446): The stripped binary doesn't even have section
+        # headers, so the linker can't handle it.  Eventually we'll have
+        # linker stubs.  For now, just use the unstripped library to link.
+        link_file = "${libs_file}.debug"
       }
       install_files += [
         {
-          source = rebase_path(libs_file, root_build_dir)
+          source = rebase_path(link_file, root_build_dir)
           dest = "lib/" + get_path_info(libs_file, "file")
         },
       ]
@@ -413,7 +419,7 @@
               sources += [ "//zircon/$file" ]
             }
           } else {
-            libs = [ rebase_path(libs_file, root_build_dir) ]
+            libs = [ rebase_path(link_file, root_build_dir) ]
           }
           deps = []
           public_deps = []
diff --git a/zircon/system/ulib/c/BUILD.gn b/zircon/system/ulib/c/BUILD.gn
index 8faf452..5365512 100644
--- a/zircon/system/ulib/c/BUILD.gn
+++ b/zircon/system/ulib/c/BUILD.gn
@@ -296,7 +296,12 @@
       },
       {
         sdk = {
-          source = rebase_path("$target_out_dir/libc.so", root_build_dir)
+          # TODO(TC-446): The stripped binary doesn't even have section
+          # headers, so the linker can't handle it.  Eventually we'll have
+          # linker stubs.  For now, just use the unstripped library to link
+          # against.  This matches what library() gives the SDK via
+          # zircon_library().
+          source = rebase_path("$target_out_dir/libc.so.debug", root_build_dir)
           link = "lib/libc.so"
         }
       },
diff --git a/zircon/system/ulib/zircon/BUILD.gn b/zircon/system/ulib/zircon/BUILD.gn
index ac45a4c..adfa003 100644
--- a/zircon/system/ulib/zircon/BUILD.gn
+++ b/zircon/system/ulib/zircon/BUILD.gn
@@ -83,6 +83,21 @@
     # than as an independent library.  Legacy integration likewise does not
     # use a //zircon/public/lib/zircon buts instead uses libs=["zircon"].
     # See //zircon/public/sysroot.
+    #
+    # The stripped binary doesn't even have section headers, so the linker
+    # can't handle it.  Eventually we'll have linker stubs.  For now, just
+    # use the unstripped library to link against.  (In the case of the vDSO
+    # we don't really need to strip it in the first place, since its
+    # segments are embedded in the kernel and the stripped file is never
+    # put on a device.  But there's no reasonable way to disable the
+    # standard stripping behavior for a single target.)  The legacy build
+    # needs there to be a -L directory where libzircon.so is the name to
+    # link against so -lzircon works.  So mock up such a directory using a
+    # linker script to redirect to the actual unstripped file name, which
+    # is not that.
+    link_file = "$target_gen_dir/libzircon.so"
+    debug_file = rebase_path("$target_out_dir/libzircon.so.debug")
+    write_file(link_file, [ "INPUT($debug_file)" ])
     metadata = {
       legacy_sysroot = [
         {
@@ -109,7 +124,8 @@
         },
         {
           sdk = {
-            source = rebase_path("$target_out_dir/libzircon.so", root_build_dir)
+            source = rebase_path("$target_out_dir/libzircon.so.debug",
+                                 root_build_dir)
             link = "lib/libzircon.so"
           }
         },
@@ -122,15 +138,15 @@
         },
       ]
 
-      # TODO(BLD-353): This is not actually for the SDK (see above).
-      # This is special-cased so no //zircon/public/lib/zircon gets
-      # made, but //build/config/fuchsia:compiler_sysroot can look up
-      # the metadata to find the right lib_dirs.
+      # TODO(BLD-353): This is not actually for the SDK (see above).  This
+      # is special-cased so no //zircon/public/lib/zircon gets made, but
+      # //build/config/fuchsia:compiler_sysroot can look up the metadata to
+      # find the right lib_dirs.
       legacy_targets = [
         {
           target_name = "zircon"
           libs = []
-          libs = [ rebase_path("$target_out_dir/libzircon.so", root_build_dir) ]
+          libs = [ rebase_path(link_file, root_build_dir) ]
         },
       ]
     }