1- const Builder = @import ("std" ).build .Builder ;
1+ const std = @import ("std" );
2+ const fs = std .fs ;
3+ const log = std .log ;
4+
5+ const Allocator = std .mem .Allocator ;
6+ const Builder = std .build .Builder ;
7+ const FileSource = std .build .FileSource ;
8+ const LibExeObjStep = std .build .LibExeObjStep ;
9+ const InstallDir = std .build .InstallDir ;
10+ const Step = std .build .Step ;
211
312pub fn build (b : * Builder ) void {
4- // Standard target options allows the person running `zig build` to choose
5- // what target to build for. Here we do not override the defaults, which
6- // means any target is allowed, and the default is native. Other options
7- // for restricting supported target set are available.
813 const target = b .standardTargetOptions (.{});
9-
10- // Standard release options allow the person running `zig build` to select
11- // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
1214 const mode = b .standardReleaseOptions ();
1315
1416 const enable_logging = b .option (bool , "log" , "Whether to enable logging" ) orelse false ;
@@ -27,17 +29,13 @@ pub fn build(b: *Builder) void {
2729 const exe_opts = b .addOptions ();
2830 exe .addOptions ("build_options" , exe_opts );
2931 exe_opts .addOption (bool , "enable_logging" , enable_logging );
30-
3132 exe .install ();
3233
33- const run_cmd = exe .run ();
34- run_cmd .step .dependOn (b .getInstallStep ());
35- if (b .args ) | args | {
36- run_cmd .addArgs (args );
37- }
34+ const elf_symlink = symlink (exe , "ld.zld" );
35+ elf_symlink .step .dependOn (& exe .step );
3836
39- const run_step = b . step ( "run" , "Run the app " );
40- run_step . dependOn (& run_cmd .step );
37+ const macho_symlink = symlink ( exe , "ld64.zld " );
38+ macho_symlink . step . dependOn (& exe .step );
4139
4240 const tests = b .addTest ("src/test.zig" );
4341 tests .setBuildMode (mode );
@@ -47,8 +45,52 @@ pub fn build(b: *Builder) void {
4745 const test_opts = b .addOptions ();
4846 tests .addOptions ("build_options" , test_opts );
4947 test_opts .addOption (bool , "enable_qemu" , is_qemu_enabled );
48+ test_opts .addOption (bool , "enable_logging" , enable_logging );
5049
5150 const test_step = b .step ("test" , "Run library and end-to-end tests" );
52- test_step .dependOn (& exe .step );
5351 test_step .dependOn (& tests .step );
5452}
53+
54+ fn symlink (exe : * LibExeObjStep , name : []const u8 ) * CreateSymlinkStep {
55+ const step = CreateSymlinkStep .create (exe .builder , exe .getOutputSource (), name );
56+ exe .builder .getInstallStep ().dependOn (& step .step );
57+ return step ;
58+ }
59+
60+ const CreateSymlinkStep = struct {
61+ pub const base_id = .custom ;
62+
63+ step : Step ,
64+ builder : * Builder ,
65+ source : FileSource ,
66+ target : []const u8 ,
67+
68+ pub fn create (
69+ builder : * Builder ,
70+ source : FileSource ,
71+ target : []const u8 ,
72+ ) * CreateSymlinkStep {
73+ const self = builder .allocator .create (CreateSymlinkStep ) catch unreachable ;
74+ self .* = CreateSymlinkStep {
75+ .builder = builder ,
76+ .step = Step .init (.log , builder .fmt ("symlink {s} -> {s}" , .{
77+ source .getDisplayName (),
78+ target ,
79+ }), builder .allocator , make ),
80+ .source = source ,
81+ .target = builder .dupe (target ),
82+ };
83+ return self ;
84+ }
85+
86+ fn make (step : * Step ) anyerror ! void {
87+ const self = @fieldParentPtr (CreateSymlinkStep , "step" , step );
88+ const rel_source = fs .path .basename (self .source .getPath (self .builder ));
89+ const source_path = self .builder .getInstallPath (.bin , rel_source );
90+ const target_path = self .builder .getInstallPath (.bin , self .target );
91+ fs .atomicSymLink (self .builder .allocator , source_path , target_path ) catch | err | {
92+ log .err ("Unable to symlink {s} -> {s}" , .{ source_path , target_path });
93+ return err ;
94+ };
95+ }
96+ };
0 commit comments