ziglang / zig

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

ability to pass compiler flags directly to llvm from build.zig for zig code #12726

Open ssrimindset opened 2 years ago

ssrimindset commented 2 years ago

I think it will be pretty useful to be able to pass flags to clang/llvm itsef. I use them quite often in low level scenarious. For it to be possilbe, all it needs is to add another function which will pass them to main.zig clang_argv

If it's intentional not to do so, can you explain why?

const std = @import("std");

pub fn build(b: *std.build.Builder) void {
    const exe = b.addExecutable("test", "src/main.zig");

    // ignore the flags themselves, they are just to illustrate the point
    const exe_cflags = [_][]const u8{
        "-fno-exceptions",
        "-fno-jump-tables",
        "-mno-avx",
        "-mllvm -adce-remove-control-flow=false", // -mllvm flags would be really nice too
        "-Xlinker --split" // and linker flags
    };

    // EXAMPLE, why its currently impossible to pass flags directly to zig compiler?
    // i know you can control some things like strip via exe.strip = true, but not everything is exposed
    exe.addLLVMFlags(&exe_cflags); // or exe.addBackendFlags(&exe_cflags);
    // EXAMPLE, but possible with c source files
    exe.addCSourceFile("src/test.c", &exe_cflags);

    exe.setTarget(b.standardTargetOptions(.{}));
    exe.setBuildMode(b.standardReleaseOptions());
    exe.install(); 
}
andrewrk commented 2 years ago

This is intentionally not supported because Zig has multiple linker backends and multiple compiler backends - idea being that you can switch from LLVM to a different one seamlessly. Setting this global state wreaks havoc on this abstraction.

However, I recognize that when using LLVM, some advanced use cases would benefit from this ability. So the trick is to balance the API, making it difficult enough to use that nobody stumbles upon it, but still possible to use when the person knows what they are doing.

ni-vzavalishin commented 11 months ago

One particular use case where I was looking forward to this possibility (just theoretically, not that far with zig usage yet) is floating point fast math. The standard fast math option of clang is often too aggressive as, in my and some of my colleagues' experience, it may quite often cause lots of precision loss in the computations. However, fast-math in clang has more granular control, and IIRC it's just one or two granular options which are causing trouble. The majority of fast-math options are simply about ignoring boundary cases like INFs, NaNs and distinct signed zero, and do not affect computation precision. I'd assume it's the same in LLVM in general.

Not fully sure, how does Zig configure release options, but I assume it's the same fast-math as in clang, in which case more granular control could be highly desirable.

fawzi commented 8 months ago

I might have missed something, but I also want to pass some linker flags to zig, and I do not know how. I am building a plugin with zig. It will be manually loaded in a C application, that makes some functions (i.e. symbols) available (the API of the plugin). On macOS (unlike on linux) by default all symbols must be resolved, so when building the shared library it complains about the undefined symbols. To avoid that I should pass either -undefined dynamic_lookup or -Wl,-U,symbol_name for all symbols of the API. but I do not find how...

fawzi commented 8 months ago

it seems that for my use case a solution has been added to the linker, see https://github.com/ziglang/zig/issues/3085 , also -Wl,-undefined,dynamic_lookup should work as described in https://github.com/ziglang/zig/issues/8180 and I still miss how to pass it using build.zig, but that is not exactly this issue anymore

fawzi commented 8 months ago

also that is solved, lib.linker_allow_shlib_undefined = true, not all options of the library objects are available at construction time in Build.SharedLibraryOptions...(thanks !no ones uncle)