From 00af9ab3115e79335d97a4fdff0fabb09548c3b6 Mon Sep 17 00:00:00 2001 From: Matt Epperson Date: Sun, 1 Mar 2026 16:01:36 -0800 Subject: [PATCH] Make pdfs deterministic Sets an environment variable that removes a timestamp from the pdf --- examples/generated/source_sync/example.pdf | Bin 27374 -> 27367 bytes typst/private/tests/simple/BUILD.bazel | 27 +++++++++++++++++++++ typst/private/typst.bzl | 15 +++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/examples/generated/source_sync/example.pdf b/examples/generated/source_sync/example.pdf index b05c770c3f023a9d0933d8089faa076f8e337ac1..917cb44baafdb59d6c7d38ab2a90e94e26513e36 100644 GIT binary patch delta 6402 zcmZ{HXEfYh*Edlj>ZMJhi!MrrQAf*=sA2S8NAJCte-K2EE;`YB8H7O+QKR=7f?$+{ zFbtx+dGGhbyViX@&)NIKS-;;dXYaMohy7~~cXtlA@rMkqWZEn0M`>_l(zFM%oB)XD zF~vO&j#T`dJ%Mm(=e?QjM1JW}Gxh%q%iB55|4fXW2=zTP2!W$`YO%3#BJhH6G z00NIr+=Tji0lq}_q##@mjm!zrGXFWxLRmtOOuXY-fx4;yd;Tcg@rHXT6ti>l;tpy^ z^Y74(Fx79Jah-WAEKPU|0=S1?HokbCVfllJWOeTyTjlyuAbZ*=20a*afSg_H!KIr+ zTgJgK%%()!_l8lJoLyQY0TT{r|F=Yv{-F+^$)1eJv{hao+>AkR}HBy+@J8IIZbX zbCoZs*B!fm^B24zUROaOxk$(|tG*?K8gn`;*7!YWc%MlOevt8K_^Bmd@YD|BVXo!` z3P;?$dF6u!y+ZS#1W?3Do56Ct)-!pU_To41umZD8^fzyu7K+!dn2UPTcioyS;}4m> zvy*FTPvXk({ywZAD^OP{5DG3H94sLrxkiv=JuKyz;4un#rj`mPh~M1ONhKkf&7KW< z#m)3x<;4g^z}ISNsRX82NvVXmJQ{~eDir3)Ee(-h0+cj=m;-1O!oom(?GDgsDBKtR z%Cq{9u7A*LI(M%A+~0c8paaK%BbGiv)aemmW{+aV5pn50sV}G$e~iCiUFV)F~B=f(VZu9zIY$kY1Qs znQ=7*3uZ6b0d0IMKDHIXO6AF_*wVoYZe(#{tD|dD+gtAU%Oxv_WyDIfWL9$@zDcRn z6NvR@X|0MKA~TJXD`C9TYEzw`PcLby#m(v+oz|4+%YzS>x$B*%AnfVkWN~g-<0VS& z?uR=|(;sGYzaL3o&!ff~zDX~?w_P(b(DFaoKCn0M0sMi>tgs84KT|1K*Svs8_t9)g zZ(-)l9$_D|K!f%@^+%D44dVQ|-qFvK<4B0-50lUzv^)dZw-AhvJ>O%LMOxT9QIaRh zFXOA)IefE&2aBHTJ>#L7V=j(S%qd@lwYs{)6b)zeQrM zYTHuP)z!>%!tTa@S!6PrcAp%tqK;6HbT9fAH11q}hspfupPgM%vwI2mAzx{C1cDI= zC4K#+k}+zL-O8Aw%N^{No@s7aNfwf$MYb=^* z1(J%SRP;zEd%RCKIFhRuaJOxL zReYjaARFr+{?8WKRHK=_=j5ic0UZFrRfO9^M{Ht|P4BV2HC+cRqLUtX8UAOEPv9jf z=)}g>50g|+PT3Y|&7ai|nILEa!q`le?Qz}gzk!2ZMvsUf`|!s^OpWzMA}QJqLykY^ z@5*&zZZFlc(D^g&e)*C!XFGeLn^~LK&02|J?Q9O^>K}(qd`J6V&TQX2YX-!*7FAg7 zoQ1Fwi&K-0mL@|!W6`{BWl-yT)8n=npWLaXr9Dc!a>puh2ws)%XnXlDJ}Gjhoa52_ z37N5id2;iD+eN&mp$01#!)frW%tAfMUVXePQ1=5ayFhlA^M4{#k|m`gl9!pp7$Qsu zsx;Je;Ml6d5mPvpiw>M^1q6M!Vump7@y{rWcON&0d~qHha1mR{cJ0g*j=#1mc}M5S z+19gNj*2gk3P5Y_*O(B`!%GvZw$`pLx6`gpAPm1$K8$}g+5=M8UK^GM#zcw5FbPdE z26I$LC1idlUxx7a(h{$vTm9{_B2LH@dka{G_tW%6LM6IqH0^p0NGk_IlhCyGhEy}| z>n5g{2oLdES_Ome?X6ic{<0F# z@K>8;w!a^oSK_;ftSaa0D^#GPDsk(_kFN}8RVKEvd)|a2N=5C0T-;UrrW1C3{YS25 zk*~Mi{oC?tm+t}K7o;$9r-U6(B{<{)4Zjp~3?~Xa#jI3xj^|~bcj2H3#Ka>gqjlX~ zCSkArpv;3>xqg}z?;ej1*dwC9{1VYnmtFWK)nT%n=2>r`1u@@I*YBd65N4;QTWl~? zKQh*5A8*!@E$rzMuWQXXL0+Fy-FZE0n9BMRO?-4lQ|Aqs#oN(mS(GkWT2H+afU`4h zi)qkr1yK_J{QKjOqjTPLx6mQEMh4ie-0kO**AE9ANY%PEqz?JtMEK-8tK_t$3nUJa zW_B3dKH;;`F{eF{oy@|Hm+i_rrV0Hs>R-{FtTlOYiNq282}JGl7OC#@g!ueW zzBG_K%6|o~Zsllc2X(wQdc(=Le8TdrpbJ%gdV`g!@h`hX9#Vh2nv13WC@T;)!xyAP zDwmye{Uf|ceI&Dy(as*mZ-2WPbDc+s*$A3>n+NSy^WZu ziYUDSG19A-zMB&Kkbw5UI~ft_&9mB=(y%uyprjp4%tj}$RZ)1MyBtUse|DHhfhc}6hHiB>$+r4L%$tEyX!%bf6nu0G~Iow5>Cc;hp% z%j^4rhEasG?{N<_!?kBw>6mG(1iro{rts2AbP51h!1cR>s-MX`X(T_;3ikp^d&BSP zT8gR)u_PWBk?QgE8`tVWWO(#WWDKKPkBi6?4a1#k<>{n(lmwhKs|TXL@@i?9zFyIc zZ>@a6?4%Vhn%#g|u+G@eDkx*4P9v9 zSyibdK;J}eTdC>1z4BW)d?C#JHwx}v{SP}OMu-2J^M%kW2ZC?xA#+%mFoSKC^StGR;wKr`M;b4Z$L#D|GK=qDU57<4V2xHP z!7rKrVOq-kfEnzR0}iyxg6g-Gyb22)tA7Qg+wigQFV$REk|*8T2QxhzZ=TOOLz@m`0CSA)8XbTm^WUBw*MGC*drgKy3 zYqWdcdrbaI^^dYbN;vOQ^+Vxv(S6j%u#gl(5zF_@?b>>{yi&gZXcxBXBbu8g!m7*= zg5HvvQ>8ysD-N!JAbvH@a@?o3()XJM8vzvoka=RIKKzDxxRq)tBMfAGTmQWEr2Ol8 zyW2Cej5VXoS?u1UIQY%(l}O`21_dG;gINZJv~fnBk@asIiy8CO>*bVk7n;x2@eIQq zEyh?o!V9is?Fdio(1O|<4gS-cVd@O&2HQ@dy`ty+uVsOcG4*dx@lbBPIBiB95bq&b zcF(5s@>g}KWOI0IP0X!^zGQt*JhFP15bnJDn!D@$Hs>SXxEc|b*8;h6Qr0$%+u7Ik z*cG0$5Re7`QN7-mZHM{XSAq!bG?-Tzk=ObapAo98u24J;A?eSq!Ho9OjP~FA zfk>j~lYbzcohX?db;%=-ORQD2nOdXxBOv1I00ECSmAzF#s_k%gq$y`GrL=0BbQP$k zf{sUChJY5U$=rTJtkVo@p)xL<+9^U}}nZWLP zxl0p&e!LMLlDth-RdBE6P>cpaej+p`mlH2d!y7mqRt3a4J;W|a_PaaQ_bRJq3ZDv5 zK<3g8^J65l6ODMZ0#t_y!kptXD0IMsM{32*pWeBLmk}h zm6T2fzGHjTfb@1DvOzhJ$9704wxrM7Zhce|uY}Dyr)HB&AnTxvn<^#MIf&}5m;`hI zq4X>=opXyTC8x?R%TkOurGdjp2E-Dd-f#(oxd^-i9SLX{dJE**gv9CDxDQI-k*cj} zKCLB9ImZTDyujf?rtF!cUY*HdjNek0s(k?cIb(WxWzGv#?-$6W-Je|!=ft7 z(L>dtrasNMcR(vl>_1=i=)|@Hv*-CQf9$P8h49@3PQ-YyS)Z}pL1hakqtm{v{0AYt zyGG0V4dFZXKQ$HH-%NvIQ_{O&t=sN^%6x3G?pTVq?cFy8xBg5D3u!`J3t0+a$)v$g zD-dK>_D|;Suml!`*}V(y zFbg%EfQHXcN_iQ!mr-x4H8y;e8N5o;?=p+b4c2-QcMa{47J@hg*~yNEI1hIK%f~xb z#N`MskQLNT=|QF?p@;IyD4Ruq4etcgXSODiKDH*K8#zK;1m*q=!NWK2s$DB5JPrwj zDx6}vk9Vu2#bcwasNY1fJ?N8vi;E!Vd}=sG96{Z8SnaCg{lV#=x==T{JSf{gh4nG| zglnG`6I+xFL9_hCVAU~GWuRLir6@TGoh2x^nPrTgw!1-0ID~mpnql^3-tV~s>RZ5{ z?Asj0J5IC$3>YpVal5j7=zACVjfa%{0uN=qjp+TIyvO0{_OIrdtrbi$Vu@Q^^UU z?IXfEW5d|cgArjI=+| zeyUs_YeNs`R?^UbEiA?_r9m|7BL~{jSy1jm=w@&Yd|Oh)l0HMSjXBbQelIy92{I3O zI)lZR;YOnbgY+jMaH&fO9R``!)3W|!olfnK`qjA(@AXP9x{Bs1vxu7@R7Z1#x~Z!! zuizs3bK#pZ_eU7t`#-5M7k@*4DC)LC+WS9QXLs;_A_L6ljIgY{Kry@SqVQ#|hO}=T zq+~jcfFGYZZilpk`fB9((asUfLEu=qSq%ybK+B&yGjfw>=^2MaVsPt_HRj0w^4hmfWtn?jGV%&2bbQnX8 zG}F?40U#u7G6D@@xs|ia?_pgX-N-_w z=9pnM2+0+xPhy+_(_@+W>Q_yp`?%6nb16>3oXdfLw1+K8l|bMjh7&ddiaEB`FgDgu z3zPTfC*Sb@;OI#tK!u!CC&3?kDB>Q#Uzi00ya_Uha@f)5>LMnS{Nl7Eorz_~EBIqB z6?E2)L0Y7RvaxX|W?ekd<+KCGjuGWMsEb*z9PLM6Dv&x>q_jU!0iQX(PCx>C;!i?z z78q)Gx1&#`(@sL@yFLfiFARHs;awO^3W)SQsw-YS;Alv8JtsV9k0v}dQP|UGISm>C z&P?#XjcQ+vvCP=O#1qRHVM}(*6M_{C+@xFL<3%bFT;(4wpTmqG=xB`9bu?Z2JJ|$# z;;-P-faszJyl%2qkIE?CBWc9p@x`;>c?y;_c!w#a`_*}6)vMLTUKTLIhNoA}t}Z-P zLb{4PKWl}UQkgYuA0H4T(uycfqCHfBxUX9(Q9fo8oW!a`6uS>1Hf4CF!>9wb9cD@6 zAg2L&MJW-Aq{-Xt_+&AkV+Na>k`sZ;zAJoq zJ4bk(){t`HepU@IwZQb0NFYLz;$X1QU-{25<|SrjeX8JPYvtqU?)Kcu$Cj1nIrP75 zTKX*`?t%UbNp{qmbD8=LPTB9Q&U`2(a_t?K}6nLKS&rR ztd&M*!~MTdE&4Wa0zjPgKhI-zBP0ILMOa8e0`f0RQb_W@F=1ixfB6cFN&eeTTvX`4 zeIa0R;s1w;{r|)wVq*VFEFv!cuYjTwVj^kAPKrYRbHy?;ysSL`GnF>wMDqYFDM`%9 J`2w!^e*haYIadGx delta 6422 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 UP8JA!0U>@qA$%5=cWQF~1$^yebN~PV 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, ),