addExecutable main function in C conflicts with root_source_file in zig

My program’s main function is located in C/C++ code, for convenience working with winapi. I was able to use Zig code as library with such setup:

build.zig

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const lib = b.addStaticLibrary(.{
        .name = "zigpart",
        .root_source_file = .{ .path = "src/main.zig" },
        .target = target,
        .optimize = optimize,
    });

    const exe = b.addExecutable(.{
      .name = "zigc",
      .target = target,
      .optimize = optimize,
    });

    exe.linkLibrary(lib);
    exe.addCSourceFile(.{ .file = .{ .path = "src/c.c" }, .flags = &[_][]const u8{} });
    exe.linkLibC();

    b.installArtifact(exe);
}

Though it resolves my problem, my initial and simplest idea was to not have separate static lib for zig fails. Specifying executable like this:

const exe = b.addExecutable(.{
    .name = "zigc",
    .root_source_file = .{ .path = "src/main.zig" },
    .target = target,
    .optimize = optimize,
});
exe.addCSourceFile(.{ .file = .{ .path = "src/c.c" }, .flags = &[_][]const u8{} });
exe.linkLibC();

will fail, because start.zig in std expects the main entrypoint inside main.zig, such requirement is disabled in case build mode is library, this why earlier solution passes.

error: root struct of file 'main' has no member named 'main'

My questions are:

  1. Is there a solution, without adding separate static lib for zig? I was thinking of adding zig file through addModule, instead of root_source_file, but this seems to only modify @import behaviour and I cannot use @import inside C code.
  2. I believe not having the main function in zig while compiling executable should not be an error. It is the linker’s job to verify that the entrypoint exists in the final step. Same way as linker will fail if it sees double declaration of the main function in C and Zig code simultaneously. Is there a Github issue or tracking discussion about this?
pub const _start = void;
pub const WinMainCRTStartup = void;

in your root zig source file.

Full working example

5 Likes