Playing with Windows on ARM64

Following on from the teaser in ARM Windows installation as of today - #4 by dra27, if you’re lucky enough to have an ARM64 Windows machine, it’s just about possible to get a few opam packages installed and working it!

You’ll need Visual Studio 2022 (Community) with the following packages:

  • MSVC v143 - VS 2022 C++ ARM64/ARM64EC build tools (Latest)
  • MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest)
  • C++/CLI support for v143 build tools (Latest)
  • C++ Clang Compiler for Windows (18.1.8)
    That’s not a typo: you need Clang and both the x64/x86 and ARM64 MSVC packages

Install Git for Windows as normal (winget install Git.Git, etc.) and Cygwin (adding the make and patch packages - no compilers or libraries needed, it’s just to get the shell).

Clone my opam fork and check out branch windows-on-arm64. From a Cygwin bash terminal, cd to that clone and run make cold. After a little while, that should leave an ARM64 opam.exe in the current directory which should be copied to a location which you then add to PATH.

From Cmd/PowerShell, you can now run:

PS > opam init --bare
PS > opam switch create --empty windows-on-arm64
PS > opam pin add --yes ocaml-variants git+https://github.com/dra27/ocaml.git#windows-on-arm64

Dune needs a trivial pin (which I think may be more to do with a recent Windows SDK issue, than arm64-specific):

PS > opam pin add dune git+https://github.com/dra27/dune.git#windows-on-arm64

Unfortunately, it’s not quite enough to get opam’s dependencies installing through opam (dose3 failed for me, which is odd because it works with make cold and topkg was freezing, although that’s less surprising). But it’s kinda cool how much is working straightaway, and it certainly looks like we’ll have native Windows ARM64 support at some point in the future, therefore!

Aside from the usual “packages which don’t work properly” issue, there’re two glaring problems:

  1. It should be possible to install the x86 / x64 compilers, but at present this doesn’t work because the opam compiler packages need further tweaking[1]
  2. Only Clang-pretending-to-be-cl is supported at the moment - I can’t see any reason that Clang-pretending-to-be-gcc shouldn’t be doable, but as we don’t presently support that for x64 either (and it necessarily needs MSYS2, rather than Cygwin), I haven’t disappeared down that rabbit hole yet[2]

:warning: I have no timeline for upstreaming any of this, but it’s all publicly pushed and welcome to anyone to extend to a mergeable state!


  1. I’ll likely get to that at some point soon, as that unblocks general use of OCaml on Windows ARM64 machines, even if not native ARM64 use. However, it exceeds “fun messing around over Christmas and New Year”! ↩︎

  2. See 1… ↩︎

6 Likes

Nice. It seems that Microsoft also finally decided to distribute Windows ARM64 ISOs. Maybe everything is finally aligning for us who do want to test Windows builds while sitting in front of an ARM unix system :–)

1 Like

And note that VMWare fusion for Mac no longer costs money:

I have been having a go at the instructions, and failed almost at the end. We see:

PS C:\Users\john> (& opam env --switch=windows-on-arm64) -split '\r?\n' | ForEach-Object { Invoke-Expression $_ }
PS C:\Users\john> opam pin add --yes ocaml-variants git+https://github.com/dra27/ocaml.git#windows-on-arm64
[ocaml-variants.5.3.0+trunk] synchronised (git+https://github.com/dra27/ocaml.git#windows-on-arm64)
The following additional pinnings are required by ocaml-variants.5.4.0+trunk:
  - conf-msvcarm64.dev at git+https://github.com/dra27/msvs-tools.git#windows-on-arm64
  - msvs-detect.0.8.0~dev at git+https://github.com/dra27/msvs-tools.git#windows-on-arm64
  - arch-arm64.1 at git+https://github.com/dra27/msvs-tools.git#windows-on-arm64
  - ocaml-env-msvcarm64.1 at git+https://github.com/dra27/msvs-tools.git#windows-on-arm64
  - system-msvc.1 at git+https://github.com/dra27/msvs-tools.git#windows-on-arm64
  - flexdll.0.44 at git+https://github.com/dra27/flexdll.git#msvcarm64
Pin and install them? [Y/n] y
Package conf-msvcarm64 does not exist, create as a NEW package? [Y/n] y
[conf-msvcarm64.dev] synchronised (no changes)
conf-msvcarm64 is now pinned to git+https://github.com/dra27/msvs-tools.git#windows-on-arm64 (version dev)
[msvs-detect.0.8.0~dev] synchronised (no changes)
msvs-detect is now pinned to git+https://github.com/dra27/msvs-tools.git#windows-on-arm64 (version 0.8.0~dev)
Package arch-arm64 does not exist, create as a NEW package? [Y/n] y
[arch-arm64.1] synchronised (no changes)
arch-arm64 is now pinned to git+https://github.com/dra27/msvs-tools.git#windows-on-arm64 (version 1)
Package ocaml-env-msvcarm64 does not exist, create as a NEW package? [Y/n] y
[ocaml-env-msvcarm64.1] synchronised (no changes)
ocaml-env-msvcarm64 is now pinned to git+https://github.com/dra27/msvs-tools.git#windows-on-arm64 (version 1)
[system-msvc.1] synchronised (no changes)
system-msvc is now pinned to git+https://github.com/dra27/msvs-tools.git#windows-on-arm64 (version 1)
[flexdll.0.44] synchronised (no changes)
flexdll is now pinned to git+https://github.com/dra27/flexdll.git#msvcarm64 (version 0.44)
ocaml-variants is now pinned to git+https://github.com/dra27/ocaml.git#windows-on-arm64 (version 5.4.0+trunk)

[ERROR] Package conflict!
  * Missing dependency:
    - ocaml-variants → ocaml >= 5.4.0
    no matching version

Any ideas?

Thanks for trying it! Was this all done with a fresh opam root? Is opam-repository itself all up-to-date? What are opam repo and opam show ocaml - is 5.4.0 listed in the versions?

Yes, it was my fault. I started from a fresh ISO install of Windows, and now it works!

I am tantalisingly close to a built executable of my Cpdf program, but at the very last:

ocamlopt \
                          \
                             -I ../camlpdf   -g    -ccopt -L../camlpdf   camlpdf.cmxa -o cpdf \
                        cpdfyojson.cmx cpdfxmlm.cmx cpdfunicodedata.cmx cpdferror.cmx cpdfdebug.cmx cpdfjson.cmx cpdfstrftime.cmx cpdfcoord.cmx cpdfattach.cmx cpdfpagespec.cmx cpdfposition.cmx cpdfpresent.cmx cpdfmetadata.cmx cpdfbookmarks.cmx cpdfpage.cmx cpdftruetype.cmx cpdfremovetext.cmx cpdfextracttext.cmx cpdfembed.cmx cpdffont.cmx cpdftype.cmx cpdfaddtext.cmx cpdfpad.cmx cpdfocg.cmx cpdfsqueeze.cmx cpdfdraft.cmx cpdfspot.cmx cpdfpagelabels.cmx cpdfcreate.cmx cpdfannot.cmx cpdfxobject.cmx cpdfimpose.cmx cpdfchop.cmx cpdftweak.cmx cpdfprinttree.cmx cpdfua.cmx cpdftexttopdf.cmx cpdftoc.cmx cpdfjpeg.cmx cpdfjpeg2000.cmx cpdfpng.cmx cpdfimage.cmx cpdfdraw.cmx cpdfcomposition.cmx cpdfshape.cmx cpdfcolours.cmx cpdfdrawcontrol.cmx cpdfcommand.cmx cpdfcommandrun.cmx
LINK : warning LNK4098: defaultlib 'libcmt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
dyndll604ee7.obj : error LNK2001: unresolved external symbol #wcsstr
dyndll604ee7.obj : error LNK2001: unresolved external symbol #tanh
dyndll604ee7.obj : error LNK2001: unresolved external symbol #sqrt
dyndll604ee7.obj : error LNK2001: unresolved external symbol #realloc
dyndll604ee7.obj : error LNK2001: unresolved external symbol #longjmp
dyndll604ee7.obj : error LNK2001: unresolved external symbol #fwrite
dyndll604ee7.obj : error LNK2001: unresolved external symbol #fputc
dyndll604ee7.obj : error LNK2001: unresolved external symbol #floor
dyndll604ee7.obj : error LNK2001: unresolved external symbol #cosh
dyndll604ee7.obj : error LNK2001: unresolved external symbol #ceil
dyndll604ee7.obj : error LNK2001: unresolved external symbol #atan
dyndll604ee7.obj : error LNK2001: unresolved external symbol #asin
dyndll604ee7.obj : error LNK2001: unresolved external symbol #acos
dyndll604ee7.obj : error LNK2001: unresolved external symbol #_wassert
dyndll604ee7.obj : error LNK2001: unresolved external symbol #_fpreset
cpdf : fatal error LNK1120: 15 unresolved externals
** Fatal error: Error during linking

File "caml_startup", line 1:
Error: Error during linking (exit code 2)
make[1]: *** [OCamlMakefile:952: cpdf] Error 2
make[1]: Leaving directory '/cygdrive/c/Users/John/cpdf-source'
make: *** [OCamlMakefile:777: native-code] Error 2

Have you seen this before? I added -ccopt -nodefaultlibs but it fails in a different way.