Here I am conditionally building either a static or a dynamic library (haven’t tested out dynamic linking yet) but with static linking I am having problems:
zb -Dcapi -Ddemo
install
└─ install demo-c
└─ compile exe demo-c Debug native 1 errors
error: ld.lld: .zig-cache/o/bef9b298ef8e2c610d51e05466e699fe/libreplace-exe.a: Archive::children failed: truncated or malformed archive (offset to next archive member past the end of the archive after member c_api.o)
error: the following command failed with 1 compilation errors:
/home/rolex/.zv/versions/0.15.2/zig build-exe /home/rolex/zig-stuff/replace-exe/demo/demo.c .zig-cache/o/bef9b298ef8e2c610d51e05466e699fe/libreplace-exe.a -ODebug -I .zig-cache/o/a6fb089e932f705ef1065695b36c6e90 -I /home/rolex/zig-stuff/replace-exe/include -Mroot -lc --cache-dir .zig-cache --global-cache-dir /home/rolex/.cache/zig --name demo-c --zig-lib-dir /home/rolex/.zv/versions/0.15.2/lib/ --listen=-
Build Summary: 8/11 steps succeeded; 1 failed
install transitive failure
└─ install demo-c transitive failure
└─ compile exe demo-c Debug native 1 errors
As far as I can interpret, this seems to be that the lib is not built before the linking step is initiated for demo_c causing it to be a malformed archive.
I thought demo_c.step.dependOn(&lib.step); would fix it but it didn’t
Can someone point out what’s wrong with this build script?
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const capi = b.option(bool, "capi", "Build libreplace-exe for use with C/C++") orelse false;
const so = b.option(bool, "shared", "Build shared library: libreplace-exe.so instead of default static lib") orelse false;
const demo = b.option(bool, "demo", "Build & Install demo executables") orelse true;
switch (target.result.os.tag) {
.windows, .linux, .macos, .freebsd, .netbsd, .dragonfly, .openbsd => {},
else => {
std.log.err("Unsupported Target OS: {s}", .{@tagName(target.result.os.tag)});
std.log.err("Supported: Windows, Linux, macOS, FreeBSD, NetBSD, DragonFly, OpenBSD", .{});
std.process.exit(1);
},
}
// Create module for the library
const lib_mod = b.addModule("replace_exe", .{
.root_source_file = b.path("root.zig"),
.target = target,
.optimize = optimize,
});
// C API needs to import the core module and link libc
var c_lib: ?*std.Build.Step.Compile = null;
if (capi) {
const lib = b.addLibrary(.{
.name = "replace-exe",
.linkage = if (so) .dynamic else .static,
.root_module = b.createModule(.{
.root_source_file = b.path("c_api.zig"),
.target = target,
.optimize = optimize,
}),
});
lib.root_module.addImport("replace_exe", lib_mod);
lib.linkLibC();
c_lib = lib;
// Install header file for C/C++ users
const header = b.addInstallFile(b.path("include/replace_exe.h"), "include/replace_exe.h");
b.getInstallStep().dependOn(&header.step);
b.installArtifact(lib);
}
// Tests
const lib_tests = b.addTest(.{
.root_module = lib_mod,
});
const run_lib_tests = b.addRunArtifact(lib_tests);
const test_step = b.step("test", "Run library tests");
test_step.dependOn(&run_lib_tests.step);
const demo_exe = b.addExecutable(.{
.name = "demo",
.root_module = b.createModule(.{
.root_source_file = b.path("demo/demo.zig"),
.target = target,
.optimize = optimize,
}),
});
demo_exe.root_module.addImport("replace-exe", lib_mod);
const demo_exe2 = b.addExecutable(.{
.name = "demo2",
.root_module = b.createModule(.{
.root_source_file = b.path("demo/demo2.zig"),
.target = target,
.optimize = optimize,
}),
});
demo_exe2.root_module.addImport("replace-exe", lib_mod);
if (c_lib) |lib| {
const demo_c = b.addExecutable(.{ .name = "demo-c", .root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}) });
demo_c.root_module.addCSourceFile(.{ .file = b.path("demo/demo.c") });
demo_c.root_module.link_libc = true;
demo_c.root_module.linkLibrary(lib);
demo_c.addIncludePath(b.path("include"));
demo_c.step.dependOn(&lib.step);
if (demo) {
b.installArtifact(demo_c);
}
}
if (demo) {
b.installArtifact(demo_exe);
b.installArtifact(demo_exe2);
}
const run_demo = b.addRunArtifact(demo_exe);
run_demo.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_demo.addArgs(args);
}
const run_step = b.step("run", "Run the demo executable");
run_step.dependOn(&run_demo.step);
}
btw I tried addInstallArtifact hoping that it would give me a step to dependOn but that didn’t work out either:
var c_lib: ?*std.Build.Step.Compile = null;
var lib_install_step: ?*std.Build.Step.InstallArtifact = null;
if (capi) {
const lib = b.addLibrary(.{
.name = "replace-exe",
.linkage = if (so) .dynamic else .static,
.root_module = b.createModule(.{
.root_source_file = b.path("c_api.zig"),
.target = target,
.optimize = optimize,
}),
});
lib.root_module.addImport("replace_exe", lib_mod);
lib.linkLibC();
c_lib = lib;
// Install header file for C/C++ users
const header = b.addInstallFile(b.path("include/replace_exe.h"), "include/replace_exe.h");
b.getInstallStep().dependOn(&header.step);
lib_install_step = b.addInstallArtifact(lib, .{});
}
and then
if (c_lib) |lib| {
if (lib_install_step) |step| {
const demo_c = b.addExecutable(.{ .name = "demo-c", .root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}) });
demo_c.root_module.addCSourceFile(.{ .file = b.path("demo/demo.c") });
demo_c.root_module.link_libc = true;
demo_c.step.dependOn(&step.step);
demo_c.root_module.linkLibrary(lib);
demo_c.addIncludePath(b.path("include"));
if (demo) {
b.installArtifact(demo_c);
}
}
}
Results in the same error: ld.lld: .zig-cache/o/bef9b298ef8e2c610d51e05466e699fe/libreplace-exe.a: Archive::children failed: truncated or malformed archive (offset to next archive member past the end of the archive after member c_api.o)