From 8142bc20ea8bcffc076fcbde074a7e315ff0060a Mon Sep 17 00:00:00 2001 From: Xavier Bouchoux Date: Sun, 9 Jul 2023 20:46:39 +0200 Subject: [PATCH] test: linking static libraries built from intermediary object files --- test/link.zig | 4 + .../static_libs_from_object_files/build.zig | 148 ++++++++++++++++++ .../static_libs_from_object_files/main.zig | 20 +++ 3 files changed, 172 insertions(+) create mode 100644 test/link/static_libs_from_object_files/build.zig create mode 100644 test/link/static_libs_from_object_files/main.zig diff --git a/test/link.zig b/test/link.zig index 6f8134e4f4..ac0bcf3df8 100644 --- a/test/link.zig +++ b/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"), diff --git a/test/link/static_libs_from_object_files/build.zig b/test/link/static_libs_from_object_files/build.zig new file mode 100644 index 0000000000..13365ba153 --- /dev/null +++ b/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); + } +} diff --git a/test/link/static_libs_from_object_files/main.zig b/test/link/static_libs_from_object_files/main.zig new file mode 100644 index 0000000000..c0f577e7df --- /dev/null +++ b/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()); +}