const std = @import("std"); const capstone = @import("build/capstone.zig").capstone; pub fn build(b: *std.Build) !void { // A plain native build links against the host's glibc CRT objects // (/usr/lib/crt1.o). Recent toolchains emit `.sframe` unwind sections whose // R_X86_64_PC64 relocations Zig 0.16's self-hosted ELF linker cannot yet // handle, producing "unhandled relocation type" link errors. By defaulting // to an explicit-ABI (but otherwise native) target, Zig builds and links // its own bundled CRT instead, sidestepping the issue while keeping native // CPU/OS tuning. An explicit `-Dtarget=` still overrides this default. const target = b.standardTargetOptions(.{ .default_target = .{ .abi = b.graph.host.result.abi }, }); const optimize = b.standardOptimizeOption(.{}); const vaxis_dep = b.dependency("vaxis", .{}); const elfo = b.addExecutable(.{ .name = "elfo", .root_module = b.createModule(.{ .root_source_file = b.path("src/elfo.zig"), .target = target, .optimize = optimize, .link_libc = true, }), }); const shock = b.addExecutable(.{ .name = "shock", .root_module = b.createModule(.{ .root_source_file = b.path("src/shock.zig"), .target = target, .optimize = optimize, .link_libc = true, }), }); shock.root_module.addImport("vaxis", vaxis_dep.module("vaxis")); const capstone_lib = capstone(b, .{ .optimize = optimize, .target = target, }); b.installArtifact(capstone_lib); elfo.root_module.linkLibrary(capstone_lib); elfo.root_module.addImport("capstone", capstone_lib.root_module); b.installArtifact(elfo); const opt_gdb = b.option(bool, "gdb", "Run executable under gdb") orelse false; const comp_opts = b.addOptions(); comp_opts.addOption(bool, "gdb", opt_gdb); const unit_tests = b.addTest(.{ .root_module = b.createModule(.{ .optimize = optimize, .target = target, .root_source_file = b.path("tests/test.zig"), }), }); // Looooopy const c_file = b.createModule(.{ .optimize = .ReleaseFast, .target = target, .link_libc = true, }); const c_test_exe = b.addExecutable(.{ .root_module = c_file, .name = "sample_exe", }); c_file.addCSourceFile(.{ .file = b.path("tests/c/hello-world.c") }); const runner = b.addRunArtifact(elfo); runner.addArtifactArg(c_test_exe); const loop_step = b.step("loop", "Interative Programming Loop! you should run it with watch: i.e. zig build loop --watch"); loop_step.dependOn(&runner.step); // objdump comparison: per-symbol side-by-side elfo vs objdump const compare_runner = b.addRunArtifact(elfo); compare_runner.addArtifactArg(c_test_exe); compare_runner.addArg("--compare"); const objdump_step = b.step("objdump", "Compare elfo output against objdump per symbol"); objdump_step.dependOn(&compare_runner.step); // Symbol resolution test const test_symbols_mod = b.createModule(.{ .root_source_file = b.path("tests/test_symbols.zig"), .target = target, .optimize = optimize, .link_libc = true, }); test_symbols_mod.addImport("elfo", elfo.root_module); const test_symbols = b.addExecutable(.{ .name = "test_symbols", .root_module = test_symbols_mod, }); const run_test_symbols = b.addRunArtifact(test_symbols); run_test_symbols.addArtifactArg(c_test_exe); run_test_symbols.expectExitCode(0); // --- const zls_check = b.step("check", "Check if the program compiles"); zls_check.dependOn(&elfo.step); zls_check.dependOn(&shock.step); zls_check.dependOn(&unit_tests.step); const test_step = b.step("test", "Run unit tests"); test_step.dependOn(&run_test_symbols.step); const run_steps = [_]struct { *std.Build.Step, *std.Build.Step.Compile }{ .{ test_step, unit_tests }, .{ b.step("elfo", "See the pretty elfo!"), elfo }, .{ b.step("shock", "SHOCK something!"), shock }, }; const gdbscript = b.addWriteFile("gdbscript", \\r ); for (run_steps) |run| { run.@"1".root_module.addOptions("meta", comp_opts); if (opt_gdb) { const run_gdb = b.addSystemCommand(&.{"gdb"}); run_gdb.addArg("-x"); run_gdb.addFileArg(gdbscript.getDirectory().path(b, "gdbscript")); run_gdb.addArtifactArg(run.@"1"); run.@"0".dependOn(&run_gdb.step); } else { const run_unit = b.addRunArtifact(run.@"1"); run.@"0".dependOn(&run_unit.step); } } }