Add a way to link to static libraries

Also add a convenience command for extracting search paths
and library names from the  output of fx build -v.

Change-Id: I8f20a6338acbfc00570df9df09b2f4590d30bca9
Reviewed-on: https://fuchsia-review.googlesource.com/c/fargo/+/399309
Reviewed-by: Rob Tsuk <robtsuk@google.com>
diff --git a/Cargo.lock b/Cargo.lock
index d45d020..aa3961d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,14 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
 [[package]]
+name = "aho-corasick"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "ansi_term"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -113,6 +121,7 @@
  "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -277,6 +286,11 @@
 ]
 
 [[package]]
+name = "memchr"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "mio"
 version = "0.6.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -417,6 +431,22 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "regex"
+version = "1.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "remove_dir_all"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -544,6 +574,14 @@
 ]
 
 [[package]]
+name = "thread_local"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "toml"
 version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -641,6 +679,7 @@
 ]
 
 [metadata]
+"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
 "checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5"
@@ -673,6 +712,7 @@
 "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
 "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
 "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
+"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
 "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23"
 "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
@@ -687,6 +727,8 @@
 "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
 "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
 "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
+"checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
+"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
 "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
 "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
 "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
@@ -702,6 +744,7 @@
 "checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203"
 "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
 "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
 "checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
 "checksum uname 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8"
 "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
diff --git a/Cargo.toml b/Cargo.toml
index 9fa889e..123ec7c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,6 +10,7 @@
 itertools = "0.7"
 uname = "0.1.1"
 notify = "4.0.0"
+regex = "1.3.9"
 serde = { version = "1.0", features = ["derive"] }
 serde_derive = "1.0"
 serde_json = "1.0"
diff --git a/README.md b/README.md
index 22cef55..c81e14e 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,10 @@
 
 The [Fuchsia Getting
 Started](https://fuchsia.googlesource.com/fuchsia/+/master/docs/getting_started.md)
-instruction are what you need. Make sure that `fx serve` is running pointed at
+instruction are what you need, with the caveat that you have to pass ` --cargo-toml-gen ` to
+`fx set`.
+
+Make sure that `fx serve` is running pointed at
 this Fuchsia build.
 
 Once this build is complete, clone and build Fargo. For this you will need
@@ -129,32 +132,50 @@
 inside the Cargo.toml files generated as part of `fx build`. The Fargo manifest file
 Fargo.toml exists to provide those configuration.
 
-There are three properties that one can set with this file, `library_search_paths`,
-`additional_shared_libraries` and `data_files` as shown in the example below.
+There are four properties that one can set with this file, `library_search_paths`,
+`additional_shared_libraries`, `additional_static_libraries` and `data_files` as shown
+in the example below.
 
-    library_search_paths = [
-        "obj/src/graphics/lib/compute/spinel",
-        "obj/src/graphics/lib/compute/common",
-        "obj/src/graphics/lib/compute/common/vk",
-        "obj/src/graphics/lib/compute/hotsort/platforms/vk",
-        "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/intel/gen8/hotsort",
-        "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/amd/gcn3/hotsort",
-        "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/nvidia/sm50/hotsort",
-        "obj/src/graphics/lib/compute/spinel/platforms/vk",
-        "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/intel/gen8",
-        "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/amd/gcn3",
-        "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/nvidia/sm50",
-    ]
+        library_search_paths = [
+            "obj/src/graphics/lib/compute/common",
+            "obj/src/graphics/lib/compute/common/vk",
+            "obj/src/graphics/lib/compute/hotsort/platforms/vk",
+            "obj/src/graphics/lib/compute/spinel",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/amd/gcn3",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/amd/gcn3/hotsort",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/arm/bifrost8",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/arm/bifrost8/hotsort",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/intel/gen8",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/intel/gen8/hotsort",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/nvidia/sm50",
+            "obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/nvidia/sm50/hotsort",
+        ]
 
-    additional_shared_libraries = [
-        "libvulkan.so",
-        "librust-trace-provider.so",
-    ]
+        additional_shared_libraries = [
+            "libvulkan.so",
+            "librust-trace-provider.so",
+        ]
 
-    data_files = [
-        { src = "examples/shaders/copy.comp.spv", dst = "data/shaders/copy.comp.spv"},
-        { src = "examples/shaders/motioncopy.comp.spv", dst = "data/shaders/motioncopy.comp.spv"},
-    ]
+        additional_static_libraries = [
+            "hotsort_vk",
+            "hotsort_vk_hs_amd_gcn3_u64",
+            "hotsort_vk_hs_arm_bifrost8_u64",
+            "hotsort_vk_hs_intel_gen8_u64",
+            "hotsort_vk_hs_nvidia_sm35_u64",
+            "spinel_vk_spn_amd_gcn3",
+            "spinel_vk_spn_arm_bifrost8",
+            "spinel_vk_spn_intel_gen8",
+            "spinel_vk_spn_nvidia_sm50",
+        ]
+
+        data_files = [
+            { src = "src/render/shaders/copy.comp.spv", dst = "data/shaders/copy.comp.spv"},
+            { src = "src/render/shaders/motioncopy-unorm.comp.spv", dst = "data/shaders/motioncopy-unorm.comp.spv"},
+            { src = "src/render/shaders/motioncopy-srgb.comp.spv", dst = "data/shaders/motioncopy-srgb.comp.spv"},
+            { src = "examples/static/lenna.png", dst = "data/static/lenna.png"},
+            { src = "examples/static/baboon.png", dst = "data/static/baboon.png"},
+        ]
 
 `library_search_paths` are additional paths to pass to `rustc` to resolve external
 references at compile time. The paths should be the partial path from the Fuchsia build
@@ -165,6 +186,11 @@
 are expected to be found in the shared libraries folder in the Fuchsia build
 directory
 
+`additional_static_libraries` are the names of static libraries that should be included in the
+link line when building with Fargo. The `extract-linkage` command can be used to parse the link
+output of `fx build -v` for search paths and library names. On Mac, copying the rustc line producing
+the binary and executing `pbpaste | fargo extract-linkage` is one way to use `extract-linkage`.
+
 `data_files` are partial paths to additional data files to be included in the Fuchsia
 package that is created by Fargo to run Rust executables on Fuchsia. These paths should be
 the partial path from the root of the crate being compiled.
diff --git a/src/command_line.rs b/src/command_line.rs
index 291e198..179bab1 100644
--- a/src/command_line.rs
+++ b/src/command_line.rs
@@ -5,6 +5,7 @@
     cross::run_pkg_config,
     device::{netls, ssh, start_emulator, stop_emulator, StartEmulatorOptions},
     enable_networking, format_project,
+    linking::extract_linkage_information,
     manifest::load_manifest,
     random_story_name, run_binary, run_cargo, run_configure, run_program_on_target,
     run_switches_to_mode, run_tests,
@@ -34,6 +35,8 @@
     Doc(Doc),
     /// Enable networking for a running emulator
     EnableNetworking,
+    /// Extract linkage information
+    ExtractLinkage,
     /// Run cargo fmt using the Fuchsia toolchain
     Fmt,
     /// List visible Fuchsia devices
@@ -513,6 +516,10 @@
             return enable_networking();
         }
 
+        FargoCommand::ExtractLinkage => {
+            return extract_linkage_information();
+        }
+
         FargoCommand::Fmt => {
             format_project(opt.manifest_path)?;
             return Ok(());
diff --git a/src/lib.rs b/src/lib.rs
index ea37c96..23f13f0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,6 +13,7 @@
 pub mod command_line;
 mod cross;
 mod device;
+mod linking;
 mod manifest;
 mod package;
 mod sdk;
@@ -164,7 +165,7 @@
         let formatted_target_params = format!("--args={}", target_params);
         run_cargo(
             &run_cargo_options,
-            "test",
+            TEST,
             &args,
             target_options,
             None,
@@ -182,7 +183,7 @@
     target_options: &TargetOptions<'_, '_>,
     params: &[&str],
 ) -> Result<(), Error> {
-    run_cargo(run_cargo_options, "build", params, target_options, None, None)
+    run_cargo(run_cargo_options, BUILD, params, target_options, None, None)
 }
 
 fn check_binary(
@@ -340,6 +341,7 @@
     run_cargo_options: &RunCargoOptions,
     target_options: &TargetOptions<'_, '_>,
     sysroot_as_path: &PathBuf,
+    linking: bool,
 ) -> Result<String, Error> {
     let target_triple = get_target_triple(target_options);
     let sysroot_lib_pathbuf = sysroot_as_path.join("lib");
@@ -380,6 +382,13 @@
         rust_flags.push(arg);
     }
 
+    if linking {
+        for additional_lib in &run_cargo_options.fargo_manifest.additional_static_libraries {
+            let arg = format!("-l{}", additional_lib);
+            rust_flags.push(arg);
+        }
+    }
+
     Ok(rust_flags.join(" "))
 }
 
@@ -538,6 +547,11 @@
         println!("options = {:?}", options);
     }
 
+    let linking = match subcommand {
+        RUN | TEST | BUILD => true,
+        _ => false,
+    };
+
     let target_triple_uc = format!("{}_fuchsia", triple_cpu).to_uppercase();
 
     let fargo_command = make_fargo_command(
@@ -561,7 +575,7 @@
 
     let runner_env_name = format!("CARGO_TARGET_{}_RUNNER", target_triple_uc);
     let rustflags_env_name = format!("CARGO_TARGET_{}_RUSTFLAGS", target_triple_uc);
-    let rustflags = get_rustflags(options, target_options, &sysroot_as_path)?;
+    let rustflags = get_rustflags(options, target_options, &sysroot_as_path, linking)?;
 
     if options.verbose {
         println!("runner_env_name: {:?}", runner_env_name);
@@ -642,7 +656,7 @@
     writeln!(
         config,
         "rustflags = {}",
-        toml::ser::to_string(&get_rustflags(options, target_options, &sysroot_as_path)?)?
+        toml::ser::to_string(&get_rustflags(options, target_options, &sysroot_as_path, false)?)?
     )?;
     writeln!(
         config,
@@ -657,20 +671,23 @@
     Ok(())
 }
 
-static RUN: &str = "run";
-static RUN_WITH_TILES: &str = "run-with-tiles";
-static RUN_WITH_RUN: &str = "run-with-run";
-static RUN_WITH_SESSIONCTL: &str = "run-with-sessionctl";
-static DEFAULT_MOD_NAME: &str = "fargo";
-static APP_DIR: &str = "app-dir";
-static APP_NAME: &str = "app-name";
+const RUN: &str = "run";
+const RUN_WITH_TILES: &str = "run-with-tiles";
+const RUN_WITH_RUN: &str = "run-with-run";
+const RUN_WITH_SESSIONCTL: &str = "run-with-sessionctl";
+const DEFAULT_MOD_NAME: &str = "fargo";
+const APP_DIR: &str = "app-dir";
+const APP_NAME: &str = "app-name";
 
-static NOCAPTURE: &str = "nocapture";
+const BUILD: &str = "build";
+const TEST: &str = "test";
 
-static X64: &str = "x64";
+const NOCAPTURE: &str = "nocapture";
 
-static CMX_PATH: &str = "cmx-path";
+const X64: &str = "x64";
 
-static RUN_ON_TARGET: &str = "run-on-target";
+const CMX_PATH: &str = "cmx-path";
 
-static FORMAT: &str = "fmt";
+const RUN_ON_TARGET: &str = "run-on-target";
+
+const FORMAT: &str = "fmt";
diff --git a/src/linking.rs b/src/linking.rs
new file mode 100644
index 0000000..5418568
--- /dev/null
+++ b/src/linking.rs
@@ -0,0 +1,37 @@
+use failure::Error;
+use regex::Regex;
+use std::{collections::BTreeSet, io};
+
+fn parse(linker_line: &str) -> (BTreeSet<String>, BTreeSet<String>) {
+    let lib_path_re = Regex::new(r#"(-Lnative=(\S+))"#).unwrap();
+    let captures = lib_path_re.captures_iter(linker_line);
+    let lib_paths: BTreeSet<String> = captures.map(|capture| capture[2].to_string()).collect();
+    let libs_re = Regex::new(r#"(\s+-l(\S+))"#).unwrap();
+    let libs_captures = libs_re.captures_iter(linker_line);
+    let libs: BTreeSet<String> = libs_captures.map(|capture| capture[2].to_string()).collect();
+    (lib_paths, libs)
+}
+
+pub fn extract_linkage_information() -> Result<(), Error> {
+    let mut linker_text = String::new();
+    io::stdin().read_line(&mut linker_text)?;
+    let (lib_paths, libs) = parse(&linker_text);
+    println!("library_search_paths = {:#?}", lib_paths);
+    println!("additional_static_libraries = {:#?}", libs);
+    Ok(())
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_link_parsing() {
+        let (lib_paths, libs) = parse(LINKER_LINE);
+        assert!(lib_paths.len() > 0);
+        assert!(libs.len() > 0);
+    }
+
+    const LINKER_LINE: &'static str = r#"[1/128] mkdir -p ./exe.unstripped &&  ../../prebuilt/third_party/rust/mac-x64/bin/rustc --color=always --crate-name spinning_square ../../src/lib/ui/carnelian/examples/spinning_square.rs --crate-type bin --emit=dep-info=./spinning_square.d,link -Zdep-info-omit-d-target -C link-args=--Map="./exe.unstripped/spinning_square.map" --cfg=__rust_toolchain=\"g7iBlBv8Ea_O1W0mxabel89X_OWItx5s22pNG6Y1JQ8C\" --cfg=rust_panic=\"abort\" -L /Users/rob/projects/fuchsia/out/core.x64-release/gen/build/config/fuchsia/lib -Clinker=/Users/rob/projects/fuchsia/prebuilt/third_party/clang/mac-x64/bin/lld -Clink-arg=--sysroot=/Users/rob/projects/fuchsia/out/core.x64-release/gen/build/config/fuchsia -Clink-arg=-L/Users/rob/projects/fuchsia/out/core.x64-release/gen/build/config/fuchsia/lib -Clink-arg=-L/Users/rob/projects/fuchsia/prebuilt/third_party/clang/mac-x64/lib/clang/11.0.0/x86_64-fuchsia/lib -Clink-arg=--pack-dyn-relocs=relr -Clink-arg=-dynamic-linker=ld.so.1 -Clink-arg=--icf=all --remap-path-prefix /Users/rob/projects/fuchsia/=../../ -Copt-level=z -Cdebuginfo=2 --edition=2018 -Zallow-features= --target x86_64-fuchsia --cap-lints=warn -Wrust-2018-idioms -Dwarnings -Clink-args=-zstack-size=0x200000 -Cpanic=abort -Cforce-unwind-tables=yes -Zpanic_abort_tests -o "./exe.unstripped/spinning_square" -Ldependency=obj/garnet/examples/fidl/services -Ldependency=obj/src/lib/fidl/rust/fidl -Ldependency=obj/src/lib/zerocopy -Ldependency=host_x64 -Ldependency=obj/third_party/rust_crates -Ldependency=obj/src/lib/zircon/rust -Ldependency=obj/src/lib/fuchsia-async -Ldependency=obj/src/lib/fuchsia-system-alloc -Ldependency=obj/sdk/fidl/fuchsia.ui.input -Ldependency=obj/sdk/fidl/fuchsia.ui.input2 -Ldependency=obj/sdk/fidl/fuchsia.ui.views -Ldependency=obj/zircon/vdso/zx -Ldependency=obj/sdk/fidl/fuchsia.ui.input3 -Ldependency=obj/sdk/fidl/fuchsia.input -Ldependency=obj/src/lib/trace/rust -Ldependency=obj/src/lib/cstr -Ldependency=obj/src/lib/ui/carnelian -Ldependency=obj/sdk/fidl/fuchsia.fonts -Ldependency=obj/sdk/fidl/fuchsia.intl -Ldependency=obj/sdk/fidl/fuchsia.mem -Ldependency=obj/sdk/fidl/fuchsia.hardware.input -Ldependency=obj/sdk/fidl/fuchsia.images -Ldependency=obj/sdk/fidl/fuchsia.sysmem -Ldependency=obj/sdk/fidl/fuchsia.input.report -Ldependency=obj/sdk/fidl/fuchsia.math -Ldependency=obj/sdk/fidl/fuchsia.ui.app -Ldependency=obj/sdk/fidl/fuchsia.sys -Ldependency=obj/sdk/fidl/fuchsia.ui.gfx -Ldependency=obj/sdk/fidl/fuchsia.ui.policy -Ldependency=obj/sdk/fidl/fuchsia.ui.scenic -Ldependency=obj/sdk/fidl/fuchsia.scenic.scheduling -Ldependency=obj/src/graphics/lib/compute/mold -Ldependency=obj/src/graphics/lib/compute/surpass -Ldependency=obj/src/graphics/lib/compute/spinel-rs-sys -Ldependency=obj/src/lib/fdio/rust -Ldependency=obj/sdk/fidl/fuchsia.device -Ldependency=obj/sdk/fidl/fuchsia.device.manager -Ldependency=obj/src/lib/fuchsia-runtime -Ldependency=obj/src/lib/fuchsia-component -Ldependency=obj/garnet/lib/rust/io_util -Ldependency=obj/sdk/fidl/fuchsia.io -Ldependency=obj/sdk/fidl/fuchsia.sys2 -Ldependency=obj/sdk/fidl/fuchsia.component -Ldependency=obj/sdk/fidl/fuchsia.data -Ldependency=obj/sdk/fidl/fuchsia.io2 -Ldependency=obj/sdk/fidl/fuchsia.url -Ldependency=obj/src/lib/mapped-vmo -Ldependency=obj/src/lib/shared-buffer -Ldependency=obj/src/lib/syslog/rust -Ldependency=obj/sdk/fidl/fuchsia.logger -Ldependency=obj/src/lib/ui/fuchsia-framebuffer -Ldependency=obj/sdk/fidl/fuchsia.hardware.display -Ldependency=obj/src/lib/ui/fuchsia-scenic -Ldependency=obj/src/lib/ui/input-synthesis -Lnative=x64-shared -Lnative=obj/zircon/system/ulib/trace-provider -Lnative=obj/zircon/public/lib/async -Lnative=obj/zircon/public/lib/fit -Lnative=obj/zircon/public/lib/zx -Lnative=obj/zircon/public/lib/fidl -Lnative=obj/zircon/public/lib/fidl_base -Lnative=obj/zircon/public/lib/async-cpp -Lnative=obj/src/graphics/lib/compute/common -Lnative=obj/src/graphics/lib/compute/common/vk -Lnative=obj/src/graphics/lib/compute/hotsort/platforms/vk -Lnative=obj/src/graphics/lib/compute/spinel -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/amd/gcn3 -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/amd/gcn3/hotsort -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/arm/bifrost8 -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/arm/bifrost8/hotsort -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/intel/gen8 -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/intel/gen8/hotsort -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/nvidia/sm50 -Lnative=obj/src/graphics/lib/compute/spinel/platforms/vk/targets/vendors/nvidia/sm50/hotsort -ltrace-engine -lrust-trace-provider -ltrace-provider-with-fdio -lasync -lfit -lzx -lfdio -lfidl -lfidl_base -lasync-cpp -lasync-default -lsyslog -lcompute_common -lcompute_common_vk -lvulkan -lhotsort_vk -lspinel -lspinel_vk -lspinel_vk_find_target -lspinel_vk_spn_amd_gcn3 -lhotsort_vk_hs_amd_gcn3_u64 -lspinel_vk_spn_arm_bifrost8 -lhotsort_vk_hs_arm_bifrost8_u64 -lspinel_vk_spn_intel_gen8 -lhotsort_vk_hs_intel_gen8_u64 -lspinel_vk_spn_nvidia_sm50 -lhotsort_vk_hs_nvidia_sm35_u64 -Lnative=gen/zircon/system/ulib/fdio -Lnative=gen/zircon/system/ulib/trace-engine -Lnative=gen/zircon/system/ulib/syslog -lzircon --extern fidl_fidl_examples_echo=obj/garnet/examples/fidl/services/libfidl_fidl_examples_echo.rlib --extern fidl_fuchsia_ui_input=obj/sdk/fidl/fuchsia.ui.input/libfidl_fuchsia_ui_input.rlib --extern fidl=obj/src/lib/fidl/rust/fidl/libfidl.rlib --extern fuchsia_async=obj/src/lib/fuchsia-async/libfuchsia_async.rlib --extern fuchsia_trace=obj/src/lib/trace/rust/libfuchsia_trace.rlib --extern fuchsia_trace_provider=obj/src/lib/trace/rust/libfuchsia_trace_provider.rlib --extern carnelian=obj/src/lib/ui/carnelian/libcarnelian.rlib --extern fuchsia_scenic=obj/src/lib/ui/fuchsia-scenic/libfuchsia_scenic.rlib --extern fuchsia_zircon=obj/src/lib/zircon/rust/libfuchsia_zircon.rlib --extern anyhow=obj/third_party/rust_crates/libanyhow-7791292ca6d4cc50.rlib --extern euclid=obj/third_party/rust_crates/libeuclid-4687831aa0edfe47.rlib --extern futures=obj/third_party/rust_crates/libfutures-db6a965543caf277.rlib --extern thiserror=obj/third_party/rust_crates/libthiserror-eafe64cb9fc967f6.rlib && ../../prebuilt/third_party/clang/mac-x64/bin/llvm-objcopy --strip-sections "./exe.unstripped/spinning_square" "./spinning_square" && ../../prebuilt/tools/buildidtool/mac-x64/buildidtool -build-id-dir .build-id -stamp "./spinning_square.build-id.stamp" -entry "=./spinning_square" -entry ".debug=./exe.unstripped/spinning_square"
+"#;
+}
diff --git a/src/manifest.rs b/src/manifest.rs
index efbe999..9b87344 100644
--- a/src/manifest.rs
+++ b/src/manifest.rs
@@ -19,6 +19,8 @@
     #[serde(default)]
     pub additional_shared_libraries: Vec<String>,
     #[serde(default)]
+    pub additional_static_libraries: Vec<String>,
+    #[serde(default)]
     pub data_files: Vec<DataFile>,
 }