diff --git a/README.md b/README.md index ad904b2..c4f3767 100644 --- a/README.md +++ b/README.md @@ -477,6 +477,15 @@ RUN xx-cargo build --release --target-dir ./build && \ xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo ``` +### WebAssembly + +`xx-cargo` can also be used to build WebAssembly targets. Use platform `wasi/wasm` on your builds for `xx` to pick up the correct configuration. If your code is compatible you can use identical Dockerfile to build Linux and WebAssembly containers. + +When using multi-stage builds to copy build results to other stages, note that Rust adds ".wasm" suffix to the binaries built with +WebAssembly. + +Only Rust builds are supported at the moment. To build C/C++ code for WebAssembly using `xx-clang` your Dockerfile needs to set up Wasi Sysroot and `libclang-rt` itself. + ## External SDK support In addition to Linux targets, `xx` can also build binaries for MacOS and Windows. When building MacOS binaries from C, external MacOS SDK is needed in `/xx-sdk` directory. Such SDK can be built, for example, with [gen_sdk_package script in osxcross project](https://github.com/tpoechtrager/osxcross/blob/master/tools/gen_sdk_package.sh). Please consult XCode license terms when making such an image. `RUN --mount` syntax can be used in Dockerfile in order to avoid copying SDK files. No special tooling such as `ld64` linker is required in the image itself. diff --git a/base/test-cargo.bats b/base/test-cargo.bats index ec0e905..db462c7 100755 --- a/base/test-cargo.bats +++ b/base/test-cargo.bats @@ -30,9 +30,13 @@ testHelloCargo() { assert_success run xx-cargo build --verbose --color=never --manifest-path=./fixtures/hello_cargo/Cargo.toml --release --target-dir /tmp/cargobuild assert_success - xx-verify /tmp/cargobuild/$(xx-cargo --print-target-triple)/release/hello_cargo + + if [ "$TARGETARCH" = "wasm" ]; then + sfx=".wasm" + fi + xx-verify /tmp/cargobuild/$(xx-cargo --print-target-triple)/release/hello_cargo$sfx if ! xx-info is-cross; then - run /tmp/cargobuild/$(xx-cargo --print-target-triple)/release/hello_cargo + run /tmp/cargobuild/$(xx-cargo --print-target-triple)/release/hello_cargo$sfx assert_success assert_output "hello cargo" fi @@ -87,6 +91,14 @@ testHelloCargoRustup() { testHelloCargoRustup } +@test "wasm-hellocargo-rustup" { + export TARGETARCH=wasm + export TARGETOS=wasi + testHelloCargoRustup + unset TARGETOS + unset TARGETARCH +} + @test "uninstall-rustup" { export PATH="$HOME/.cargo/bin:$PATH" rustup self uninstall -y diff --git a/base/test-info-alpine.bats b/base/test-info-alpine.bats index b01b6c7..1e0ed84 100755 --- a/base/test-info-alpine.bats +++ b/base/test-info-alpine.bats @@ -98,6 +98,13 @@ load 'assert' assert_equal "mips64le" "$(TARGETPLATFORM=linux/mips64le xx-info pkg-arch)" } +@test "wasm" { + assert_equal "wasm32-alpine-wasi" "$(TARGETPLATFORM=wasi/wasm xx-info triple)" + assert_equal "wasm64-alpine-wasi" "$(TARGETPLATFORM=wasi/wasm64 xx-info triple)" + assert_equal "wasm32-alpine-wasi" "$(TARGETPLATFORM=wasi/wasm32 xx-info triple)" + assert_equal "wasm32" "$(TARGETPLATFORM=linux/wasm xx-info pkg-arch)" +} + @test "darwin" { assert_equal "x86_64-apple-macos10.6" "$(TARGETPLATFORM=darwin/amd64 xx-info triple)" assert_equal "darwin" "$(TARGETPLATFORM=darwin/amd64 xx-info os)" diff --git a/base/test-info-debian.bats b/base/test-info-debian.bats index 3654f1e..51d3b1b 100755 --- a/base/test-info-debian.bats +++ b/base/test-info-debian.bats @@ -97,6 +97,13 @@ fi assert_equal "mips64el" "$(TARGETPLATFORM=linux/mips64le xx-info pkg-arch)" } +@test "wasm" { + assert_equal "wasm32-wasi" "$(TARGETPLATFORM=wasi/wasm xx-info triple)" + assert_equal "wasm64-wasi" "$(TARGETPLATFORM=wasi/wasm64 xx-info triple)" + assert_equal "wasm32-wasi" "$(TARGETPLATFORM=wasi/wasm32 xx-info triple)" + assert_equal "wasm32" "$(TARGETPLATFORM=linux/wasm xx-info pkg-arch)" +} + @test "sysroot" { assert_equal "/" "$(xx-info sysroot)" assert_equal "/" "$(TARGETPLATFORM=linux/amd64 xx-info sysroot)" diff --git a/base/xx-cargo b/base/xx-cargo index 1af1b1b..2bba047 100755 --- a/base/xx-cargo +++ b/base/xx-cargo @@ -55,10 +55,11 @@ fi vendor=$XX_VENDOR if [ -n "$rustup" ] || [ ! -f /etc/alpine-release ]; then export XX_VENDOR="unknown" + export XX_RUSTUP=1 # this sets the correct target triple for rust libraries for subsequent calls fi if [ ! -f "$done_file" ]; then - xx-clang --setup-target-triple + XX_RUSTUP="" xx-clang --setup-target-triple if [ ! -d "$(rustc --print sysroot)/lib/rustlib/$(xx-info)" ]; then if [ -n "$rustup" ]; then execSilent rustup target add "$(xx-info)" @@ -73,13 +74,20 @@ if [ ! -f "$done_file" ]; then touch "$done_file" fi -export "CARGO_TARGET_$(xx-info | tr '[:lower:]' '[:upper:]' | tr - _)_LINKER=$(xx-info)-clang" +export "CARGO_TARGET_$(xx-info | tr '[:lower:]' '[:upper:]' | tr - _)_LINKER=$(XX_RUSTUP='' XX_VENDOR='' xx-info)-clang" if [ -n "$XX_RUSTFLAGS" ]; then export "CARGO_TARGET_$(xx-info | tr '[:lower:]' '[:upper:]' | tr - _)_RUSTFLAGS=$XX_RUSTFLAGS" fi -export "CC_$(xx-info | tr - _)=$(xx-info)-clang" +export "CC_$(xx-info | tr - _)=$(XX_RUSTUP='' XX_VENDOR='' xx-info)-clang" -if which "qemu-$(RISCV64_TARGET_ARCH='' ARM_TARGET_ARCH='' xx-info march)" >/dev/null 2>&1; then +if xx-info is-cross; then + nativeRustTriple="$(TARGETPLATFORM='' TARGETPAIR='' TARGETOS='' TARGETARCH='' TARGETVARIANT='' xx-info)" + nativeClangTriple="$(TARGETPLATFORM='' TARGETPAIR='' TARGETOS='' TARGETARCH='' TARGETVARIANT='' XX_RUSTUP='' XX_VENDOR='' xx-clang --print-target-triple)" + export "CARGO_TARGET_$(echo "$nativeRustTriple" | tr '[:lower:]' '[:upper:]' | tr - _)_LINKER=$nativeClangTriple-clang" + export "CC_$(echo "$nativeRustTriple" | tr - _)=$nativeClangTriple-clang" +fi + +if which "qemu-$(RISCV64_TARGET_ARCH='' ARM_TARGET_ARCH='' xx-info march)" >/dev/null 2>&1 && [ "$XX_OS" = "linux" ]; then export "CARGO_TARGET_$(xx-info | tr '[:lower:]' '[:upper:]' | tr - _)_RUNNER=qemu-$(RISCV64_TARGET_ARCH='' ARM_TARGET_ARCH='' xx-info march)" if [ -f /etc/alpine-release ]; then export "QEMU_LD_PREFIX=/$(RISCV64_TARGET_ARCH='' ARM_TARGET_ARCH='' xx-info)/" diff --git a/base/xx-info b/base/xx-info index 6145186..5f72dc2 100755 --- a/base/xx-info +++ b/base/xx-info @@ -110,7 +110,9 @@ distro="" # shellcheck disable=SC1091 if . /etc/os-release 2>/dev/null; then distro=$ID - XX_OS_VERSION=$VERSION_ID + if [ "$TARGETOS" = "linux" ] || [ "$TARGETOS" = "" ]; then + XX_OS_VERSION=$VERSION_ID + fi fi vendor="" @@ -130,6 +132,10 @@ case "$XX_VENDOR" in *) vendor="-${XX_VENDOR}" ;; esac +if [ -n "$XX_RUSTUP" ] && [ "$TARGETOS" = "wasi" ]; then + vendor="" +fi + if [ -z "$XX_LIBC" ]; then if [ "$distro" = "alpine" ]; then XX_LIBC="musl" @@ -139,6 +145,9 @@ if [ -z "$XX_LIBC" ]; then if [ "$TARGETOS" = "windows" ]; then XX_LIBC="mingw32" fi + if [ "$TARGETOS" = "wasi" ]; then + XX_LIBC="" + fi fi # reverse lookup if no parameters given @@ -208,6 +217,11 @@ if [ "$TARGETOS" = "darwin" ] && [ -z "$MACOSX_VERSION_MIN" ]; then fi fi +# normalize wasm because early implementation didn't have strict convention +if [ "$TARGETARCH" = "wasm32" ]; then + TARGETARCH="wasm" +fi + case "$TARGETARCH" in "amd64") XX_MARCH="x86_64" @@ -337,6 +351,26 @@ case "$TARGETARCH" in XX_RHEL_ARCH="mips64el" XX_TRIPLE="mips64el${vendor}-linux-${XX_LIBC}abi64" ;; + "wasm") + XX_MARCH="wasm32" + XX_DEBIAN_ARCH="wasm32" + XX_ALPINE_ARCH="wasm32" + XX_RHEL_ARCH="wasm32" + XX_TRIPLE="wasm32${vendor}-unknown" + if [ "$TARGETOS" = "wasi" ]; then + XX_TRIPLE="wasm32${vendor}-wasi" + fi + ;; + "wasm64") + XX_MARCH="wasm64" + XX_DEBIAN_ARCH="wasm64" + XX_ALPINE_ARCH="wasm64" + XX_RHEL_ARCH="wasm64" + XX_TRIPLE="wasm64${vendor}-unknown" + if [ "$TARGETOS" = "wasi" ]; then + XX_TRIPLE="wasm64${vendor}-wasi" + fi + ;; esac XX_PKG_ARCH=$TARGETARCH @@ -395,7 +429,7 @@ case "$1" in echo "$XX_VENDOR" ;; "libc") # this is not abi, just the prefix - echo $XX_LIBC + echo "$XX_LIBC" ;; "env") echo "XX_OS=${TARGETOS}" diff --git a/base/xx-verify b/base/xx-verify index a88b443..fe050a4 100755 --- a/base/xx-verify +++ b/base/xx-verify @@ -112,6 +112,9 @@ for f in "$@"; do "windows") expOS="MS Windows" ;; + "wasi") + expOS="WebAssembly" + ;; esac if [ -z "$expOS" ]; then @@ -226,6 +229,9 @@ for f in "$@"; do expArch2="32-bit LSB" fi ;; + "wasm" | "wasm64") + expArch="WebAssembly" + ;; esac if [ -z "$expArch" ]; then