Something went wrong. Try again.
A Zig library and CLI for reading Mobipocket (.mobi, .prc, .azw) e-books.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie <jeff@ocjtech.us>// SPDX-License-Identifier: MIT
const std = @import("std");
/// The book the tests read: a Project Gutenberg edition of *On the Origin of/// Species*. It is fetched during `zig build test` rather than committed, since/// it is several hundred kilobytes of binary that never changes with the code.////// Gutenberg regenerates these files from time to time, so this hash will/// eventually stop matching. When that happens, check the new file over and/// update the hash — the tests are written to survive the book changing.const testdata_url = "https://www.gutenberg.org/cache/epub/2009/pg2009-images.mobi";const testdata_sha256 = "44a8f228aa0f0f9ceae098885bbf1cc2db6ee79c22c3e4993f86a16daf6cafe7";
/// Download the test book and hand back the path it landed in. The build graph/// only reaches this when something depends on it, so a plain `zig build` stays/// offline, and the result is cached between runs.fn testDataPath(b: *std.Build, tls_module: *std.Build.Module) std.Build.LazyPath { const fetch = b.addExecutable(.{ .name = "fetch", .root_module = b.createModule(.{ .root_source_file = b.path("tools/fetch.zig"), // A build-time tool, so it always targets the machine doing the // building rather than whatever the library is cross-compiled for. .target = b.graph.host, .optimize = .ReleaseSafe, .imports = &.{ .{ .name = "tls", .module = tls_module }, }, }), });
const run = b.addRunArtifact(fetch); run.addArg(testdata_url); run.addArg(testdata_sha256); return run.addOutputFileArg("CharlesDarwin.mobi");}
pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const mod = b.addModule("mobi", .{ .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, });
const exe = b.addExecutable(.{ .name = "mobi", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "mobi", .module = mod }, }, }), });
b.installArtifact(exe);
const run_step = b.step("run", "Run the app");
const run_cmd = b.addRunArtifact(exe); run_step.dependOn(&run_cmd.step);
run_cmd.step.dependOn(b.getInstallStep());
run_cmd.addPassthruArgs();
// A separate module for the tests, so that the fetched book is visible to // `@embedFile` there without becoming part of the published module and // dragging the download into every dependent's build. const test_mod = b.createModule(.{ .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, }); const tls_module = b.dependency("tls", .{}).module("tls"); test_mod.addAnonymousImport("testdata", .{ .root_source_file = testDataPath(b, tls_module) });
const mod_tests = b.addTest(.{ .root_module = test_mod, });
const run_mod_tests = b.addRunArtifact(mod_tests);
const exe_tests = b.addTest(.{ .root_module = exe.root_module, });
const run_exe_tests = b.addRunArtifact(exe_tests);
const test_step = b.step("test", "Run tests"); test_step.dependOn(&run_mod_tests.step); test_step.dependOn(&run_exe_tests.step);}