对c/c++有所了解的话,都知道宏的概念。c/c++当中使用宏来实现条件编译时非常常用的一种手段。不过zig语言是不支持宏的,但是其仍然支持条件编译,依赖的便是编译时运行的能力。
看一下ghostty的main函数入口,可以发现
const entrypoint = switch (build_config.exe_entrypoint) {
.ghostty => @import("main_ghostty.zig"),
.helpgen => @import("helpgen.zig"),
.mdgen_ghostty_1 => @import("build/mdgen/main_ghostty_1.zig"),
.mdgen_ghostty_5 => @import("build/mdgen/main_ghostty_5.zig"),
.webgen_config => @import("build/webgen/main_config.zig"),
.webgen_actions => @import("build/webgen/main_actions.zig"),
.webgen_commands => @import("build/webgen/main_commands.zig"),
.bench_parser => @import("bench/parser.zig"),
.bench_stream => @import("bench/stream.zig"),
.bench_codepoint_width => @import("bench/codepoint-width.zig"),
.bench_grapheme_break => @import("bench/grapheme-break.zig"),
.bench_page_init => @import("bench/page-init.zig"),
};
/// The main entrypoint for the program.
pub const main = entrypoint.main;其main函数并不是固定的,可以根据构建的选项不同可以构建出不同的程序出来。结合zig的构建系统和编译时运行来看是如何实现条件编译的。
这里的关键在于build_config的信息是如何在编译时获得的,追踪进去可以发现
pub fn fromOptions() Config {
const options = @import("build_options");
return .{
// Unused at runtime.
.optimize = undefined,
.target = undefined,
.env = undefined,
.version = options.app_version,
.flatpak = options.flatpak,
.app_runtime = std.meta.stringToEnum(apprt.Runtime, @tagName(options.app_runtime)).?,
.font_backend = std.meta.stringToEnum(font.Backend, @tagName(options.font_backend)).?,
.renderer = std.meta.stringToEnum(rendererpkg.Impl, @tagName(options.renderer)).?,
.exe_entrypoint = std.meta.stringToEnum(ExeEntrypoint, @tagName(options.exe_entrypoint)).?,
.wasm_target = std.meta.stringToEnum(WasmTarget, @tagName(options.wasm_target)).?,
.wasm_shared = options.wasm_shared,
};
}这里的核心在于@import("build_options")这行代码,因为这里倒入的模块build_options时编译器在编译的时候根据编译选项自动生成的模块。因此上面的这个函数会在编译时运行,同理调用该函数的模块同样也在编译期上下文中,所以编译这块代码的时候可以获取到编译选项的值,从而之行对应的逻辑,也就相当于条件编译了。
可以在build.zig为入口找到其添加构建选项的地方,上面的那些选项一定是在这个过程中添加的,比如exe_entrypoint这个选项
step.addOption(ExeEntrypoint, "exe_entrypoint", self.exe_entrypoint);和cmake构建选项的作用类似,不过zig的构建系统和zig的代码很好地结合在了一起