aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnhgelus Morhtuuzh <william@herges.fr>2026-05-02 16:41:33 +0200
committerAnhgelus Morhtuuzh <william@herges.fr>2026-05-02 16:41:33 +0200
commit5556e46cc453c024defa833b964648465ddc9e39 (patch)
tree789d144376970aaeefe14bd491d8edf220aea35c
parent5bc6edf71afe1d9b115af7363e9ffd867f2a6a57 (diff)
build(zig): link statically typst
-rw-r--r--build.zig50
-rw-r--r--build.zig.zon32
-rw-r--r--go/build.zig14
-rw-r--r--go/typdown.go25
-rw-r--r--go/typdown_test.go9
-rw-r--r--lib/typst/include/typdown_typst.h (renamed from lib/typst/typdown_typst.h)0
6 files changed, 64 insertions, 66 deletions
diff --git a/build.zig b/build.zig
index 5669a1d..a934bbc 100644
--- a/build.zig
+++ b/build.zig
@@ -1,9 +1,5 @@
const std = @import("std");
-const TYPST = "lib/typst";
-const TYPST_DEBUG = TYPST ++ "/target/debug";
-const TYPST_RELEASE = TYPST ++ "/target/release";
-
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
@@ -15,23 +11,30 @@ pub fn build(b: *std.Build) void {
const install = b.getInstallStep();
+ const typst_dep = b.dependency("typst", .{});
+
// build typst module
const build_typst = b.addSystemCommand(&[_][]const u8{
"cargo", "build",
});
- build_typst.setCwd(b.path(TYPST));
+ build_typst.setCwd(typst_dep.path(""));
if (no_embed_fonts) build_typst.addArg("--no-default-features");
+ var folder: []const u8 = "debug";
switch (optimize) {
.ReleaseSmall => {
build_typst.addArg("--profile");
build_typst.addArg("small");
+ folder = "small";
+ },
+ .ReleaseFast, .ReleaseSafe => {
+ build_typst.addArg("--release");
+ folder = "release";
},
- .ReleaseFast, .ReleaseSafe => build_typst.addArg("--release"),
else => {},
}
const typst = b.addTranslateC(.{
- .root_source_file = b.path(TYPST ++ "/typdown_typst.h"),
+ .root_source_file = typst_dep.path("include/typdown_typst.h"),
.link_libc = true,
.target = target,
.optimize = optimize,
@@ -41,20 +44,18 @@ pub fn build(b: *std.Build) void {
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
- .imports = &.{
- .{ .name = "typst", .module = typst.createModule() },
- },
+ .link_libc = !target.result.isWasiLibC(),
+ .strip = optimize != .Debug,
});
- if (!target.result.isWasiLibC()) mod.link_libc = true;
- if (optimize != .Debug) mod.strip = true;
mod.addOptions("config", options);
// find typst module
- mod.linkSystemLibrary("typdown_typst", .{ .preferred_link_mode = .static });
- mod.addLibraryPath(if (optimize == .Debug) b.path(TYPST_DEBUG) else b.path(TYPST_RELEASE));
+ //mod.linkSystemLibrary("typdown_typst", .{ .preferred_link_mode = .static });
+ mod.addObjectFile(typst_dep.path("target").path(b, folder).path(b, "libtypdown_typst.so"));
+ mod.addImport("typst", typst.createModule());
const lib = b.addLibrary(.{
.name = "typdown",
- .linkage = .static,
+ .linkage = .dynamic,
.root_module = mod,
.use_llvm = true, // zig internal backend crashes during linking (for 0.15.2)
});
@@ -64,6 +65,8 @@ pub fn build(b: *std.Build) void {
// when emitting headers will be fixed
//installed_lib.emitted_h = lib.getEmittedH();
+ install.dependOn(&installed_lib.step);
+
const example_mod = b.createModule(.{
.target = target,
.optimize = optimize,
@@ -74,16 +77,6 @@ pub fn build(b: *std.Build) void {
});
example_mod.linkLibrary(lib);
example_mod.addIncludePath(b.path("include"));
- example_mod.linkSystemLibrary("typdown_typst", .{ .preferred_link_mode = .static });
- example_mod.addLibraryPath(if (optimize == .Debug) b.path(TYPST_DEBUG) else b.path(TYPST_RELEASE));
-
- const example = b.addExecutable(.{
- .name = "example",
- .root_module = example_mod,
- });
- example.step.dependOn(install);
-
- install.dependOn(&installed_lib.step);
const fmt = b.addFmt(.{
.paths = &.{
@@ -106,6 +99,13 @@ pub fn build(b: *std.Build) void {
test_step.dependOn(&run_mod_tests.step);
const examples_step = b.step("examples", "Run examples");
+
+ const example = b.addExecutable(.{
+ .name = "example",
+ .root_module = example_mod,
+ });
+ example.step.dependOn(install);
+
const example_run = b.addRunArtifact(example);
examples_step.dependOn(&example_run.step);
diff --git a/build.zig.zon b/build.zig.zon
index 18cf50d..4d33f06 100644
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -4,35 +4,9 @@
.fingerprint = 0x6d0fd8a73f35fe5b, // Changing this has security and trust implications.
.minimum_zig_version = "0.15.2",
.dependencies = .{
- // See `zig fetch --save <url>` for a command-line interface for adding dependencies.
- //.example = .{
- // // When updating this field to a new URL, be sure to delete the corresponding
- // // `hash`, otherwise you are communicating that you expect to find the old hash at
- // // the new URL. If the contents of a URL change this will result in a hash mismatch
- // // which will prevent zig from using it.
- // .url = "https://example.com/foo.tar.gz",
- //
- // // This is computed from the file contents of the directory of files that is
- // // obtained after fetching `url` and applying the inclusion rules given by
- // // `paths`.
- // //
- // // This field is the source of truth; packages do not come from a `url`; they
- // // come from a `hash`. `url` is just one of many possible mirrors for how to
- // // obtain a package matching this `hash`.
- // //
- // // Uses the [multihash](https://multiformats.io/multihash/) format.
- // .hash = "...",
- //
- // // When this is provided, the package is found in a directory relative to the
- // // build root. In this case the package's hash is irrelevant and therefore not
- // // computed. This field and `url` are mutually exclusive.
- // .path = "foo",
- //
- // // When this is set to `true`, a package is declared to be lazily
- // // fetched. This makes the dependency only get fetched if it is
- // // actually used.
- // .lazy = false,
- //},
+ .typst = .{
+ .path = "lib/typst",
+ },
},
.paths = .{
"build.zig",
diff --git a/go/build.zig b/go/build.zig
index 6517786..6399042 100644
--- a/go/build.zig
+++ b/go/build.zig
@@ -4,6 +4,8 @@ pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
+ const install_step = b.getInstallStep();
+
const typdown = b.dependency("typdown", .{
.optimize = optimize,
.target = target,
@@ -11,15 +13,10 @@ pub fn build(b: *std.Build) !void {
const lib = b.addLibrary(.{
.name = "typdown",
.root_module = typdown,
- .linkage = .static,
});
//lib.bundle_compiler_rt = true;
//lib.pie = true;
- const install = b.addInstallArtifact(lib, .{});
- // when emitting headers will be fixed
- // currently, we have to use a symlink/copy to get it
- //installed.emitted_h = lib.getEmittedH();
- b.getInstallStep().dependOn(&install.step);
+ const install_lib = b.addInstallArtifact(lib, .{});
var flags = try std.ArrayList(u8).initCapacity(b.allocator, 2);
try flags.appendSlice(b.allocator, "-linkmode external -extldflags -static");
@@ -29,7 +26,8 @@ pub fn build(b: *std.Build) !void {
"-ldflags", flags.items,
".",
});
- b.getInstallStep().dependOn(&go_build.step);
+ go_build.step.dependOn(&install_lib.step);
+ install_step.dependOn(&go_build.step);
const test_step = b.step("test", "Run tests");
test_step.dependOn(b.getInstallStep());
@@ -42,5 +40,5 @@ pub fn build(b: *std.Build) !void {
if (race) go_test.addArg("-race");
go_test.addArg("./...");
- test_step.dependOn(&go_test.step);
+ test_step.dependOn(install_step);
}
diff --git a/go/typdown.go b/go/typdown.go
index 386b779..d4bf569 100644
--- a/go/typdown.go
+++ b/go/typdown.go
@@ -28,7 +28,11 @@ var (
ErrInvalidLink = errors.New("invalid link")
)
-func Parse(content string) (template.HTML, error) {
+type Document struct {
+ ptr unsafe.Pointer
+}
+
+func Parse(content string) (*Document, error) {
code := C.uchar(0)
conv := C.CString(content)
raw := C.typdown_parse(conv, &code)
@@ -38,8 +42,25 @@ func Parse(content string) (template.HTML, error) {
if code == 1 {
panic(err)
}
- return "", err
+ return nil, err
}
+ return &Document{raw}, nil
+}
+
+func (d *Document) Deinit() {
+ C.typdown_free(d.ptr)
+}
+
+func (d *Document) RenderHTML() (template.HTML, error) {
+ code := C.uchar(0)
+ raw := C.typdown_renderHTML(d.ptr, &code)
defer C.free(unsafe.Pointer(raw))
+ if code > 0 {
+ err := codeErrors[uint8(code)]
+ if code == 1 {
+ panic(err)
+ }
+ return "", err
+ }
return template.HTML(C.GoString(raw)), nil
}
diff --git a/go/typdown_test.go b/go/typdown_test.go
index c1d8985..974f661 100644
--- a/go/typdown_test.go
+++ b/go/typdown_test.go
@@ -7,7 +7,12 @@ func TestParse(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if res != `<p>hello world</p>` {
- t.Errorf("invalid result: %s", res)
+ defer res.Deinit()
+ got, err := res.RenderHTML()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got != `<p>hello world</p>` {
+ t.Errorf("invalid result: %s", got)
}
}
diff --git a/lib/typst/typdown_typst.h b/lib/typst/include/typdown_typst.h
index 755314a..755314a 100644
--- a/lib/typst/typdown_typst.h
+++ b/lib/typst/include/typdown_typst.h