178 lines
6.3 KiB
Zig
178 lines
6.3 KiB
Zig
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
|
|
fn run_process_and_capture_stdout(b: *std.Build, argv: []const []const u8) ![]const u8 {
|
|
const result = std.process.Child.run(.{
|
|
.allocator = b.allocator,
|
|
.argv = argv,
|
|
}) catch |err| return err;
|
|
switch (result.term) {
|
|
.Exited => |exit_code| {
|
|
if (exit_code != 0) {
|
|
return error.SpawnError;
|
|
}
|
|
},
|
|
else => return error.SpawnError,
|
|
}
|
|
|
|
return result.stdout;
|
|
}
|
|
|
|
fn file_find_in_path(allocator: std.mem.Allocator, file_name: []const u8, path_env: []const u8, extension: []const u8) ?[]const u8 {
|
|
const path_env_separator = switch (builtin.os.tag) {
|
|
.windows => ';',
|
|
else => ':',
|
|
};
|
|
const path_separator = switch (builtin.os.tag) {
|
|
.windows => '\\',
|
|
else => '/',
|
|
};
|
|
var env_it = std.mem.splitScalar(u8, path_env, path_env_separator);
|
|
const result: ?[]const u8 = while (env_it.next()) |dir_path| {
|
|
const full_path = std.mem.concatWithSentinel(allocator, u8, &.{ dir_path, &[1]u8{path_separator}, file_name, extension }, 0) catch unreachable;
|
|
const file = std.fs.cwd().openFile(full_path, .{}) catch continue;
|
|
file.close();
|
|
break full_path;
|
|
} else null;
|
|
return result;
|
|
}
|
|
|
|
fn executable_find_in_path(allocator: std.mem.Allocator, file_name: []const u8, path_env: []const u8) ?[]const u8 {
|
|
const extension = switch (builtin.os.tag) {
|
|
.windows => ".exe",
|
|
else => "",
|
|
};
|
|
return file_find_in_path(allocator, file_name, path_env, extension);
|
|
}
|
|
|
|
const LLVM = struct {
|
|
module: *std.Build.Module,
|
|
|
|
fn setup(b: *std.Build, path: []const u8, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) !LLVM {
|
|
var llvm_libs = std.ArrayList([]const u8).init(b.allocator);
|
|
var flags = std.ArrayList([]const u8).init(b.allocator);
|
|
const llvm_config_path = if (b.option([]const u8, "llvm_prefix", "LLVM prefix")) |llvm_prefix| blk: {
|
|
const full_path = try std.mem.concat(b.allocator, u8, &.{ llvm_prefix, "/bin/llvm-config" });
|
|
const f = std.fs.cwd().openFile(full_path, .{}) catch return error.llvm_not_found;
|
|
f.close();
|
|
break :blk full_path;
|
|
} else executable_find_in_path(b.allocator, "llvm-config", path) orelse return error.llvm_not_found;
|
|
const llvm_components_result = try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--components" });
|
|
var it = std.mem.splitScalar(u8, llvm_components_result, ' ');
|
|
var args = std.ArrayList([]const u8).init(b.allocator);
|
|
try args.append(llvm_config_path);
|
|
try args.append("--libs");
|
|
while (it.next()) |component| {
|
|
try args.append(std.mem.trimRight(u8, component, "\n"));
|
|
}
|
|
const llvm_libs_result = try run_process_and_capture_stdout(b, args.items);
|
|
it = std.mem.splitScalar(u8, llvm_libs_result, ' ');
|
|
|
|
while (it.next()) |lib| {
|
|
const llvm_lib = std.mem.trimLeft(u8, std.mem.trimRight(u8, lib, "\n"), "-l");
|
|
try llvm_libs.append(llvm_lib);
|
|
}
|
|
|
|
const llvm_cxx_flags_result = try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--cxxflags" });
|
|
it = std.mem.splitScalar(u8, llvm_cxx_flags_result, ' ');
|
|
while (it.next()) |flag| {
|
|
const llvm_cxx_flag = std.mem.trimRight(u8, flag, "\n");
|
|
try flags.append(llvm_cxx_flag);
|
|
}
|
|
|
|
const llvm_lib_dir = std.mem.trimRight(u8, try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--libdir" }), "\n");
|
|
|
|
if (optimize != .ReleaseSmall) {
|
|
try flags.append("-g");
|
|
}
|
|
|
|
try flags.append("-fno-rtti");
|
|
|
|
const llvm = b.createModule(.{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
|
|
llvm.addLibraryPath(.{ .cwd_relative = llvm_lib_dir });
|
|
|
|
llvm.addCSourceFiles(.{
|
|
.files = &.{"src/llvm.cpp"},
|
|
.flags = flags.items,
|
|
});
|
|
llvm.addIncludePath(.{ .cwd_relative = "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1" });
|
|
llvm.addIncludePath(.{ .cwd_relative = "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1/x86_64-pc-linux-gnu" });
|
|
|
|
const needed_libraries: []const []const u8 = &.{ "unwind", "z" };
|
|
|
|
llvm.addObjectFile(.{ .cwd_relative = "/usr/lib/libstdc++.so.6" });
|
|
|
|
const lld_libs: []const []const u8 = &.{ "lldCommon", "lldCOFF", "lldELF", "lldMachO", "lldMinGW", "lldWasm" };
|
|
|
|
for (needed_libraries) |lib| {
|
|
llvm.linkSystemLibrary(lib, .{});
|
|
}
|
|
|
|
for (llvm_libs.items) |lib| {
|
|
llvm.linkSystemLibrary(lib, .{});
|
|
}
|
|
|
|
for (lld_libs) |lib| {
|
|
llvm.linkSystemLibrary(lib, .{});
|
|
}
|
|
|
|
return LLVM{
|
|
.module = llvm,
|
|
};
|
|
}
|
|
|
|
fn link(llvm: LLVM, target: *std.Build.Step.Compile) void {
|
|
if (target.root_module != llvm.module) {
|
|
target.root_module.addImport("llvm", llvm.module);
|
|
} else {
|
|
// TODO: should we allow this case?
|
|
unreachable;
|
|
}
|
|
}
|
|
};
|
|
|
|
pub fn build(b: *std.Build) !void {
|
|
const target = b.standardTargetOptions(.{});
|
|
const optimize = b.standardOptimizeOption(.{});
|
|
const env = try std.process.getEnvMap(b.allocator);
|
|
const path = env.get("PATH") orelse unreachable;
|
|
|
|
const exe_mod = b.createModule(.{
|
|
.root_source_file = b.path("src/main.zig"),
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
|
|
const llvm = try LLVM.setup(b, path, target, optimize);
|
|
|
|
const exe = b.addExecutable(.{
|
|
.name = "bloat-buster",
|
|
.root_module = exe_mod,
|
|
});
|
|
|
|
llvm.link(exe);
|
|
|
|
b.installArtifact(exe);
|
|
|
|
const run_cmd = b.addRunArtifact(exe);
|
|
run_cmd.step.dependOn(b.getInstallStep());
|
|
if (b.args) |args| {
|
|
run_cmd.addArgs(args);
|
|
}
|
|
const run_step = b.step("run", "Run the app");
|
|
run_step.dependOn(&run_cmd.step);
|
|
|
|
const exe_unit_tests = b.addTest(.{
|
|
.root_module = exe_mod,
|
|
});
|
|
llvm.link(exe_unit_tests);
|
|
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
|
|
|
const test_step = b.step("test", "Run unit tests");
|
|
test_step.dependOn(&run_exe_unit_tests.step);
|
|
}
|