From 315eb73bfa812985922560e1a8ffea073b707291 Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Thu, 5 Mar 2026 11:03:21 -0800 Subject: [PATCH] move png to opt in at build time --- build.zig | 58 +++++++++++++++++++++++++------------------- src/http/handler.zig | 46 ++++++++++++++++++++--------------- 2 files changed, 59 insertions(+), 45 deletions(-) diff --git a/build.zig b/build.zig index 8e0f6f3..7e29547 100644 --- a/build.zig +++ b/build.zig @@ -6,6 +6,14 @@ pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const version = GitVersion.getVersion(b, .{}); + const download_geoip = b.option(bool, "download-geoip", "Download GeoIP database for tests") orelse false; + const enable_png = b.option(bool, "enable-png", "Enable PNG image generation (adds zigimg, freetype, and embedded fonts)") orelse false; + const build_options = b.addOptions(); + build_options.addOption([]const u8, "version", version); + build_options.addOption(bool, "download_geoip", download_geoip); + build_options.addOption(bool, "enable_png", enable_png); + const httpz = b.dependency("httpz", .{ .target = target, .optimize = optimize, @@ -16,21 +24,21 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); - const zigimg = b.dependency("zigimg", .{ + const zigimg = if (enable_png) b.dependency("zigimg", .{ .target = target, .optimize = optimize, - }); + }) else null; - const freetype = b.dependency("ghostty", .{ + const freetype = if (enable_png) b.dependency("ghostty", .{ .target = target, .optimize = optimize, }).builder.dependency("freetype", .{ .target = target, .optimize = optimize, - }); + }) else null; - const jetbrains_mono = b.dependency("jetbrains_mono", .{}); - const nerd_fonts = b.dependency("nerd_fonts_symbols_only", .{}); + const jetbrains_mono = if (enable_png) b.dependency("jetbrains_mono", .{}) else null; + const nerd_fonts = if (enable_png) b.dependency("nerd_fonts_symbols_only", .{}) else null; const openflights = b.dependency("openflights", .{}); @@ -116,12 +124,6 @@ pub fn build(b: *std.Build) void { maxminddb.installHeadersDirectory(maxminddb_upstream.path("include"), "", .{}); - const version = GitVersion.getVersion(b, .{}); - const download_geoip = b.option(bool, "download-geoip", "Download GeoIP database for tests") orelse false; - const build_options = b.addOptions(); - build_options.addOption([]const u8, "version", version); - build_options.addOption(bool, "download_geoip", download_geoip); - const root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, @@ -129,31 +131,37 @@ pub fn build(b: *std.Build) void { }); root_module.addImport("httpz", httpz.module("httpz")); root_module.addImport("zeit", zeit.module("zeit")); - root_module.addImport("zigimg", zigimg.module("zigimg")); - root_module.addImport("freetype", freetype.module("freetype")); + if (zigimg) |dep| root_module.addImport("zigimg", dep.module("zigimg")); + if (freetype) |dep| root_module.addImport("freetype", dep.module("freetype")); root_module.addAnonymousImport("airports.dat", .{ .root_source_file = openflights.path("data/airports.dat"), }); - root_module.addAnonymousImport("JetBrainsMono-Regular.ttf", .{ - .root_source_file = jetbrains_mono.path("fonts/ttf/JetBrainsMono-Regular.ttf"), + if (jetbrains_mono) |dep| root_module.addAnonymousImport("JetBrainsMono-Regular.ttf", .{ + .root_source_file = dep.path("fonts/ttf/JetBrainsMono-Regular.ttf"), }); - root_module.addAnonymousImport("LexiGulim.ttf", .{ + if (enable_png) root_module.addAnonymousImport("LexiGulim.ttf", .{ .root_source_file = b.path("libs/2914-LexiGulim090423.ttf"), }); - root_module.addAnonymousImport("SymbolsNerdFont-Regular.ttf", .{ - .root_source_file = nerd_fonts.path("SymbolsNerdFont-Regular.ttf"), + if (nerd_fonts) |dep| root_module.addAnonymousImport("SymbolsNerdFont-Regular.ttf", .{ + .root_source_file = dep.path("SymbolsNerdFont-Regular.ttf"), }); root_module.addOptions("build_options", build_options); root_module.addIncludePath(maxminddb_upstream.path("include")); root_module.addIncludePath(b.path("libs/phoon_14Aug2014")); root_module.addIncludePath(b.path("libs/sunriset")); root_module.addConfigHeader(maxminddb_config); - const libs = &[_]*std.Build.Step.Compile{ - maxminddb, - phoon, - sunriset, - freetype.artifact("freetype"), - }; + + var libs_buf: [4]*std.Build.Step.Compile = undefined; + libs_buf[0] = maxminddb; + libs_buf[1] = phoon; + libs_buf[2] = sunriset; + var libs_len: usize = 3; + if (freetype) |dep| { + libs_buf[libs_len] = dep.artifact("freetype"); + libs_len += 1; + } + const libs = libs_buf[0..libs_len]; + const exe = b.addExecutable(.{ .name = "wttr", .root_module = root_module, diff --git a/src/http/handler.zig b/src/http/handler.zig index 53a2821..6263d99 100644 --- a/src/http/handler.zig +++ b/src/http/handler.zig @@ -9,9 +9,10 @@ const Json = @import("../render/Json.zig"); const V2 = @import("../render/V2.zig"); const Custom = @import("../render/Custom.zig"); const Prometheus = @import("../render/Prometheus.zig"); -const Png = @import("../render/Png.zig"); +const Png = if (build_options.enable_png) @import("../render/Png.zig") else struct {}; const help = @import("help.zig"); const types = @import("../weather/types.zig"); +const build_options = @import("build_options"); const log = std.log.scoped(.handler); @@ -98,7 +99,10 @@ fn handleWeatherInternal( const req_alloc = req.arena; // Check for PNG request - const is_png = std.mem.endsWith(u8, location_query, ".png"); + const is_png = if (comptime build_options.enable_png) + std.mem.endsWith(u8, location_query, ".png") + else + false; const location_str = if (is_png) location_query[0 .. location_query.len - 4] else location_query; // Resolve location. By the time we get here, we really @@ -168,28 +172,30 @@ fn handleWeatherInternal( res.headers.add("X-Location-Coordinates", coords_header); // Render weather data - if (is_png) { - res.content_type = .PNG; - var png_renderer = Png.init(req_alloc); - defer png_renderer.deinit(); + if (comptime build_options.enable_png) { + if (is_png) { + res.content_type = .PNG; + var png_renderer = Png.init(req_alloc); + defer png_renderer.deinit(); - var png_buffer: [1024 * 1024]u8 = undefined; - var png_writer_impl = std.Io.Writer.fixed(&png_buffer); - const png_writer = &png_writer_impl; + var png_buffer: [1024 * 1024]u8 = undefined; + var png_writer_impl = std.Io.Writer.fixed(&png_buffer); + const png_writer = &png_writer_impl; - render_options.format = .ansi; // Force ANSI for PNG - try renderWeatherData(png_writer, weather, params, render_options); + render_options.format = .ansi; // Force ANSI for PNG + try renderWeatherData(png_writer, weather, params, render_options); - const text_output = png_buffer[0..png_writer_impl.end]; - try png_renderer.buffer.appendSlice(req_alloc, text_output); + const text_output = png_buffer[0..png_writer_impl.end]; + try png_renderer.buffer.appendSlice(req_alloc, text_output); - const png_options = Png.PngOptions{ - .transparency = params.transparency orelse 150, - .background = params.background, - .add_frame = params.add_frame, - }; - try png_renderer.render(res.writer(), png_options); - return; + const png_options = Png.PngOptions{ + .transparency = params.transparency orelse 150, + .background = params.background, + .add_frame = params.add_frame, + }; + try png_renderer.render(res.writer(), png_options); + return; + } } // Set content type based on format if (params.format) |fmt| {