Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide a libc for windows using mingw-w64 #2868

Merged
merged 13 commits into from
Jul 12, 2019
Merged

provide a libc for windows using mingw-w64 #2868

merged 13 commits into from
Jul 12, 2019

Conversation

andrewrk
Copy link
Member

@andrewrk andrewrk commented Jul 11, 2019

This is part of #514, shipping libc for every target. It adds the following libcs available (showing a snippet from zig targets here):

Available libcs:
  aarch64_be-linux-gnu
  aarch64_be-linux-musl
+  aarch64_be-windows-gnu
  aarch64-linux-gnu
  aarch64-linux-musleabi
+  aarch64-windows-gnu
  armeb-linux-gnueabi
  armeb-linux-gnueabihf
  armeb-linux-musleabi
  armeb-linux-musleabihf
+  armeb-windows-gnu
  arm-linux-gnueabi
  arm-linux-gnueabihf
  arm-linux-musleabi
  arm-linux-musleabihf
+  arm-windows-gnu
  i386-linux-gnu
  i386-linux-musl
+  i386-windows-gnu
  mips64el-linux-gnuabi64
  mips64el-linux-gnuabin32
  mips64el-linux-musl
  mips64-linux-gnuabi64
  mips64-linux-gnuabin32
  mips64-linux-musl
  mipsel-linux-gnu
  mipsel-linux-musl
  mips-linux-gnu
  mips-linux-musl
  powerpc64le-linux-gnu
  powerpc64le-linux-musl
  powerpc64-linux-gnu
  powerpc64-linux-musl
  powerpc-linux-gnu
  powerpc-linux-musl
  riscv32-linux-musl
  riscv64-linux-gnu
  riscv64-linux-musl
  s390x-linux-gnu
  s390x-linux-musl
  sparc-linux-gnu
  sparcv9-linux-gnu
  wasm32-freestanding-musl
  x86_64-linux-gnu (native)
  x86_64-linux-gnux32
  x86_64-linux-musl
+  x86_64-windows-gnu

This is done by shipping the headers from mingw-w64 project, v6.0.0 (the latest tagged release). In addition to that, zig ships with the mingw-w64 C runtime source files, and lazily builds them from source for the target and then caches the result. When the result is not cached it takes about 60 seconds, which is one of the motivations for #2865.

The instructions for updating to a newer mingw-w64 version are in the wiki: https://github.com/ziglang/zig/wiki/Updating-libc-Headers#windows

The total cost in bytes of this new feature is +59 MiB in installation size (+5 MiB in the download tarball size):

$ cat $(find libc/mingw -type f) $(find libc/include/any-windows-any -type f) | wc -c
61845091
$ cat $(find libc/mingw -type f) $(find libc/include/any-windows-any -type f) | xz | wc -c
5241776

I think that's a small price to pay for being able to cross-compile for Windows out-of-the-box. That said, @daurnimator got me thinking about how features like this might be provided in the future with a more minimal zig core. A potential future project, once we have the Zig package manager (#943) would be to have zig packages able to provide a libc for a specific target. That requires the ability to plug into the linker driver. Something to consider for a future project.

With these changes, I can build hello-world.c on any machine and produce hello-world.exe:

#include <stdio.h>

int main(int argc, char **argv) {
    puts("hello");
    return 0;
}
$ zig build-exe --c-source hello-world.c -target x86_64-windows-gnu --library c
$ file hello-world.exe
hello-world.exe: PE32+ executable (console) x86-64, for MS Windows

Until #2865 is done, a workaround to see progress is --verbose-cc.

I took this a step further, and was able to build SDL2 for windows in the zig-sdl repo:

andy@xps ~/d/zig-sdl> zig build -Dx86_64-windows-gnu
andy@xps ~/d/zig-sdl> ls zig-cache/lib/
SDL2.lib
andy@xps ~/d/zig-sdl> ls zig-cache/bin/
sdl-zig-demo.exe  sdl-zig-demo.pdb

And running it on a Windows machine...

zig-sdl-demo

What about the msvc target ABI?

Zig can cross compile Zig code for the windows-msvc target. However, cross compiling C code for this target currently does not work, because the windows.h headers have some kind of incompatibility with clang's C .h headers with the target ABI set to MSVC. I'm not sure whose fault this is - mingw-w64, clang, or both - but a future project would be to send upstream patches to fix this. And then theoretically this same libc can handle both windows-gnu and windows-msvc, since they are in fact ABI-compatible.

Unfortunately we cannot ship microsoft's official windows.h headers due to license restrictions.

What's left to do before merging

  • get all the tests passing (check for regressions)
  • fix the #pragma pack alignment warnings (they simply need to be silenced)
  • figure out why it segfaults at the end
  • add x86_64-windows-gnu to the test matrix
  • handle .def files better - include support for the rest of the system dlls, but don't put them on the linker line unless requested

andrewrk added 8 commits July 9, 2019 23:34
zig can now cross compile hello.c targeting windows
windows.h has files such as pshpack1.h which do #pragma packing,
triggering a clang warning. So for this target, this warning is
disabled.

this commit also improves the error message printed when no libc can be
used, printing the "zig triple" rather than the "llvm triple".
@daurnimator
Copy link
Contributor

libc/mingw/lib-common/* seem to contain a list of what is in each windows library.
Instead of lumping them all under --library c, can we split them up?

@andrewrk
Copy link
Member Author

Yep, that's what the last checkbox item is for.

andrewrk added 5 commits July 12, 2019 14:44
 * fixed --verbose-cc printing an extra "zig" before the rest of
   the command line
 * windows-gnu targets use libfoo.a, foo.o extensions to match mingw
   conventions.
also zig build handles --verbose and linkSystemLibrary better
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants