move png to opt in at build time
All checks were successful
Generic zig build / build (push) Successful in 2m37s
Generic zig build / deploy (push) Successful in 33s

This commit is contained in:
Emil Lerch 2026-03-05 11:03:21 -08:00
parent 102d5c09ea
commit 315eb73bfa
Signed by: lobo
GPG key ID: A7B62D657EF764F8
2 changed files with 59 additions and 45 deletions

View file

@ -6,6 +6,14 @@ pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); 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", .{ const httpz = b.dependency("httpz", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
@ -16,21 +24,21 @@ pub fn build(b: *std.Build) void {
.optimize = optimize, .optimize = optimize,
}); });
const zigimg = b.dependency("zigimg", .{ const zigimg = if (enable_png) b.dependency("zigimg", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); }) else null;
const freetype = b.dependency("ghostty", .{ const freetype = if (enable_png) b.dependency("ghostty", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}).builder.dependency("freetype", .{ }).builder.dependency("freetype", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); }) else null;
const jetbrains_mono = b.dependency("jetbrains_mono", .{}); const jetbrains_mono = if (enable_png) b.dependency("jetbrains_mono", .{}) else null;
const nerd_fonts = b.dependency("nerd_fonts_symbols_only", .{}); const nerd_fonts = if (enable_png) b.dependency("nerd_fonts_symbols_only", .{}) else null;
const openflights = b.dependency("openflights", .{}); const openflights = b.dependency("openflights", .{});
@ -116,12 +124,6 @@ pub fn build(b: *std.Build) void {
maxminddb.installHeadersDirectory(maxminddb_upstream.path("include"), "", .{}); 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(.{ const root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"), .root_source_file = b.path("src/main.zig"),
.target = target, .target = target,
@ -129,31 +131,37 @@ pub fn build(b: *std.Build) void {
}); });
root_module.addImport("httpz", httpz.module("httpz")); root_module.addImport("httpz", httpz.module("httpz"));
root_module.addImport("zeit", zeit.module("zeit")); root_module.addImport("zeit", zeit.module("zeit"));
root_module.addImport("zigimg", zigimg.module("zigimg")); if (zigimg) |dep| root_module.addImport("zigimg", dep.module("zigimg"));
root_module.addImport("freetype", freetype.module("freetype")); if (freetype) |dep| root_module.addImport("freetype", dep.module("freetype"));
root_module.addAnonymousImport("airports.dat", .{ root_module.addAnonymousImport("airports.dat", .{
.root_source_file = openflights.path("data/airports.dat"), .root_source_file = openflights.path("data/airports.dat"),
}); });
root_module.addAnonymousImport("JetBrainsMono-Regular.ttf", .{ if (jetbrains_mono) |dep| root_module.addAnonymousImport("JetBrainsMono-Regular.ttf", .{
.root_source_file = jetbrains_mono.path("fonts/ttf/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_source_file = b.path("libs/2914-LexiGulim090423.ttf"),
}); });
root_module.addAnonymousImport("SymbolsNerdFont-Regular.ttf", .{ if (nerd_fonts) |dep| root_module.addAnonymousImport("SymbolsNerdFont-Regular.ttf", .{
.root_source_file = nerd_fonts.path("SymbolsNerdFont-Regular.ttf"), .root_source_file = dep.path("SymbolsNerdFont-Regular.ttf"),
}); });
root_module.addOptions("build_options", build_options); root_module.addOptions("build_options", build_options);
root_module.addIncludePath(maxminddb_upstream.path("include")); root_module.addIncludePath(maxminddb_upstream.path("include"));
root_module.addIncludePath(b.path("libs/phoon_14Aug2014")); root_module.addIncludePath(b.path("libs/phoon_14Aug2014"));
root_module.addIncludePath(b.path("libs/sunriset")); root_module.addIncludePath(b.path("libs/sunriset"));
root_module.addConfigHeader(maxminddb_config); root_module.addConfigHeader(maxminddb_config);
const libs = &[_]*std.Build.Step.Compile{
maxminddb, var libs_buf: [4]*std.Build.Step.Compile = undefined;
phoon, libs_buf[0] = maxminddb;
sunriset, libs_buf[1] = phoon;
freetype.artifact("freetype"), 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(.{ const exe = b.addExecutable(.{
.name = "wttr", .name = "wttr",
.root_module = root_module, .root_module = root_module,

View file

@ -9,9 +9,10 @@ const Json = @import("../render/Json.zig");
const V2 = @import("../render/V2.zig"); const V2 = @import("../render/V2.zig");
const Custom = @import("../render/Custom.zig"); const Custom = @import("../render/Custom.zig");
const Prometheus = @import("../render/Prometheus.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 help = @import("help.zig");
const types = @import("../weather/types.zig"); const types = @import("../weather/types.zig");
const build_options = @import("build_options");
const log = std.log.scoped(.handler); const log = std.log.scoped(.handler);
@ -98,7 +99,10 @@ fn handleWeatherInternal(
const req_alloc = req.arena; const req_alloc = req.arena;
// Check for PNG request // 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; 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 // Resolve location. By the time we get here, we really
@ -168,28 +172,30 @@ fn handleWeatherInternal(
res.headers.add("X-Location-Coordinates", coords_header); res.headers.add("X-Location-Coordinates", coords_header);
// Render weather data // Render weather data
if (is_png) { if (comptime build_options.enable_png) {
res.content_type = .PNG; if (is_png) {
var png_renderer = Png.init(req_alloc); res.content_type = .PNG;
defer png_renderer.deinit(); var png_renderer = Png.init(req_alloc);
defer png_renderer.deinit();
var png_buffer: [1024 * 1024]u8 = undefined; var png_buffer: [1024 * 1024]u8 = undefined;
var png_writer_impl = std.Io.Writer.fixed(&png_buffer); var png_writer_impl = std.Io.Writer.fixed(&png_buffer);
const png_writer = &png_writer_impl; const png_writer = &png_writer_impl;
render_options.format = .ansi; // Force ANSI for PNG render_options.format = .ansi; // Force ANSI for PNG
try renderWeatherData(png_writer, weather, params, render_options); try renderWeatherData(png_writer, weather, params, render_options);
const text_output = png_buffer[0..png_writer_impl.end]; const text_output = png_buffer[0..png_writer_impl.end];
try png_renderer.buffer.appendSlice(req_alloc, text_output); try png_renderer.buffer.appendSlice(req_alloc, text_output);
const png_options = Png.PngOptions{ const png_options = Png.PngOptions{
.transparency = params.transparency orelse 150, .transparency = params.transparency orelse 150,
.background = params.background, .background = params.background,
.add_frame = params.add_frame, .add_frame = params.add_frame,
}; };
try png_renderer.render(res.writer(), png_options); try png_renderer.render(res.writer(), png_options);
return; return;
}
} }
// Set content type based on format // Set content type based on format
if (params.format) |fmt| { if (params.format) |fmt| {