Clause
← All dokumentation

Det engelska originalet har ändrats sedan översättningen gjordes, så delar av den kan vara inaktuella. Läs på engelska

Översatt från det engelska originalet · 1e3a39c8-dirty · 2026-10-26

Kompilering

clau kompilerar Erlang/OTP 29-moduler via LLVM till verifierad IR, bitkod eller inbyggda objektfiler. -o/--output länkar positionella indata (eller ett valt projektmål), deras ingångs-startobjekt och runtime till en körbar fil (länkning); projektbyggen länkar körbara mål till utdata i deras manifest (projekt). Genererade objekt kan också köras genom en C++-testrigg länkad med runtime (se exemplet nedan).

Godtagen delmängd av källkoden

Namngivna moduler i det vanliga OTP 29-språket: ordnade funktionsklausuler med mönster och guards; matchningar, konstruktorer, operatorer och inbyggda funktioner (inbyggda funktioner); case, if, receive, catch, try ... of ... catch Class:Reason:Stack ... after med stackspårningar, maybe ... else ... end; list-, binary- och map-comprehensions (mönster); tupel-records och native records; funs, lokala, fjärr- och dynamiska anrop (M:F(...), apply/2,3); processer och portar. Anrop körs på explicita processramar med äkta svansanrop (exekveringsmodell); kroppsrekursion begränsas av processtacken (obegränsad som standard), inte av den inbyggda stacken. Moduler som en batch namnger men inte deklarerar kommer från biblioteket. Matchningskvalificerare i comprehensions från den experimentella funktionen compr_assign avvisas som [heap expressions] notimpl.

Godtagna attribut: module, export, file, tupel- och native-record, export_record, import_record, typ-/spec-former, doc/moduledoc, behaviour/behavior (behaviours), varje informativt attribut (vsn, author, copyright, deprecated, dialyzer, användardefinierade -name(Term); behålls för module_info(attributes)), -import(Module, [F/A, ...]) (importer) och -compile med alternativ som inte ändrar något som Clause genererar: {no_auto_import, ...}, varningsalternativ (nowarn_*, warn_*, {nowarn_unused_function, [...]}) samt tips om optimering, felsökning och rapportering (inline, {inline, [F/A]}, {inline_size, N}, {inline_effort, N}, inline_list_funcs, debug_info, deterministic, report*, verbose, ...) samt Clauses eget {clause_liveness, strict} (strikt livaktighet). {parse_transform, Module} kör transformen på värdens Erlang/OTP före analysen (parse transforms). on_load, nifs, export_all, andra compile-alternativ och parametriserade moduler avvisas; diagnostiken namnger dem, till exempel [behavior-changing attributes] notimpl [module="m" operation="-compile option export_all"]. Varje modul får module_info/0,1. Källfiler som börjar med #! följer reglerna för escripts (implicit modul och export av main/1, -mode godtas). Typ-/spec-former analyseras men ändrar aldrig genererad kod. Rena syntaxlägen (--parse-check, --print-ast, --print-source, ...) godtar hela grammatiken.

Strikt livaktighet

-compile({clause_liveness, strict}). talar om för analysen av levande exporter att modulen aldrig namnger koden den anropar genom sina egna atomer. Dess atomliteraler behåller inga andra modulers exporter (dess eget namn behåller fortfarande dess egna, eftersom feltupler namnger den för format_error/1), dess record-taggar inga, och dess atomproducerande inbyggda funktioner och binary_to_term/1,2 räknas varken som en källa till modulnamn eller som ett dynamiskt anrop. Den får inte heller skicka andra modulers namn till inbyggda funktioner som anropar dem via namn, som spawn/4 med en nod eller erlang:get_module_info/1,2. Dess egna anrop via namn räknas fortfarande: M:F(...) eller apply/3 med en literal modul och en funktion som bestäms vid körning behåller den modulens exporter, och anrop med en modul som bestäms vid körning är dynamiska anrop, som når de moduler som andra modulers atomer namnger.

Alternativet ändrar ingen genererad kod, endast vilka exporter en körbar fil behåller. Ett felaktigt löfte utelämnar en export som modulen anropar via namn, vilket då kastar undef. Biblioteksmoduler sätter det där deras atomer endast är data: epp (token- och makronamn, maskinen, applikationsnamn), erl_error (en atomplatshållare i utskrivna argumentlistor; error_info namnger modulerna i koden som kastar), erl_features (funktionslistan i en beam-fil) och file (felorsaker, begärandetaggar; modulerna som en io-begäran namnger är avsändarens atomer). Utan det behöll apply/3 i file:io_request/3 och list_to_atom/1 i epp varje export i ett program som förbehandlar en fil, inklusive hela erl_eval; med det (och -if-villkor evaluerade i C++) minskar dess extra kompileringstid jämfört med ett hello-world med cirka 40 %.

Kör exemplet med kompilerade moduler

client:main/1 gör exemplet till ett program:

./build/debug/bin/clau -O2 -o build/demo examples/compile/answer.erl examples/compile/client.erl
./build/demo     # prints 42, -7 and {record,map,binary,list,integer,other}

Samma moduler kan också köras genom en C++-testrigg. Från ett Windows x64 Developer PowerShell med den byggda kompilatorn:

$tool = './build/debug/bin/clau.exe'
& $tool -O0 --emit obj --artifact-dir build/example-aot examples/compile/answer.erl examples/compile/client.erl
cmake -S examples/compile -B build/example-native -G Ninja -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=Debug "-DGENERATED_DIR:PATH=$((Resolve-Path build/example-aot).Path)"
cmake --build build/example-native
./build/example-native/bin/Debug/compiled_modules.exe

Det skriver ut 42, -7, record, map, binary, list, integer, other, en per rad. Testriggen registrerar moduler explicit, skapar en kontext och avkodar resultat; den är ett exempel på en värd, inte en ingångspunkt för produktion. På Unix används build/debug/bin/clau, clang++ och -DGENERATED_DIR="$PWD/build/example-aot". CTest codegen_examples kör dessa kommandon för varje policy.

Andra åtgärder på samma källfiler:

& $tool -O2 --emit llvm-ir --artifact-dir build/example-ir examples/compile/answer.erl examples/compile/client.erl
& $tool --print-types --verbose examples/compile/answer.erl examples/compile/client.erl
& $tool --print-ir --print-optimized-ir examples/compile/answer.erl examples/compile/client.erl
& $tool -O2 --no-type-specialization --verbose examples/compile/answer.erl examples/compile/client.erl

Utskrift av abstrakt format

--print-abstr (en frontend-åtgärd) skriver ut varje tolkad modul som de former i OTP:s abstrakta format som epp skulle lämna till en parse transform, en file:consult/1-term per rad, samma termer som erlc +to_abstr skriver (transforms).

Utskrift av källkod

--print-source (en frontend-åtgärd, som --print-ast) skriver ut varje tolkad modul som Erlang-källkod; --print-types skriver ut samma text med typannoteringar. Utskrivaren (print_source, expression_source, type_source i printing.hpp; compiler/src/printing/source_*) är återanvändbar:

Alternativ

AlternativBeteende
--emit obj|llvm-ir|llvm-bcPublicera en artefakt per modul
--artifact-dir DIRArtefaktrot (kräver --emit)
-o PATH / --output PATHLänka en körbar fil (länkning); i konflikt med --emit
--linker PATH, --runtime-library PATHClang-drivrutin och runtime-arkiv för -o
--no-cacheVarken läs eller skriv byggcacher
--cache-inference-in-dirs PATTERNKan upprepas: moduler i matchande kataloger behåller sina inferensresultat i byggcachen, utöver de implicita OTP-applikationskatalogerna (inferenscache)
--build-dir DIRDär Clause håller temporära filer (under DIR/tmp); ersätter build_dir för varje valt projektmål; positionella indata har ingen utan alternativet (byggkatalog)
--entry MODULE[:FUNCTION[/ARITY]]Den körbara filens ingångsfunktion/1 (annars funktion/0; /0 eller /1 väljer en); valideras i varje kompileringsläge och lägger till startartefakten clausev1_start (körbara filer); IR- och assemblerinspektioner utelämnar då det som den inte kan nå (levande exporter)
--target-triple TRIPLEMålmaskin; --target väljer projektmål
-O0 / -O2 / -OsGenerisk standardkod + LLVM O0 / begränsad specialisering + LLVM O2 / LLVM Os, ingen specialisering, en sektion per symbol och länkarens borttagning av orefererad kod och data
--no-type-specializationStäng av varianter oavsett alternativens ordning
--jobs <n>Optimera och emittera objektmoduler på n trådar (standard: varje hårdvarutråd), varje modul i en egen LLVM-kontext; objekten är desamma för alla antal; --jobs 1, IR- och assemblerinspektioner behåller alla moduler i en kontext
--ltoLänka modulerna som bitkod med LLD:s optimering vid länkning (Windows MSVC- och ELF-mål; kräver -o eller ett projektbygge som länkar) (länkning)
--keep-exportsBehåll varje export i en körbar fil anropbar i stället för att utelämna dem som den inte kan nå; kräver -o, ett projektbygge som länkar eller en IR-/assemblerinspektion (levande exporter)
--shellLänka det interaktiva Erlang-skalet och varje biblioteksmodul, med varje export anropbar; utan --entry startar den körbara filen skalet, så clau --shell -o erl utan indata bygger ett skal med endast biblioteket; kräver -o eller ett projektbygge som länkar (interaktivt skal)
--fips=PATHLås programmet till FIPS-läge med användarens OpenSSL FIPS-provider i PATH (modul och fipsmodule.cnf, kopierade bredvid den körbara filen); medför --with-crypto; en saknad eller felformad provider gör att bygget misslyckas (FIPS)
--with-crypto[=PATH]Länka runtime-arkivet för crypto och lägg till biblioteksmodulen crypto i batchen, för program som når crypto endast genom dynamiska anrop (program som anropar den länkas ändå med den); PATH är en OpenSSL-installation eller ett källträd ≥ 3.1.2 att länka i stället för den som Clause byggdes med; kräver -o eller ett projektbygge som länkar (crypto)
-gErlangs radtabeller i objekt och länkade körbara filer (CodeView/PDB på MSVC-mål, DWARF på andra) (felsökning)
--print-ir / --print-optimized-irVerifierad IR före/efter LLVM-pass, med Erlang-källrader som kommentarer
--print-asmVarje moduls målassembler efter den valda kedjan, där varje följd av maskinkod kommenteras med den IR-instruktion och Erlang-rad den kommer från (assemblerlistningar)
--print-typesVarje modul som Erlang-källkod annoterad med härledda typer (semantik); stannar före LLVM
--verboseFashändelserna [pp], [parse] och [comp] på stderr, sedan sammanfattningen [index] ... av katalogindexet
--print-stage-times[time] <stage> <subject>: <ms> ms på stderr: plan per projektmanifest (inläsning av det och expansion av varje valt måls mönster), preprocess, parse och transform (moduler med parse transforms) per källfil, compile per batch (antal moduler, projektmål), link per körbar fil; (cached) följer ett steg som återanvände ett cachat resultat. Före en batchs totala compile kommer dess faser med samma subjekt: index, calls, liveness (körbara filer och inspektioner med en ingångspunkt), declared-types, inference-cache (med N of M covered modules reused, inferenscache), inference, inference-store, contracts, lower, optimize, emit (de som kördes; med objektutdata på flera --jobs-trådar flyttar optimize också varje modul till en egen LLVM-kontext och verifierar den, och emit verifierar och emitterar modulerna parallellt). Efter inference: rader inference pass N med passets arbetssteg av inferensens arbetsbudget (N of BUDGET work steps) och hur det slutade (inputs changed, fun results changed, settled, eller det sista passet efter ostabiliserade pass), med namnet på den funktion som kördes när budgeten tog slut, sedan (varje pass efter det första) ; skipped: N components, W work steps: komponenter som behållits från sin senaste genomgång eftersom inget de läser ändrades och det arbete som dessa genomgångar kostade (räknat i passets arbetssteg), sedan ; N lattice joins som passet körde (nästlade räknas) med , costly: C components given term() inputs när kostsamma rekursiva komponenter förlorade sina lokala indata (inferens), och sedan (varje pass som samlade lokala indata) ; inputs: F functions, S slots changed (kinds) med varje ändrad indataplats typ av ändring (first från ingen, integer bound, union member på toppnivån, shape, deeper behållarnästling, function types, term()) och N fun reads not final (fun F/A-värden som läste en sammanfattning som senare ändrades), sedan ; graph: N nodes (+M), W widenings sedan föregående pass och ; clean: C of K components (A inputs differ, B callees differ), X changed, T ms (P% of pass), S work steps: komponenter vars medlemmars indata och direkt anropade funktioners sammanfattningar är lika med föregående pass, de av dem vars sammanfattningar ändå ändrades, och tiden och arbetet som lades på dem; sedan inference lattice (ingen tid) med hur ofta varje gitteroperation kördes över alla pass (join av två medlemmar, nästlade räknas, widen, meet, within, subtract, truncate) och hur många anrop som upprepade ett med samma operander tidigare i sitt pass och i något pass (svaren som grafen behåller används för dem, och de operationer som ett svar körde nästlat körs eller räknas inte igen), sedan sammanfogningarna av annat än två medlemmar och uppslagen av behållarnästling med dem som grafen behöll svaret på (spårning av upprepningar saktar ned profilerad inferens med cirka 7 %); sedan inference churn med tiden som lades på att samla indata och hur många lokala indataplatser som ändrades en gång, två gånger, ... över alla pass, och inference churned <module>:<function>/<arity> #<argument> (ingen tid) för de 10 mest ändrade platserna med sin senaste ändrings typ och fakta före och efter den (vardera avkortat till 200 tecken); sedan (ingen tid) upp till 10 inference clean-changed <module>:<function>/<arity>-komponenter som var rena men ändrades, med passet som först såg det och hur ofta (ett beroende utöver indata och direkta anrop, som fun F/A); sedan (ingen tid) inference facts N efter varje pass som samlade indata: fakta för varje sammanfattning och lokal indata, deras största och genomsnittliga trädstorlek (noder räknade en gång per sökväg), den bredaste unionen, hur många som når budgetarna för behållardjup, unionsmedlemmar och tupel-/map-element, sammanfattningarna med flest (32) funktionstyper och beroende fakta; sedan inference largest med det största faktumet i var och en av de 3 komponenter som tog längst tid (avkortat till 200 tecken); sedan inference slowest <module>:<function>/<arity> för de 10 funktioner (rekursiva grupper namnger en medlem and N more) som tog längst tid över alla pass, med deras arbetssteg och det arbetets andel av budgeten för de pass som körde dem (877450 work steps, 43.9% of 10 passes of 200000 budget), widened to term() när en budget breddade ett av deras fakta, och de gittersammanfogningar som deras genomgångar körde och de grafnoder de skapade; sedan inference costliest <module>:<function>/<arity> för de 10 funktioner på minst 10 ms som tog längst tid per arbetssteg, med den tiden i mikrosekunder, deras arbetssteg, gittersammanfogningar (och sammanfogningar per arbetssteg) och skapade noder; sedan inference rounds <module>:<function>/<arity> and N more för de 10 långsammaste rekursiva grupperna: lösningar över alla pass, rundor som körts mot taket per lösning (8 + 4 per medlem), lösningar som nådde taket eller förbrukade sin åttondel av passets budget (varje medlem breddad till term()), lösningar som gav upp direkt eftersom ett tidigare pass gjorde det (remembered) eller slutade med passets budget förbrukad, genomgångar av medlemmar (och de som hoppades över eftersom inget de läser ändrades, och de som återspelades: en senare lösning tog medlemmens senaste genomgång igen eftersom inget den läste ändrades) och andelen genomgångar och återspelningar som ändrade en sammanfattning (växte, indata av funktionstyp ändrades, eller växlade tillbaka till en av medlemmens 4 senaste sammanfattningar), och de medlemmar som ändrades per runda i den sista lösningen i tio grupper av rundor, sedan ; N solves repeated the previous fixed point, M reached it after R rounds in total: lösningar som slutade på de sammanfattningar som föregående pass slutade med, och lösningar som nådde dem före konvergens, med antalet rundor det tog (det som skulle hoppas över om de användes som startvärden). En cachad kompilering skriver inga faser
--asn1-option OPTION, --asn1-outdir DIR, --generate-asn1Kompilera .asn/.asn1/.set.asn-indata till Module.erl och Module.hrl med ett asn1ct-alternativ (kan upprepas), till DIR (läggs till i include-sökvägen), eller generera dem endast (ASN.1)
--print-envSkriv ut den lösta kompileringsmiljön som TOML på stdout och avsluta utan att bearbeta källfiler (miljörapport)
--print-inputsFörbehandla och tolka indata, lägg till modulerna som de namnger så som kompileringen gör, lista sedan varje källfil i batchen på stdout och stanna före kompileringen (projekt)

Assemblerlistningar

--print-asm kör den valda kedjan (som --print-optimized-ir gör) och skriver sedan ut varje indatamoduls assembler från samma målmaskin som skriver objekt, en modul i taget. Kommentarer använder målets markör (# på x86, // på AArch64 ELF, ; på Apple, @ på ARM):

# erlang answer.erl:3: value() -> 42.
#     ir store i64 687, ptr %frame.slots, align 8
	movq	$687, 32(%r15,%r12,8)
#     ir br i1 %4, label %return.inline, label %return.service

Miljörapport

--print-env validerar hela kommandoraden (konflikter, läsbara positionella indata, projektplanering), skriver sedan ut det som kommandot skulle använda som ett TOML-dokument på stdout, avslutar med 0 och läser ingen källfil. Sökvägar är absoluta, med /.

# clau compile environment (--print-env)
command = ["clau", "--print-env", "-O2", "-o", "app", "main.erl"]  # as given
actions = ["link"]          # see below
working_directory = "/work"

[[targets]]                 # one per selected project target; one for positional inputs
name = "app"                # project targets only
project = "/work/project.toml"
sources = ["/work/src/main.erl"]           # globs and search paths resolved
library_directory = "/clau/library"     # application dirs, searched before source_search_paths
build_dir = "/work/build"   # "" for positional inputs without --build-dir
entry = "main:main"         # or "auto" when linking without --entry
output = "/work/app"        # linking only: final name (".exe" on Windows)
linker = "/usr/bin/clang++" # linking only; "" when none is found
runtime_library = "/clau/lib/libclause_runtime.a"

[targets.options]           # manifest option names
source_search_paths = []    # directories, patterns expanded
include_dirs = []           # search order, patterns expanded
defines = []
applications = { "stdlib" = "/otp/lib/stdlib" }  # last mapping wins
enabled_features = ["maybe_expr"]                # OTP defaults plus changes

[targets.backend]
target_triple = "x86_64-unknown-linux-gnu"  # host when not given
optimization = "O2"
type_specialization = true  # O2 without --no-type-specialization
debug_info = false
lto = false
keep_exports = false        # --keep-exports or the project option
shell = false               # --shell or the project option
emit = "none"               # or obj, llvm-ir, llvm-bc
artifact_dir = "/work/build/aot"

(Arrayer skrivs ut med ett element per rad.) actions listar frontend-åtgärderna (print-pp, parse-check, print-ast, print-source, print-abstr, annars preprocess-check; print-inputs ensamt ersätter dem), annars inspektionerna (print-types, print-ir, print-optimized-ir, print-asm), annars emit, link (-o) eller compile. I ett projektbygge länkar även mål med en output. Moduler som hittas senare via namn (genom source_search_paths eller biblioteket) listas inte: att hitta dem kräver tolkning (det gör --print-inputs). --print-env kan inte kombineras med --new-project.

Kompileringscache

En batch med en byggkatalog (varje projektmål, positionella indata med --build-dir) behåller sitt kompileringsutfall i byggcachen: diagnostiken i ordning, misslyckandet och, när en körbar fil eller --emit behöver dem, objekten (eller bitkoden) för varje modul och startmodulen. Ett senare bygge av samma batch med samma alternativ spelar upp diagnostiken igen och länkar eller publicerar de sparade objekten exakt som nya; --print-stage-times visar då [time] compile ... (cached). --print-ir, --print-optimized-ir, --print-asm och --print-types beräknar alltid om, och --no-cache varken läser eller skriver.

Backend

LLVM SDK

Stabil LLVM 23.1.x, minst 23.1.1. LLVM är ett värdberoende: arkitektur, C++-standardbibliotek och Windows CRT måste matcha kompilatorverktyget. Projektkoden behåller undantag/RTTI; inget undantag får avvecklas genom LLVM. Runtime använder aldrig LLVM.

Referensuppsättning för Windows x64: värdens clang-cl 23.1.2 i C:/Program Files/LLVM/bin, SDK thirdparty/clang+llvm-23.1.2-x86_64-pc-windows-msvc, Visual Studio 18 x64-verktyg, Windows SDK 10.0.26100.0, Ninja, /MT, _ITERATOR_DEBUG_LEVEL=0. Automatiskt val tillämpar /MT- och iteratorinställningarna; en explicit LLVM_DIR gör det inte, och länkproben misslyckas då.

PCRE2

Runtimens inbyggda re-funktioner använder PCRE2 10.47, den version som OTP 29 medföljer (erts/emulator/pcre/vendor.info), så att mönstersyntax, alternativ och infångningar beter sig som i OTP: 8-bitars kodenheter, Unicode-stöd, ingen JIT, oförändrad pcre2_match (OTP:s patch för att lämna ifrån sig körningen förs inte över). PCRE2 är licensierad under BSD-3-Clause med PCRE2-undantaget för kompilerade binärer; ingen PCRE2-fil checkas in. CMake (cmake/Pcre2Dependencies.cmake) löser den i denna ordning:

  1. -DCLAUSE_PCRE2_ROOT=<source directory> har företräde (ingen nedladdning); versionen i dess configure.ac måste vara 10.47.
  2. En installerad PCRE2 på minst 10.47 (CLAUSE_PCRE2_SYSTEM=ON, standard): CMake-paketet (find_package(pcre2 CONFIG COMPONENTS 8BIT), statiska bibliotek föredras), annars pkg-config libpcre2-8, där en statisk libpcre2-8.a föredras framför det delade biblioteket.
  3. Den fastlåsta versionen, nedladdad till thirdparty/pcre2-10.47 och verifierad (pcre2-10.47.tar.bz2, SHA-256 47fe8c99461250d42f89e6e8fdaeba9da057855d06eb7fc08d9ca03fd08d7bc7); -DCLAUSE_DOWNLOAD_PCRE2=OFF stänger av nedladdningen.

En källkatalog (1 eller 3) bygger objektbiblioteket clause_pcre2 från de listade .c-filerna med de distribuerade config.h.generic, pcre2.h.generic och pcre2_chartables.c.dist kopierade till byggträdet (inget genereringssteg, inga varningsflaggor från projektet, utanför clang-tidy och Lizard), och dess objekt läggs till i själva clause_runtime: arkivet är självständigt och varje konsument (länkningar med clau, nästlade testprogram, runtime_link, examples/compile) får PCRE2 med det. Ett installerat bibliotek blir i stället en extra länkarindata som registreras i clause_runtime.link bredvid arkivet (en indata per rad), som clau lägger till i varje länkning; ett delat bibliotek gör att de körbara filerna beror på det vid körning. Per plattform: Windows använder nedladdningen (ingen system-PCRE2 söks i praktiken); Linux och macOS använder en installerad PCRE2 10.47 eller nyare när den finns, annars nedladdningen. PCRE2 länkas alltid in i runtimen, även i program som aldrig anropar re.

zlib

Runtimens zlib-modul och komprimerade externa termer använder zlib 1.3.2, den version som OTP 29 medföljer (erts/emulator/zlib/vendor.info), så att komprimerade bytes är lika med OTP:s. CMake kompilerar dess bibliotekskällor (cmake/ZlibDependencies.cmake, clause_add_runtime_zlib) till objektbiblioteket clause_runtime_zlib, vars objekt läggs till i clause_runtime som PCRE2:s; -DCLAUSE_RUNTIME_ZLIB_ROOT=<source directory> har företräde, annars laddas versionen ned till thirdparty/zlib-1.3.2 och verifieras (SHA-256 bb329a0a2cd0274d05519d61c667c062e06990d72e125ee2dfa8de64f0119d16) på varje värd. zlibs licens är zlib-licensen. Kompilatorns LLVM behåller sin egen zlib; de två möts aldrig i en binär.

zstd

Runtimens zstd-modul använder zstd 1.5.7, den version som OTP 29 medföljer (erts/emulator/zstd/vendor.info), så att ramarna är lika med OTP:s. CMake kompilerar dess bibliotekskällor (common, compress, decompress; enkeltrådat, utan assembleravkodaren; cmake/ZstdDependencies.cmake, clause_add_runtime_zstd) till objektbiblioteket clause_runtime_zstd, vars objekt läggs till i clause_runtime som zlibs; -DCLAUSE_RUNTIME_ZSTD_ROOT=<source directory> har företräde, annars laddas versionen ned till thirdparty/zstd-1.5.7 och verifieras (SHA-256 eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3), samma arkiv som Windows LLVM-bygget använder. zstds licens är BSD-3-Clause (eller GPL-2.0).

OpenSSL

Runtimens inbyggda crypto-funktioner använder OpenSSL:s libcrypto, fastlåst till 4.1.0, med alla versioner från 3.1.2 (den senaste med en FIPS-validerad provider) godtagna, i ett separat clause_runtime_crypto-arkiv som endast program som anropar crypto länkar. Var det kommer från, hur Clause och clau bygger det från källkod, länkning (--with-crypto[=PATH]) och FIPS-läge (--fips=PATH) beskrivs i crypto.

Övriga förutsättningar: CMake ≥ 3.28, en C++23-kompilator, Boost ≥ 1.90, toml++ 3.4.0 och kvalitetsverktygen. OTP behövs endast för valfria granskningar och återskapande av fixturer.