Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318const std = @import("std");
/// The package version, single-sourced from build.zig.zon.const version_string = blk: { const zon = @embedFile("build.zig.zon"); const marker = ".version = \""; const start = (std.mem.indexOf(u8, zon, marker) orelse @compileError("no version in build.zig.zon")) + marker.len; const end = std.mem.indexOfScalarPos(u8, zon, start, '"') orelse @compileError("unterminated version in build.zig.zon"); break :blk zon[start..end];};
pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const use_llvm = b.option(bool, "llvm", "Use the LLVM backend for compile steps") orelse true; const external_uucode = b.option(bool, "external_uucode", "Use an externally provided uucode module instead of the built-in dependency") orelse false; const root_source_file = b.path("src/main.zig");
// Dependencies const zigimg_dep = b.dependency("zigimg", .{ .optimize = optimize, .target = target, }); const uucode_mod = if (!external_uucode) blk: { const uucode_dep = b.lazyDependency("uucode", .{ .target = target, .optimize = optimize, .fields = @as([]const []const u8, &.{ "east_asian_width", "grapheme_break", "general_category", "is_emoji_presentation", }), }) orelse break :blk null; break :blk uucode_dep.module("uucode"); } else null;
// Module const vaxis_mod = b.addModule("vaxis", .{ .root_source_file = root_source_file, .target = target, .optimize = optimize, }); vaxis_mod.addImport("zigimg", zigimg_dep.module("zigimg")); if (uucode_mod) |mod| { vaxis_mod.addImport("uucode", mod); } else { // External uucode mode: consumer wires up their own uucode module on // the vaxis module. Skip examples, bench, tests, and docs steps since // they all depend on uucode being available here. return; }
// Exposes the terminal input parser over a C ABI (see include/vaxis.h), const c_api_options = b.addOptions(); c_api_options.addOption([]const u8, "version", version_string); const c_api_mod = b.createModule(.{ .root_source_file = b.path("src/c_api.zig"), .target = target, .optimize = optimize, .pic = true, .link_libc = true, .imports = &.{ .{ .name = "vaxis", .module = vaxis_mod }, .{ .name = "build_options", .module = c_api_options.createModule() }, }, });
// Compile the C API once as PIC, then use the resulting object for both // library formats. Building two libraries directly from c_api_mod would // run Zig's frontend and code generator once per linkage. const c_api_object = b.addObject(.{ .name = "vaxis-c-api", .root_module = c_api_mod, .use_llvm = use_llvm, });
const static_mod = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true, }); static_mod.addObject(c_api_object); const static_lib = b.addLibrary(.{ // the DLL import library is also named vaxis.lib on Windows .name = if (target.result.os.tag == .windows) "vaxis-static" else "vaxis", .linkage = .static, .root_module = static_mod, .use_llvm = use_llvm, });
const shared_mod = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true, }); shared_mod.addObject(c_api_object); const shared_lib = b.addLibrary(.{ .name = "vaxis", .linkage = .dynamic, .root_module = shared_mod, .use_llvm = use_llvm, .version = std.SemanticVersion.parse(version_string) catch unreachable, });
const install_static = b.addInstallArtifact(static_lib, .{}); const install_shared = b.addInstallArtifact(shared_lib, .{}); const install_headers = b.addInstallDirectory(.{ .source_dir = b.path("include"), .install_dir = .header, .install_subdir = "", }); const lib_static_step = b.step("lib-static", "Build the static C library"); lib_static_step.dependOn(&install_static.step); lib_static_step.dependOn(&install_headers.step); const lib_shared_step = b.step("lib-shared", "Build the shared C library"); lib_shared_step.dependOn(&install_shared.step); lib_shared_step.dependOn(&install_headers.step); const lib_step = b.step("lib", "Build the C library (static and shared)"); lib_step.dependOn(lib_static_step); lib_step.dependOn(lib_shared_step);
// Examples const Example = enum { cli, counter, fuzzy, image, main, scroll, split_view, table, text_input, text_view, list_view, vaxis, view, vt, }; var examples: std.EnumMap(Example, *std.Build.Module) = .init(.{}); inline for (comptime std.enums.values(Example)) |example| { examples.put( example, b.createModule(.{ .root_source_file = b.path( b.fmt("examples/{t}.zig", .{example}), ), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "vaxis", .module = vaxis_mod }, }, }), ); } const example_option = b.option(Example, "example", "Example to run (default: text_input)") orelse .text_input; const example_step = b.step("example", "Run example"); const example = b.addExecutable(.{ .name = b.fmt("example-{t}", .{example_option}), .root_module = examples.get(example_option) orelse unreachable, .use_llvm = use_llvm, });
b.getInstallStep().dependOn(&example.step);
const example_run = b.addRunArtifact(example); example_step.dependOn(&example_run.step);
// Benchmarks const bench_step = b.step("bench", "Run benchmarks"); const bench = b.addExecutable(.{ .name = "bench", .use_llvm = use_llvm, .root_module = b.createModule(.{ .root_source_file = b.path("bench/bench.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "vaxis", .module = vaxis_mod }, }, }), }); const bench_run = b.addRunArtifact(bench); bench_run.addPassthruArgs(); bench_step.dependOn(&bench_run.step);
// Tests const tests_step = b.step("test", "Run tests");
const tests = b.addTest(.{ .use_llvm = use_llvm, .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "zigimg", .module = zigimg_dep.module("zigimg") }, .{ .name = "uucode", .module = uucode_mod.? }, }, }), });
// Let's make sure that all of the examples compile and can run any tests // that they may have defined. var it = examples.iterator(); while (it.next()) |v| { const e = b.addTest(.{ .use_llvm = use_llvm, .root_module = v.value.*, }); const r = b.addRunArtifact(e); tests_step.dependOn(&r.step); }
const tests_run = b.addRunArtifact(tests); b.installArtifact(tests); tests_step.dependOn(&tests_run.step);
// C API tests: Zig unit tests plus a C program linked against the // static library // The tests also import include/vaxis.h, translated to Zig, to check // that the header matches the ABI const vaxis_h = b.addTranslateC(.{ .root_source_file = b.path("include/vaxis.h"), .target = target, .optimize = optimize, }); const c_api_tests = b.addTest(.{ .use_llvm = use_llvm, .root_module = b.createModule(.{ .root_source_file = b.path("src/c_api.zig"), .target = target, .optimize = optimize, .link_libc = true, .imports = &.{ .{ .name = "vaxis", .module = vaxis_mod }, .{ .name = "build_options", .module = c_api_options.createModule() }, .{ .name = "vaxis_h", .module = vaxis_h.createModule() }, }, }), }); tests_step.dependOn(&b.addRunArtifact(c_api_tests).step);
const c_test_mod = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true, }); c_test_mod.addCSourceFile(.{ .file = b.path("examples/c/parse.c"), .flags = &.{ "-std=c99", "-pedantic-errors" }, }); c_test_mod.addIncludePath(b.path("include")); c_test_mod.linkLibrary(static_lib); const c_test = b.addExecutable(.{ .name = "example-c-parse", .root_module = c_test_mod, .use_llvm = use_llvm, }); tests_step.dependOn(&b.addRunArtifact(c_test).step);
const c_runtime_mod = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true, }); c_runtime_mod.addCSourceFile(.{ .file = b.path("examples/c/runtime.c"), .flags = &.{ "-std=c99", "-pedantic-errors" }, }); c_runtime_mod.addIncludePath(b.path("include")); c_runtime_mod.linkLibrary(static_lib); const c_runtime_test = b.addExecutable(.{ .name = "example-c-runtime", .root_module = c_runtime_mod, .use_llvm = use_llvm, }); tests_step.dependOn(&b.addRunArtifact(c_runtime_test).step);
const c_tty_mod = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true, }); c_tty_mod.addCSourceFile(.{ .file = b.path("examples/c/tty.c"), .flags = &.{ "-std=c99", "-pedantic-errors" }, }); c_tty_mod.addIncludePath(b.path("include")); c_tty_mod.linkLibrary(static_lib); const c_tty_test = b.addExecutable(.{ .name = "example-c-tty", .root_module = c_tty_mod, .use_llvm = use_llvm, }); tests_step.dependOn(&b.addRunArtifact(c_tty_test).step);
// Docs const docs_step = b.step("docs", "Build the vaxis library docs"); const docs_obj = b.addObject(.{ .name = "vaxis", .use_llvm = use_llvm, .root_module = b.createModule(.{ .root_source_file = root_source_file, .target = target, .optimize = optimize, }), }); const docs = docs_obj.getEmittedDocs(); docs_step.dependOn(&b.addInstallDirectory(.{ .source_dir = docs, .install_dir = .prefix, .install_subdir = "docs", }).step);}