diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a425a7..ea3891b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,8 @@ env: GITHUB_REF: '${{ github.ref }}' WINDOWS_TARGET: x86_64-pc-windows-msvc MACOS_TARGET: x86_64-apple-darwin - LINUX_TARGET: x86_64-unknown-linux-musl + LINUX_AMD64_TARGET: x86_64-unknown-linux-musl + LINUX_ARM64_TARGET: aarch64-unknown-linux-musl # Space separated paths to include in the archive. RELEASE_ADDS: README.md LICENSE-APACHE LICENSE-MIT @@ -22,15 +23,17 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - build: [linux, macos, windows] include: - - build: linux + - target: x86_64-unknown-linux-musl os: ubuntu-latest rust: stable - - build: macos + - target: aarch64-unknown-linux-musl + os: ubuntu-latest + rust: stable + - target: x86_64-apple-darwin os: macos-latest rust: stable - - build: windows + - target: x86_64-pc-windows-msvc os: windows-latest rust: stable @@ -49,67 +52,56 @@ jobs: echo "using version tag ${GITHUB_REF:10}" echo ::set-output name=version::"${GITHUB_REF:10}" - - name: Install musl-tools (Linux) - if: matrix.build == 'linux' + - name: Install C compilation tooling (Linux) + if: matrix.os == 'ubuntu-latest' run: | sudo apt-get update -y - sudo apt-get install musl-tools -y + sudo apt-get install clang gcc-aarch64-linux-gnu -y + echo "TARGET_CC=clang" >> $GITHUB_ENV + echo "CFLAGS_aarch64_unknown_linux_musl=--sysroot=/usr/aarch64-linux-gnu" >> $GITHUB_ENV + echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=/usr/aarch64-linux-gnu/bin/ld" >> $GITHUB_ENV - name: Install p7zip (MacOS) - if: matrix.build == 'macos' + if: matrix.os == 'macos-latest' run: brew install p7zip - - name: Build (Linux) - if: matrix.build == 'linux' - run: | - rustup target add ${{ env.LINUX_TARGET }} - cargo build --release --target ${{ env.LINUX_TARGET }} + - name: Add rustup target + run: rustup target add ${{ matrix.target }} - - name: Build (MacOS) - if: matrix.build == 'macos' - run: cargo build --release + - name: Build + run: cargo build --release --target ${{ matrix.target }} - - name: Build (Windows) - if: matrix.build == 'windows' - run: cargo build --release - env: - RUSTFLAGS: -Ctarget-feature=+crt-static + - name: Set RUSTFLAGS (Windows) + if: matrix.os == 'windows-latest' + run: echo "RUSTFLAGS=-Ctarget-feature=+crt-static" >> $GITHUB_ENV - name: Create artifact directory run: | mkdir ${{ env.RELEASE_DIR }} - mkdir -p ${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_TARGET }} - mkdir -p ${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.MACOS_TARGET }} - mkdir -p ${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.WINDOWS_TARGET }} + mkdir -p ${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ matrix.target }} - - name: Create tarball (Linux) - if: matrix.build == 'linux' + - name: Move binaries (Linux/MacOS) + if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' run: | - mv ./target/${{ env.LINUX_TARGET }}/release/${{ env.RELEASE_BIN }} ${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_TARGET }}/${{ env.RELEASE_BIN }} - mv ${{ env.RELEASE_ADDS }} ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_TARGET }} - 7z a -ttar -so -an ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_TARGET }} | 7z a -si ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_TARGET }}.tar.gz + mv ./target/${{ matrix.target }}/release/${{ env.RELEASE_BIN }} ${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ matrix.target }}/${{ env.RELEASE_BIN }} + mv ${{ env.RELEASE_ADDS }} ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ matrix.target }} - - name: Create tarball (Windows) - if: matrix.build == 'windows' + - name: Move binaries (Windows) + if: matrix.os == 'windows-latest' shell: bash run: | - cp ./target/release/${{ env.RELEASE_BIN }}.exe ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.WINDOWS_TARGET }}/${{ env.RELEASE_BIN }}.exe - cp ./target/release/${{ env.RELEASE_BIN }}.exe wasm-pack-init.exe - mv ${{ env.RELEASE_ADDS }} ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.WINDOWS_TARGET }} + cp ./target/${{ matrix.target }}/release/${{ env.RELEASE_BIN }}.exe ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ matrix.target }}/${{ env.RELEASE_BIN }}.exe + cp ./target/${{ matrix.target }}/release/${{ env.RELEASE_BIN }}.exe wasm-pack-init.exe + mv ${{ env.RELEASE_ADDS }} ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ matrix.target }} mv wasm-pack-init.exe ${{ env.RELEASE_DIR }} - 7z a -ttar -so -an ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.WINDOWS_TARGET }} | 7z a -si ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.WINDOWS_TARGET }}.tar.gz - - name: Create tarball (MacOS) - if: matrix.build == 'macos' - run: | - mv ./target/release/${{ env.RELEASE_BIN }} ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.MACOS_TARGET }}/${{ env.RELEASE_BIN }} - mv ${{ env.RELEASE_ADDS }} ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.MACOS_TARGET }} - 7z a -ttar -so -an ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.MACOS_TARGET }} | 7z a -si ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ env.MACOS_TARGET }}.tar.gz + - name: Create tarball + run: 7z a -ttar -so -an ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ matrix.target }} | 7z a -si ./${{ env.RELEASE_DIR }}/${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-${{ matrix.target }}.tar.gz - name: Upload Zip uses: actions/upload-artifact@v1 with: - name: ${{ matrix.build }} + name: ${{ matrix.target }} path: ./${{ env.RELEASE_DIR }} release: @@ -133,30 +125,45 @@ jobs: tag_name: ${{ steps.get_version.outputs.VERSION }} release_name: ${{ steps.get_version.outputs.VERSION }} - - name: Download Linux tarball - uses: actions/download-artifact@v1 + - name: Download Linux amd64 tarball + uses: actions/download-artifact@v2 + with: + name: ${{ env.LINUX_AMD64_TARGET }} + + - name: Download Linux arm64 tarball + uses: actions/download-artifact@v2 with: - name: linux + name: ${{ env.LINUX_ARM64_TARGET }} - name: Download Windows tarball - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: - name: windows + name: ${{ env.WINDOWS_TARGET }} - name: Download MacOS tarball - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: - name: macos + name: ${{ env.MACOS_TARGET }} + + - name: Release Linux amd64 tarball + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_AMD64_TARGET }}.tar.gz + asset_content_type: application/gzip + asset_name: wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_AMD64_TARGET }}.tar.gz - - name: Release Linux tarball + - name: Release Linux arm64 tarball uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./linux/wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_TARGET }}.tar.gz + asset_path: ./wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_ARM64_TARGET }}.tar.gz asset_content_type: application/gzip - asset_name: wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_TARGET }}.tar.gz + asset_name: wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.LINUX_ARM64_TARGET }}.tar.gz - name: Release Windows tarball uses: actions/upload-release-asset@v1 @@ -164,7 +171,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./windows/wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.WINDOWS_TARGET }}.tar.gz + asset_path: ./wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.WINDOWS_TARGET }}.tar.gz asset_content_type: application/gzip asset_name: wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.WINDOWS_TARGET }}.tar.gz @@ -174,7 +181,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./windows/wasm-pack-init.exe + asset_path: ./wasm-pack-init.exe asset_content_type: application/vnd.microsoft.portable-executable asset_name: wasm-pack-init.exe @@ -184,6 +191,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./macos/wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.MACOS_TARGET }}.tar.gz + asset_path: ./wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.MACOS_TARGET }}.tar.gz asset_content_type: application/gzip asset_name: wasm-pack-${{ steps.get_version.outputs.VERSION }}-${{ env.MACOS_TARGET }}.tar.gz diff --git a/src/command/utils.rs b/src/command/utils.rs index 4a735e2..7c6ec0c 100644 --- a/src/command/utils.rs +++ b/src/command/utils.rs @@ -37,6 +37,7 @@ fn find_manifest_from_cwd() -> Result { /// Construct our `pkg` directory in the crate. pub fn create_pkg_dir(out_dir: &Path) -> Result<(), failure::Error> { + let _ = fs::remove_dir_all(&out_dir); // Clean up any existing directory and ignore errors fs::create_dir_all(&out_dir)?; fs::write(out_dir.join(".gitignore"), "*")?; Ok(()) diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index 3bd9249..7682b42 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -8,8 +8,8 @@ mod npm; -use std::fs; use std::path::Path; +use std::{collections::HashMap, fs}; use self::npm::{ repository::Repository, CommonJSPackage, ESModulesPackage, NoModulesPackage, NpmPackage, @@ -575,14 +575,25 @@ impl CrateData { target: Target, ) -> Result<(), Error> { let pkg_file_path = out_dir.join("package.json"); + // Check if a `package.json` was already generated by wasm-bindgen, if so + // we merge the NPM dependencies already specified in it. + let existing_deps = if pkg_file_path.exists() { + // It's just a map of dependency names to versions + Some(serde_json::from_str::>( + &fs::read_to_string(&pkg_file_path)?, + )?) + } else { + None + }; let npm_data = match target { - Target::Nodejs => self.to_commonjs(scope, disable_dts, out_dir), - Target::NoModules => self.to_nomodules(scope, disable_dts, out_dir), - Target::Bundler => self.to_esmodules(scope, disable_dts, out_dir), - Target::Web => self.to_web(scope, disable_dts, out_dir), + Target::Nodejs => self.to_commonjs(scope, disable_dts, existing_deps, out_dir), + Target::NoModules => self.to_nomodules(scope, disable_dts, existing_deps, out_dir), + Target::Bundler => self.to_esmodules(scope, disable_dts, existing_deps, out_dir), + Target::Web => self.to_web(scope, disable_dts, existing_deps, out_dir), }; let npm_json = serde_json::to_string_pretty(&npm_data)?; + fs::write(&pkg_file_path, npm_json) .with_context(|_| format!("failed to write: {}", pkg_file_path.display()))?; Ok(()) @@ -657,7 +668,13 @@ impl CrateData { }) } - fn to_commonjs(&self, scope: &Option, disable_dts: bool, out_dir: &Path) -> NpmPackage { + fn to_commonjs( + &self, + scope: &Option, + disable_dts: bool, + dependencies: Option>, + out_dir: &Path, + ) -> NpmPackage { let data = self.npm_data(scope, false, disable_dts, out_dir); let pkg = &self.data.packages[self.current_idx]; @@ -683,6 +700,7 @@ impl CrateData { homepage: data.homepage, types: data.dts_file, keywords: data.keywords, + dependencies, }) } @@ -690,6 +708,7 @@ impl CrateData { &self, scope: &Option, disable_dts: bool, + dependencies: Option>, out_dir: &Path, ) -> NpmPackage { let data = self.npm_data(scope, true, disable_dts, out_dir); @@ -719,10 +738,17 @@ impl CrateData { types: data.dts_file, side_effects: false, keywords: data.keywords, + dependencies, }) } - fn to_web(&self, scope: &Option, disable_dts: bool, out_dir: &Path) -> NpmPackage { + fn to_web( + &self, + scope: &Option, + disable_dts: bool, + dependencies: Option>, + out_dir: &Path, + ) -> NpmPackage { let data = self.npm_data(scope, false, disable_dts, out_dir); let pkg = &self.data.packages[self.current_idx]; @@ -750,6 +776,7 @@ impl CrateData { types: data.dts_file, side_effects: false, keywords: data.keywords, + dependencies, }) } @@ -757,6 +784,7 @@ impl CrateData { &self, scope: &Option, disable_dts: bool, + dependencies: Option>, out_dir: &Path, ) -> NpmPackage { let data = self.npm_data(scope, false, disable_dts, out_dir); @@ -784,6 +812,7 @@ impl CrateData { homepage: data.homepage, types: data.dts_file, keywords: data.keywords, + dependencies, }) } diff --git a/src/manifest/npm/commonjs.rs b/src/manifest/npm/commonjs.rs index e421c9c..eaf681d 100644 --- a/src/manifest/npm/commonjs.rs +++ b/src/manifest/npm/commonjs.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use manifest::npm::repository::Repository; #[derive(Serialize)] @@ -21,4 +23,6 @@ pub struct CommonJSPackage { pub types: Option, #[serde(skip_serializing_if = "Option::is_none")] pub keywords: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub dependencies: Option>, } diff --git a/src/manifest/npm/esmodules.rs b/src/manifest/npm/esmodules.rs index 68d2174..837f07e 100644 --- a/src/manifest/npm/esmodules.rs +++ b/src/manifest/npm/esmodules.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use manifest::npm::repository::Repository; #[derive(Serialize)] @@ -25,4 +27,6 @@ pub struct ESModulesPackage { pub side_effects: bool, #[serde(skip_serializing_if = "Option::is_none")] pub keywords: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub dependencies: Option>, } diff --git a/src/manifest/npm/nomodules.rs b/src/manifest/npm/nomodules.rs index 6ac2508..20567cc 100644 --- a/src/manifest/npm/nomodules.rs +++ b/src/manifest/npm/nomodules.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use manifest::npm::repository::Repository; #[derive(Serialize)] @@ -21,4 +23,6 @@ pub struct NoModulesPackage { pub types: Option, #[serde(skip_serializing_if = "Option::is_none")] pub keywords: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub dependencies: Option>, } diff --git a/tests/all/manifest.rs b/tests/all/manifest.rs index f7cf57a..78fdc6a 100644 --- a/tests/all/manifest.rs +++ b/tests/all/manifest.rs @@ -1,5 +1,5 @@ use assert_cmd::prelude::*; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::fs; use std::path::PathBuf; use utils::{self, fixture}; @@ -319,6 +319,54 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() { assert_eq!(actual_files, expected_files); } +#[test] +fn it_creates_a_package_json_with_npm_dependencies_provided_by_wasm_bindgen() { + let fixture = fixture::js_hello_world(); + let out_dir = fixture.path.join("pkg"); + let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); + // Write a `package.json` in the out_dir, as wasm-bindgen does: + utils::manifest::create_wbg_package_json( + &out_dir, + r#" + { "foo": "^1.2.3" } + "#, + ) + .unwrap(); + assert!(crate_data + .write_package_json(&out_dir, &None, true, Target::Bundler) + .is_ok()); + let package_json_path = &out_dir.join("package.json"); + fs::metadata(package_json_path).unwrap(); + utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); + let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); + assert_eq!(pkg.name, "js-hello-world"); + assert_eq!(pkg.repository.ty, "git"); + assert_eq!( + pkg.repository.url, + "https://github.com/rustwasm/wasm-pack.git" + ); + assert_eq!(pkg.module, "js_hello_world.js"); + + let actual_files: HashSet = pkg.files.into_iter().collect(); + let expected_files: HashSet = [ + "js_hello_world_bg.wasm", + "js_hello_world_bg.js", + "js_hello_world.js", + ] + .iter() + .map(|&s| String::from(s)) + .collect(); + assert_eq!(actual_files, expected_files); + + let dependencies: Option> = pkg.dependencies; + assert!(dependencies.is_some()); + let mut expected_dependencies: HashMap = HashMap::new(); + expected_dependencies.insert("foo".to_owned(), "^1.2.3".to_owned()); + + assert_eq!(dependencies.unwrap(), expected_dependencies); +} + #[test] fn it_errors_when_wasm_bindgen_is_not_declared() { let fixture = fixture::bad_cargo_toml(); diff --git a/tests/all/utils/manifest.rs b/tests/all/utils/manifest.rs index da5d2ea..4b911ba 100644 --- a/tests/all/utils/manifest.rs +++ b/tests/all/utils/manifest.rs @@ -1,6 +1,6 @@ -use std::fs::File; use std::io::prelude::*; use std::path::Path; +use std::{collections::HashMap, fs::File}; use failure::Error; use serde_json; @@ -27,6 +27,7 @@ pub struct NpmPackage { pub side_effects: bool, pub homepage: Option, pub keywords: Option>, + pub dependencies: Option>, } fn default_none() -> String { @@ -52,3 +53,8 @@ pub fn read_package_json(path: &Path, out_dir: &Path) -> Result Result<(), Error> { + let manifest_path = out_dir.join("package.json"); + Ok(std::fs::write(manifest_path, contents)?) +}