Merge pull request #602 from drager/improve-error-message

Improve error message when wasm32-unknown-unknown is missing
master
ashley williams 6 years ago committed by GitHub
commit 294741411c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      docs/src/SUMMARY.md
  2. 37
      docs/src/non-rustup-setups.md
  3. 2
      docs/src/prerequisites/index.md
  4. 79
      src/build/mod.rs
  5. 141
      src/build/wasm_target.rs
  6. 2
      src/command/build.rs
  7. 2
      src/command/test.rs

@ -25,4 +25,5 @@
- [Packaging and publishing](./tutorials/npm-browser-packages/packaging-and-publishing.md)
- [Using your library](./tutorials/npm-browser-packages/using-your-library.md)
- [`Cargo.toml` Configuration](./cargo-toml-configuration.md)
- [Non-rustup setups](./non-rustup-setups.md)
- [Contributing](./contributing.md)

@ -0,0 +1,37 @@
# Non-Rustup setups
`wasm-pack` compiles your code using the `wasm32-unknown-unknown` target. `wasm-pack` will automatically add this target for Rustup setups if you don't already have it installed by doing `rustup target add wasm32-unknown-unknown`. However, if you're not using Rustup we won't be able to this automatically and you'll have to do this yourself.
## Manually add wasm32-unknown-unknown
*Disclaimer: This is not guaranteed to work for every setup. These instructions below are specific for setups that match the exact rustc release, which means that the downloaded wasm32 target can be incompatible.*
To manually add the `wasm32-unknown-unknown` target you will need to download it from the rust-lang website and put the contents in the correct folder.
All the targets for all the different `rustc` versions are not presented in a human way on a website (yet) for you to just select the one you want and download it, one reason for this is that Rustup handles all of this for you and the packaging of targets was mainly built for tools. However, the following steps will walk through how to do this.
First, check what version of `rustc` you're using by running `rustc --version`. This should display something like: `rustc 1.33.0 (2aa4c46cf 2019-02-28)`. Then you need to download the correct wasm32 target for your rustc version. The rustc version is part of the url, which means for `rustc 1.33.0` the url will look like this: `https://static.rust-lang.org/dist/rust-std-1.33.0-wasm32-unknown-unknown.tar.gz`.
Here's some examples of urls for different rustc versions:
* Nightly https://static.rust-lang.org/dist/rust-std-nightly-wasm32-unknown-unknown.tar.gz
* Specific date nightly (2019-03-10) https://static.rust-lang.org/dist/2019-03-10/rust-std-nightly-wasm32-unknown-unknown.tar.gz
* Beta https://static.rust-lang.org/dist/rust-std-beta-wasm32-unknown-unknown.tar.gz
You should be able to download this either by doing `wget https://static.rust-lang.org/dist/rust-std-1.33.0-wasm32-unknown-unknown.tar.gz` or by just visiting the url in a web browser.
After you have downloaded this tarball at a location of your choice, you should unpack it. This should result in a folder named `rust-std-1.33.0-wasm32-unknown-unknown` that contains some folders and files, but the interesting one is a folder called `rust-std-wasm32-unknown-unknown` which contains a `lib` and that should contain a `rustlib` folder and in that, a folder called `wasm32-unknown-unknown`. This is the folder we want to move.
Here's how the structure should look like for rustc 1.33.0:
```
rust-std-1.33.0-wasm32-unknown-unknown
├── components
├── install.sh
├── rust-installer-version
└── rust-std-wasm32-unknown-unknown
├── lib
   └── rustlib
   └── wasm32-unknown-unknown
```
To know where we should move this `wasm32-unknown-unknown` folder we need to run `rustc --print sysroot` which should print a path that looks something like this (this will vary on different operating systems): `/home/user/rust/rust-1.33.0-2019-02-28-2aa4c46cf`. That folder should contain a `lib` folder that contains a `rustlib` folder. We should move the `wasm32-unknown-unknown` to this folder.
On unix-like operating systems we can do that with the following command:
`mv rust-std-1.33.0-wasm32-unknown-unknown/rust-std-wasm32-unknown-unknown/lib/rustlib/wasm32-unknown-unknown /home/user/rust/rust-1.33.0-2019-02-28-2aa4c46cf/lib/rustlib/` and that should be it!

@ -17,3 +17,5 @@ you're excited about that work- you should reach out to the maintainers and get
involved!
[npm]: prerequisites/npm.html
Using a non-rustup setup? Learn how to configure it for wasm-pack [here](./non-rustup-setups.html).

@ -4,12 +4,13 @@ use child;
use command::build::BuildProfile;
use emoji;
use failure::{Error, ResultExt};
use log::info;
use std::path::{Path, PathBuf};
use std::path::Path;
use std::process::Command;
use std::str;
use PBAR;
pub mod wasm_target;
/// Ensure that `rustc` is present and that it is >= 1.30.0
pub fn check_rustc_version() -> Result<String, Error> {
let local_minor_version = rustc_minor_version();
@ -47,80 +48,6 @@ fn rustc_minor_version() -> Option<u32> {
otry!(pieces.next()).parse().ok()
}
/// Get rustc's sysroot as a PathBuf
fn get_rustc_sysroot() -> Result<PathBuf, Error> {
let command = Command::new("rustc")
.args(&["--print", "sysroot"])
.output()?;
if command.status.success() {
Ok(String::from_utf8(command.stdout)?.trim().into())
} else {
Err(format_err!(
"Getting rustc's sysroot wasn't successful. Got {}",
command.status
))
}
}
/// Checks if the wasm32-unknown-unknown is present in rustc's sysroot.
fn is_wasm32_target_in_sysroot(sysroot: &PathBuf) -> bool {
let wasm32_target = "wasm32-unknown-unknown";
let rustlib_path = sysroot.join("lib/rustlib");
info!("Looking for {} in {:?}", wasm32_target, rustlib_path);
if rustlib_path.join(wasm32_target).exists() {
info!("Found {} in {:?}", wasm32_target, rustlib_path);
true
} else {
info!("Failed to find {} in {:?}", wasm32_target, rustlib_path);
false
}
}
fn check_wasm32_target() -> Result<bool, Error> {
let sysroot = get_rustc_sysroot()?;
// If wasm32-unknown-unknown already exists we're ok.
if is_wasm32_target_in_sysroot(&sysroot) {
Ok(true)
// If it doesn't exist, then we need to check if we're using rustup.
} else {
// If sysroot contains .rustup, then we can assume we're using rustup
// and use rustup to add the wasm32-unknown-unknown target.
if sysroot.to_string_lossy().contains(".rustup") {
rustup_add_wasm_target().map(|()| true)
} else {
Ok(false)
}
}
}
/// Add wasm32-unknown-unknown using `rustup`.
fn rustup_add_wasm_target() -> Result<(), Error> {
let mut cmd = Command::new("rustup");
cmd.arg("target").arg("add").arg("wasm32-unknown-unknown");
child::run(cmd, "rustup").context("Adding the wasm32-unknown-unknown target with rustup")?;
Ok(())
}
/// Ensure that `rustup` has the `wasm32-unknown-unknown` target installed for
/// current toolchain
pub fn check_for_wasm32_target() -> Result<(), Error> {
let msg = format!("{}Checking for the Wasm target...", emoji::TARGET);
PBAR.info(&msg);
// Check if wasm32 target is present, otherwise bail.
match check_wasm32_target() {
Ok(true) => Ok(()),
Ok(false) => bail!("wasm32-unknown-unknown target not found!"),
Err(err) => Err(err),
}
}
/// Run `cargo build` targetting `wasm32-unknown-unknown`.
pub fn cargo_build_wasm(
path: &Path,

@ -0,0 +1,141 @@
//! Checking for the wasm32 target
use child;
use emoji;
use failure::{Error, ResultExt};
use log::info;
use std::fmt;
use std::path::PathBuf;
use std::process::Command;
use PBAR;
struct Wasm32Check {
rustc_path: PathBuf,
sysroot: PathBuf,
found: bool,
is_rustup: bool,
}
impl fmt::Display for Wasm32Check {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let target = "wasm32-unknown-unknown";
if self.found {
let rustup_string = if self.is_rustup {
"It looks like Rustup is being used.".to_owned()
} else {
format!("It looks like Rustup is not being used. For non-Rustup setups, the {} target needs to be installed manually. See https://rustwasm.github.io/wasm-pack/book/prerequisites/index.html#target-wasm32-unknown-unknown on how to do this.", target)
};
writeln!(
f,
"{} target not found in sysroot: {:?}",
target, self.sysroot
)
.and_then(|_| {
writeln!(
f,
"\nUsed rustc from the following path: {:?}",
self.rustc_path
)
})
.and_then(|_| writeln!(f, "{}", rustup_string))
} else {
write!(
f,
"sysroot: {:?}, rustc path: {:?}, was found: {}, isRustup: {}",
self.sysroot, self.rustc_path, self.found, self.is_rustup
)
}
}
}
/// Ensure that `rustup` has the `wasm32-unknown-unknown` target installed for
/// current toolchain
pub fn check_for_wasm32_target() -> Result<(), Error> {
let msg = format!("{}Checking for the Wasm target...", emoji::TARGET);
PBAR.info(&msg);
// Check if wasm32 target is present, otherwise bail.
match check_wasm32_target() {
Ok(ref wasm32_check) if wasm32_check.found => Ok(()),
Ok(wasm32_check) => bail!("{}", wasm32_check),
Err(err) => Err(err),
}
}
/// Get rustc's sysroot as a PathBuf
fn get_rustc_sysroot() -> Result<PathBuf, Error> {
let command = Command::new("rustc")
.args(&["--print", "sysroot"])
.output()?;
if command.status.success() {
Ok(String::from_utf8(command.stdout)?.trim().into())
} else {
Err(format_err!(
"Getting rustc's sysroot wasn't successful. Got {}",
command.status
))
}
}
/// Checks if the wasm32-unknown-unknown is present in rustc's sysroot.
fn is_wasm32_target_in_sysroot(sysroot: &PathBuf) -> bool {
let wasm32_target = "wasm32-unknown-unknown";
let rustlib_path = sysroot.join("lib/rustlib");
info!("Looking for {} in {:?}", wasm32_target, rustlib_path);
if rustlib_path.join(wasm32_target).exists() {
info!("Found {} in {:?}", wasm32_target, rustlib_path);
true
} else {
info!("Failed to find {} in {:?}", wasm32_target, rustlib_path);
false
}
}
fn check_wasm32_target() -> Result<Wasm32Check, Error> {
let sysroot = get_rustc_sysroot()?;
let rustc_path = which::which("rustc")?;
// If wasm32-unknown-unknown already exists we're ok.
if is_wasm32_target_in_sysroot(&sysroot) {
Ok(Wasm32Check {
rustc_path,
sysroot,
found: true,
is_rustup: false,
})
// If it doesn't exist, then we need to check if we're using rustup.
} else {
// If sysroot contains .rustup, then we can assume we're using rustup
// and use rustup to add the wasm32-unknown-unknown target.
if sysroot.to_string_lossy().contains(".rustup") {
rustup_add_wasm_target().map(|()| Wasm32Check {
rustc_path,
sysroot,
found: true,
is_rustup: true,
})
} else {
Ok(Wasm32Check {
rustc_path,
sysroot,
found: false,
is_rustup: false,
})
}
}
}
/// Add wasm32-unknown-unknown using `rustup`.
fn rustup_add_wasm_target() -> Result<(), Error> {
let mut cmd = Command::new("rustup");
cmd.arg("target").arg("add").arg("wasm32-unknown-unknown");
child::run(cmd, "rustup").context("Adding the wasm32-unknown-unknown target with rustup")?;
Ok(())
}

@ -299,7 +299,7 @@ impl Build {
fn step_check_for_wasm_target(&mut self) -> Result<(), Error> {
info!("Checking for wasm-target...");
build::check_for_wasm32_target()?;
build::wasm_target::check_for_wasm32_target()?;
info!("Checking for wasm-target was successful.");
Ok(())
}

@ -236,7 +236,7 @@ impl Test {
fn step_check_for_wasm_target(&mut self) -> Result<(), Error> {
info!("Adding wasm-target...");
build::check_for_wasm32_target()?;
build::wasm_target::check_for_wasm32_target()?;
info!("Adding wasm-target was successful.");
Ok(())
}

Loading…
Cancel
Save