node-datachannel icon indicating copy to clipboard operation
node-datachannel copied to clipboard

Compiling on windows on ARM64

Open ShyneTurtle opened this issue 9 months ago • 23 comments

Hey, I recently tried to download the webtorrent module and this dependency failed to build, after looking into it further it complained about openSSL, so i installed that, added it to the PATH and created the OPENSSL_ROOT_DIR env variable that cmake was complaining about, but now i'm getting tons of errors about function references.

I know github doesn't have WoA64 build servers yet so i'm gonna need your help to walk me through how to get it compiling.

Here's an extract of the build logs: https://pastebin.com/nkUUupcm

ShyneTurtle avatar Feb 07 '25 19:02 ShyneTurtle

Looks like linker can not find OpenSSL static libs. You need to either install OpenSSL static libs or link dynamically.

Could you please replace this line and re-build? https://github.com/murat-dogan/node-datachannel/blob/5eb81072bc729a403a6148b656d6b88bce52463e/CMakeLists.txt#L23

set(OPENSSL_USE_STATIC_LIBS FALSE)

murat-dogan avatar Feb 08 '25 20:02 murat-dogan

Installation fails again, here are the logs: https://pastebin.com/j0Ka3hZb sorry for the wait i was on vacation

ShyneTurtle avatar Feb 18 '25 15:02 ShyneTurtle

Thanks for the Log. It still tries to link static. Could you also please comment this line; https://github.com/murat-dogan/node-datachannel/blob/431e160d1e40427c47c8547a3acaba7359ceb34f/CMakeLists.txt#L15

murat-dogan avatar Feb 18 '25 18:02 murat-dogan

here's the logs https://pastebin.com/vTx3vWnG

ShyneTurtle avatar Feb 19 '25 18:02 ShyneTurtle

It still tries to link statically. And I don't know why.

I have checked GitHub runners now, but unfortunately, there is no win arm64 yet to find a solution or better have prebuilt binaries.

murat-dogan avatar Mar 01 '25 11:03 murat-dogan

I believe I managed to cross compile for ARM64 on Windows using VCPKG successfully. The steps I used are as follows. I do not have a windows on arm based machine, so I can't test if it actually works.

  1. Install Visual Studio Build Tools with the following "individual components" enabled.
    • C++ Modules for v143 build tools (ARM64 -- experimental)
    • C++ Universal Windows Platform support for v143 build tools (ARV64/ARM64EC)
    • MSVC v143 - VS 2022 C++ ARM64/ARM64EC build tools (Latest)
    • MSVC v143 - VS 2022 C++ ARM64/ARM64EC Spectre-mitigated libs (Latest)
  2. Initialize command prompt for cross compile using "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64
    • If the host is an ARM64 machine, then you'd replace amd64_arm64 with just arm64
  3. Install VCPKG and set VCPKG_ROOT=<VCPKG install directory>
  4. Install openssl with vcpkg using %VCPKG_ROOT%\vcpkg install openssl:arm64-windows-static
  5. To compile, run npx cmake-js build -A ARM64 -a ARM64 --CDCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%\scripts\buildsystems\vcpkg.cmake --CDVCPKG_TARGET_TRIPLET=arm64-windows-static

funniray avatar Mar 06 '25 12:03 funniray

Hey there,

I tested this in parallels on my mac mini and I found that it almost immediately crashes when running in Release mode, however Debug builds work fine. I suspect it's due to this bug in openssl. I'll see if I'm able to find a workaround.

funniray avatar Mar 06 '25 17:03 funniray

Hello @funniray,

Thank you for sharing this. By using the info that you have provided and some others, I could build it here; https://github.com/murat-dogan/node-datachannel/actions/runs/13737250799

@ShyneTurtle Could you please try this binary if it works? https://github.com/murat-dogan/node-datachannel/releases/download/v0.26.0/node-datachannel-v0.26.0-napi-v8-win32-arm64.tar.gz

murat-dogan avatar Mar 08 '25 12:03 murat-dogan

Hey, i've never worked with precompiled libraries with node, could you walk me through installing it ? tried to look it up but didn't find any ressources. and thanks for the help @funniray

ShyneTurtle avatar Mar 08 '25 18:03 ShyneTurtle

@murat-dogan I tested that prebuilt binary on my m4 mac mini via a windows arm64 vm and found it to have the same behavior as my earlier attempts that almost immediately crashed due to access violations. Image

After a few hours of reading and testing, I was able to successfully compile openssl statically for windows on arm using clangcl and vcpkg. It worked almost the same as the prior instructions, but needed a custom triplet/toolchain for vcpkg installed. You would most likely include this file as an overlay triplet. Part of the triplet was recycled from https://github.com/Neumann-A/my-vcpkg-triplets/. Some things used may be un-necessary, I didn't want to push my luck too far, especially as compile times were much longer than expected.

ClangCL (in my case) was installed via the visual studio installer via the C++ Clang Compiler for Windows and MSBuild support for LLVM (clang-cl) toolset options. I was only able to get openssl itself statically compiled via clangcl, with node-datachannel itself being compiled via MSVC. Image

funniray avatar Mar 09 '25 01:03 funniray

@ShyneTurtle

could you walk me through installing it

It should be as simple as copying the build folder to the root directory of the node-datachannel folder.

funniray avatar Mar 09 '25 01:03 funniray

https://github.com/openssl/openssl/issues/26239#issuecomment-2561590370

With OpenSSL 3.2, there are no reported errors. What do you think?

murat-dogan avatar Mar 09 '25 10:03 murat-dogan

With OpenSSL 3.2, there are no reported errors.

Two comments down he said

Please ignore both of my comments. I see now. Its the debug build that is not affected. Both ARM configs were affected for me.

Personally, trying to get openssl to work on windows on arm, I've tried openssl 3.4.1 (latest) openssl 3.0.8#2 (closest to nodejs's built in version, just in case) openssl 1.1.1n (in case it was a regression in openssl 3)

so far, every release build I've tried that was built with msvc will result in an access violation, crashing the nodejs thread with no output. The only ways I've actually got it to run successfully was to use a clang built binary or to run a debug binary. I was unable to get a working binary with msvc using the -DNO_INTERLOCKEDOR64 flag as suggested, but I might've done it wrong.

funniray avatar Mar 09 '25 13:03 funniray

Running npx jest with the file you sent failed all tests.

I can install clang, what are the steps you used to build successfuly @funniray ?

I have to say the downer is that the laptop can run x64 apps through emulation (this is my dev machine) but because of node runtime checks it won't even try the binary.

ShyneTurtle avatar Mar 11 '25 17:03 ShyneTurtle

I did some testing and I came to the conclusion that -DNO_INTERLOCKEDOR64 is able to successfully create a binary with msvc that compiles and passes the test.

With that being said, after a few hours of trial and error, I was unable to make vcpkg correctly use the cflag. You can see my attempt here.

I did make another branch that just compiles openssl directly without using vcpkg. I was able to get it to successfully compile a binary using msvc and it successfully passed all tests on my m4 mac mini. @ShyneTurtle You can try the build from here.

A few notable things about this branch

  • OpenSSL is configured for VC-WIN64-CLANGASM-ARM. This is what vcpkg does by default for arm64. Essentially, MSVC is used for C compilation/linking and clang is only used as the ARM64 assembler.
  • the CFLAGS environment variable is set for both the configure and make step. This probably is only required during the configure step, but I haven't checked
  • I am using Jom instead of nmake for building openssl, as nmake isn't parallelized.
  • I'd love to use either ninja or even jom to build node-datachannel itself, but if I attempt to change the generator to either nmake or ninja, cmake tells me that it's unavailable for arm64. I'm unsure why this is the case

funniray avatar Mar 12 '25 23:03 funniray

Super @funniray

Thanks for your work.

I think we can use vcpkg + your suggestions to build the all versions of Windows (x64, x86, arm64) Like

jobs:
  build-windows:
    runs-on: windows-2022
    strategy:
      matrix:
        node-version: [18]
        arch: [x64, x86, arm64] 
        include:
          - arch: x64
            vcpkg_triplet: x64-windows-static-custom
            msvc_arch: amd64
          - arch: x86
            vcpkg_triplet: x86-windows-static-custom
            msvc_arch: amd64_x86
          - arch: arm64
            vcpkg_triplet: arm64-windows-static-custom
            msvc_arch: amd64_arm64

    steps:
      - uses: actions/checkout@v4
      ......

I have tried to make it with prebuild, with no success.

What you think and could you please create a PR for this?

murat-dogan avatar Mar 14 '25 09:03 murat-dogan

I spent a bit more time trying to get vcpkg to compile with -DNO_INTERLOCKEDOR64 and I was able to check the logs and I confirmed it was indeed compiling with the -DNO_INTERLOCKEDOR64 flag.

With that being said, the vcpkg binaries are still somehow crashing with the same exception on the same line as binaries built without -DNO_INTERLOCKEDOR64.

I'm really not sure where to go with vcpkg from here, especially as -DNO_INTERLOCKEDOR64 fixes the exceptions when building openssl directly without vcpkg.

funniray avatar Mar 14 '25 12:03 funniray

@ShyneTurtle Did you have any chance to try the binary that was generated by @funniray?

@funniray How can we continue? It will be good to have win arm64 prebuilt binaries.

And also, if we can merge all windows build jobs and use vcpkg, it will be very nice. https://github.com/murat-dogan/node-datachannel/issues/330#issuecomment-2724148848

But not sure where to continue.

murat-dogan avatar Mar 29 '25 15:03 murat-dogan

Sorry, i was busy for the last few weeks.

@funniray 's build passed all the tests on my Snapdragon X1 laptop !

ShyneTurtle avatar Mar 29 '25 18:03 ShyneTurtle

I posted this on another thread, but it may be of use.

The /Od disabled flag resolves the vcpkg issue here.

We didn't try the various /Ox options, but they may offer more insight into the problem.

https://learn.microsoft.com/en-us/cpp/build/reference/o-options-optimize-code?view=msvc-170

Nick7K avatar Mar 29 '25 21:03 Nick7K

@murat-dogan

How can we continue?

I'm honestly not sure, I know that it is possible to adapt my solution that builds openssl from source to other windows platforms (x86/x64). VCPKG is really annoying to test locally, as the package cache is in odd locations, and I don't have an amazing setup to run cross compiled code on my test machine.

@Nick7K

The /Od disabled flag resolves the vcpkg issue here.

That sounds about right as the debug version of openssl works fine. However, I don't believe it's an acceptable solution, especially as arm64 devices are already relatively underpowered

funniray avatar Apr 02 '25 14:04 funniray

I tried making a new build with vs 17.14 and I can confirm that the build passes tests successfully

Image

The currently windows-2025 image only has visual studio 17.13, but I'm sure they'll update eventually

I've also noticed that there are native arm images for both windows and ubuntu via github actions partner images. I'm unsure if you should use them for building, but they might be useful for testing

funniray avatar May 15 '25 21:05 funniray

Hello, any updates on this ? will there be a new npm release i can use to include in my project, or another way i could manually include it ?

ShyneTurtle avatar Aug 23 '25 14:08 ShyneTurtle

The windows server 2022 and 2025 images both are on 17.14, so they should now build OpenSSL via VCPKG without an issue.

funniray avatar Aug 25 '25 11:08 funniray

Hello @ShyneTurtle

Could you please test this binary? https://github.com/murat-dogan/node-datachannel/releases/download/v0.29.0/node-datachannel-v0.29.0-napi-v8-win32-arm64.tar.gz

Built with github actions with latest MSVC & VCPKG

murat-dogan avatar Sep 15 '25 07:09 murat-dogan

Sure thing, how can i use the .node file ? i'm not familiar with the inner workings of node modules

ShyneTurtle avatar Sep 16 '25 09:09 ShyneTurtle

https://github.com/murat-dogan/node-datachannel/issues/330#issuecomment-2708604203

Please check here

murat-dogan avatar Sep 17 '25 09:09 murat-dogan

Here's the tests:

 PASS  test/jest-tests/basic.test.ts
 PASS  test/jest-tests/p2p.test.ts
 PASS  test/jest-tests/streams.test.ts
 PASS  test/jest-tests/polyfill.test.ts
 PASS  test/jest-tests/websocket.test.ts (5.326 s)
A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks. Active timers can also cause this, ensure that .unref() was called on them.

Test Suites: 5 passed, 5 total
Tests:       11 passed, 11 total
Snapshots:   0 total
Time:        6.187 s

and the result of the detectOpenHandles:

Jest has detected the following 4 open handles potentially keeping Jest from exiting:

  ●  ThreadSafeCallback callback

      64 |       });
      65 |
    > 66 |       dc1 = peer1.createDataChannel('test-p2p');
         |                   ^
      67 |       dc1.onOpen(() => {
      68 |         p1DCMock();
      69 |         dc1.sendMessage('Hello From Peer1');

      at test/jest-tests/p2p.test.ts:66:19
      at Object.<anonymous> (test/jest-tests/p2p.test.ts:9:12)


  ●  ThreadSafeCallback callback

      65 |
      66 |       dc1 = peer1.createDataChannel('test-p2p');
    > 67 |       dc1.onOpen(() => {
         |           ^
      68 |         p1DCMock();
      69 |         dc1.sendMessage('Hello From Peer1');
      70 |       });

      at test/jest-tests/p2p.test.ts:67:11
      at Object.<anonymous> (test/jest-tests/p2p.test.ts:9:12)


  ●  ThreadSafeCallback callback

      69 |         dc1.sendMessage('Hello From Peer1');
      70 |       });
    > 71 |       dc1.onMessage((msg) => {
         |           ^
      72 |         p1DCMessageMock(msg);
      73 |         peer1.close();
      74 |         peer2.close();

      at test/jest-tests/p2p.test.ts:71:11
      at Object.<anonymous> (test/jest-tests/p2p.test.ts:9:12)

  ●  ThreadSafeCallback callback

      55 |         peer1.addRemoteCandidate(candidate, mid);
      56 |       });
    > 57 |       peer2.onDataChannel((dc) => {
         |             ^
      58 |         p2DCMock();
      59 |         dc2 = dc;
      60 |         dc2.onMessage((msg) => {

      at test/jest-tests/p2p.test.ts:57:13
      at Object.<anonymous> (test/jest-tests/p2p.test.ts:9:12)

ShyneTurtle avatar Sep 19 '25 06:09 ShyneTurtle

The main point, then, is that it is ok for Windows ARM64. From this version on, it will also generate a binary for Windows ARM64. Thank you all.

For open handles, please follow here; https://github.com/murat-dogan/node-datachannel/issues/366

murat-dogan avatar Sep 21 '25 15:09 murat-dogan