build: use Zig system packaging options

This allows dynamically linking against system libraries, which is
particularly useful for packaging.
This commit is contained in:
Mitchell Hashimoto
2024-10-24 10:03:11 -07:00
parent 61aff898bd
commit 8bb8b01e54
9 changed files with 388 additions and 269 deletions

464
build.zig
View File

@ -94,12 +94,6 @@ pub fn build(b: *std.Build) !void {
"Enables the use of libadwaita when using the gtk rendering backend.", "Enables the use of libadwaita when using the gtk rendering backend.",
) orelse true; ) orelse true;
config.static = b.option(
bool,
"static",
"Statically build as much as possible for the exe",
) orelse true;
const conformance = b.option( const conformance = b.option(
[]const u8, []const u8,
"conformance", "conformance",
@ -221,6 +215,40 @@ pub fn build(b: *std.Build) !void {
}; };
}; };
// These are all our dependencies that can be used with system
// packages if they exist. We set them up here so that we can set
// their defaults early. The first call configures the integration and
// subsequent calls just return the configured value.
{
// These dependencies we want to default false if we're on macOS.
// On macOS we don't want to use system libraries because we
// generally want a fat binary. This can be overridden with the
// `-fsys` flag.
for (&[_][]const u8{
"freetype",
"harfbuzz",
"fontconfig",
"libpng",
"zlib",
"oniguruma",
}) |dep| {
_ = b.systemIntegrationOption(
dep,
.{ .default = !target.result.isDarwin() },
);
}
// These default to false because they're rarely available as
// system packages so we usually want to statically link them.
for (&[_][]const u8{
"glslang",
"spirv-cross",
"simdutf",
}) |dep| {
_ = b.systemIntegrationOption(dep, .{ .default = false });
}
}
// We can use wasmtime to test wasm // We can use wasmtime to test wasm
b.enable_wasmtime = true; b.enable_wasmtime = true;
@ -653,10 +681,6 @@ pub fn build(b: *std.Build) !void {
const wasm_config: BuildConfig = config: { const wasm_config: BuildConfig = config: {
var copy = config; var copy = config;
// Always static for the wasm app because we want all of our
// dependencies in a fat static library.
copy.static = true;
// Backends that are fixed for wasm // Backends that are fixed for wasm
copy.font_backend = .web_canvas; copy.font_backend = .web_canvas;
@ -748,12 +772,7 @@ pub fn build(b: *std.Build) !void {
{ {
if (emit_test_exe) b.installArtifact(main_test); if (emit_test_exe) b.installArtifact(main_test);
_ = try addDeps(b, main_test, config: { _ = try addDeps(b, main_test, config);
var copy = config;
copy.static = true;
break :config copy;
});
const test_run = b.addRunArtifact(main_test); const test_run = b.addRunArtifact(main_test);
test_step.dependOn(&test_run.step); test_step.dependOn(&test_run.step);
} }
@ -807,17 +826,6 @@ fn createMacOSLib(
optimize: std.builtin.OptimizeMode, optimize: std.builtin.OptimizeMode,
config: BuildConfig, config: BuildConfig,
) !struct { *std.Build.Step, std.Build.LazyPath } { ) !struct { *std.Build.Step, std.Build.LazyPath } {
// Modify our build configuration for macOS builds.
const macos_config: BuildConfig = config: {
var copy = config;
// Always static for the macOS app because we want all of our
// dependencies in a fat static library.
copy.static = true;
break :config copy;
};
const static_lib_aarch64 = lib: { const static_lib_aarch64 = lib: {
const lib = b.addStaticLibrary(.{ const lib = b.addStaticLibrary(.{
.name = "ghostty", .name = "ghostty",
@ -829,7 +837,7 @@ fn createMacOSLib(
lib.linkLibC(); lib.linkLibC();
// Create a single static lib with all our dependencies merged // Create a single static lib with all our dependencies merged
var lib_list = try addDeps(b, lib, macos_config); var lib_list = try addDeps(b, lib, config);
try lib_list.append(lib.getEmittedBin()); try lib_list.append(lib.getEmittedBin());
const libtool = LibtoolStep.create(b, .{ const libtool = LibtoolStep.create(b, .{
.name = "ghostty", .name = "ghostty",
@ -853,7 +861,7 @@ fn createMacOSLib(
lib.linkLibC(); lib.linkLibC();
// Create a single static lib with all our dependencies merged // Create a single static lib with all our dependencies merged
var lib_list = try addDeps(b, lib, macos_config); var lib_list = try addDeps(b, lib, config);
try lib_list.append(lib.getEmittedBin()); try lib_list.append(lib.getEmittedBin());
const libtool = LibtoolStep.create(b, .{ const libtool = LibtoolStep.create(b, .{
.name = "ghostty", .name = "ghostty",
@ -888,12 +896,6 @@ fn createIOSLib(
optimize: std.builtin.OptimizeMode, optimize: std.builtin.OptimizeMode,
config: BuildConfig, config: BuildConfig,
) !struct { *std.Build.Step, std.Build.LazyPath } { ) !struct { *std.Build.Step, std.Build.LazyPath } {
const ios_config: BuildConfig = config: {
var copy = config;
copy.static = true;
break :config copy;
};
const lib = b.addStaticLibrary(.{ const lib = b.addStaticLibrary(.{
.name = "ghostty", .name = "ghostty",
.root_source_file = b.path("src/main_c.zig"), .root_source_file = b.path("src/main_c.zig"),
@ -909,7 +911,7 @@ fn createIOSLib(
lib.linkLibC(); lib.linkLibC();
// Create a single static lib with all our dependencies merged // Create a single static lib with all our dependencies merged
var lib_list = try addDeps(b, lib, ios_config); var lib_list = try addDeps(b, lib, config);
try lib_list.append(lib.getEmittedBin()); try lib_list.append(lib.getEmittedBin());
const libtool = LibtoolStep.create(b, .{ const libtool = LibtoolStep.create(b, .{
.name = "ghostty", .name = "ghostty",
@ -938,9 +940,14 @@ fn addDeps(
try config.addOptions(exe_options); try config.addOptions(exe_options);
step.root_module.addOptions("build_options", exe_options); step.root_module.addOptions("build_options", exe_options);
// We maintain a list of our static libraries and return it so that
// we can build a single fat static library for the final app.
var static_libs = LazyPathList.init(b.allocator); var static_libs = LazyPathList.init(b.allocator);
errdefer static_libs.deinit(); errdefer static_libs.deinit();
const target = step.root_module.resolved_target.?;
const optimize = step.root_module.optimize.?;
// For dynamic linking, we prefer dynamic linking and to search by // For dynamic linking, we prefer dynamic linking and to search by
// mode first. Mode first will search all paths for a dynamic library // mode first. Mode first will search all paths for a dynamic library
// before falling back to static. // before falling back to static.
@ -949,106 +956,167 @@ fn addDeps(
.search_strategy = .mode_first, .search_strategy = .mode_first,
}; };
const target = step.root_module.resolved_target.?; // Freetype
const optimize = step.root_module.optimize.?; _ = b.systemIntegrationOption("freetype", .{}); // Shows it in help
if (config.font_backend.hasFreetype()) {
const freetype_dep = b.dependency("freetype", .{
.target = target,
.optimize = optimize,
.@"enable-libpng" = true,
});
step.root_module.addImport("freetype", freetype_dep.module("freetype"));
// Dependencies if (b.systemIntegrationOption("freetype", .{})) {
const cimgui_dep = b.dependency("cimgui", .{ step.linkSystemLibrary2("bzip2", dynamic_link_opts);
.target = target, step.linkSystemLibrary2("freetype", dynamic_link_opts);
.optimize = optimize, } else {
}); step.linkLibrary(freetype_dep.artifact("freetype"));
const js_dep = b.dependency("zig_js", .{ try static_libs.append(freetype_dep.artifact("freetype").getEmittedBin());
.target = target, }
.optimize = optimize, }
});
const libxev_dep = b.dependency("libxev", .{
.target = target,
.optimize = optimize,
});
const objc_dep = b.dependency("zig_objc", .{
.target = target,
.optimize = optimize,
});
const fontconfig_dep = b.dependency("fontconfig", .{ // Harfbuzz
.target = target, _ = b.systemIntegrationOption("harfbuzz", .{}); // Shows it in help
.optimize = optimize, if (config.font_backend.hasHarfbuzz()) {
}); const harfbuzz_dep = b.dependency("harfbuzz", .{
const freetype_dep = b.dependency("freetype", .{ .target = target,
.target = target, .optimize = optimize,
.optimize = optimize, .@"enable-freetype" = true,
.@"enable-libpng" = true, .@"enable-coretext" = config.font_backend.hasCoretext(),
}); });
const glslang_dep = b.dependency("glslang", .{
.target = target, step.root_module.addImport(
.optimize = optimize, "harfbuzz",
}); harfbuzz_dep.module("harfbuzz"),
const spirv_cross_dep = b.dependency("spirv_cross", .{ );
.target = target, if (b.systemIntegrationOption("harfbuzz", .{})) {
.optimize = optimize, step.linkSystemLibrary2("harfbuzz", dynamic_link_opts);
}); } else {
const highway_dep = b.dependency("highway", .{ step.linkLibrary(harfbuzz_dep.artifact("harfbuzz"));
.target = target, try static_libs.append(harfbuzz_dep.artifact("harfbuzz").getEmittedBin());
.optimize = optimize, }
}); }
const simdutf_dep = b.dependency("simdutf", .{
.target = target, // Fontconfig
.optimize = optimize, _ = b.systemIntegrationOption("fontconfig", .{}); // Shows it in help
}); if (config.font_backend.hasFontconfig()) {
const utfcpp_dep = b.dependency("utfcpp", .{ const fontconfig_dep = b.dependency("fontconfig", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); });
const libpng_dep = b.dependency("libpng", .{ step.root_module.addImport(
.target = target, "fontconfig",
.optimize = optimize, fontconfig_dep.module("fontconfig"),
}); );
const macos_dep = b.dependency("macos", .{
.target = target, if (b.systemIntegrationOption("fontconfig", .{})) {
.optimize = optimize, step.linkSystemLibrary2("fontconfig", dynamic_link_opts);
}); } else {
step.linkLibrary(fontconfig_dep.artifact("fontconfig"));
try static_libs.append(fontconfig_dep.artifact("fontconfig").getEmittedBin());
}
}
// Libpng - Ghostty doesn't actually use this directly, its only used
// through dependencies, so we only need to add it to our static
// libs list if we're not using system integration. The dependencies
// will handle linking it.
if (!b.systemIntegrationOption("libpng", .{})) {
const libpng_dep = b.dependency("libpng", .{
.target = target,
.optimize = optimize,
});
step.linkLibrary(libpng_dep.artifact("png"));
try static_libs.append(libpng_dep.artifact("png").getEmittedBin());
}
// Zlib - same as libpng, only used through dependencies.
if (!b.systemIntegrationOption("zlib", .{})) {
const zlib_dep = b.dependency("zlib", .{
.target = target,
.optimize = optimize,
});
step.linkLibrary(zlib_dep.artifact("z"));
try static_libs.append(zlib_dep.artifact("z").getEmittedBin());
}
// Oniguruma
const oniguruma_dep = b.dependency("oniguruma", .{ const oniguruma_dep = b.dependency("oniguruma", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); });
const opengl_dep = b.dependency("opengl", .{}); step.root_module.addImport("oniguruma", oniguruma_dep.module("oniguruma"));
if (b.systemIntegrationOption("oniguruma", .{})) {
step.linkSystemLibrary2("oniguruma", dynamic_link_opts);
} else {
step.linkLibrary(oniguruma_dep.artifact("oniguruma"));
try static_libs.append(oniguruma_dep.artifact("oniguruma").getEmittedBin());
}
// Glslang
const glslang_dep = b.dependency("glslang", .{
.target = target,
.optimize = optimize,
});
step.root_module.addImport("glslang", glslang_dep.module("glslang"));
if (b.systemIntegrationOption("glslang", .{})) {
step.linkSystemLibrary2("glslang", dynamic_link_opts);
} else {
step.linkLibrary(glslang_dep.artifact("glslang"));
try static_libs.append(glslang_dep.artifact("glslang").getEmittedBin());
}
// Spirv-cross
const spirv_cross_dep = b.dependency("spirv_cross", .{
.target = target,
.optimize = optimize,
});
step.root_module.addImport("spirv_cross", spirv_cross_dep.module("spirv_cross"));
if (b.systemIntegrationOption("spirv-cross", .{})) {
step.linkSystemLibrary2("spirv-cross", dynamic_link_opts);
} else {
step.linkLibrary(spirv_cross_dep.artifact("spirv_cross"));
try static_libs.append(spirv_cross_dep.artifact("spirv_cross").getEmittedBin());
}
// Simdutf
if (b.systemIntegrationOption("simdutf", .{})) {
step.linkSystemLibrary2("simdutf", dynamic_link_opts);
} else {
const simdutf_dep = b.dependency("simdutf", .{
.target = target,
.optimize = optimize,
});
step.linkLibrary(simdutf_dep.artifact("simdutf"));
try static_libs.append(simdutf_dep.artifact("simdutf").getEmittedBin());
}
// Sentry
const sentry_dep = b.dependency("sentry", .{ const sentry_dep = b.dependency("sentry", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.backend = .breakpad, .backend = .breakpad,
}); });
const zlib_dep = b.dependency("zlib", .{ step.root_module.addImport("sentry", sentry_dep.module("sentry"));
.target = target, if (target.result.os.tag != .windows) {
.optimize = optimize, // Sentry
}); step.linkLibrary(sentry_dep.artifact("sentry"));
const harfbuzz_dep = b.dependency("harfbuzz", .{ try static_libs.append(sentry_dep.artifact("sentry").getEmittedBin());
.target = target,
.optimize = optimize, // We also need to include breakpad in the static libs.
.@"enable-freetype" = true, const breakpad_dep = sentry_dep.builder.dependency("breakpad", .{
.@"enable-coretext" = config.font_backend.hasCoretext(), .target = target,
}); .optimize = optimize,
const ziglyph_dep = b.dependency("ziglyph", .{ });
.target = target, try static_libs.append(breakpad_dep.artifact("breakpad").getEmittedBin());
.optimize = optimize, }
});
const vaxis_dep = b.dependency("vaxis", .{
.target = target,
.optimize = optimize,
.libxev = false,
.images = false,
});
const wuffs_dep = b.dependency("wuffs", .{
.target = target,
.optimize = optimize,
});
const zf_dep = b.dependency("zf", .{
.target = target,
.optimize = optimize,
});
const z2d_dep = b.dependency("z2d", .{});
// Wasm we do manually since it is such a different build. // Wasm we do manually since it is such a different build.
if (step.rootModuleTarget().cpu.arch == .wasm32) { if (step.rootModuleTarget().cpu.arch == .wasm32) {
const js_dep = b.dependency("zig_js", .{
.target = target,
.optimize = optimize,
});
step.root_module.addImport("zig-js", js_dep.module("zig-js")); step.root_module.addImport("zig-js", js_dep.module("zig-js"));
return static_libs; return static_libs;
@ -1100,9 +1168,6 @@ fn addDeps(
}); });
} }
// If we're building a lib we have some different deps
const lib = step.kind == .lib;
// We always require the system SDK so that our system headers are available. // We always require the system SDK so that our system headers are available.
// This makes things like `os/log.h` available for cross-compiling. // This makes things like `os/log.h` available for cross-compiling.
if (step.rootModuleTarget().isDarwin()) { if (step.rootModuleTarget().isDarwin()) {
@ -1110,36 +1175,50 @@ fn addDeps(
try addMetallib(b, step); try addMetallib(b, step);
} }
// We always need the Zig packages // Other dependencies, mostly pure Zig
// TODO: This can't be the right way to use the new Zig modules system, step.root_module.addImport("opengl", b.dependency(
// so take a closer look at this again later. "opengl",
if (config.font_backend.hasFontconfig()) step.root_module.addImport( .{},
"fontconfig", ).module("opengl"));
fontconfig_dep.module("fontconfig"), step.root_module.addImport("vaxis", b.dependency("vaxis", .{
); .target = target,
if (config.font_backend.hasHarfbuzz()) step.root_module.addImport( .optimize = optimize,
"harfbuzz", .libxev = false,
harfbuzz_dep.module("harfbuzz"), .images = false,
); }).module("vaxis"));
step.root_module.addImport("oniguruma", oniguruma_dep.module("oniguruma")); step.root_module.addImport("wuffs", b.dependency("wuffs", .{
step.root_module.addImport("freetype", freetype_dep.module("freetype")); .target = target,
step.root_module.addImport("glslang", glslang_dep.module("glslang")); .optimize = optimize,
step.root_module.addImport("spirv_cross", spirv_cross_dep.module("spirv_cross")); }).module("wuffs"));
step.root_module.addImport("xev", libxev_dep.module("xev")); step.root_module.addImport("xev", b.dependency("libxev", .{
step.root_module.addImport("opengl", opengl_dep.module("opengl")); .target = target,
step.root_module.addImport("sentry", sentry_dep.module("sentry")); .optimize = optimize,
step.root_module.addImport("ziglyph", ziglyph_dep.module("ziglyph")); }).module("xev"));
step.root_module.addImport("vaxis", vaxis_dep.module("vaxis"));
step.root_module.addImport("wuffs", wuffs_dep.module("wuffs"));
step.root_module.addImport("zf", zf_dep.module("zf"));
step.root_module.addImport("z2d", b.addModule("z2d", .{ step.root_module.addImport("z2d", b.addModule("z2d", .{
.root_source_file = z2d_dep.path("src/z2d.zig"), .root_source_file = b.dependency("z2d", .{}).path("src/z2d.zig"),
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
})); }));
step.root_module.addImport("ziglyph", b.dependency("ziglyph", .{
.target = target,
.optimize = optimize,
}).module("ziglyph"));
step.root_module.addImport("zf", b.dependency("zf", .{
.target = target,
.optimize = optimize,
}).module("zf"));
// Mac Stuff // Mac Stuff
if (step.rootModuleTarget().isDarwin()) { if (step.rootModuleTarget().isDarwin()) {
const objc_dep = b.dependency("zig_objc", .{
.target = target,
.optimize = optimize,
});
const macos_dep = b.dependency("macos", .{
.target = target,
.optimize = optimize,
});
// This is a bit of a hack that should probably be fixed upstream // This is a bit of a hack that should probably be fixed upstream
// in zig-objc, but we need to add the apple SDK paths to the // in zig-objc, but we need to add the apple SDK paths to the
// zig-objc module so that it can find the objc runtime headers. // zig-objc module so that it can find the objc runtime headers.
@ -1158,89 +1237,32 @@ fn addDeps(
} }
// cimgui // cimgui
const cimgui_dep = b.dependency("cimgui", .{
.target = target,
.optimize = optimize,
});
step.root_module.addImport("cimgui", cimgui_dep.module("cimgui")); step.root_module.addImport("cimgui", cimgui_dep.module("cimgui"));
step.linkLibrary(cimgui_dep.artifact("cimgui")); step.linkLibrary(cimgui_dep.artifact("cimgui"));
try static_libs.append(cimgui_dep.artifact("cimgui").getEmittedBin()); try static_libs.append(cimgui_dep.artifact("cimgui").getEmittedBin());
// Glslang
step.linkLibrary(glslang_dep.artifact("glslang"));
try static_libs.append(glslang_dep.artifact("glslang").getEmittedBin());
// Highway // Highway
const highway_dep = b.dependency("highway", .{
.target = target,
.optimize = optimize,
});
step.linkLibrary(highway_dep.artifact("highway")); step.linkLibrary(highway_dep.artifact("highway"));
try static_libs.append(highway_dep.artifact("highway").getEmittedBin()); try static_libs.append(highway_dep.artifact("highway").getEmittedBin());
// simdutf // utfcpp - This is used as a dependency on our hand-written C++ code
step.linkLibrary(simdutf_dep.artifact("simdutf")); const utfcpp_dep = b.dependency("utfcpp", .{
try static_libs.append(simdutf_dep.artifact("simdutf").getEmittedBin()); .target = target,
.optimize = optimize,
// utfcpp });
step.linkLibrary(utfcpp_dep.artifact("utfcpp")); step.linkLibrary(utfcpp_dep.artifact("utfcpp"));
try static_libs.append(utfcpp_dep.artifact("utfcpp").getEmittedBin()); try static_libs.append(utfcpp_dep.artifact("utfcpp").getEmittedBin());
// Spirv-Cross // If we're building an exe then we have additional dependencies.
step.linkLibrary(spirv_cross_dep.artifact("spirv_cross")); if (step.kind != .lib) {
try static_libs.append(spirv_cross_dep.artifact("spirv_cross").getEmittedBin());
if (target.result.os.tag != .windows) {
// Sentry
step.linkLibrary(sentry_dep.artifact("sentry"));
try static_libs.append(sentry_dep.artifact("sentry").getEmittedBin());
// We also need to include breakpad in the static libs.
const breakpad_dep = sentry_dep.builder.dependency("breakpad", .{
.target = target,
.optimize = optimize,
});
try static_libs.append(breakpad_dep.artifact("breakpad").getEmittedBin());
}
// Dynamic link
if (!config.static) {
step.addIncludePath(freetype_dep.path(""));
step.linkSystemLibrary2("bzip2", dynamic_link_opts);
step.linkSystemLibrary2("freetype2", dynamic_link_opts);
step.linkSystemLibrary2("libpng", dynamic_link_opts);
step.linkSystemLibrary2("oniguruma", dynamic_link_opts);
step.linkSystemLibrary2("zlib", dynamic_link_opts);
if (config.font_backend.hasFontconfig()) {
step.linkSystemLibrary2("fontconfig", dynamic_link_opts);
}
if (config.font_backend.hasHarfbuzz()) {
step.linkSystemLibrary2("harfbuzz", dynamic_link_opts);
}
}
// Other dependencies, we may dynamically link
if (config.static) {
step.linkLibrary(oniguruma_dep.artifact("oniguruma"));
try static_libs.append(oniguruma_dep.artifact("oniguruma").getEmittedBin());
step.linkLibrary(zlib_dep.artifact("z"));
try static_libs.append(zlib_dep.artifact("z").getEmittedBin());
step.linkLibrary(libpng_dep.artifact("png"));
try static_libs.append(libpng_dep.artifact("png").getEmittedBin());
// Freetype
step.linkLibrary(freetype_dep.artifact("freetype"));
try static_libs.append(freetype_dep.artifact("freetype").getEmittedBin());
// Harfbuzz
if (config.font_backend.hasHarfbuzz()) {
step.linkLibrary(harfbuzz_dep.artifact("harfbuzz"));
try static_libs.append(harfbuzz_dep.artifact("harfbuzz").getEmittedBin());
}
// Only Linux gets fontconfig
if (config.font_backend.hasFontconfig()) {
// Fontconfig
step.linkLibrary(fontconfig_dep.artifact("fontconfig"));
}
}
if (!lib) {
// We always statically compile glad // We always statically compile glad
step.addIncludePath(b.path("vendor/glad/include/")); step.addIncludePath(b.path("vendor/glad/include/"));
step.addCSourceFile(.{ step.addCSourceFile(.{
@ -1515,8 +1537,6 @@ fn benchSteps(
if (install) b.installArtifact(c_exe); if (install) b.installArtifact(c_exe);
_ = try addDeps(b, c_exe, config: { _ = try addDeps(b, c_exe, config: {
var copy = config; var copy = config;
copy.static = true;
var enum_name: [64]u8 = undefined; var enum_name: [64]u8 = undefined;
@memcpy(enum_name[0..name.len], name); @memcpy(enum_name[0..name.len], name);
std.mem.replaceScalar(u8, enum_name[0..name.len], '-', '_'); std.mem.replaceScalar(u8, enum_name[0..name.len], '-', '_');

0
nix/build-support/fetch-zig-cache.sh Normal file → Executable file
View File

View File

@ -28,6 +28,7 @@
fontconfig, fontconfig,
freetype, freetype,
glib, glib,
glslang,
gtk4, gtk4,
libadwaita, libadwaita,
gnome, gnome,
@ -41,6 +42,9 @@
libXi, libXi,
libXinerama, libXinerama,
libXrandr, libXrandr,
libxml2,
spirv-cross,
simdutf,
zlib, zlib,
alejandra, alejandra,
pandoc, pandoc,
@ -59,9 +63,14 @@
freetype freetype
harfbuzz harfbuzz
libpng libpng
libxml2
oniguruma oniguruma
simdutf
zlib zlib
glslang
spirv-cross
libX11 libX11
libXcursor libXcursor
libXi libXi
@ -123,9 +132,14 @@ in
freetype freetype
harfbuzz harfbuzz
libpng libpng
libxml2
oniguruma oniguruma
simdutf
zlib zlib
glslang
spirv-cross
libX11 libX11
libXcursor libXcursor
libXext libXext

View File

@ -12,11 +12,6 @@ pub fn build(b: *std.Build) !void {
}); });
const imgui = b.dependency("imgui", .{}); const imgui = b.dependency("imgui", .{});
const freetype = b.dependency("freetype", .{
.target = target,
.optimize = optimize,
.@"enable-libpng" = true,
});
const lib = b.addStaticLibrary(.{ const lib = b.addStaticLibrary(.{
.name = "cimgui", .name = "cimgui",
.target = target, .target = target,
@ -24,11 +19,30 @@ pub fn build(b: *std.Build) !void {
}); });
lib.linkLibC(); lib.linkLibC();
lib.linkLibCpp(); lib.linkLibCpp();
lib.linkLibrary(freetype.artifact("freetype"));
if (target.result.os.tag == .windows) { if (target.result.os.tag == .windows) {
lib.linkSystemLibrary("imm32"); lib.linkSystemLibrary("imm32");
} }
// For dynamic linking, we prefer dynamic linking and to search by
// mode first. Mode first will search all paths for a dynamic library
// before falling back to static.
const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
.preferred_link_mode = .dynamic,
.search_strategy = .mode_first,
};
if (b.systemIntegrationOption("freetype", .{})) {
lib.linkSystemLibrary2("freetype", dynamic_link_opts);
} else {
const freetype = b.dependency("freetype", .{
.target = target,
.optimize = optimize,
.@"enable-libpng" = true,
});
lib.linkLibrary(freetype.artifact("freetype"));
module.addIncludePath(freetype.builder.dependency("freetype", .{}).path("include"));
}
lib.addIncludePath(imgui.path("")); lib.addIncludePath(imgui.path(""));
module.addIncludePath(b.path("vendor")); module.addIncludePath(b.path("vendor"));

View File

@ -25,18 +25,6 @@ pub fn build(b: *std.Build) !void {
if (target.result.os.tag != .windows) { if (target.result.os.tag != .windows) {
lib.linkSystemLibrary("pthread"); lib.linkSystemLibrary("pthread");
} }
if (freetype_enabled) {
const freetype_dep = b.dependency("freetype", .{ .target = target, .optimize = optimize });
lib.linkLibrary(freetype_dep.artifact("freetype"));
}
if (libxml2_enabled) {
const libxml2_dep = b.dependency("libxml2", .{
.target = target,
.optimize = optimize,
.iconv = libxml2_iconv_enabled,
});
lib.linkLibrary(libxml2_dep.artifact("xml2"));
}
lib.addIncludePath(upstream.path("")); lib.addIncludePath(upstream.path(""));
lib.addIncludePath(b.path("override/include")); lib.addIncludePath(b.path("override/include"));
@ -142,6 +130,31 @@ pub fn build(b: *std.Build) !void {
}); });
} }
} }
// For dynamic linking, we prefer dynamic linking and to search by
// mode first. Mode first will search all paths for a dynamic library
// before falling back to static.
const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
.preferred_link_mode = .dynamic,
.search_strategy = .mode_first,
};
// Freetype2
_ = b.systemIntegrationOption("freetype", .{}); // So it shows up in help
if (freetype_enabled) {
if (b.systemIntegrationOption("freetype", .{})) {
lib.linkSystemLibrary2("freetype", dynamic_link_opts);
} else {
const freetype_dep = b.dependency(
"freetype",
.{ .target = target, .optimize = optimize },
);
lib.linkLibrary(freetype_dep.artifact("freetype"));
}
}
// Libxml2
_ = b.systemIntegrationOption("libxml2", .{}); // So it shows up in help
if (libxml2_enabled) { if (libxml2_enabled) {
try flags.appendSlice(&.{ try flags.appendSlice(&.{
"-DENABLE_LIBXML2", "-DENABLE_LIBXML2",
@ -154,6 +167,17 @@ pub fn build(b: *std.Build) !void {
"-Werror=implicit-function-declaration", "-Werror=implicit-function-declaration",
}); });
} }
if (b.systemIntegrationOption("libxml2", .{})) {
lib.linkSystemLibrary2("libxml-2.0", dynamic_link_opts);
} else {
const libxml2_dep = b.dependency("libxml2", .{
.target = target,
.optimize = optimize,
.iconv = libxml2_iconv_enabled,
});
lib.linkLibrary(libxml2_dep.artifact("xml2"));
}
} }
lib.addCSourceFiles(.{ lib.addCSourceFiles(.{

View File

@ -23,13 +23,13 @@ pub fn build(b: *std.Build) !void {
module.addIncludePath(upstream.path("include")); module.addIncludePath(upstream.path("include"));
module.addIncludePath(b.path("")); module.addIncludePath(b.path(""));
// Dependencies // For dynamic linking, we prefer dynamic linking and to search by
const zlib_dep = b.dependency("zlib", .{ .target = target, .optimize = optimize }); // mode first. Mode first will search all paths for a dynamic library
lib.linkLibrary(zlib_dep.artifact("z")); // before falling back to static.
if (libpng_enabled) { const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
const libpng_dep = b.dependency("libpng", .{ .target = target, .optimize = optimize }); .preferred_link_mode = .dynamic,
lib.linkLibrary(libpng_dep.artifact("png")); .search_strategy = .mode_first,
} };
var flags = std.ArrayList([]const u8).init(b.allocator); var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit(); defer flags.deinit();
@ -43,7 +43,30 @@ pub fn build(b: *std.Build) !void {
"-fno-sanitize=undefined", "-fno-sanitize=undefined",
}); });
if (libpng_enabled) try flags.append("-DFT_CONFIG_OPTION_USE_PNG=1");
// Zlib
if (b.systemIntegrationOption("zlib", .{})) {
lib.linkSystemLibrary2("zlib", dynamic_link_opts);
} else {
const zlib_dep = b.dependency("zlib", .{ .target = target, .optimize = optimize });
lib.linkLibrary(zlib_dep.artifact("z"));
}
// Libpng
_ = b.systemIntegrationOption("libpng", .{}); // So it shows up in help
if (libpng_enabled) {
try flags.append("-DFT_CONFIG_OPTION_USE_PNG=1");
if (b.systemIntegrationOption("libpng", .{})) {
lib.linkSystemLibrary2("libpng", dynamic_link_opts);
} else {
const libpng_dep = b.dependency(
"libpng",
.{ .target = target, .optimize = optimize },
);
lib.linkLibrary(libpng_dep.artifact("png"));
}
}
lib.addCSourceFiles(.{ lib.addCSourceFiles(.{
.root = upstream.path(""), .root = upstream.path(""),

View File

@ -41,13 +41,13 @@ pub fn build(b: *std.Build) !void {
try apple_sdk.addPaths(b, module); try apple_sdk.addPaths(b, module);
} }
const freetype_dep = b.dependency("freetype", .{ // For dynamic linking, we prefer dynamic linking and to search by
.target = target, // mode first. Mode first will search all paths for a dynamic library
.optimize = optimize, // before falling back to static.
.@"enable-libpng" = true, const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
}); .preferred_link_mode = .dynamic,
lib.linkLibrary(freetype_dep.artifact("freetype")); .search_strategy = .mode_first,
module.addIncludePath(freetype_dep.builder.dependency("freetype", .{}).path("include")); };
var flags = std.ArrayList([]const u8).init(b.allocator); var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit(); defer flags.deinit();
@ -61,15 +61,28 @@ pub fn build(b: *std.Build) !void {
"-DHAVE_PTHREAD=1", "-DHAVE_PTHREAD=1",
}); });
} }
if (freetype_enabled) try flags.appendSlice(&.{
"-DHAVE_FREETYPE=1",
// Let's just assume a new freetype // Freetype
"-DHAVE_FT_GET_VAR_BLEND_COORDINATES=1", _ = b.systemIntegrationOption("freetype", .{}); // So it shows up in help
"-DHAVE_FT_SET_VAR_BLEND_COORDINATES=1", if (freetype_enabled) {
"-DHAVE_FT_DONE_MM_VAR=1", try flags.appendSlice(&.{
"-DHAVE_FT_GET_TRANSFORM=1", "-DHAVE_FREETYPE=1",
});
// Let's just assume a new freetype
"-DHAVE_FT_GET_VAR_BLEND_COORDINATES=1",
"-DHAVE_FT_SET_VAR_BLEND_COORDINATES=1",
"-DHAVE_FT_DONE_MM_VAR=1",
"-DHAVE_FT_GET_TRANSFORM=1",
});
if (b.systemIntegrationOption("freetype", .{})) {
lib.linkSystemLibrary2("freetype", dynamic_link_opts);
} else {
lib.linkLibrary(freetype.artifact("freetype"));
module.addIncludePath(freetype.builder.dependency("freetype", .{}).path("include"));
}
}
if (coretext_enabled) { if (coretext_enabled) {
try flags.appendSlice(&.{"-DHAVE_CORETEXT=1"}); try flags.appendSlice(&.{"-DHAVE_CORETEXT=1"});
lib.linkFramework("CoreText"); lib.linkFramework("CoreText");
@ -99,7 +112,7 @@ pub fn build(b: *std.Build) !void {
var it = module.import_table.iterator(); var it = module.import_table.iterator();
while (it.next()) |entry| test_exe.root_module.addImport(entry.key_ptr.*, entry.value_ptr.*); while (it.next()) |entry| test_exe.root_module.addImport(entry.key_ptr.*, entry.value_ptr.*);
test_exe.linkLibrary(freetype_dep.artifact("freetype")); test_exe.linkLibrary(freetype.artifact("freetype"));
const tests_run = b.addRunArtifact(test_exe); const tests_run = b.addRunArtifact(test_exe);
const test_step = b.step("test", "Run tests"); const test_step = b.step("test", "Run tests");
test_step.dependOn(&tests_run.step); test_step.dependOn(&tests_run.step);

View File

@ -20,10 +20,22 @@ pub fn build(b: *std.Build) !void {
try apple_sdk.addPaths(b, &lib.root_module); try apple_sdk.addPaths(b, &lib.root_module);
} }
const zlib_dep = b.dependency("zlib", .{ .target = target, .optimize = optimize }); // For dynamic linking, we prefer dynamic linking and to search by
lib.linkLibrary(zlib_dep.artifact("z")); // mode first. Mode first will search all paths for a dynamic library
lib.addIncludePath(upstream.path("")); // before falling back to static.
lib.addIncludePath(b.path("")); const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
.preferred_link_mode = .dynamic,
.search_strategy = .mode_first,
};
if (b.systemIntegrationOption("zlib", .{})) {
lib.linkSystemLibrary2("zlib", dynamic_link_opts);
} else {
const zlib_dep = b.dependency("zlib", .{ .target = target, .optimize = optimize });
lib.linkLibrary(zlib_dep.artifact("z"));
lib.addIncludePath(upstream.path(""));
lib.addIncludePath(b.path(""));
}
var flags = std.ArrayList([]const u8).init(b.allocator); var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit(); defer flags.deinit();

View File

@ -20,7 +20,6 @@ const WasmTarget = @import("os/wasm/target.zig").Target;
/// build types, etc. /// build types, etc.
pub const BuildConfig = struct { pub const BuildConfig = struct {
version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 }, version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 },
static: bool = false,
flatpak: bool = false, flatpak: bool = false,
libadwaita: bool = false, libadwaita: bool = false,
app_runtime: apprt.Runtime = .none, app_runtime: apprt.Runtime = .none,