-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15708 from xxxbxxx/build-link
build: avoid repeating objects when linking a static library
- Loading branch information
Showing
4 changed files
with
174 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} |