diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f242f10d971..660cd7e4888 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,15 +18,7 @@ jobs: uses: google-github-actions/release-please-action@v3 with: token: ${{ secrets.NOIR_RELEASES_TOKEN }} - release-type: simple - package-name: noir - bump-minor-pre-major: true - bump-patch-for-minor-pre-major: true - prerelease: true # Marks GitHub Releases for 0.x.x versions as "Pre-release" - pull-request-title-pattern: "chore(noir): Release ${version}" - extra-files: | - Cargo.toml - flake.nix + command: manifest update-lockfile: name: Update lockfile diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 938fa0aa181..6c62e4b5d13 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -2,7 +2,6 @@ name: Wasm on: [push, pull_request] -# This will cancel previous runs when a branch or PR is updated concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} cancel-in-progress: true @@ -11,19 +10,16 @@ jobs: build: name: Build Wasm runs-on: ubuntu-latest - steps: - name: Checkout sources uses: actions/checkout@v3 - - name: Setup rust toolchain - uses: dtolnay/rust-toolchain@master + - name: Setup Nix + uses: cachix/install-nix-action@v20 with: - toolchain: 1.66.0 - - - name: Install wasm-pack - run: cargo install wasm-pack + nix_path: nixpkgs=channel:nixos-22.11 + github_access_token: ${{ secrets.GITHUB_TOKEN }} - - name: Build wasm crate - working-directory: ./crates/wasm - run: ./build-wasm + - name: Build wasm package + run: | + nix build -L .#wasm diff --git a/.gitignore b/.gitignore index 351f5e16a7f..9684106d30c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ node_modules pkg/ # Nix stuff +**/outputs result .envrc.local .direnv/ diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000000..21b27ccaacf --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,4 @@ +{ + ".": "0.6.0", + "crates/wasm": "0.6.0" +} diff --git a/crates/wasm/Cargo.toml b/crates/wasm/Cargo.toml index 7660f67bd57..5c139d96164 100644 --- a/crates/wasm/Cargo.toml +++ b/crates/wasm/Cargo.toml @@ -27,4 +27,4 @@ gloo-utils = { version = "0.1", features = ["serde"] } getrandom = { version = "*", features = ["js"] } [build-dependencies] -build-data = "0.1.3" +build-data = "0.1.3" \ No newline at end of file diff --git a/crates/wasm/README.md b/crates/wasm/README.md index 55c5cc4fb19..7f36b4d9eb4 100644 --- a/crates/wasm/README.md +++ b/crates/wasm/README.md @@ -4,15 +4,10 @@ In order to build the wasm package, the following must be installed: -- [wasm-pack](https://github.com/rustwasm/wasm-pack) -- [jq](https://github.com/stedolan/jq) - ## Build The wasm package can be built using the command below: ```bash -./build-wasm +nix build -L #wasm ``` - -Using `wasm-pack` directly isn't recommended as it doesn't generate a complete `package.json` file, resulting in files being omitted from the published package. diff --git a/crates/wasm/build-wasm b/crates/wasm/build-wasm deleted file mode 100755 index 6b574b71d03..00000000000 --- a/crates/wasm/build-wasm +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash - -# Clear out the existing build artifacts as these aren't automatically removed by wasm-pack. -if [ -d ./pkg/ ]; then - rm -rf ./pkg/ -fi - -# Build the new wasm package -wasm-pack build --scope noir-lang --target nodejs --out-dir pkg/nodejs - -wasm-pack build --scope noir-lang --target web --out-dir pkg/web - -COMMIT_SHORT=$(git rev-parse --short HEAD) -VERSION_APPENDIX="" -if [ -n "$COMMIT_SHORT" ]; then - VERSION_APPENDIX="-$COMMIT_SHORT" -else - VERSION_APPENDIX="-NOGIT" -fi - -jq -s '.[0] * .[1]' pkg/nodejs/package.json pkg/web/package.json | jq '.files = ["nodejs", "web", "package.json"]' | jq ".version += \"$VERSION_APPENDIX\"" | jq '.main = "./nodejs/" + .main | .module = "./web/" + .module | .types = "./web/" + .types | .peerDependencies = { "@noir-lang/noir-source-resolver": "1.1.2" }' | tee ./pkg/package.json - -rm pkg/nodejs/package.json pkg/nodejs/README.md pkg/nodejs/.gitignore - -rm pkg/web/package.json pkg/web/README.md pkg/web/.gitignore \ No newline at end of file diff --git a/crates/wasm/build.sh b/crates/wasm/build.sh new file mode 100755 index 00000000000..900c1868c08 --- /dev/null +++ b/crates/wasm/build.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +function require_command { + if ! command -v "$1" >/dev/null 2>&1; then + echo "Error: $1 is required but not installed." >&2 + exit 1 + fi +} + +require_command toml2json +require_command jq +require_command cargo +require_command wasm-bindgen +require_command wasm-opt + +export pname=$(toml2json < Cargo.toml | jq -r .package.name) + +./preBuild.sh +cargo build --lib --release --package noir_wasm --target wasm32-unknown-unknown +./postBuild.sh +./installPhase.sh + diff --git a/crates/wasm/installPhase.sh b/crates/wasm/installPhase.sh new file mode 100755 index 00000000000..598425b589a --- /dev/null +++ b/crates/wasm/installPhase.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +mkdir -p $out +cp README.md $out/ +cp ./crates/wasm/package.json $out/ +cp -r ./pkg/* $out/ \ No newline at end of file diff --git a/crates/wasm/package.json b/crates/wasm/package.json new file mode 100644 index 00000000000..92ac0c5b153 --- /dev/null +++ b/crates/wasm/package.json @@ -0,0 +1,23 @@ +{ + "name": "@noir-lang/noir_wasm", + "collaborators": [ + "The Noir Team " + ], + "version": "0.6.0", + "files": [ + "nodejs", + "web", + "package.json" + ], + "main": "./nodejs/noir_wasm.js", + "types": "./web/noir_wasm.d.ts", + "module": "./web/noir_wasm.js", + "sideEffects": false, + "peerDependencies": { + "@noir-lang/noir-source-resolver": "1.1.2" + }, + "repository": { + "type": "git", + "url": "https://github.com/noir-lang/noir_wasm.git" + } +} diff --git a/crates/wasm/postBuild.sh b/crates/wasm/postBuild.sh new file mode 100755 index 00000000000..1b01901adbe --- /dev/null +++ b/crates/wasm/postBuild.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# TODO: Handle the wasm target being built in release mode +WASM_BINARY=./target/wasm32-unknown-unknown/release/${pname}.wasm +NODE_WASM=./pkg/nodejs/${pname}_bg.wasm +BROWSER_WASM=./pkg/web/${pname}_bg.wasm + +wasm-bindgen $WASM_BINARY --out-dir ./pkg/nodejs --typescript --target nodejs +wasm-bindgen $WASM_BINARY --out-dir ./pkg/web --typescript --target web +wasm-opt $NODE_WASM -o $NODE_WASM -O +wasm-opt $BROWSER_WASM -o $BROWSER_WASM -O diff --git a/crates/wasm/preBuild.sh b/crates/wasm/preBuild.sh new file mode 100644 index 00000000000..aa334e022c6 --- /dev/null +++ b/crates/wasm/preBuild.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Clear out the existing build artifacts as these aren't automatically removed by wasm-pack. +if [ -d ./pkg/ ]; then + rm -rf ./pkg/ +fi \ No newline at end of file diff --git a/crates/wasm/wasm.nix b/crates/wasm/wasm.nix deleted file mode 100644 index 332db3de0cc..00000000000 --- a/crates/wasm/wasm.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ nixpkgs ? import {} }: - -let - rustOverlay = builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz"; - llvm11stdenv = pkgs.llvmPackages_10.stdenv; - - # NixOS 22.05 - pinnedPkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/0938d73bb143f4ae037143572f11f4338c7b2d1c.tar.gz"; - - - pkgs = import pinnedPkgs { - overlays = [ (import rustOverlay) ]; - }; - - rustbin = pkgs.rust-bin.stable.latest.default.override { - extensions = [ "rust-src" ]; - targets = [ "wasm32-unknown-unknown" ]; - }; -in -pkgs.mkShell.override { stdenv = llvm11stdenv;} { - - nativeBuildInputs = with pkgs; [ - binaryen - jq - ]; - - buildInputs = with pkgs; [ - pkg-config - rustbin - wasm-pack - ]; - -} \ No newline at end of file diff --git a/flake.nix b/flake.nix index c02dbe14542..b62e415e62f 100644 --- a/flake.nix +++ b/flake.nix @@ -64,6 +64,11 @@ # We include rust-src to ensure rust-analyzer works. # See https://discourse.nixos.org/t/rust-src-not-found-and-other-misadventures-of-developing-rust-on-nixos/11570/4 extensions = [ "rust-src" ]; + targets = [ "wasm32-unknown-unknown" ] + ++ pkgs.lib.optional (pkgs.hostPlatform.isx86_64 && pkgs.hostPlatform.isLinux) "x86_64-unknown-linux-gnu" + ++ pkgs.lib.optional (pkgs.hostPlatform.isAarch64 && pkgs.hostPlatform.isLinux) "aarch64-unknown-linux-gnu" + ++ pkgs.lib.optional (pkgs.hostPlatform.isx86_64 && pkgs.hostPlatform.isDarwin) "x86_64-apple-darwin" + ++ pkgs.lib.optional (pkgs.hostPlatform.isAarch64 && pkgs.hostPlatform.isDarwin) "aarch64-apple-darwin"; }; craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain; @@ -164,6 +169,19 @@ buildInputs = [ ] ++ extraBuildInputs; }; + # Combine the environmnet with cargo args needed to build wasm package + noirWasmArgs = wasmEnvironment // { + pname = "noir_wasm"; + + src = ./.; + + cargoExtraArgs = "--package noir_wasm --target wasm32-unknown-unknown"; + + buildInputs = [ ] ++ extraBuildInputs; + + doCheck = false; + }; + # The `port` is parameterized to support parallel test runs without colliding static servers testArgs = port: testEnvironment // { # We provide `barretenberg-transcript00` from the overlay to the tests as a URL hosted via a static server @@ -192,6 +210,7 @@ # Build *just* the cargo dependencies, so we can reuse all of that work between runs native-cargo-artifacts = craneLib.buildDepsOnly nativeArgs; wasm-cargo-artifacts = craneLib.buildDepsOnly wasmArgs; + noir-wasm-cargo-artifacts = craneLib.buildDepsOnly noirWasmArgs; noir-native = craneLib.buildPackage (nativeArgs // { inherit GIT_COMMIT GIT_DIRTY; @@ -210,6 +229,13 @@ # We don't want to run checks or tests when just building the project doCheck = false; }); + + wasm-bindgen-cli = pkgs.callPackage ./wasm-bindgen-cli.nix { + rustPlatform = pkgs.makeRustPlatform { + rustc = rustToolchain; + cargo = rustToolchain; + }; + }; in rec { checks = { @@ -252,12 +278,49 @@ git nil nixpkgs-fmt + toml2json llvmPackages.lldb # This ensures the right lldb is in the environment for running rust-lldb + wasm-bindgen-cli ]; shellHook = '' eval "$(starship init bash)" ''; }); + + # TODO: This fails with a "section too large" error on MacOS so we should limit to linux targets + # or fix the failure + packages.wasm = craneLib.buildPackage (noirWasmArgs // { + + inherit GIT_COMMIT; + inherit GIT_DIRTY; + doCheck = false; + + cargoArtifacts = noir-wasm-cargo-artifacts; + + COMMIT_SHORT = builtins.substring 0 7 GIT_COMMIT; + VERSION_APPENDIX = if GIT_DIRTY == "true" then "-dirty" else ""; + PKG_PATH = "./pkg"; + + nativeBuildInputs = with pkgs; [ + which + git + jq + rustToolchain + wasm-bindgen-cli + binaryen + toml2json + ]; + + postBuild = '' + bash crates/wasm/postBuild.sh + ''; + + installPhase = '' + bash crates/wasm/installPhase.sh + ''; + + }); }); } + diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000000..e9219dcfe44 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,26 @@ +{ + "bootstrap-sha": "63d84a30fcbc117443cd3b404e872cb3c2f26111", + "release-type": "simple", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "prerelease": true, + "group-pull-request-title-pattern": "chore(noir): Release ${version}", + "packages": { + ".": { + "release-type": "simple", + "component": "root", + "extra-files": ["Cargo.toml", "flake.nix"] + }, + "crates/wasm": { + "release-type": "node", + "component": "noir_wasm" + } + }, + "plugins": [ + { + "type": "linked-versions", + "groupName": "noir", + "components": ["root", "noir_wasm"] + } + ] +} diff --git a/wasm-bindgen-cli.nix b/wasm-bindgen-cli.nix new file mode 100644 index 00000000000..38b7b0a79c1 --- /dev/null +++ b/wasm-bindgen-cli.nix @@ -0,0 +1,37 @@ +{ lib +, rustPlatform +, fetchCrate +, nodejs +, pkg-config +, openssl +, stdenv +, curl +, darwin +, runCommand +}: + +rustPlatform.buildRustPackage rec { + pname = "wasm-bindgen-cli"; + version = "0.2.86"; + + src = fetchCrate { + inherit pname version; + sha256 = "sha256-56EOiLbdgAcoTrkyvB3t9TjtLaRvGxFUXx4haLwE2QY="; + }; + + cargoSha256 = "sha256-4CPBmz92PuPN6KeGDTdYPAf5+vTFk9EN5Cmx4QJy6yI="; + + nativeBuildInputs = [ pkg-config ]; + + buildInputs = [ openssl ] ++ lib.optionals stdenv.isDarwin [ curl darwin.apple_sdk.frameworks.Security ]; + + doCheck = false; + + meta = with lib; { + homepage = "https://rustwasm.github.io/docs/wasm-bindgen/"; + license = with licenses; [ asl20 /* or */ mit ]; + description = "Facilitating high-level interactions between wasm modules and JavaScript"; + maintainers = with maintainers; [ nitsky rizary ]; + mainProgram = "wasm-bindgen"; + }; +} \ No newline at end of file