Something went wrong. Try again.
Open a URI in the user's chosen application from Zig: the desktop portal on Linux, ShellExecuteExW on Windows, Launch Services on macOS.
Something went wrong. Try again.
zig-openuri build.zig
6.9 kB · 160 lines
Zig
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie <jeff@ocjtech.us>// SPDX-License-Identifier: MIT
const std = @import("std");
pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{});
const docs_port = b.option(u16, "docs-port", "Port for `zig build docs-serve` (default 8000)") orelse 8000;
const mod = createModule(b, target, optimize, .{ .public = true, .link = true }) orelse return;
const exe = b.addExecutable(.{ .name = "openuri", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .imports = &.{.{ .name = "openuri", .module = mod }}, }), }); b.installArtifact(exe);
const run = b.addRunArtifact(exe); run.addPassthruArgs(); const run_step = b.step("run", "Run the openuri command"); run_step.dependOn(&run.step);
// Compile everything without running or linking it. The cross targets // are here because nothing else proves the Windows and macOS code still // compiles: CI runs on Linux, and linking for macOS needs Apple's SDK, // which is why this compiles without emitting a binary. const check_step = b.step("check", "Compile for every supported platform without linking"); check_step.dependOn(&exe.step); const cross_targets = [_]std.Target.Query{ .{ .cpu_arch = .x86_64, .os_tag = .linux }, .{ .cpu_arch = .aarch64, .os_tag = .linux }, .{ .cpu_arch = .x86_64, .os_tag = .windows }, .{ .cpu_arch = .aarch64, .os_tag = .windows }, .{ .cpu_arch = .x86_64, .os_tag = .macos }, .{ .cpu_arch = .aarch64, .os_tag = .macos }, }; for (cross_targets) |query| { const cross_target = b.resolveTargetQuery(query); const cross_mod = createModule(b, cross_target, optimize, .{ .public = false, .link = false }) orelse continue; const cross_exe = b.addExecutable(.{ .name = "openuri", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = cross_target, .optimize = optimize, .imports = &.{.{ .name = "openuri", .module = cross_mod }}, }), }); check_step.dependOn(&cross_exe.step); }
// Generated from the doc comments. The object exists only to emit them. const docs_obj = b.addObject(.{ .name = "openuri", .root_module = mod }); const install_docs = b.addInstallDirectory(.{ .source_dir = docs_obj.getEmittedDocs(), .install_dir = .prefix, .install_subdir = "docs", }); const docs_step = b.step("docs", "Build the API documentation into zig-out/docs"); docs_step.dependOn(&install_docs.step);
// The viewer fetches `sources.tar` and `main.wasm` at runtime, which a // browser refuses from a `file://` page, so it has to be served. const docs_server = b.addExecutable(.{ .name = "docs-server", .root_module = b.createModule(.{ .root_source_file = b.path("tools/docs_server.zig"), // Always the machine running the build, never whatever -Dtarget // the library is being built for. .target = b.graph.host, .optimize = .Debug, }), }); const run_docs_server = b.addRunArtifact(docs_server); run_docs_server.step.dependOn(&install_docs.step); run_docs_server.addDirectoryArg(docs_obj.getEmittedDocs()); run_docs_server.addArg(b.fmt("{d}", .{docs_port})); // It runs until interrupted, so its output has to reach the terminal. run_docs_server.stdio = .inherit; const docs_serve_step = b.step("docs-serve", "Serve the API documentation over HTTP"); docs_serve_step.dependOn(&run_docs_server.step); check_step.dependOn(&docs_server.step);
const test_step = b.step("test", "Run the tests"); const unit_tests = [_]*std.Build.Step.Compile{ b.addTest(.{ .name = "openuri-test", .root_module = mod, .use_llvm = true }), b.addTest(.{ .name = "openuri-cli-test", .root_module = exe.root_module, .use_llvm = true }), b.addTest(.{ .name = "docs-server-test", .root_module = docs_server.root_module }), }; for (unit_tests) |unit_test| { test_step.dependOn(&b.addRunArtifact(unit_test).step); check_step.dependOn(&unit_test.step); }
// The Linux path end to end, against a fake portal on a private bus. if (target.result.os.tag == .linux) { if (b.lazyDependency("mdbus", .{ .target = target, .optimize = optimize })) |mdbus| { const portal_test = b.addTest(.{ .name = "openuri-portal-test", .root_module = b.createModule(.{ .root_source_file = b.path("tests/portal_test.zig"), .target = target, .optimize = optimize, .imports = &.{ .{ .name = "openuri", .module = mod }, .{ .name = "mdbus", .module = mdbus.module("mdbus") }, }, }), .use_llvm = true, }); test_step.dependOn(&b.addRunArtifact(portal_test).step); check_step.dependOn(&portal_test.step); } }}
/// The `openuri` module for `target`, with what each platform's opener needs:/// mdbus on Linux, shell32 on Windows, Launch Services on macOS. Null while/// the lazy mdbus dependency is still being fetched.fn createModule( b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, how: struct { /// The module that packages depending on this one import. public: bool, /// Link the platform's libraries. The compile-only cross checks /// cannot: Zig looks for macOS frameworks even when it emits no /// binary, and they are only found in Apple's SDK. link: bool, },) ?*std.Build.Module { const options: std.Build.Module.CreateOptions = .{ .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, }; const mod = if (how.public) b.addModule("openuri", options) else b.createModule(options); switch (target.result.os.tag) { .linux => { const mdbus = b.lazyDependency("mdbus", .{ .target = target, .optimize = optimize }) orelse return null; mod.addImport("mdbus", mdbus.module("mdbus")); }, .windows => if (how.link) mod.linkSystemLibrary("shell32", .{}), .macos => if (how.link) { mod.link_libc = true; mod.linkFramework("CoreFoundation", .{}); mod.linkFramework("CoreServices", .{}); }, else => {}, } return mod;}