t0g ← •MonoTime@ #!build/obj2/for_build # to emulate on makefile transition: NO_LDL → rm_lf=-ldl; no_fPIC → rm_f=-fPIC; something something PIE ⟨Spawn, WaitForOne⟩ ← ⟨⟩ •Import "fork.bqn" ⟨Serialize, Deserialize⟩ ← •Import "serialize.bqn" # modes: # 0: single string option # 1: toggle # 2: flag list opts ← ⟨ ⟨0, "j", "4"⟩ # number of parallel jobs ⟨1, "verbose", 0⟩ # log more things ⟨1, "rebuild", 0⟩ # forcibly rebuild everything # TODO clean ⟨0, "CC", @⟩ # the C compiler ⟨0, "LD", @⟩ # linker of the final binary; default CC, or CXX if REPLXX=1 ⟨1, "color", 1⟩ # whether to enable colored diagnostics ⟨0, "os", @⟩ # target OS (linux, bsd, macos); used for .so vs .dylib, and changing linker flags for bsd ⟨0, "arch", @⟩ # target architecture (x86-64, aarch64, generic); used for Singeli target deciding ⟨0, "OUTPUT", ""⟩ # output location; default depends ⟨2, "f", ⟨⟩⟩ # C flags for CBQN files ⟨2, "CCFLAGS", ⟨⟩⟩ # flags for all C compiler & linker invocations ⟨2, "lf", ⟨⟩⟩ # linker flags ⟨2, "LDFLAGS", ⟨⟩⟩ # more linker flags (identical to lf) ⟨2, "rm_f", ⟨⟩⟩ # forcibly remove C compiler flag(s) ⟨2, "rm_lf", ⟨⟩⟩ # forcibly remove linker flag(s) # also define the default OUTPUT value (default default being "BQN") ⟨1, "shared", 0⟩ # build a shared library; OUTPUT = "libcbqn.[so|dylib]" ⟨1, "wasi", 0⟩ # build with WASI; OUTPUT = "BQN.wasm" ⟨1, "emcc", 0⟩ # build with emscripten; OUTPUT = ".", is used as a directory ⟨1, "FFI", @⟩ # enable FFI through libffi; default ≡ ¬wasi∨emcc ⟨1, "pkgconfig", 1⟩ # attempt to use pkg-config to find libffi inclusion flags ⟨1, "singeli", 0⟩ # enable Singeli ⟨1, "REPLXX", 0⟩ # enable replxx # TODO options for forcing around the bytecode/singeli/replxx directories # CBQN toggles ⟨1, "rtverify", 0⟩ ⟨1, "heapverify", 0⟩ ⟨1, "c", 0⟩ # disable some default flags ⟨1, "O3", @⟩ # -O3; default ≡ ¬c ⟨1, "g", @⟩ # -g; default ≡ debug ⟨1, "native", 0⟩ # -march=native & use native arch as lower & upper bound for Singeli ⟨1, "debug", 0⟩ # -DDEBUG & -g ⟨0, "CXX", "c++"⟩ # C++ compiler (for replxx) ⟨2, "REPLXX_FLAGS", ⟨"-std=c++11", "-Os"⟩⟩ # default replxx C++ build flags ⟩ Log ← •Out _verboseLog ← {𝔽_𝕣:⊢} onExitList ← ⟨⟩ OnExit ← {𝕊: {𝕏@}¨ onExitList} _assert_ ← { 𝔾𝕩?𝕩; Log 𝕨𝔽𝕩 ⋄ OnExit@ ⋄ •Exit 1} SepArgs ← {' ' ((¬-˜⊢×·+`»⊸>)∘≠⊔⊢) 𝕩} Lowercase ← {𝕩 - (-´"Aa")×(𝕩≥'A')∧𝕩≤'Z'} getOpt ← { args ← ×∘≠¨⊸/ •args [ot, on0, od] ← ⍉>opts on ← Lowercase¨ on0 ot1 ← 1=ot ot2 ← 2=ot s1 ← ⊑∘⊐⟜'='¨ args # start of = hs ← s1<≠¨args # has value fl ← hs∧'+'=(0⌈s1-1)⊑¨args # is appended flag, i.e. "f+=a b c" s0 ← s1-fl # end of key ks ← s0↑¨args # keys ks Lowercase¨↩ # lowercase keys vs ← (1+s1)↓¨args # values {𝕊: "Unknown option -- "∾⊑(¬ks∊on)/ks}_assert_(∧´) ks∊on ci ← on⊐ks # index in option specification {𝕊: ∾⟨"Error: Unexpected '+=' for '",ks⊑˜⊑/¬𝕩,"'"⟩}_assert_(∧´) (ci⊏ot2)∨¬fl Gr ← {(≠ot)↑ci⊔𝕩} gvs ← Gr vs # values for each option {𝕊: ∾⟨"Error: Multiple values given for '",on⊑˜⊑/¬𝕩,"'"⟩}_assert_(∧´) ot2∨1≥≠¨gvs {𝕊: ∾⟨"Error: Expected value to be provided for ",⊑𝕩/ks⟩}_assert_(¬∨´) (¬ci⊏ot1) ∧ ¬hs # f='a b' f+='c d' → "a" "b" "c d" gvs ↩ (Gr fl) (∾{𝕨?⋈𝕩;×≠𝕩?SepArgs 𝕩;⋈⟨⟩}¨)¨⌾(ot2⊸/) gvs # map toggles to their actual values, error on invalid gvs ↩ on {𝕨{𝕊: ∾⟨"Error: Invalid value for '",𝕨,"'"⟩}_assert_⊢ ∧´𝕩∊""‿"0"‿"1" ⋄ ≠◶⊢‿(⋈"0"≢⊑) 𝕩}¨⌾(ot1⊸/) gvs gvs ↩ ((¬ot2) ⋈∘⊢⍟⊣¨ od) {×≠𝕩?𝕩;𝕨}¨ gvs # map in defaults gvs ↩ (¬ot2) ⋈⁼∘⊢⍟⊣¨ gvs # disclose options with only one expected result # •Show [ks, fl, hs, ci, vs] # •Show {𝕩/˜×(≠1⊑⊢)˘𝕩} ⍉[on, gvs] {(⊑on⊐