Menu

#579 Support ARM64 w/ Clang

3.0 Series
open
nobody
None
5
2025-04-27
2024-05-29
No

The latest attempt building NSIS for WoA using MSYS2 CLANGARM64 fails w/

scons: *** [build/urelease/System/unicode/Source/Call-arm64CPP.o] Source `Contrib/System/Source/Call-arm64CPP.S' not found, needed by target `build/urelease/System/unicode/Source/Call-arm64CPP.o'.
scons: building terminated because of errors.
due to missing assembly.

Also, please feel to upstream any of the patches so far.

Discussion

  • Jason

    Jason - 2024-05-29

    The arm64 assembly file for the system plugin is missing because noone has written one yet. The amd64 assembly file is only half complete, it doesn't support callbacks which need to be implemented. You can use SKIPPLUGINS="System" to get past this error.

    I took a quick look at all the patches, and there are a few things to note:

    • Clang specific stuff should idealy be put in its own file (perhaps make a copy in 'SCons/Config/clang'), instead of changing 'SCons/Config/gnu'. There is a section in Sconstruct where the specific compiler tools are included (approx line 545).
    • Clang also shouldn't use crossmingw.py as a cross compile tool, because that's specific to gcc mingw32/mingw-w64. If you still need it, make a copy specific to clang and include that in the file mentioned above.
    • Forcing C++11 is somewhat scary for backwards compatibility. My ubuntu 12.04 VM has gcc 4.6.2 which doesn't support C++11 and will break there.
    • Regarding the fixes for the directory structure, this can be fixed on the command line to scons by specifying 'NSIS_CONFIG_CONST_DATA_PATH=no'.
    • We can't remove the ansi build just yet, so all those '*target_suffix' changes still have to remain the same for now. I was recently thinking about adding a build option to turn off building ansi stubs for x86, since makensis already warns that it's deprecated (but still supported).
    • There's a good chance the patch for uninitialized variables will get upstreamed.
    • I have to test if the changes to the Makensisw RC file will compile in all my test VMs, so that's a maybe.
    • Those few extra checks for 'aarch64' will probably get upstreamed too.

    Thanks for having a go at supporting another system. Last time I tried a WoA build, it was with MSVC and most of the tools worked but the installers did not work. So let us know if you do manage to get the installers themselves to work.

     
  • Milos Komarcevic

    Thanks for the feedback. It would be great to add as much you think makes sense now to ease experimenting on this platform.

    mingw-w64 no longer implies the GCC toolchain exclusively, as LLVM-MinGW (basis for the MSYS2 CLANGARM64 environment ) is the only viable (non-MSVC) WoA option until GCC 15 arrives:

    https://www.mingw-w64.org/downloads/#llvm-mingw

    https://www.phoronix.com/news/GCC-aarch64-w64-mingw32

    I don't know SCons at all, but I wish it could be as flexible leveraging all of these toolchains on Windows as e.g. CMake is seamlessly able to.

     

    Last edit: Milos Komarcevic 2024-05-30
  • Arthur Klassen

    Arthur Klassen - 2024-10-29

    I'm sorry to hear this. C++11 and following can be threatening but the net benefit is fantastic.

    nsExec does not interoperate with, for instance C:\Windows\System32\netsh.exe as it currently stands. I believe this can be fixed by (

    • run CreateProcess on the targeted tool directly, rather than through a CreateProcess-of-the-DLL
    • while forcing TIMEOUT=0 on the Exec call

    I've written our own extension that successfully calls CreateProcess, where using stock nsExec on netsh does not. A workaround like the above would be very welcome indeed

     
    • Anders

      Anders - 2024-10-30

      64-bit netsh related report here. It is not supposed to use the DLL thing when running 32-bit NSIS on 64-bit Windows. I don't even remember why the DLL thing exists.

       
  • Arthur Klassen

    Arthur Klassen - 2024-10-30

    Thanks for the reply @anders_k! I was wondering if I had chosen a too-stale thread to reply to.

    We are using amd64-unicode (which I didn't explicitly state before -- sorry), so 32-bit NSIS doesn't enter into this, right?

    What I do know is that my extension dll that calls CreateProcess directly works, nsExec::ExecToLog fails to launch netsh on Windows-on-ARM.

    I also know that C:\Windows\System32\netsh.exe on a Windows-on-ARM system is, despite the misleading name of its location, an Aarch64 executable.

    Also, looking back through the history, I didn't see a drop-dead reason for the multi-layered CreateProcess call was being done. It strikes me as conceivable that it was a way to thunk between 32-bit and 64-bit environments in pre-win2k or Windows95 timeframes?

    Is there something else I'm missing? tia...

     

    Last edit: Arthur Klassen 2024-10-30
    • Anders

      Anders - 2024-10-31

      For part 1, I assume the fix is going to change if (!IsWOW64()) { to if (sizeof(void*) < 8 && !IsWOW64()) {.

      As for the timeout, I don't really understand why you would need TIMEOUT=0 because 0 is already the default. If you don't do this, does it respond with "timeout" on the stack after nsExec::Exec?

       
  • Arthur Klassen

    Arthur Klassen - 2024-11-06

    Anders...

    I don't know what the right patch is, exactly, in nsExec. All I know for sure is that

    1. we cannot get netsh (and possibly other tools) to reliably launch from nsExec::Exec* methods WHEN we have generated an amd64-unicode installer and we are running it on Windows-on-ARM.
    2. we CAN get netsh to run from our own DLL that calls CreateProcess directly on the tool we want to run.

    Currently, we are relying on our DLL to launch our tool but if nxExec were to run correctly again, we would prefer to use that. I don't know whether the fix is:

    1. NOT to do the double CreateProcess -- and I don't understand what the double launch is getting when a TIMEOUT is not involved. I suspectd the double launch is being done regardless to keep the code path consistent, so maybe NOT do the double CreateProcess when timeout is 0?
    2. To do something like what I think the code is doing for non-64-bit operation on a 64-bit system, to copy nsExec.dll to some WoW-directory before doing the first of the two CreateProcess calls. I don't know what the ARM64 analog for that is at all.
    3. something else entirely?

    We can't possibly be the only ones who will ever bump into this and given that compiling an ARM64-NSIS framework is not on yet either, it would be to others' benefit at all to have a clear path forward, no?

    If you don't know which is the right approach, we will be using our own DLL and will add the stdout capture that we've come to rely on from nsexec for ourselves.
    If you DO have some idea what the right approach is, I am willing to create a patch to submit back to you around that work when I get it done.

     
    • Anders

      Anders - 2024-11-17

      Did you try changing nsExec with my suggestion above?

       
      • Arthur Klassen

        Arthur Klassen - 2024-11-19

        Hey Anders... the patch you suggested did the trick. We'll patch the version of nsExec.dll we're using for the moment and will look forward to consuming the REAL version when it gets rolled into an official release.

        Thanks for your patience with my failure-to-grok. ...ank

         
        • aicom

          aicom - 2025-01-21

          FWIW, I independently debugged this (before I saw this report) in my own NSIS 3.10 based installer, and the specific problem with relaunching on ARM64 is the fact that the code is overwriting the IMAGE_FILE_LARGE_ADDRESS_AWARE flag on the new binary (which was present in the original NsExec.dll).

          If you enable loader snaps on the temporary binary using gflags.exe, you will see the following:

          0db8:41ec @ 495392140 - _LdrpInitialize - ERROR: Process initialization failed with status 0xc0000017
          0db8:41ec @ 495392140 - LdrpInitializationFailure - ERROR: Process initialization failed with status 0xc0000017
          

          If I manually modify the PE header of the dropped binary to restore the IMAGE_FILE_LARGE_ADDRESS_AWARE flag, the binary loads properly. I know it doesn't really matter anymore after r7445, but I thought I'd post it anyway since it wasn't trivial to debug why NsExec was silently broken on ARM64.

           
          👍
          2
          • Anders

            Anders - 2025-02-02

            Are you saying no 64-bit executables without IMAGE_FILE_LARGE_ADDRESS_AWARE set can run on ARM64?

            We don't actually need a large address space for a program that is a simple one function thing but setting the flag would not hurt.

             
  • Arthur Klassen

    Arthur Klassen - 2024-11-18

    I did not parse that as a "try nsexec.dll with this change", so I did not try it. sorry. will give it a shot.

     
  • Hernan Martinez

    Hernan Martinez - 2025-04-27

    I super second this. Nsis already builds with Clang (just see the CLANG64 builds by MSYS).

    I can help testing the ARM64 , changes and builds. Right now I'm hitting:

    scons: *** [build/urelease/System/unicode/Source/Call-arm64CPP.o] Source Contrib/System/Source/Call-arm64CPP.S' not found, needed by targetbuild/urelease/System/unicode/Source/Call-arm64CPP.o'.
    scons: building terminated because of errors.

    While building in the CLANGARM64 environment

     
    • Anders

      Anders - 2025-04-27

      The ARM64 assembly file has not been written yet. There is some code in system.c that is supposed to let you build a minimal version that lets MUI2 work (but not generic System::Call) but I don't remember off the top of my head how exactly you get that to happen. Perhaps if you create a Call-arm64CPP.S file with just the word END in it (or .end if clang uses GCC syntax)?

      scons SKIPPLUGINS=system ... if you want to skip this plug-in completely.

       

Log in to post a comment.

MongoDB Logo MongoDB