zig icon indicating copy to clipboard operation
zig copied to clipboard

Linking a library breaks custom include path.

Open akvadrako opened this issue 4 years ago • 2 comments

Hello. When I link a library zig ignores my custom C include path. This happens with zig build using addIncludeDir / linkSystemLibrary and with zig test.

This works:

+ zig test test.zig -lc -I/usr/include --verbose-cimport
info(compilation): C import source: zig-cache/o/2a90da3393a01cc0fa4c030e3dcfc2e9/cimport.h
info(compilation): C import .d file: zig-cache/o/2a90da3393a01cc0fa4c030e3dcfc2e9/cimport.h.d
info(compilation): C import output: zig-cache/o/374c29744e6df4dd75900432d0b0d106/cimport.zig
All 1 tests passed.

This doesn't:

+ rm -Rf zig-cache/
+ zig test test.zig -lc -lsqlite3 -I/usr/include --verbose-cimport
info(compilation): C import source: zig-cache/o/3dcb7b23c8547bc89df8b3e30f538803/cimport.h
info(compilation): C import .d file: zig-cache/o/3dcb7b23c8547bc89df8b3e30f538803/cimport.h.d
info(compilation): C import output: zig-cache/o/d257b652d20562f873e013bcef5fb230/cimport.zig
./test.zig:9:14: error: container '.cimport:5:15' has no member called 'FAN_REPORT_FID'
    eq(512, c.FAN_REPORT_FID);
             ^

For my example I am using a linux header that differs from the built-in headers:

    const c = @cImport({
        @cInclude("linux/fanotify.h");
    });

    eq(512, c.FAN_REPORT_FID);

A related issue is that if I run the first command above, then the second command works. If I delete zig-cache in between, it fails.

  • Zig 0.8.0 6cd7193
  • Test Case: https://github.com/akvadrako/zig-testcase-include

akvadrako avatar Apr 22 '21 12:04 akvadrako

Once you add the -lsqlite3 your #include is not picking up the header file from /usr/include but the Zig-provided one in lib/libc/include/any-linux-any/linux/fanotify.h.

Zig is adding a -isystem /usr/include right after your -I/usr/include and according to GCC and Clang manuals this makes the compiler skip the -I part:

If a standard system include directory, or a directory specified with -isystem, is also specified with -I, the -I option is ignored.
The directory is still searched but as a system directory at its normal position in the system include chain. 
This is to ensure that GCC’s procedure to fix buggy system headers and the ordering for the #include_next directive are not inadvertently changed.
If you really need to change the search order for system directories, use the -nostdinc and/or -isystem options.

LemonBoy avatar Apr 22 '21 13:04 LemonBoy

@LemonBoy thanks for that investigation. I suppose the correct fix would be to not implicitly append include paths, though if people value the magic at least it should avoid adding -isystem when the -I already exists.

BTW, for now as a workaround I'm doing the translate-c part as a separate build step.

akvadrako avatar Apr 23 '21 21:04 akvadrako