Commit 8142bc20ea

Xavier Bouchoux <xavierb@gmail.com>
2023-07-09 20:46:39
test: linking static libraries built from intermediary object files
1 parent 6bc9c4f
Changed files (3)
test
link
static_libs_from_object_files
test/link/static_libs_from_object_files/build.zig
@@ -0,0 +1,148 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+const Build = std.Build;
+const FileSource = Build.FileSource;
+const Step = Build.Step;
+const Run = Step.Run;
+const WriteFile = Step.WriteFile;
+
+pub fn build(b: *Build) void {
+    const nb_files = b.option(u32, "nb_files", "Number of c files to generate.") orelse 10;
+
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    // generate c files
+    const files = b.allocator.alloc(std.Build.FileSource, nb_files) catch unreachable;
+    defer b.allocator.free(files);
+    {
+        for (files[0 .. nb_files - 1], 1..nb_files) |*file, i| {
+            const wf = WriteFile.create(b);
+            file.* = wf.add(b.fmt("src_{}.c", .{i}), b.fmt(
+                \\extern int foo_0();
+                \\extern int bar_{}();
+                \\extern int one_{};
+                \\int one_{} = 1;
+                \\int foo_{}() {{ return one_{} + foo_0(); }}
+                \\int bar_{}() {{ return bar_{}(); }}
+            , .{ i - 1, i - 1, i, i, i - 1, i, i - 1 }));
+        }
+
+        {
+            const wf = WriteFile.create(b);
+            files[nb_files - 1] = wf.add("src_last.c", b.fmt(
+                \\extern int foo_0();
+                \\extern int bar_{}();
+                \\extern int one_{};
+                \\int foo_last() {{ return one_{} + foo_0(); }}
+                \\int bar_last() {{ return bar_{}(); }}
+            , .{ nb_files - 1, nb_files - 1, nb_files - 1, nb_files - 1 }));
+        }
+    }
+
+    add(b, test_step, files, .Debug);
+    add(b, test_step, files, .ReleaseSafe);
+    add(b, test_step, files, .ReleaseSmall);
+    add(b, test_step, files, .ReleaseFast);
+}
+
+fn add(b: *Build, test_step: *Step, files: []const std.Build.FileSource, optimize: std.builtin.OptimizeMode) void {
+    const flags = [_][]const u8{
+        "-Wall",
+        "-std=c11",
+    };
+
+    // all files at once
+    {
+        const exe = b.addExecutable(.{
+            .name = "test1",
+            .root_source_file = .{ .path = "main.zig" },
+            .optimize = optimize,
+            .target = .{},
+        });
+
+        for (files) |file| {
+            exe.addCSourceFileSource(.{ .source = file, .args = &flags });
+        }
+
+        const run_cmd = b.addRunArtifact(exe);
+        run_cmd.skip_foreign_checks = true;
+        run_cmd.expectExitCode(0);
+
+        test_step.dependOn(&run_cmd.step);
+    }
+
+    // using static librairies
+    {
+        const lib_a = b.addStaticLibrary(.{
+            .name = "test2_a",
+            .target = .{},
+            .optimize = optimize,
+        });
+        const lib_b = b.addStaticLibrary(.{
+            .name = "test2_b",
+            .target = .{},
+            .optimize = optimize,
+        });
+
+        for (files, 1..) |file, i| {
+            const lib = if (i & 1 == 0) lib_a else lib_b;
+            lib.addCSourceFileSource(.{ .source = file, .args = &flags });
+        }
+
+        const exe = b.addExecutable(.{
+            .name = "test2",
+            .root_source_file = .{ .path = "main.zig" },
+            .optimize = optimize,
+        });
+        exe.linkLibrary(lib_a);
+        exe.linkLibrary(lib_b);
+
+        const run_cmd = b.addRunArtifact(exe);
+        run_cmd.skip_foreign_checks = true;
+        run_cmd.expectExitCode(0);
+
+        test_step.dependOn(&run_cmd.step);
+    }
+
+    // using static librairies and object files
+    {
+        const lib_a = b.addStaticLibrary(.{
+            .name = "test3_a",
+            .target = .{},
+            .optimize = optimize,
+        });
+        const lib_b = b.addStaticLibrary(.{
+            .name = "test3_b",
+            .target = .{},
+            .optimize = optimize,
+        });
+
+        for (files, 1..) |file, i| {
+            const obj = b.addObject(.{
+                .name = b.fmt("obj_{}", .{i}),
+                .target = .{},
+                .optimize = optimize,
+            });
+            obj.addCSourceFileSource(.{ .source = file, .args = &flags });
+
+            const lib = if (i & 1 == 0) lib_a else lib_b;
+            lib.addObject(obj);
+        }
+
+        const exe = b.addExecutable(.{
+            .name = "test3",
+            .root_source_file = .{ .path = "main.zig" },
+            .optimize = optimize,
+        });
+        exe.linkLibrary(lib_a);
+        exe.linkLibrary(lib_b);
+
+        const run_cmd = b.addRunArtifact(exe);
+        run_cmd.skip_foreign_checks = true;
+        run_cmd.expectExitCode(0);
+
+        test_step.dependOn(&run_cmd.step);
+    }
+}
test/link/static_libs_from_object_files/main.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+extern fn foo_last() i32;
+extern fn bar_last() i32;
+
+export const one_0: i32 = 1;
+
+export fn foo_0() i32 {
+    return 1234;
+}
+export fn bar_0() i32 {
+    return 5678;
+}
+
+pub fn main() anyerror!void {
+    const foo_expected: i32 = 1 + 1234;
+    const bar_expected: i32 = 5678;
+    try std.testing.expectEqual(foo_expected, foo_last());
+    try std.testing.expectEqual(bar_expected, bar_last());
+}
test/link.zig
@@ -20,6 +20,10 @@ pub const cases = [_]Case{
         .build_root = "test/link/interdependent_static_c_libs",
         .import = @import("link/interdependent_static_c_libs/build.zig"),
     },
+    .{
+        .build_root = "test/link/static_libs_from_object_files",
+        .import = @import("link/static_libs_from_object_files/build.zig"),
+    },
     .{
         .build_root = "test/link/glibc_compat",
         .import = @import("link/glibc_compat/build.zig"),