ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.63k stars 2.53k forks source link

`--libc` flag doesn't work properly on Windows #20781

Open noxabellus opened 3 months ago

noxabellus commented 3 months ago

Zig Version

0.13.0

Steps to Reproduce

I first noticed this issue while trying to cross compile my project which depends on bdwgc, from a windows 11 x86_64 vm for an aarch64-windows-msvc target. Strangely, I am able to compile the bdwgc module I've created directly, but trying to build it as a dependency from my own module's build script causes errors: either I get a series of errors saying the libc libs are x64 and I need aarch ones; or when I supply a libc file pointing to the correct binaries, an error saying that process.h cannot be found.

Why the former error is happening, I haven't been able to nail down. As I said, I do have the binaries and if I run the cross targeted build in bdwgc's directory it works fine. The second issue seems more definitely a compiler issue, though, so I decided to try and track that first.

I have produced a minimal reproduction here that recreates the missing header issue with no cross compilation or external libraries (other than libc, of course).

I can compile the following code with zig build-exe repro.zig -Dtarget=x86_64-windows-msvc

const std = @import("std");

const c = @cImport(@cInclude("process.h"));

pub fn main() void {
    std.debug.print("pid: {}\n", .{c.getpid()});
}

However, if I run zig libc, I get the following output:

# The directory that contains `stdlib.h`.
# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`
include_dir=C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt

# The system-specific include directory. May be the same as `include_dir`.
# On Windows it's the directory that includes `vcruntime.h`.
# On POSIX it's the directory that includes `sys/errno.h`.
sys_include_dir=C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.40.33807\include

# The directory that contains `crt1.o` or `crt2.o`.
# On POSIX, can be found with `cc -print-file-name=crt1.o`.
# Not needed when targeting MacOS.
crt_dir=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\ucrt\x64

# The directory that contains `vcruntime.lib`.
# Only needed when targeting MSVC on Windows.
msvc_lib_dir=C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.40.33807\Lib\x64

# The directory that contains `kernel32.lib`.
# Only needed when targeting MSVC on Windows.
kernel32_lib_dir=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\um\x64

# The directory that contains `crtbeginS.o` and `crtendS.o`
# Only needed when targeting Haiku.
gcc_dir=

Saving this to x86_64.libc and running the command again, supplying this libc file like so zig build-exe repro.zig -Dtarget=x86_64-windows-msvc -lc --libc x86_64.libc

Produces this error:

repro.zig:3:11: error: C import failed
const c = @cImport(@cInclude("process.h"));
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
referenced by:
    main: repro.zig:6:36
    callMain: C:\Users\noxab\.zvm\0.13.0\lib\std\start.zig:514:17
    remaining reference traces hidden; use '-freference-trace' to see all reference traces
C:\Users\noxab\AppData\Local\zig\o\aabd1583e5f4b478fdf610e387722295\cimport.h:1:10: error: 'process.h' file not found       
#include <process.h>

If I run Get-Item "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\process.h" | Format-List, I can confirm the file does exist in the directory supplied in the libc file:

    Directory: C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt

Name           : process.h
Length         : 11893
CreationTime   : 1/8/2024 5:04:24 PM
LastWriteTime  : 1/8/2024 5:04:24 PM
LastAccessTime : 7/24/2024 4:15:17 PM
Mode           : -a----
...

Observed Behavior

Passing a generated libc file directly into a libc compiler option produces errors.

Expected Behavior

Passing a generated libc file directly into a libc compiler option works the same as no libc compiler option

squeek502 commented 3 months ago

Attempting to reproduce this, but I'm getting completely different results/errors.

This command is a bit strange:

zig build-exe repro.zig -Dtarget=x86_64-windows-msvc
  1. -Dtarget=x86_64-windows-msvc is a build system-specific option. The build-exe equivalent is -target
  2. This isn't linking libc

Changing to -target and adding -lc gives me:

> zig build-exe repro.zig -target x86_64-windows-msvc -lc
error: lld-link: undefined symbol: getpid
    note: referenced by C:\Users\Ryan\Programming\Zig\tmp\repro.zig:6
    note:               repro.exe.obj:(repro.main)

To fix that, I have to add -loldnames


For the --libc part:

> zig libc > x86_64.libc
> zig build-exe repro.zig -target x86_64-windows-msvc -lc -loldnames --libc x86_64.libc
error: unable to find dynamic system library 'oldnames' using strategy 'paths_first'. searched paths: none

Without oldnames I'm back to the getpid linker error:

> zig build-exe repro.zig -target x86_64-windows-msvc -lc --libc x86_64.libc
error: lld-link: undefined symbol: getpid
    note: referenced by C:\Users\Ryan\Programming\Zig\tmp\repro.zig:8
    note:               repro.exe.obj:(repro.main)
noxabellus commented 3 months ago
  1. -Dtarget=x86_64-windows-msvc is a build system-specific option. The build-exe equivalent is -target

What the heck is happening when I run with that flag, then? Is it still doing a gnu build?

  1. This isn't linking libc

This one is just a copy/paste problem, I did in fact pass -lc, but when I was copying out my inputs to make the issue I missed that bit.

After changing -Dtarget=x86_64-windows-msvc to -target x85_64-windows-msvc I needed to add oldnames as well, which compiles; but then adding the libc parameter I get the same unable to find dynamic system library 'oldnames' and without -loldnames I'm back to 'process.h' file not found

(Edit: Apologies for accidentally closing the issue, noob mistake. I've reopened it now.)

alexrp commented 3 months ago

What the heck is happening when I run with that flag, then?

Excerpt from zig build-exe --help:

  -D[macro]=[value]         Define C [macro] to [value] (1 if [value] omitted)

Is it still doing a gnu build?

Yes, Zig defaults to MinGW for Windows.

noxabellus commented 3 months ago

I bypassed the header issue by just manually adding the symbols I needed in my zig code, now it's saying that the libs are all missing. And again, if I go to the provided directory and Get-Item the files it says are missing, they in fact are not