Skip to content

support asmjs-unknown-emscripten and wasm32-unknown-emscripten #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ matrix:
- env: TARGET=thumbv7em-none-eabi RUN=1
- env: TARGET=thumbv7em-none-eabihf RUN=1
- env: TARGET=thumbv7m-none-eabi RUN=1

# Other targets
- env: TARGET=asmjs-unknown-emscripten STD=1
- env: TARGET=wasm32-unknown-emscripten STD=1

env: TARGET=x86_64-unknown-linux-gnu CPP=1 DYLIB=1 OPENSSL=0.5.5 RUN=1 DEPLOY=1

install:
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Added

- Support for emscripten targets.

## [v0.1.9] - 2017-02-08

### Added
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ worst, "hang" (never terminate).
| `arm-unknown-linux-musleabi` | 1.1.15 | 5.3.1 | N/A | | 2.8.0 | ✓ |
| `armv7-unknown-linux-gnueabihf` | 2.15 | 4.6.2 | 1.0.2j | ✓ | 2.8.0 | ✓ |
| `armv7-unknown-linux-musleabihf` | 1.1.15 | 5.3.1 | N/A | | 2.8.0 | ✓ |
| `asmjs-unknown-emscripten` | N/A | N/A | N/A | | N/A | |
| `i686-unknown-freebsd` [1] | 10.2 | 5.3.0 | 1.0.2j | | N/A | |
| `i686-unknown-linux-gnu` | 2.15 | 4.6.2 | 1.0.2j | ✓ | N/A | ✓ |
| `i686-unknown-linux-musl` | 1.1.15 | 5.3.1 | N/A | | N/A | ✓ |
Expand All @@ -177,6 +178,7 @@ worst, "hang" (never terminate).
| `thumbv7em-none-eabi` [3] | 2.2.0 | 5.3.1 | N/A | | N/A | |
| `thumbv7em-none-eabihf` [3] | 2.2.0 | 5.3.1 | N/A | | N/A | |
| `thumbv7m-none-eabi` [3] | 2.2.0 | 5.3.1 | N/A | | N/A | |
| `wasm32-unknown-emscripten` | N/A | N/A | N/A | | N/A | |
| `x86_64-pc-windows-gnu`[1] | N/A | 5.3.1 | | ✓ | N/A | |
| `x86_64-unknown-dragonfly` [1] [2] | 4.6.0 | 5.3.0 | 1.0.2j | | N/A | ✓ |
| `x86_64-unknown-freebsd` [1] | 10.2 | 5.3.0 | 1.0.2j | | N/A | |
Expand Down
17 changes: 15 additions & 2 deletions ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ main() {

export QEMU_STRACE=1

# `cross run` test for thumb targets
# `cross run` test for thumb and emscripten targets
case $TARGET in
thumb*-none-eabi*)
td=$(mktemp -d)
Expand All @@ -30,7 +30,20 @@ main() {
popd

rm -rf $td
;;
;;
*-emscripten)
td=$(mktemp -d)

cargo init --bin --name hello $td

pushd $td
cross build --target $TARGET
popd

rm -rf $td

return
;;
esac

# `cross build` test for targets where `std` is not available
Expand Down
19 changes: 19 additions & 0 deletions docker/asmjs-unknown-emscripten/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM ubuntu:16.04

RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates \
cmake \
gcc \
libc6-dev \
make \
pkg-config

COPY emscripten.sh /
RUN bash /emscripten.sh 1.37.2

RUN apt-get install --no-install-recommends -y \
nodejs \
python

ENV NODE=/usr/bin/nodejs
45 changes: 45 additions & 0 deletions docker/binaryen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
set -ex

main() {
local version=$1

local dependencies=(
ca-certificates
cmake
curl
g++
ninja-build
)

apt-get update
local purge_list=()
for dep in ${dependencies[@]}; do
dpkg -L $dep || (
apt-get install --no-install-recommends -y $dep &&
purge_list+=( $dep )
)
done

local td=$(mktemp -d)

curl -L https://github.com/WebAssembly/binaryen/archive/$version.tar.gz | \
tar -C $td --strip-components=1 -xz

pushd $td
cmake -G Ninja
nice ninja

mkdir /binaryen
cp -r bin lib src /binaryen
cp -r src/js /binaryen/src

# Cleanup
popd

apt-get purge --auto-remove -y ${purge_list[@]}

rm -rf $td
rm $0
}

main "${@}"
67 changes: 67 additions & 0 deletions docker/emscripten.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
set -ex

main() {
local version=$1

local dependencies=(
ca-certificates
cmake
curl
g++
ninja-build
python
)

apt-get update
local purge_list=()
for dep in ${dependencies[@]}; do
dpkg -L $dep || (
apt-get install --no-install-recommends -y $dep &&
purge_list+=( $dep )
)
done

local td=$(mktemp -d)

mkdir $td/{build,fastcomp}

curl -L https://github.com/kripken/emscripten-fastcomp/archive/$version.tar.gz |
tar --strip-components=1 -C $td/fastcomp -xz

mkdir $td/fastcomp/tools/clang
curl -L https://github.com/kripken/emscripten-fastcomp-clang/archive/$version.tar.gz |
tar --strip-components=1 -C $td/fastcomp/tools/clang -xz

pushd $td
cmake \
-G Ninja \
-DCLANG_INCLUDE_TESTS=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_TARGETS_TO_BUILD="X86;JSBackend" \
$td/fastcomp

nice ninja
ninja install

mkdir /emscripten
curl -L https://github.com/kripken/emscripten/archive/$version.tar.gz |
tar --strip-components=1 -C /emscripten -xz

# TODO build tools/optimizer. I have no idea if `rustc` calls `emcc` in
# a way that makes uses of that optimizer though.

# Put `emcc` in `$PATH`
ln -s /emscripten/emcc /usr/local/bin

# Cleanup
popd

apt-get purge --auto-remove -y ${purge_list[@]}

rm -rf $td
rm $0
}

main "${@}"
23 changes: 23 additions & 0 deletions docker/wasm32-unknown-emscripten/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM ubuntu:16.04

RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates \
cmake \
gcc \
libc6-dev \
make \
pkg-config

COPY emscripten.sh /
RUN bash /emscripten.sh 1.37.2

RUN apt-get install --no-install-recommends -y \
nodejs \
python

COPY binaryen.sh /
RUN bash /binaryen.sh version_27

ENV BINARYEN=/binaryen \
NODE=/usr/bin/nodejs
53 changes: 43 additions & 10 deletions src/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ pub fn run(target: &Target,
verbose: bool)
-> Result<ExitStatus> {
let root = root.path();
let home_dir = env::home_dir().ok_or_else(|| "couldn't get home directory. Is $HOME not set?")?;
let home_dir = env::home_dir()
.ok_or_else(|| "couldn't get home directory. Is $HOME not set?")?;
let cargo_dir = env::var_os("CARGO_HOME")
.map(PathBuf::from)
.unwrap_or_else(|| home_dir.join(".cargo"));
Expand All @@ -48,12 +49,12 @@ pub fn run(target: &Target,
fs::create_dir(&cargo_dir).ok();
fs::create_dir(&xargo_dir).ok();

let mut cmd = if uses_xargo {
let mut cargo = if uses_xargo {
Command::new("xargo")
} else {
Command::new("cargo")
};
cmd.args(args);
cargo.args(args);

// We create/regenerate the lockfile on the host system because the Docker
// container doesn't have write access to the root of the Cargo project
Expand All @@ -66,29 +67,61 @@ pub fn run(target: &Target,

let mut docker = Command::new("docker");

docker.arg("run");

let must_run_emcc_first = if target.is_emscripten() {
let temp_dir = env::temp_dir();
let cache_dir = temp_dir.join(format!("cross-{}", target.triple()));

if !cache_dir.exists() {
fs::create_dir(&cache_dir).chain_err(|| {
format!("couldn't create a directory in {}",
temp_dir.display())
})?;
}

docker.args(&["-v", &format!("{}:{}", cache_dir.display(), "/tmp")]);

!cache_dir.join(".emscripten").exists()
} else {
false
};

docker
.arg("run")
.arg("--rm")
.args(&["--user", &format!("{}:{}", id::user(), id::group())])
.args(&["-e", "CARGO_HOME=/cargo"])
.args(&["-e", "CARGO_TARGET_DIR=/target"])
.args(&["-e", "HOME=/tmp"])
.args(&["-e", &format!("USER={}", id::username())]);

if let Some(strace) = env::var("QEMU_STRACE").ok() {
docker.args(&["-e", &format!("QEMU_STRACE={}", strace)]);
}

docker
.args(&["-e", "XARGO_HOME=/xargo"])
docker.args(&["-e", "XARGO_HOME=/xargo"])
.args(&["-v", &format!("{}:/xargo", xargo_dir.display())])
.args(&["-v", &format!("{}:/cargo", cargo_dir.display())])
.args(&["-v", &format!("{}:/project:ro", root.display())])
.args(&["-v", &format!("{}:/rust:ro", rustc::sysroot(verbose)?.display())])
.args(&["-v",
&format!("{}:/rust:ro", rustc::sysroot(verbose)?.display())])
.args(&["-v", &format!("{}:/target", target_dir.display())])
.args(&["-w", "/project"])
.args(&["-it", &image(toml, target)?])
.args(&["sh", "-c", &format!("PATH=$PATH:/rust/bin {:?}", cmd)])
.run_and_get_status(verbose)
.args(&["-it", &image(toml, target)?]);

if must_run_emcc_first {
docker.args(&["sh",
"-c",
&format!("emcc 2>/dev/null; \
PATH=$PATH:/rust/bin {:?}",
cargo)]);
} else {
docker.args(&["sh",
"-c",
&format!("PATH=$PATH:/rust/bin {:?}", cargo)]);
}

docker.run_and_get_status(verbose)
}

fn image(toml: Option<&Toml>, target: &Target) -> Result<String> {
Expand Down
18 changes: 17 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ pub enum Target {
Thumbv7emNoneEabi,
Thumbv7emNoneEabihf,
Thumbv7mNoneEabi,

// Emscripten
AsmjsUnknownEmscripten,
Wasm32UnknownEmscripten,
}

impl Target {
Expand Down Expand Up @@ -177,9 +181,17 @@ impl Target {
}
}

fn is_emscripten(&self) -> bool {
match *self {
Target::AsmjsUnknownEmscripten |
Target::Wasm32UnknownEmscripten => true,
_ => false,
}
}

fn needs_docker(&self) -> bool {
self.is_linux() || self.is_bare_metal() || self.is_bsd() ||
!self.is_builtin() || self.is_windows()
!self.is_builtin() || self.is_windows() || self.is_emscripten()
}

fn needs_qemu(&self) -> bool {
Expand Down Expand Up @@ -211,6 +223,7 @@ impl Target {
ArmUnknownLinuxMusleabi => "arm-unknown-linux-musleabi",
Armv7UnknownLinuxGnueabihf => "armv7-unknown-linux-gnueabihf",
Armv7UnknownLinuxMusleabihf => "armv7-unknown-linux-musleabihf",
AsmjsUnknownEmscripten => "asmjs-unknown-emscripten",
I686AppleDarwin => "i686-apple-darwin",
I686UnknownFreebsd => "i686-unknown-freebsd",
I686UnknownLinuxGnu => "i686-unknown-linux-gnu",
Expand All @@ -228,6 +241,7 @@ impl Target {
Thumbv7emNoneEabi => "thumbv7em-none-eabi",
Thumbv7emNoneEabihf => "thumbv7em-none-eabihf",
Thumbv7mNoneEabi => "thumbv7m-none-eabi",
Wasm32UnknownEmscripten => "wasm32-unknown-emscripten",
X86_64AppleDarwin => "x86_64-apple-darwin",
X86_64PcWindowsGnu => "x86_64-pc-windows-gnu",
X86_64UnknownDragonfly => "x86_64-unknown-dragonfly",
Expand All @@ -253,6 +267,7 @@ impl Target {
"arm-unknown-linux-musleabi" => ArmUnknownLinuxMusleabi,
"armv7-unknown-linux-gnueabihf" => Armv7UnknownLinuxGnueabihf,
"armv7-unknown-linux-musleabihf" => Armv7UnknownLinuxMusleabihf,
"asmjs-unknown-emscripten" => AsmjsUnknownEmscripten,
"i686-apple-darwin" => I686AppleDarwin,
"i686-unknown-freebsd" => I686UnknownFreebsd,
"i686-unknown-linux-gnu" => I686UnknownLinuxGnu,
Expand All @@ -270,6 +285,7 @@ impl Target {
"thumbv7em-none-eabi" => Thumbv7emNoneEabi,
"thumbv7em-none-eabihf" => Thumbv7emNoneEabihf,
"thumbv7m-none-eabi" => Thumbv7mNoneEabi,
"wasm32-unknown-emscripten" => Wasm32UnknownEmscripten,
"x86_64-apple-darwin" => X86_64AppleDarwin,
"x86_64-pc-windows-gnu" => X86_64PcWindowsGnu,
"x86_64-unknown-dragonfly" => X86_64UnknownDragonfly,
Expand Down