ziglang / zig

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

figure out how to handle precompiled headers #3495

Open slaide opened 4 years ago

slaide commented 4 years ago
use @cImport({
  @cInclude("src/stb_image.h");
});

pub fn main()void{
  var x:c_int=0;
  var y:c_int=0;
  var n:c_int=0;
  var image=stbi_load(c"image.jpg",&x,&y,&n,0);
}

compiled with: zig build-exe test.zig --c-source -std=c17 -DSTB_IMAGE_IMPLEMENTATION src/stb_image.h -lc produces this error: Build Dependencies...start...compiling C objects [0/1] start.S...lld: error: unclosed comment in a linker script

this code succeeds in c however, with the same std specified and also with clang, so the problem is not within the c-source file.

the define basically differentiates between the file being used as a header file, and the actual definitions.

including the file directly in the zig source via cImport with the defintion fails because the source translation fails to properly translate the code, which is ok, since the header itself works.

link to file: https://github.com/nothings/stb/blob/master/stb_image.h

andrewrk commented 4 years ago

Thanks for the bug report. I can reproduce this. It appears to be a bug in LLD. The next step here will be narrowing it down and making an upstream bug report.

LemonBoy commented 4 years ago

It appears to be a bug in LLD

Nah, once again it's not LLD's fault. When you try to compile a header both Clang and Zig produce a so-called pre-compiled header that's far from being an object file.

To achieve your objective you have to build a small .c file (let's call it stb_image_impl.c) containing just the following:

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

This means that once you compile this .c file (and not the header itself, that only contains the implementation code) you'll get an object containing all the stb_image routines. Linking your zig code against this object is easy-peasy lemon-squeezy and works as intended:

zig build-exe test.zig --c-source -std=c17 stb_image_impl.c -lc

this code succeeds in c however, with the same std specified and also with clang, so the problem is not within the c-source file.

No it's not, trying to build only the header with clang (clang-9 -S -std=c17 -DSTB_IMAGE_IMPLEMENTATION stb_image.h) gives you a stb_image.h.gch, a precompiled header. The difference (and maybe the real issue here) is that Clang knows what to do with such a file while Zig does not and tries to feed it to the linker as if it were an object file.

andrewrk commented 4 years ago

TIL about precompiled headers. I thought it was some legacy Microsoft thing.

Zig has absolutely no use for them apart from a possible implementation of optimizing its caching strategy. Users should never have to see them.

Of course, since zig exposes clang, this behavior should remain as is, and we need smarter detection of when a precompiled header is output rather than an object file.

On a related note, I regret pushing back on you @LemonBoy when you had zig look at file extensions with regards to how to handle --c-source. I'm going to open a proposal soon with regards to that. I've thought of a better CLI.

andrewrk commented 4 years ago

related: #3508