Handle target specific outputs such as .wasm
authorTatsuya Kawano <tatsuya@hibaridb.org>
Thu, 5 Oct 2017 01:37:04 +0000 (09:37 +0800)
committerTatsuya Kawano <tatsuya@hibaridb.org>
Thu, 5 Oct 2017 01:37:04 +0000 (09:37 +0800)
Fixes #4535

- Do not add metadata to wasm32 bin target because generated .js will
  refer corresponding .wasm.
- Handle different usages of "-" and "_" in .js and .wasm file names.
  (e.g "foo-bar.js" vs. "foo_bar.wasm")
- Change file mode of cargo_rustc/context.rs (100755 -> 100644)

src/cargo/ops/cargo_rustc/context.rs [changed mode: 0755->0644]
tests/build.rs

old mode 100755 (executable)
new mode 100644 (file)
index 0ee0614..a502d70
@@ -463,6 +463,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         // - OSX encodes the dylib name in the executable
         // - Windows rustc multiple files of which we can't easily link all of them
         //
+        // No metadata for bin because of an issue
+        // - wasm32 rustc/emcc encodes the .wasm name in the .js (rust-lang/cargo#4535)
+        //
         // Two exceptions
         // 1) Upstream dependencies (we aren't exporting + need to resolve name conflict)
         // 2) __CARGO_DEFAULT_LIB_METADATA env var
@@ -478,9 +481,11 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         // doing this eventually.
         let __cargo_default_lib_metadata = env::var("__CARGO_DEFAULT_LIB_METADATA");
         if !unit.profile.test &&
-            (unit.target.is_dylib() || unit.target.is_cdylib()) &&
+            (unit.target.is_dylib() || unit.target.is_cdylib() ||
+                 (unit.target.is_bin() && self.target_triple().starts_with("wasm32-"))) &&
             unit.pkg.package_id().source_id().is_path() &&
-            !__cargo_default_lib_metadata.is_ok() {
+            !__cargo_default_lib_metadata.is_ok()
+        {
             return None;
         }
 
@@ -652,11 +657,21 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
                                 suffix,
                                 linkable,
                             );
-                            for (suffix, linkable) in suffixes {
+                            for (suffix, linkable, should_replace_hyphens) in suffixes {
+                                // wasm bin target will generate two files in deps such as
+                                // "web-stuff.js" and "web_stuff.wasm". Note the different usages of
+                                // "-" and "_". should_replace_hyphens is a flag to indicate that
+                                // we need to convert the stem "web-stuff" to "web_stuff", so we
+                                // won't miss "web_stuff.wasm".
+                                let conv = |s: String| if should_replace_hyphens {
+                                    s.replace("-", "_")
+                                } else {
+                                    s
+                                };
                                 let filename =
-                                    out_dir.join(format!("{}{}{}", prefix, stem, suffix));
+                                    out_dir.join(format!("{}{}{}", prefix, conv(stem.clone()), suffix));
                                 let link_dst = link_stem.clone().map(|(ld, ls)| {
-                                    ld.join(format!("{}{}{}", prefix, ls, suffix))
+                                    ld.join(format!("{}{}{}", prefix, conv(ls), suffix))
                                 });
                                 ret.push((filename, link_dst, linkable));
                             }
@@ -1174,27 +1189,32 @@ fn parse_crate_type(
     Ok(Some((prefix.to_string(), suffix.to_string())))
 }
 
+// (not a rustdoc)
+// Return a list of 3-tuples (suffix, linkable, should_replace_hyphens).
+//
+// should_replace_hyphens will be used by the caller to replace "-" with "_"
+// in a bin_stem. See the caller side (calc_target_filenames()) for details.
 fn add_target_specific_suffixes(
     target_triple: &str,
     crate_type: &str,
     suffix: &str,
     linkable: bool,
-) -> Vec<(String, bool)> {
-    let mut suffixes = vec![(suffix.to_string(), linkable)];
+) -> Vec<(String, bool, bool)> {
+    let mut ret = vec![(suffix.to_string(), linkable, false)];
 
     // rust-lang/cargo#4500
     if target_triple.ends_with("pc-windows-msvc") && crate_type.ends_with("dylib") &&
         suffix == ".dll"
     {
-        suffixes.push((format!("{}.lib", suffix), false));
+        ret.push((".dll.lib".to_string(), false, false));
     }
 
     // rust-lang/cargo#4535
-    if target_triple == "wasm32-unknown-emscripten" && crate_type == "bin" &&
+    if target_triple.starts_with("wasm32-") && crate_type == "bin" &&
         suffix == ".js"
     {
-        suffixes.push((".wasm".to_string(), false));
+        ret.push((".wasm".to_string(), false, true));
     }
 
-    suffixes
+    ret
 }
index 8105b913bc82b1b3ed931bf9a286c4261d99e336..843795f7281e1470057389c9752b65966c7da1a6 100644 (file)
@@ -3371,7 +3371,7 @@ fn cdylib_final_outputs() {
     let p = project("foo")
         .file("Cargo.toml", r#"
             [project]
-            name = "foo"
+            name = "foo-bar"
             authors = []
             version = "0.1.0"
 
@@ -3383,11 +3383,11 @@ fn cdylib_final_outputs() {
     assert_that(p.cargo_process("build"), execs().with_status(0));
 
     let files = if cfg!(windows) {
-        vec!["foo.dll.lib", "foo.dll"]
+        vec!["foo_bar.dll.lib", "foo_bar.dll"]
     } else if cfg!(target_os = "macos") {
-        vec!["libfoo.dylib"]
+        vec!["libfoo_bar.dylib"]
     } else {
-        vec!["libfoo.so"]
+        vec!["libfoo_bar.so"]
     };
 
     for file in files {
@@ -3408,7 +3408,7 @@ fn wasm32_final_outputs() {
     let p = project("foo")
         .file("Cargo.toml", r#"
             [project]
-            name = "foo"
+            name = "foo-bar"
             authors = []
             version = "0.1.0"
         "#)
@@ -3449,11 +3449,11 @@ fn wasm32_final_outputs() {
 
     let pkgid = packages
         .package_ids()
-        .filter(|id| id.name() == "foo")
+        .filter(|id| id.name() == "foo-bar")
         .collect::<Vec<_>>();
     let pkg = packages.get(pkgid[0]).expect("Can't get package");
 
-    let target = Target::bin_target("foo", p.root().join("src/main.rs"), None);
+    let target = Target::bin_target("foo-bar", p.root().join("src/main.rs"), None);
 
     let unit = Unit {
         pkg: &pkg,
@@ -3478,7 +3478,7 @@ fn wasm32_final_outputs() {
     let target_filenames = ctx.target_filenames(&unit).expect("Can't get target file names");
 
     // Verify the result.
-    let mut expected = vec!["debug/foo.js", "debug/foo.wasm"];
+    let mut expected = vec!["debug/foo-bar.js", "debug/foo_bar.wasm"];
 
     assert_eq!(target_filenames.len(), expected.len());