Skip to content

Add a prebuilt version for Apple Silicon (M1) #4334

Closed

Description

@d3lm

wasm-pack uses wasm-opt and it tries to download the binary for it when it gets executed. However, if you run this on an M1 it gives the following error:

Error: no prebuilt wasm-opt binaries are available for this platform: Unrecognized target!

It would be great if there was a prebuilt version for ARM so wasm-opt runs out of the box on an M1 Mac.

Activity

  1. kripken commented on Nov 17, 2021

    @kripken
    Member

    cc @sbc100

  2. sbc100 commented on Nov 17, 2021

    @sbc100
    Member

    @alexcrichton is this something wasm-pack can do or should we try to do it here in the binaryen CI? Do you want to have go at this?

    Even if we don't build an arm binary wasm-pack should be able to download and use the x86 version right? That might be the quickest way to get things working.

  3. alexcrichton commented on Nov 18, 2021

    @alexcrichton
    Contributor

    Ah I don't work on wasm-pack any more, so I don't know where this would best be done.

  4. sbc100 commented on Nov 18, 2021

    @sbc100
    Member

    @d3lm can you open a bug on wasm-pack and suggest they just the x86-64 binary when running on arm? (for now).

  5. d3lm commented on Nov 19, 2021

    @d3lm
    Author

    @sbc100 Yep I can do that. Thanks.

  6. d3lm commented on Nov 19, 2021

    @d3lm
    Author

    But just to understand, the x86-64 does not work out of the box on arm right? You'd have to run this via rosetta no?

  7. sbc100 commented on Nov 19, 2021

    @sbc100
    Member

    My understanding is the M1 macs do support running x86-64 out of the box (i.e. they ship with whatever tooling they need to make this work).

  8. sbc100 commented on Nov 19, 2021

    @sbc100
    Member

    My understanding is that x86-64 binaries can be executed transparently without any special commands and launch sequences.

  9. d3lm commented on Nov 19, 2021

    @d3lm
    Author

    Ah ok, and wasm-pack doesn't have a prebuilt x86-64?

  10. sbc100 commented on Nov 19, 2021

    @sbc100
    Member

    Binaryen does provide and x86-64 prebuilt of wasm-opt. I'm suggesting the wasm-opt look for this binary rather than the aarch64 (arm64) version (which doesn't not exist).

  11. d3lm commented on Nov 20, 2021

    @d3lm
    Author

    Aha! Got it. Thanks a lot.

  12. d3lm commented on Dec 3, 2021

    @d3lm
    Author

    Ok, after some discussion I still think it would be best to have a osx_aarch64 release of binaryen because wasm-pack simply downloads it like this

    Tool::WasmOpt => {
      Ok(format!(
        "https://github.com/WebAssembly/binaryen/releases/download/{vers}/binaryen-{vers}-{target}.tar.gz",
         vers = "version_90",
         target = target,
       ))
    }

    Why can't we add a build for macos-12 too? It's quite common and I think it would be right to ship a release for it as part of binaryen.

  13. sbc100 commented on Dec 3, 2021

    @sbc100
    Member

    So the binaryen filenames are of the form binaryen-version_100-x86_64-macos.tar.gz so why can't wasm-pack simply do if (target == aarch64-macos) target = x86_64-macos right before trying to download?

    Of course, if you want to get the last bit of performance benefit from having a native arm64 build, and you would like to contribute the github action recipe for building it that would be most welcome. But I don't see why you can't use the x86_64 version for now.

    As for targeting a certain/newer macos version, what would be point of that? I don't know of any benefit of targeting a more recent version, but maybe I'm missing something? I think we we want to be as compatible as can with all versions (within reason) which means setting a low minimum version when build, right?

  14. d3lm commented on Dec 3, 2021

    @d3lm
    Author

    Because that requires rosetta and it'd be great if we could avoid rosetta and have a native arm64 build. Or am I wrong?

  15. d3lm commented on Dec 3, 2021

    @d3lm
    Author

    I see if I can contribute and submit an action for building it for arm64.

  16. d3lm commented on Dec 3, 2021

    @d3lm
    Author

    I actually think that building for Apple Sillicon in a GitHub action is not really possible right now, because there's no environment that runs an M1. Tho, you could pass -DCMAKE_OSX_ARCHITECTURES=arm64 to cmake, but I am not sure if that would be enough. Do you have any experience with this?

  17. sbc100 commented on Dec 3, 2021

    @sbc100
    Member

    Because that requires rosetta and it'd be great if we could avoid rosetta and have a native arm64 build. Or am I wrong?

    Why is avoiding rosetta an important goal here? Don't all M1 macs ship with rosetta builtin? I get that it would be nice to have.. but it doesn't seem particularly urgent or important?

    Do you have an M1 mac that doesn't have rosetta installed?

    Or are you worried about that overhead of running wasm-opt in emulation mode? (is your wasm-opt phase very slow?)

  18. sbc100 commented on Dec 3, 2021

    @sbc100
    Member

    Yes, if we wanted to have github build these binaries I imagine it would be cross compile.. i.e. produce an arm64 build on x86_64 hardware.

  19. d3lm commented on Dec 3, 2021

    @d3lm
    Author

    Don't all M1 macs ship with rosetta builtin?

    I think so yes.

    Do you have an M1 mac that doesn't have rosetta installed?

    No, because I think it's installed by default.

    Or are you worried about that overhead of running wasm-opt in emulation mode?

    Yes, but that may be unjustified worries, because I have not yet seen any performance issues.

    For the time being, I submitted a PR to wasm-pack wasm-bindgen/wasm-pack#1088 that downloads the x86_64 build for aarch64. If issues pop up we can re-evaluate or try to set up a native arm64 build on x86_64 hardware.

  20. sbc100 commented on Dec 3, 2021

    @sbc100
    Member

    Great! That sounds a good place to be for now.

  21. kripken commented on Dec 3, 2021

    @kripken
    Member

    Another option here is to make a wasm build of wasm-opt. With node-pthreads support + exceptions support that should run pretty fast in recent node. Not as fast as a native M1 build I'm sure, but it might be faster than an x86_64 build emulated on M1... which makes this potentially interesting.

  22. d3lm commented on Dec 3, 2021

    @d3lm
    Author

    @kripken I actually had the same idea! That would work too which would eliminate the interoperability issues across different systems.

  23. kripken commented on Dec 7, 2021

    @kripken
    Member

    I did a little testing of that now using this diff:

    diff --git a/CMakeLists.txt b/CMakeLists.txt
    index e540b1f57..0dc9c204b 100644
    --- a/CMakeLists.txt
    +++ b/CMakeLists.txt
    @@ -265,26 +265,32 @@ else()
         add_nondebug_compile_flag("-UNDEBUG")
       endif()
     endif()
     
     if(EMSCRIPTEN)
       # link with -O3 for metadce and other powerful optimizations. note that we
       # must use add_link_options so that this appears after CMake's default -O2
       add_link_options("-O3")
       add_link_flag("-s SINGLE_FILE")
       add_link_flag("-s ALLOW_MEMORY_GROWTH=1")
    -  add_compile_flag("-s DISABLE_EXCEPTION_CATCHING=0")
    -  add_link_flag("-s DISABLE_EXCEPTION_CATCHING=0")
    +  add_compile_flag("-fwasm-exceptions")
    +  add_link_flag("-fwasm-exceptions")
    +  add_compile_flag("-pthread")
    +  add_link_flag("-pthread")
    +  add_link_flag("-s PROXY_TO_PTHREAD")
    +  add_link_flag("-s EXIT_RUNTIME")
    +  add_link_flag("-Wno-pthreads-mem-growth")
       # make the tools immediately usable on Node.js
       add_link_flag("-s NODERAWFS")
       # in opt builds, LTO helps so much (>20%) it's worth slow compile times
    -  add_nondebug_compile_flag("-flto")
    +  #add_nondebug_compile_flag("-flto")
     endif()
     
     # clang doesn't print colored diagnostics when invoked from Ninja
     if(UNIX AND CMAKE_GENERATOR STREQUAL "Ninja")
       if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
         add_compile_flag("-fdiagnostics-color=always")
       elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
         add_compile_flag("-fcolor-diagnostics")
       endif()
     endif()
    diff --git a/src/support/threads.cpp b/src/support/threads.cpp
    index ab9de4175..7aec720ba 100644
    --- a/src/support/threads.cpp
    +++ b/src/support/threads.cpp
    @@ -132,24 +132,25 @@ void ThreadPool::initialize(size_t num) {
           threads.clear();
           return;
         }
       }
       DEBUG_POOL("initialize() waiting\n");
       condition.wait(lock, [this]() { return areThreadsReady(); });
       DEBUG_POOL("initialize() is done\n");
     }
     
     size_t ThreadPool::getNumCores() {
    -#ifdef __EMSCRIPTEN__
    +#if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)
       return 1;
     #else
       size_t num = std::max(1U, std::thread::hardware_concurrency());
       if (getenv("BINARYEN_CORES")) {
         num = std::stoi(getenv("BINARYEN_CORES"));
       }
       return num;
     #endif
     }
     
     ThreadPool* ThreadPool::get() {
       DEBUG_POOL("::get()\n");
       // lock on the creation

    Everything works as expected when I optimize some large files, but it is surprisingly slow. It is using multiple cores, and in fact uses them more than a native build. Native has this:

    66.95user 0.67system 0:14.33elapsed 471%CPU (0avgtext+0avgdata 608316maxresident)k
    

    and node 16.5 has this:

    768.36user 237.38system 2:37.22elapsed 639%CPU (0avgtext+0avgdata 762028maxresident)k
    

    I'm not sure what's going wrong here. Perhaps the slower wasm atomics are hurting us since they are all sequentially consistent...? Anyhow, sadly using wasm isn't a easy solution for this issue.

  24. d3lm commented on Dec 8, 2021

    @d3lm
    Author

    Thanks so much for investigating a WASM version of wasm-opt @kripken. Appreciate it a lot!

    It's a bummer that it's so much slower 😞 but I can also imagine that Atomics are slowing it down a lot. I can't imagine that using pthreads (which is mapped to web workers or worker threads) would be a problem here.

    I'd love to loop @tschneidereit in as well. Maybe you have an idea why it would be significantly slower than native?

    I suppose we have to wait for an M1 environment for GitHub actions or build an aarch64 with a cross compiler. WDYT @kripken?

  25. dschuff commented on Dec 16, 2021

    @dschuff
    Member

    If we have a recent enough SDK on our existing mac builder, It should be very straightforward to cross-compile for aarch64.

  26. tlively commented on May 16, 2025

    @tlively
    Member

    We now have MacOS Arm releases.

  27. ghost closed this as completedon May 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions