diff --git a/examples/generated/source_sync/example.pdf b/examples/generated/source_sync/example.pdf index b05c770..917cb44 100644 Binary files a/examples/generated/source_sync/example.pdf and b/examples/generated/source_sync/example.pdf differ diff --git a/typst/private/tests/simple/BUILD.bazel b/typst/private/tests/simple/BUILD.bazel index 46c1483..04f62a3 100644 --- a/typst/private/tests/simple/BUILD.bazel +++ b/typst/private/tests/simple/BUILD.bazel @@ -1,5 +1,6 @@ load("@bazel_skylib//rules:build_test.bzl", "build_test") load("@bazel_skylib//rules:copy_file.bzl", "copy_file") +load("@bazel_skylib//rules:diff_test.bzl", "diff_test") load("//typst:typst.bzl", "typst") filegroup( @@ -29,3 +30,29 @@ build_test( ":simple", ], ) + +# Determinism test: two separate targets from the same source must produce +# byte-identical PDFs (SOURCE_DATE_EPOCH=0 is set by default). +typst( + name = "deterministic_a", + src = "simple.typ", + data = [ + ":frown", + ":smile", + ], +) + +typst( + name = "deterministic_b", + src = "simple.typ", + data = [ + ":frown", + ":smile", + ], +) + +diff_test( + name = "deterministic_test", + file1 = ":deterministic_a", + file2 = ":deterministic_b", +) diff --git a/typst/private/typst.bzl b/typst/private/typst.bzl index 6627ba2..7894ea9 100644 --- a/typst/private/typst.bzl +++ b/typst/private/typst.bzl @@ -33,6 +33,9 @@ def _typst_impl(ctx): _rlocationpath(src, ctx.workspace_name), )) + env = {"SOURCE_DATE_EPOCH": "0"} + env.update(ctx.attr.env) + ctx.actions.run( mnemonic = "TypstC", executable = toolchain_info.process_wrapper, @@ -40,6 +43,7 @@ def _typst_impl(ctx): outputs = [pdf_outfile], tools = toolchain_info.all_files, inputs = depset([ctx.file.src] + ctx.files.data), + env = env, ) return [ @@ -48,16 +52,21 @@ def _typst_impl(ctx): ] typst = rule( - doc = "TODO", + doc = "Compile a Typst document to PDF.", implementation = _typst_impl, attrs = { "data": attr.label_list( - doc = "TODO", + doc = "Additional data dependencies (images, templates, etc.).", allow_files = True, mandatory = False, ), + "env": attr.string_dict( + doc = "Additional environment variables for the typst compiler action. " + + "SOURCE_DATE_EPOCH=0 is set by default for deterministic output. " + + "Override with a different value to opt out.", + ), "src": attr.label( - doc = "TODO", + doc = "The .typ source file to compile.", allow_single_file = [".typ"], mandatory = True, ),