BQN-based build system
This commit is contained in:
parent
efcc6a28be
commit
d38316e670
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,6 +8,7 @@ libcbqn.so
|
|||||||
|
|
||||||
# build system things
|
# build system things
|
||||||
/build/obj/
|
/build/obj/
|
||||||
|
/build/obj2/
|
||||||
/build/singeliLocal
|
/build/singeliLocal
|
||||||
/build/replxxLocal
|
/build/replxxLocal
|
||||||
/build/bytecodeLocal
|
/build/bytecodeLocal
|
||||||
|
|||||||
3
build/build
Executable file
3
build/build
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
DIR="$(dirname $0)"
|
||||||
|
"$DIR/obj2/for_build" "$DIR/src/build.bqn" "$@"
|
||||||
@ -13,7 +13,7 @@ depfile ← (At buildDir) •file.At filename∾".d"
|
|||||||
prefix ← "si_"∾ (∧`'.'⊸≠)⊸/ •file.Name srcfile
|
prefix ← "si_"∾ (∧`'.'⊸≠)⊸/ •file.Name srcfile
|
||||||
|
|
||||||
# invoke singeli, which creates the result file
|
# invoke singeli, which creates the result file
|
||||||
(⟨"-d" ⋄ tmpfile ⋄ "-o" ⋄ resfile ⋄ "-n" ⋄ prefix ⋄ srcfile⟩) •Import siDir •file.At "singeli"
|
(⟨"-l", "gen=src/singeli/gen", "-d" ⋄ tmpfile ⋄ "-o" ⋄ resfile ⋄ "-n" ⋄ prefix ⋄ srcfile⟩) •Import siDir •file.At "singeli"
|
||||||
|
|
||||||
# output dependency file
|
# output dependency file
|
||||||
deps ← siDir⊸•file.At¨ •file.Lines tmpfile
|
deps ← siDir⊸•file.At¨ •file.Lines tmpfile
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit 2fefe457b47005f1aff2e67f73bbef7eb9173833
|
Subproject commit f60a3c73450b8d5ae18bdc76f090b20437cf7ab2
|
||||||
545
build/src/build.bqn
Executable file
545
build/src/build.bqn
Executable file
@ -0,0 +1,545 @@
|
|||||||
|
#!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⊐<Lowercase 𝕩)⊑gvs}
|
||||||
|
}
|
||||||
|
|
||||||
|
SH ← {
|
||||||
|
c‿o‿e ← •SH⎊{𝕊: 𝕩 {𝕊: ∾⟨"Error: Failed to spawn ",⊑𝕨⟩}_assert_⊢ 0} 𝕩
|
||||||
|
Log⍟(×≠) e
|
||||||
|
𝕩 {𝕊: ∾⟨"Error: ",⊑𝕨," exited with error code ",•Repr 𝕩⟩}_assert_(0=⊢) c
|
||||||
|
o
|
||||||
|
}
|
||||||
|
|
||||||
|
rootDir ← •file.Parent⍟2 •file.path
|
||||||
|
AtRoot ← rootDir⊸•file.At
|
||||||
|
|
||||||
|
po ← { # parsed options
|
||||||
|
⟨
|
||||||
|
verbose, j, rebuildAll, output,
|
||||||
|
os, arch, native,
|
||||||
|
emcc, wasm, replxx, singeli,
|
||||||
|
bytecodeDir, replxxDir, singeliDir,
|
||||||
|
CBQNc, REPLXXc, Linker
|
||||||
|
⟩⇐
|
||||||
|
|
||||||
|
custom ← GetOpt "c"
|
||||||
|
DOpt ← {@⊸≡◶⟨⊢,𝕨⟩ GetOpt 𝕩}
|
||||||
|
j ⇐ •BQN GetOpt "j"
|
||||||
|
rebuildAll ⇐ GetOpt "rebuild"
|
||||||
|
{𝕊: _verboseLog ↩ {Log𝕨𝔽𝕩⋄𝕩}}⍟⊢ verbose⇐GetOpt "verbose"
|
||||||
|
|
||||||
|
Max1 ← {𝕩 {𝕊: a‿b←2↑𝕩/𝕨 ⋄ ∾⟨"Error: '",a,"' and '",b,"' cannot both be enabled"⟩}_assert_(1≥+´) GetOpt¨ 𝕩}
|
||||||
|
Max1 "REPLXX"‿"shared"‿"wasi"‿"emcc"
|
||||||
|
|
||||||
|
|
||||||
|
shared ← GetOpt "shared"
|
||||||
|
native ⇐ GetOpt "native"
|
||||||
|
emcc ⇐ GetOpt "emcc"
|
||||||
|
wasi ← GetOpt "wasi"
|
||||||
|
wasm ⇐ wasi∨emcc
|
||||||
|
|
||||||
|
cc ← {emcc? "emcc"; "clang"} DOpt "CC"
|
||||||
|
cxx ← GetOpt "CXX"
|
||||||
|
ffi ← (¬wasm) DOpt "FFI"
|
||||||
|
debug ← GetOpt "debug"
|
||||||
|
singeli ⇐ GetOpt "singeli"
|
||||||
|
replxx ⇐ GetOpt "REPLXX"
|
||||||
|
|
||||||
|
uname ← ⊢◶""‿{𝕊: Lowercase 1⊑•SH⎊1‿""‿"" "uname"‿"-sm"} ∧´ (@≡GetOpt)¨ "os"‿"arch"
|
||||||
|
InUname ← {𝕊: ∨´ 𝕩⍷uname}
|
||||||
|
|
||||||
|
os ⇐ Lowercase {InUname"linux"? "linux"; InUname"darwin"? "macos"; InUname"bsd"? "bsd"; "linux"} DOpt "os"
|
||||||
|
linux‿bsd‿macos ← os⊸≡¨ {𝕊: "Error: Unsupported OS; options:"∾1↓∾", "⊸∾¨𝕩}_assert_(⊑os<⊸∊⊢) "linux"‿"bsd"‿"macos"
|
||||||
|
|
||||||
|
arch ⇐ {'-'¨⌾(('_'=𝕩)⊸/)𝕩} Lowercase {InUname"x86_64"? "x86-64"; ∨´InUname¨"aarch64"‿"arm64"? "aarch64"; "generic"} DOpt "arch"
|
||||||
|
{𝕊: "Error: Unsupported arch; options:"∾1↓∾", "⊸∾¨𝕩}_assert_(⊑arch <⊸∊⊢) "x86-64"‿"aarch64"‿"generic"
|
||||||
|
|
||||||
|
{𝕊: "Error: Cannot use Singeli on x86-64 without 'native'"}_assert_¬ (arch≡"x86-64")∧singeli∧¬native
|
||||||
|
{𝕊: "Error: Cannot use Singeli on generic arch"}_assert_¬ singeli ∧ arch≡"generic"
|
||||||
|
|
||||||
|
output ⇐ GetOpt "OUTPUT"
|
||||||
|
output ↩ •wdpath•file.At {𝕊:
|
||||||
|
wasi? "BQN.wasm";
|
||||||
|
emcc? ".";
|
||||||
|
shared? "libcbqn." ∾ macos⊑"so"‿"dylib";
|
||||||
|
"BQN"
|
||||||
|
}⍟(""≡⊢) output
|
||||||
|
|
||||||
|
exportSymbols ← ffi∨shared
|
||||||
|
|
||||||
|
GetLibs ← { 𝕊:
|
||||||
|
getLibs ↩ {
|
||||||
|
¬ffi? ⟨⟨⟩,⟨⟩⟩;
|
||||||
|
GetOpt "pkgconfig"? 0=⊑ •SH⎊1 "pkg-config"‿"--exists"‿"libffi"?
|
||||||
|
{SepArgs ¯1↓SH⟨"pkg-config",𝕩,"libffi"⟩}¨ ⟨"--cflags", "--libs"⟩;
|
||||||
|
⟨⟨⟩, ⟨"-lffi"⟩⟩
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SubmoduleDir ← "build"⊸•file.At⍟(@≢⊢) {𝕨≡0?@; •file.Exists r←AtRoot "build"•file.At 𝕩∾"Local"? r; 𝕩∾"Submodule"}
|
||||||
|
LogDir ← {𝕩≡@? 𝕨∾": not used"; 𝕨∾" directory: "∾AtRoot 𝕩}_verboseLog
|
||||||
|
bytecodeDir ⇐ 1 SubmoduleDir "bytecode" ⋄ "Bytecode" LogDir bytecodeDir
|
||||||
|
replxxDir ⇐ replxx SubmoduleDir "replxx" ⋄ "REPLXX" LogDir replxxDir
|
||||||
|
singeliDir ⇐ singeli SubmoduleDir "singeli" ⋄ "Singeli" LogDir singeliDir
|
||||||
|
{𝕊: "Output location: "∾𝕩}_verboseLog output
|
||||||
|
|
||||||
|
CBQNc ⇐ { 𝕊:
|
||||||
|
isClang ← ∨´"clang"⍷SH cc‿"--version" # TODO exclude from hash?
|
||||||
|
args ← ⟨
|
||||||
|
cc,
|
||||||
|
"-std=gnu11",
|
||||||
|
"-Wall", "-Wno-unused-function",
|
||||||
|
"-fms-extensions", "-ffp-contract=off", "-fno-math-errno", "-fvisibility=hidden",
|
||||||
|
"-DBYTECODE_DIR="∾•file.Name bytecodeDir,
|
||||||
|
"-DSINGELI="∾•Repr singeli,
|
||||||
|
"-DFFI="∾•Repr 2×ffi
|
||||||
|
⟩
|
||||||
|
args∾↩ isClang⊑⟨
|
||||||
|
⟨"-Wno-parentheses"⟩
|
||||||
|
⟨"-Wno-microsoft-anon-tag", "-Wno-bitwise-instead-of-logical", "-Wno-unknown-warning-option"⟩
|
||||||
|
⟩
|
||||||
|
args∾↩ 0⊑GetLibs@
|
||||||
|
|
||||||
|
args∾↩ GetOpt "f"
|
||||||
|
args∾↩ GetOpt "CCFLAGS"
|
||||||
|
args∾↩ ( wasm) / ⟨"-DWASM"⟩
|
||||||
|
args∾↩ ( wasi) / ⟨"-DWASI", "-DNO_MMAP", "-DCATCH_ERRORS=0", "-D_WASI_EMULATED_MMAN", "--target=wasm32-wasi"⟩
|
||||||
|
args∾↩ ( emcc) / ⟨"-DEMCC", "-O3"⟩
|
||||||
|
args∾↩ ( replxx) / ⟨"-DUSE_REPLXX", "-I"∾replxxDir∾"/include"⟩ # TODO maybe move to main.c only, and have it be in its own separate cache dir, so that adding replxx doesn't recompile everything?
|
||||||
|
args∾↩ ( debug DOpt "g") / ⟨"-g"⟩
|
||||||
|
args∾↩ ((¬custom) DOpt "O3") / ⟨"-O3"⟩
|
||||||
|
args∾↩ ( native) / ⟨"-march=native"⟩
|
||||||
|
args∾↩ ( debug) / ⟨"-DDEBUG"⟩
|
||||||
|
args∾↩ ( GetOpt "color") / ⟨isClang⊑"-fdiagnostics-color=always"‿"-fcolor-diagnostics"⟩ # TODO exclude from hash?
|
||||||
|
args∾↩ ( GetOpt "rtverify") / ⟨"-DRT_VERIFY", "-DEEQUAL_NEGZERO"⟩
|
||||||
|
args∾↩ (GetOpt "heapverify") / ⟨"-DHEAP_VERIFY"⟩
|
||||||
|
args∾↩ ( exportSymbols) / ⟨"-DCBQN_EXPORT"⟩
|
||||||
|
args∾↩ ( shared) / ⟨"-DCBQN_SHARED", "-shared", "-fPIC"⟩
|
||||||
|
args ↩ args (¬∘∊/⊣) GetOpt "rm_f"
|
||||||
|
{"CBQN C compiler: "∾•Repr 𝕩} _verboseLog args
|
||||||
|
cbqnc ↩ args
|
||||||
|
}
|
||||||
|
|
||||||
|
REPLXXc ⇐ { 𝕊:
|
||||||
|
args ← ⟨cxx, "-DREPLXX_STATIC=1", "-I"∾replxxDir∾"/include"⟩
|
||||||
|
args∾↩ GetOpt "REPLXX_FLAGS"
|
||||||
|
{"REPLXX C++ compiler: "∾•Repr 𝕩} _verboseLog args
|
||||||
|
replxxc ↩ args
|
||||||
|
}
|
||||||
|
|
||||||
|
Linker ⇐ { 𝕊:
|
||||||
|
args ← ⟨{replxx? cxx; cc} DOpt "LD", "-lm"⟩
|
||||||
|
args∾↩ 1⊑GetLibs@
|
||||||
|
args∾↩ (¬bsd) / ⟨"-ldl"⟩
|
||||||
|
args∾↩ GetOpt "lf"
|
||||||
|
args∾↩ GetOpt "LDFLAGS"
|
||||||
|
args∾↩ ( wasi) / ⟨"-lwasi-emulated-mman", "--target=wasm32-wasi", "-Wl,-z,stack-size=8388608", "-Wl,--initial-memory=67108864"⟩
|
||||||
|
args∾↩ ( emcc) / ⟨"-s", "EXPORTED_FUNCTIONS=_main,_cbqn_runLine,_cbqn_evalSrc", "-s", "EXPORTED_RUNTIME_METHODS=ccall,cwrap", "-s", "ALLOW_MEMORY_GROWTH=1"⟩
|
||||||
|
args∾↩ ( exportSymbols) / ⟨"-rdynamic"⟩
|
||||||
|
args∾↩ ( linux ∧ arch≡"x86-64") / ⟨"-no-pie"⟩
|
||||||
|
args ↩ args (¬∘∊/⊣) GetOpt "rm_lf"
|
||||||
|
{"linker: "∾•Repr 𝕩} _verboseLog args
|
||||||
|
linker ↩ args
|
||||||
|
}
|
||||||
|
|
||||||
|
{𝕊: CBQNc@ ⋄ REPLXXc⍟replxx @ ⋄ Linker@}⍟⊢ verbose
|
||||||
|
}
|
||||||
|
|
||||||
|
Hash ← {(32↑∾"0a"+↕¨10‿26)⊏˜{𝕨+2×𝕩}˝5‿⌊⥊32‿1•bit._cast∾(↕4)•Hash¨<𝕩}
|
||||||
|
|
||||||
|
MkDir ← {•file.Exists𝕩?@; •file.CreateDir𝕩}
|
||||||
|
|
||||||
|
allObjDir ← "build/obj2"
|
||||||
|
MkDir AtRoot allObjDir
|
||||||
|
|
||||||
|
isFileTheSame ← {
|
||||||
|
ks‿vs ← ⟨⟩‿⟨⟩
|
||||||
|
{
|
||||||
|
i ← ⊑ks⊐<𝕨
|
||||||
|
i<≠ks? 𝕩 ≡ i⊑vs;
|
||||||
|
ks∾↩ <𝕨
|
||||||
|
vs∾↩ <t←•file.Modified 𝕨
|
||||||
|
𝕩 ≡ t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateSubmodule ← {
|
||||||
|
done ← ⟨⟩
|
||||||
|
{
|
||||||
|
𝕩≡@? @;
|
||||||
|
"Local"≡¯5↑𝕩? @;
|
||||||
|
⊑𝕩<⊸∊done? @;
|
||||||
|
done∾↩ <𝕩
|
||||||
|
SH ⟨"git", "submodule", "update", "--init", AtRoot 𝕩⟩
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# gets/creates a directory of cacheable objects; key is the unique identifier of when it can be reused
|
||||||
|
GetCache ← { 𝕊 basename‿desc‿key:
|
||||||
|
hash ⇐ Hash key
|
||||||
|
folder ⇐ allObjDir•file.At basename∾"-"∾hash
|
||||||
|
MkDir AtRoot folder
|
||||||
|
|
||||||
|
File ⇐ folder⊸•file.At
|
||||||
|
{𝕊: desc∾": "∾AtRoot𝕩} _verboseLog folder
|
||||||
|
|
||||||
|
dataPath ← AtRoot File "data"
|
||||||
|
prevKs‿prevVs ← •file.Exists◶⟨⟨⟩‿⟨⟩, {Deserialize ⟨8‿'c',8⟩•bit._cast •FBytes 𝕩}⟩ dataPath
|
||||||
|
|
||||||
|
IsUpToDate ⇐ { 𝕊:
|
||||||
|
i ← ⊑prevKs⊐<𝕩
|
||||||
|
i<≠prevKs?
|
||||||
|
{@:0; ∧´ AtRoot⊸IsFileTheSame´¨𝕩} i⊑prevVs;
|
||||||
|
0
|
||||||
|
}
|
||||||
|
newKs‿newVs ← ⟨⟩‿⟨⟩
|
||||||
|
Update ⇐ {key𝕊data: newKs∾↩ <key ⋄ newVs∾↩ <data} # data≡@ means failed to build
|
||||||
|
onExitList∾↩ {{ 𝕊:
|
||||||
|
jKs ← newKs∾prevKs
|
||||||
|
jVs ← newVs∾prevVs
|
||||||
|
dataPath •FBytes ⟨8,8‿'c'⟩•bit._cast Serialize (<∊jKs) /¨ jKs‿jVs
|
||||||
|
}⍟{𝕊: 0≠≠newKs}}
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleKs‿ruleVs ← ⟨⟩‿⟨⟩
|
||||||
|
AddRule ← { 𝕊 cache‿cacheKey‿dst‿GetCMD‿disp‿customDeps:
|
||||||
|
ruleKs∾↩ <dst
|
||||||
|
ruleVs∾↩ {
|
||||||
|
cache ⇐ cache
|
||||||
|
cacheKey ⇐ cacheKey
|
||||||
|
disp ⇐ disp
|
||||||
|
CMD ⇐ GetCMD
|
||||||
|
ruleDeps ⇐ customDeps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# dependency resolution & thread management
|
||||||
|
Run ← { 𝕊:
|
||||||
|
ruleDeps ← {𝕩.ruleDeps}¨ ruleVs
|
||||||
|
ruleSrcs0 ← ruleKs⊐∾ruleDeps
|
||||||
|
! ∧´ ruleSrcs0<≠ruleKs
|
||||||
|
ruleSrcs ← ((≠∾˜≠¨/↕∘≠)ruleDeps) ⊔ ruleSrcs0
|
||||||
|
req ← ⟨⟩
|
||||||
|
ruleN ← 0¨ ruleKs # number of children (i.e. how many have this in their ruleP list)
|
||||||
|
ruleP ← ⟨⟩¨ ruleKs # parent rules (i.e. which ones require this)
|
||||||
|
rebuildAll ← po.rebuildAll
|
||||||
|
|
||||||
|
Require ← {
|
||||||
|
v ← 𝕩⊑ruleVs
|
||||||
|
rebuild ← rebuildAll
|
||||||
|
chi ← 𝕩⊑ruleSrcs
|
||||||
|
chr ← Require¨ chi
|
||||||
|
rebuild∨↩ ∨´ chr
|
||||||
|
# rebuild∨↩ ¬•file.Exists AtRoot 𝕩⊑ruleKs # not really needed unless someone deletes a specific file without deleting the data file
|
||||||
|
rebuild∨↩ ¬v.cache.IsUpToDate v.cacheKey
|
||||||
|
{
|
||||||
|
ruleN (+´chr)⊸+⌾(𝕩⊸⊑)↩
|
||||||
|
ruleP ∾⟜𝕩¨⌾((chr/chi)⊸⊏)↩
|
||||||
|
req∾↩ 𝕩
|
||||||
|
}⍟rebuild 𝕩
|
||||||
|
rebuild
|
||||||
|
}
|
||||||
|
anyRebuilt ← Require ⊑ruleKs⊐<𝕩
|
||||||
|
|
||||||
|
left ← (req⊏ruleN=0)/req
|
||||||
|
|
||||||
|
RequestJob ← { 𝕊:
|
||||||
|
0=≠left? @;
|
||||||
|
(left↓˜↩ ¯1) ⊢ ¯1⊑left
|
||||||
|
}
|
||||||
|
|
||||||
|
FinishJob ← { i𝕊tb:
|
||||||
|
v ← i⊑ruleVs
|
||||||
|
Log⍟(×≠) 1⊑tb
|
||||||
|
⊢◶⟨
|
||||||
|
{ 𝕊:
|
||||||
|
v.cacheKey v.cache.Update @
|
||||||
|
}
|
||||||
|
{ 𝕊:
|
||||||
|
v.cacheKey v.cache.Update 3⊑tb
|
||||||
|
ps ← i⊑ruleP
|
||||||
|
ruleN -⟜1⌾(ps⊸⊏)↩
|
||||||
|
left∾↩ (0=ps⊏ruleN)/ps
|
||||||
|
}
|
||||||
|
⟩ ⊑tb
|
||||||
|
⊑tb
|
||||||
|
}
|
||||||
|
|
||||||
|
threads ← Spawn∘(•file.At "runner.bqn")¨ ↕(≠req)⌊po.j
|
||||||
|
work ← ⟨⟩
|
||||||
|
free ← threads
|
||||||
|
Ts ← {𝕩.t}¨
|
||||||
|
|
||||||
|
storedOut ← ⟨⟩
|
||||||
|
Log ↩ {storedOut∾↩ <𝕩∾@+10}
|
||||||
|
# Log ↩ {𝕊:1}
|
||||||
|
currLive ← ⟨⟩
|
||||||
|
e ← @+27
|
||||||
|
UpdateLive ← {
|
||||||
|
•term.OutRaw (∾(0⌈¯1+≠currLive)⥊<(e∾"[2K"∾e∾"[1F")) ∾ (•ToUTF8 ∾storedOut) ∾ 1↓∾((@+10)∾•ToUTF8)¨ 𝕩
|
||||||
|
•term.Flush @
|
||||||
|
currLive ↩ 𝕩
|
||||||
|
storedOut ↩ ⟨⟩
|
||||||
|
}
|
||||||
|
FmtTime ← {{(""≡◶⊢‿"0" ¯1↓𝕩)∾'.'∾¯1↑𝕩} •Repr ⌊0.5+ 10×𝕩}
|
||||||
|
onExitList∾↩ {{𝕊: UpdateLive ⟨⟩}}
|
||||||
|
|
||||||
|
tmap ← ⟨⟩ # threads in the order they're displayed on-screen (dynamically calculated so that if there's only ever only one job in parallel, there are no pointless empty lines)
|
||||||
|
doneCount ← 0
|
||||||
|
stopping ← 0
|
||||||
|
Fail ← {stopping↩1 ⋄ Log 𝕩}
|
||||||
|
t0 ← •MonoTime@
|
||||||
|
DoneLine ← {𝕊: ∾⟨•Repr doneCount, "/", •Repr ≠req⟩}
|
||||||
|
{ 𝕊:
|
||||||
|
{𝕊:
|
||||||
|
t ← ¯1⊑free ⋄ free↓˜↩ ¯1
|
||||||
|
|
||||||
|
i ← RequestJob@ ⋄ v←i⊑ruleVs
|
||||||
|
t.Request v.CMD@
|
||||||
|
work∾↩ {t⇐t, i⇐i, v⇐v, t0⇐•MonoTime@}
|
||||||
|
|
||||||
|
}•_while_{𝕊: ∧´0<≠¨ left‿free}⍟¬ stopping
|
||||||
|
|
||||||
|
t1 ← •MonoTime@
|
||||||
|
tmap ↩ ⍷tmap∾Ts work
|
||||||
|
UpdateLive (<DoneLine@)∾{
|
||||||
|
𝕩≡≠work? "";
|
||||||
|
o ← 𝕩⊑work
|
||||||
|
∾⟨"[", FmtTime t1-o.t0, "] ", o.v.disp⟩
|
||||||
|
}¨ (Ts work) ⊐tmap
|
||||||
|
|
||||||
|
dm ← 0.1 WaitForOne Ts work
|
||||||
|
lm ← ¬dm
|
||||||
|
{𝕊: Fail "Error: Fork died" ⋄ dm‿lm∧↩<dm≠¯1}⍟⊢ ∨´dm=¯1
|
||||||
|
done ← dm/work
|
||||||
|
work ↩ lm/work
|
||||||
|
{𝕩.i FinishJob 𝕩.t.Take@? doneCount+↩1; Fail "Error: During '"∾𝕩.v.disp∾"'"}¨ done
|
||||||
|
free∾↩ Ts done
|
||||||
|
}•_while_{𝕊: (0<≠work) ∨ (¬stopping)∧0<≠left}@
|
||||||
|
|
||||||
|
Log ∾⟨DoneLine@, " in ", FmtTime t0-˜•MonoTime@, "s", stopping/"; failed to build"⟩
|
||||||
|
|
||||||
|
¬stopping
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MakeCCInv ← { 𝕊 GetArgs‿Init‿cache‿id‿src‿customDeps: # src should be CBQN-base-dir-relative, so that cache doesn't store
|
||||||
|
key ⇐ id
|
||||||
|
dst ⇐ cache.File key∾".o"
|
||||||
|
GetCMD ← { 𝕊:
|
||||||
|
Init @
|
||||||
|
dep ← AtRoot cache.File id∾".d"
|
||||||
|
⟨"sh", rootDir, (GetArgs@)∾⟨"-MT", "o", "-MMD", "-MF", dep, "-o", AtRoot dst, "-c", src⟩, dep⟩
|
||||||
|
}
|
||||||
|
AddRule ⟨cache, key, dst, GetCMD, •file.Name src, customDeps⟩
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeSingeliInv ← { 𝕊 args‿Init‿cache‿id‿src‿customDeps: # src should be CBQN-base-dir-relative, so that cache doesn't store
|
||||||
|
key ⇐ id
|
||||||
|
dst ⇐ cache.File key∾".c"
|
||||||
|
GetCMD ← { 𝕊:
|
||||||
|
Init @
|
||||||
|
dep ← AtRoot cache.File id∾".d"
|
||||||
|
⟨"singeli", rootDir, AtRoot dst, AtRoot po.singeliDir, args, AtRoot src, dep⟩
|
||||||
|
}
|
||||||
|
AddRule ⟨cache, key, dst, GetCMD, •file.Name src, customDeps⟩
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeLinkerInv ← { 𝕊 GetArgs‿cache‿name‿srcs:
|
||||||
|
dst ⇐ cache.File name
|
||||||
|
GetCMD ← { 𝕊:
|
||||||
|
args ← GetArgs@
|
||||||
|
⟨"sh", rootDir, ⟨⊑args, "-o", dst⟩∾srcs∾1↓args, @⟩
|
||||||
|
}
|
||||||
|
AddRule ⟨cache, name, dst, GetCMD, "link", srcs⟩
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# actual CBQN/Singeli/REPLXX definitions
|
||||||
|
cachedBin‿linkerCache ← {
|
||||||
|
Shorten ← {r ← {𝕩↓˜¯1-⊑'.'⊐˜⌽𝕩}¨ •file.Name¨ 𝕩 ⋄ ! ∧´ ∊r ⋄ r}
|
||||||
|
cbqnSrc ← ∾{⌽(⊑𝕩)⊸•file.At¨ 1↓𝕩}¨ ⌽⟨
|
||||||
|
⟨"src/builtins/", "arithd.c", "arithm.c", "cmp.c", "sfns.c", "squeeze.c", "select.c", "slash.c", "group.c", "sort.c", "search.c", "selfsearch.c", "fold.c", "scan.c", "md1.c", "md2.c", "fns.c", "sysfn.c", "internal.c", "inverse.c"⟩
|
||||||
|
⟨"src/core/", "tyarr.c", "harr.c", "fillarr.c", "stuff.c", "derv.c", "mm.c", "heap.c"⟩
|
||||||
|
⟨"src/", "load.c", "main.c", "rtwrap.c", "vm.c", "ns.c", "nfns.c", "ffi.c"⟩
|
||||||
|
⟨"src/jit/", "nvm.c"⟩
|
||||||
|
⟨"src/utils/", "utf.c", "hash.c", "file.c", "mut.c", "each.c", "bits.c"⟩
|
||||||
|
⟩
|
||||||
|
singeliMap ← ⟨
|
||||||
|
"src/core/stuff.c"‿"equal", "src/utils/mut.c"‿"copy", "src/utils/bits.c"‿"bits"
|
||||||
|
"src/builtins/arithd.c"‿"dyarith", "src/builtins/cmp.c"‿"cmp", "src/builtins/squeeze.c"‿"squeeze"
|
||||||
|
"src/builtins/select.c"‿"select", "src/builtins/fold.c"‿"fold", "src/builtins/scan.c"‿"scan"
|
||||||
|
"src/builtins/scan.c"‿"neq", "src/builtins/slash.c"‿"slash", "src/builtins/slash.c"‿"constrep"
|
||||||
|
⟩
|
||||||
|
objs ← ⟨⟩
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
replxxCache ← {
|
||||||
|
¬po.replxx? @;
|
||||||
|
replxxCache ← GetCache ⟨"replxx", "REPLXX object file location", po.REPLXXc@⟩
|
||||||
|
|
||||||
|
replxxSrc ← (po.replxxDir•file.At"src")⊸•file.At¨⟨"ConvertUTF.cpp", "wcwidth.cpp", "conversion.cxx", "escape.cxx", "history.cxx", "prompt.cxx", "replxx.cxx", "replxx_impl.cxx", "terminal.cxx", "util.cxx", "windows.cxx"⟩
|
||||||
|
objs∾↩ {𝕩.dst}¨ (Shorten replxxSrc) {MakeCCInv ⟨po.REPLXXc, ⊢, replxxCache, 𝕨, 𝕩, ⟨⟩⟩}¨ replxxSrc
|
||||||
|
|
||||||
|
replxxCache
|
||||||
|
}
|
||||||
|
|
||||||
|
singeliObjs ← @
|
||||||
|
singeliCache ← {
|
||||||
|
¬po.singeli? @;
|
||||||
|
singeliCache ← GetCache ⟨"singeli", "Singeli generated code location", ⟨po.native, po.arch⟩⟩
|
||||||
|
|
||||||
|
# genArithTables
|
||||||
|
ga ← "src/singeli/src/genArithTables.bqn"
|
||||||
|
gaDefs ← singeliCache.File "arDefs.singeli"
|
||||||
|
gaTables ← singeliCache.File "arTables.c"
|
||||||
|
AddRule ⟨
|
||||||
|
singeliCache, "genArithTables",
|
||||||
|
gaDefs, # am cheating and only using arDefs.singeli as destination; ¯\_(ツ)_/¯
|
||||||
|
{𝕊: ⟨"runbqn", rootdir, AtRoot ga, AtRoot¨ gaDefs‿gaTables, ⟨ga⟩⟩},
|
||||||
|
•file.Name ga, ⟨⟩
|
||||||
|
⟩
|
||||||
|
|
||||||
|
singeliArgs ← ⟨"-l", "gen="∾singeliCache.folder⟩∾{
|
||||||
|
po.native? ⟨⟩;
|
||||||
|
"-a" ⋈ {"x86-64":"X86_64"; "aarch64":"AARCH64"} po.arch
|
||||||
|
}
|
||||||
|
singeliObjs ↩ {𝕩.dst}¨ {MakeSingeliInv ⟨singeliArgs, {𝕊:UpdateSubmodule po.singeliDir}, singeliCache, 𝕩, "src/singeli/src/"•file.At 𝕩∾".singeli", (𝕩≡"dyarith")/⟨gaDefs⟩⟩}¨ 1⊑¨singeliMap
|
||||||
|
|
||||||
|
singeliCache
|
||||||
|
}
|
||||||
|
|
||||||
|
cbqnCache ← {
|
||||||
|
cbqnCache ← GetCache ⟨"cbqn", "CBQN object file location", ⟨po.CBQNc@, {po.singeli? singeliCache.hash; @}⟩⟩
|
||||||
|
ruleDeps ← {
|
||||||
|
¬po.singeli? ⟨⟩¨ cbqnSrc;
|
||||||
|
((≠cbqnSrc) ∾˜ cbqnSrc⊐⊑¨singeliMap) ⊔ singeliObjs
|
||||||
|
}
|
||||||
|
|
||||||
|
singeliArgs ← {po.singeli? ⟨"-DSINGELI_DIR="∾•file.Name singeliCache.folder⟩; ⟨⟩}
|
||||||
|
objs∾↩ {𝕩.dst}¨ {a‿b‿c: MakeCCInv ⟨po.CBQNc∾singeliArgs˙, {𝕊:UpdateSubmodule po.bytecodeDir ⋄ UpdateSubmodule po.replxxDir}, cbqnCache, a, b, c⟩}¨ <˘⍉[Shorten cbqnSrc, cbqnSrc, ruleDeps] # updates replxx because needs replxx.h
|
||||||
|
|
||||||
|
cbqnCache
|
||||||
|
}
|
||||||
|
|
||||||
|
linkerCache ← GetCache ⟨"linker", "linker cached result location", ⟨
|
||||||
|
po.Linker@,
|
||||||
|
cbqnCache.hash,
|
||||||
|
{po.replxx? replxxCache.hash; @}
|
||||||
|
{po.singeli? singeliCache.hash; @}
|
||||||
|
⟩⟩
|
||||||
|
res ← MakeLinkerInv ⟨po.Linker, linkerCache, {po.emcc? "BQN.js"; "res"}, objs⟩
|
||||||
|
|
||||||
|
res.dst ⋈ linkerCache
|
||||||
|
}
|
||||||
|
|
||||||
|
outPath ← •wdpath •file.At po.output
|
||||||
|
{ 𝕊:
|
||||||
|
po.emcc?
|
||||||
|
SH ⟨"cp", AtRoot cachedBin, outPath •file.At •file.Name cachedBin⟩
|
||||||
|
SH ⟨"cp", AtRoot linkerCache.File "BQN.wasm", outPath •file.At "BQN.wasm"⟩
|
||||||
|
;
|
||||||
|
SH ⟨"cp", AtRoot cachedBin, outPath⟩
|
||||||
|
}⍟⊢ Run cachedBin
|
||||||
|
|
||||||
|
OnExit@
|
||||||
110
build/src/fork.bqn
Normal file
110
build/src/fork.bqn
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
sz←"u64" ⋄ ssz←"i64" ⋄ nfds←sz
|
||||||
|
|
||||||
|
libc_fork ← @ •FFI "i32"‿"fork"
|
||||||
|
libc_pipe ← @ •FFI "i32"‿"pipe"‿">&i32"
|
||||||
|
libc_read ← @ •FFI ssz‿"read"‿"i32"‿"&i8"‿sz
|
||||||
|
libc_write ← @ •FFI ssz‿"write"‿"i32"‿"*i8"‿sz
|
||||||
|
libc_close ← @ •FFI "i32"‿"close"‿">i32"
|
||||||
|
libc_poll ← @ •FFI "i32"‿"poll"‿"&i16"‿nfds‿"i32"
|
||||||
|
|
||||||
|
Pipe ← { 𝕊: readfd‿writefd ⇐
|
||||||
|
⟨c, readfd‿writefd⟩ ← Libc_pipe 0‿0
|
||||||
|
! c=0
|
||||||
|
Write ⇐ {Libc_write ⟨writefd, 𝕩, ≠𝕩⟩}
|
||||||
|
Read ⇐ {n‿b ← Libc_read ⟨readfd, 𝕩⥊0, 𝕩⟩ ⋄ !n≥0 ⋄ n↑b}
|
||||||
|
}
|
||||||
|
|
||||||
|
BiDiFork ← { 𝕊:
|
||||||
|
p1 ← Pipe@
|
||||||
|
p2 ← Pipe@
|
||||||
|
pid ⇐ Libc_fork@
|
||||||
|
! pid≥0
|
||||||
|
parent ⇐ pid=0
|
||||||
|
CloseWR ← {! ¬∨´ Libc_close¨ {𝕨.writefd‿𝕩.readfd}´ ⌽⍟parent 𝕩}
|
||||||
|
CloseWR p1‿p2
|
||||||
|
r‿w ⇐ ⌽⍟parent p1‿p2
|
||||||
|
Read‿readfd ⇐ r
|
||||||
|
Write‿writefd ⇐ w
|
||||||
|
Close ⇐ CloseWR∘p2‿p1
|
||||||
|
}
|
||||||
|
|
||||||
|
FFn ← { 𝕊 fn:
|
||||||
|
f ← BiDiFork@
|
||||||
|
{f.parent? Fn f ⋄ f.Close@ ⋄ •Exit 0; f}
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteAll ← {p𝕊x: {𝕩-p.Write 𝕩-⊸↑x}•_while_× ≠x}
|
||||||
|
_readAll ← {p E _𝕣 n: ⊑⍟(¬=) {v←p.Read n-≠𝕩 ⋄ 0<≠v? 𝕩∾v; <E"eof"}•_while_(=∧n≠≠) ↕0}
|
||||||
|
|
||||||
|
WriteSz ← {
|
||||||
|
𝕨 WriteAll (32‿8•bit._cast ⋈≠𝕩)∾𝕩
|
||||||
|
}
|
||||||
|
_readSz ← { 𝔽_𝕣 s:
|
||||||
|
r ← s <∘𝔽 _readAll 4
|
||||||
|
{
|
||||||
|
=r? n ← ⊑8‿32•bit._cast r ⋄ s !_readAll n;
|
||||||
|
⊑r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serialize‿Deserialize ← •Import "serialize.bqn"
|
||||||
|
|
||||||
|
c_make ← 1
|
||||||
|
c_request ← 2
|
||||||
|
c_take ← 3
|
||||||
|
c_one ← 4
|
||||||
|
|
||||||
|
control ← FFn {{ 𝕊 control:
|
||||||
|
pids‿procs ← ⋈˜⟨⟩
|
||||||
|
{𝕊:
|
||||||
|
ty‿cmd ← Deserialize •Exit _readSz control
|
||||||
|
|
||||||
|
ty◶⟨ !
|
||||||
|
{ 𝕊program: # c_make
|
||||||
|
p ← FFn {{ 𝕊 p:
|
||||||
|
f ← ⟨•file.Parent program, •file.Name program⟩ •BQN •FChars program
|
||||||
|
{𝕊: p WriteSz Serialize F Deserialize •Exit _readSz p}•_while_ 1@
|
||||||
|
}}
|
||||||
|
control WriteAll 32‿8•bit._cast ⋈p.pid
|
||||||
|
pids∾↩ <p.pid
|
||||||
|
procs∾↩ <p
|
||||||
|
}
|
||||||
|
{ 𝕊pid‿data: # c_request
|
||||||
|
p ← (⊑pids⊐pid)⊑procs
|
||||||
|
p WriteSz data
|
||||||
|
}
|
||||||
|
{ 𝕊pid: # c_take
|
||||||
|
p ← (⊑pids⊐pid)⊑procs
|
||||||
|
control WriteSz !_readSz p
|
||||||
|
}
|
||||||
|
{ 𝕊limit‿sel: # c_one
|
||||||
|
ms ← limit×1e3
|
||||||
|
"poll time limit too large" ! (ms≡∞) ∨ ms<2⋆31
|
||||||
|
p ← (pids⊐sel)⊏procs
|
||||||
|
fds ← {𝕩.readfd}¨ p
|
||||||
|
ret‿res ← Libc_poll ⟨⥊ ∾⟜1‿0˘ 32‿16•bit._cast ≍˘fds ⋄ ≠fds ⋄ ∞⊸≡◶⌊‿¯1 ms⟩
|
||||||
|
! ret≥0
|
||||||
|
control WriteSz Serialize {¯1¨⌾((¬𝕩∊0‿1)⊸/)𝕩} ¯1⊏˘∘‿4⥊res
|
||||||
|
}
|
||||||
|
⟩ cmd
|
||||||
|
}•_while_ 1@
|
||||||
|
}}
|
||||||
|
AskControl ← {control WriteSz Serialize 𝕨‿𝕩}
|
||||||
|
|
||||||
|
Spawn ⇐ {
|
||||||
|
c_make AskControl 𝕩
|
||||||
|
pid ← ⊑8‿32•bit._cast control !_readAll 4
|
||||||
|
{
|
||||||
|
pid⇐pid
|
||||||
|
Request ⇐ {c_request AskControl pid⋈Serialize 𝕩}
|
||||||
|
Take ⇐ {𝕊: c_take AskControl pid ⋄ Deserialize !_readSz control}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 𝕩: list of spawn results to wait on
|
||||||
|
# 𝕨: if present, maximum time to wait; 0 to return immediately
|
||||||
|
# result: boolean mask of which have finished (if 𝕨 isn't given, guaranteed to have at least one `1`)
|
||||||
|
WaitForOne ⇐ {
|
||||||
|
c_one AskControl ⟨𝕨⊣∞ ⋄ {𝕩.pid}¨ 𝕩⟩
|
||||||
|
Deserialize !_readSz control
|
||||||
|
}
|
||||||
57
build/src/runner.bqn
Normal file
57
build/src/runner.bqn
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
chdir ← @•FFI"i32"‿"chdir"‿">*u8:c8"
|
||||||
|
Split ← {𝕩⊔˜(⊢-˜+`׬)𝕩=𝕨}
|
||||||
|
SimplifyPath ← {
|
||||||
|
1↓∾'/'⊸∾¨ {(∊××) ⌊`⌾⌽ +` ¬⊸- ".."⊸≡¨𝕩}⊸/ "."⊸≢¨⊸/ '/'Split𝕩
|
||||||
|
}
|
||||||
|
Good ← { 𝕊 dir‿t0‿t1‿o‿e‿deps:
|
||||||
|
⟨1, o∾e, t1-t0, deps ⋈¨ (•file.Modified dir•file.At⊢)¨ deps⟩
|
||||||
|
}
|
||||||
|
|
||||||
|
_runSingeli_ ← { runArgs GetDeps _𝕣_ dir runFile:
|
||||||
|
t0 ← •MonoTime@
|
||||||
|
e←@ ⋄ deps←@
|
||||||
|
{𝕊:
|
||||||
|
runArgs •Import runFile
|
||||||
|
deps ↩ GetDeps@
|
||||||
|
}⎊{𝕊: e↩•CurrentError@} @
|
||||||
|
t1 ← •MonoTime@
|
||||||
|
{
|
||||||
|
e≢@? ⟨0, e⟩;
|
||||||
|
Good ⟨dir,t0,t1,"","",deps⟩
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"sh"‿dir‿cmd‿depf:
|
||||||
|
t0 ← •MonoTime@
|
||||||
|
Chdir @∾˜ •ToUTF8 dir
|
||||||
|
c‿o‿e ← •SH cmd
|
||||||
|
t1 ← •MonoTime@
|
||||||
|
{
|
||||||
|
0: @≡depf?
|
||||||
|
Good ⟨dir,t0,t1,o,e,⟨⟩⟩;
|
||||||
|
0:
|
||||||
|
deps ← •FLines depf
|
||||||
|
deps {𝕩/˜1»∧`'\'=¯1⊑∘↑¨𝕩}↩ # remove all but the initial rule
|
||||||
|
deps {𝕩↓˜1+⊑𝕩⊐':'}⌾⊑↩ # remove rule name
|
||||||
|
deps ¯1⊸↓¨⌾(¯1↓⊢)↩ # remove trailing backslashes
|
||||||
|
deps ({𝕩/˜¬∧`𝕩=' '}⌽)⍟2¨↩ # trim whitespace from both sides
|
||||||
|
deps (∾' 'Split¨⊢)↩ # split each on spaces
|
||||||
|
deps {¬∨´"/build/obj2/"⍷𝕩}¨⊸/↩ # remove autogenerated dependencies, those are handled manually
|
||||||
|
deps SimplifyPath¨↩ # remove "."s & ".."s
|
||||||
|
deps {dir<○≠𝕩? dir≡(≠dir)↑𝕩? (≠dir)↓𝕩; 𝕩}¨↩ # relativize
|
||||||
|
Good ⟨dir,t0,t1,o,e,deps⟩;
|
||||||
|
# c≠0:
|
||||||
|
⟨0, o∾e⟩
|
||||||
|
} c
|
||||||
|
;
|
||||||
|
"singeli"‿dir‿dst‿singeliDir‿args‿src‿dep:
|
||||||
|
prefix ← "si_"∾ (∧`'.'⊸≠)⊸/ •file.Name src
|
||||||
|
argsFinal ← args∾⟨"-d" ⋄ dep ⋄ "-o" ⋄ dst ⋄ "-n" ⋄ prefix ⋄ src⟩
|
||||||
|
argsFinal {𝕊: src<⊸∾ SimplifyPath¨ singeliDir⊸•file.At¨ •FLines dep}_runSingeli_ dir singeliDir •file.At "singeli"
|
||||||
|
;
|
||||||
|
"runbqn"‿dir‿file‿args‿deps:
|
||||||
|
args deps _runSingeli_ dir file
|
||||||
|
;
|
||||||
|
0⋈"unknown command"
|
||||||
|
}
|
||||||
54
build/src/serialize.bqn
Normal file
54
build/src/serialize.bqn
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
eltype2bit ← ⟨1,8,16,32,64,8‿'c',16‿'c',32‿'c'⟩
|
||||||
|
eltypeWidth ← ⟨1,1,2,4,8,1,2,4⟩
|
||||||
|
|
||||||
|
SStep ← •Type◶⟨
|
||||||
|
{
|
||||||
|
𝕩 •internal.Squeeze↩
|
||||||
|
eltype ← •internal.ElType𝕩
|
||||||
|
×∘≠¨⊸/ ⟨
|
||||||
|
⟨0, eltype⟩
|
||||||
|
32‿8•bit._cast ⋈=𝕩
|
||||||
|
64‿8•bit._cast ≢𝕩
|
||||||
|
{
|
||||||
|
eltype=8? SStep¨ ⥊𝕩;
|
||||||
|
⟨eltype⊑eltype2bit, 8⟩•bit._cast (8×·⌈≠÷8˙)⊸↑⍟(0=eltype) ⥊𝕩
|
||||||
|
}𝕩
|
||||||
|
⟩
|
||||||
|
}
|
||||||
|
{ ⟨⟨1⟩, 64‿8•bit._cast⋈𝕩⟩ }
|
||||||
|
{ ⟨⟨2⟩, 32‿8•bit._cast⋈𝕩⟩ }
|
||||||
|
{𝕊:!"Cannot serialize functions"}
|
||||||
|
{𝕊:!"Cannot serialize 1-modifiers"}
|
||||||
|
{𝕊:!"Cannot serialize 2-modifiers"}
|
||||||
|
{𝕊:!"Cannot serialize namespaces"}
|
||||||
|
⟩
|
||||||
|
|
||||||
|
Serialize ⇐ {
|
||||||
|
lists ← ⟨⟩
|
||||||
|
{0=•Type⊑𝕩? 𝕊¨𝕩; lists∾↩<𝕩 ⋄ 1} SStep 𝕩
|
||||||
|
∾lists
|
||||||
|
}
|
||||||
|
Deserialize ⇐ {
|
||||||
|
s←𝕩
|
||||||
|
off←0
|
||||||
|
Next ← {r←𝕩↑off↓s ⋄ off+↩𝕩 ⋄ r}
|
||||||
|
Read ← { 𝕊:
|
||||||
|
type ← ⊑Next 1
|
||||||
|
type◶⟨
|
||||||
|
{𝕊:
|
||||||
|
et ← ⊑Next 1
|
||||||
|
rank ← ⊑8‿32•bit._cast Next 4
|
||||||
|
shape ← 8‿64•bit._cast Next rank×8
|
||||||
|
shape⥊{
|
||||||
|
et=8? Read¨ ↕×´shape;
|
||||||
|
⟨8, et⊑eltype2bit⟩•bit._cast Next (⌈÷⟜8)⍟(0=et) (et⊑eltypeWidth)×´shape
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{𝕊: ⊑⟨8, 64 ⟩•bit._cast Next 8}
|
||||||
|
{𝕊: ⊑⟨8, 32‿'c'⟩•bit._cast Next 4}
|
||||||
|
⟩@
|
||||||
|
}
|
||||||
|
r ← Read@
|
||||||
|
off=≠s? r;
|
||||||
|
! "invalid input: data after end"
|
||||||
|
}
|
||||||
5
makefile
5
makefile
@ -37,6 +37,8 @@ shared-o3:
|
|||||||
@${MAKE} i_OUTPUT=libcbqn.so i_SHARED=1 i_t=shared_o3 i_f="-O3" run_incremental_0
|
@${MAKE} i_OUTPUT=libcbqn.so i_SHARED=1 i_t=shared_o3 i_f="-O3" run_incremental_0
|
||||||
shared-c:
|
shared-c:
|
||||||
@${MAKE} i_OUTPUT=libcbqn.so i_SHARED=1 custom=1 run_incremental_0
|
@${MAKE} i_OUTPUT=libcbqn.so i_SHARED=1 custom=1 run_incremental_0
|
||||||
|
forbuild:
|
||||||
|
@${MAKE} i_singeli=0 i_t=forbuild i_f="-O2" i_FFI=2 i_OUTPUT=build/obj2/for_build i_f='-DFOR_BUILD' run_incremental_0
|
||||||
c:
|
c:
|
||||||
@${MAKE} custom=1 run_incremental_0
|
@${MAKE} custom=1 run_incremental_0
|
||||||
|
|
||||||
@ -179,6 +181,9 @@ single-c:
|
|||||||
|
|
||||||
# actual build
|
# actual build
|
||||||
run_incremental_0:
|
run_incremental_0:
|
||||||
|
ifeq ($(i_t),forbuild)
|
||||||
|
mkdir -p build/obj2
|
||||||
|
endif
|
||||||
ifeq ($(verbose),1)
|
ifeq ($(verbose),1)
|
||||||
@echo "build directory: $$(${MAKE} builddir)"
|
@echo "build directory: $$(${MAKE} builddir)"
|
||||||
@echo " bytecode: build/$(BYTECODE_DIR)"
|
@echo " bytecode: build/$(BYTECODE_DIR)"
|
||||||
|
|||||||
@ -352,4 +352,5 @@ static NOINLINE B or_SA(B t, B w, B x) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "../gen/arTables.c"
|
#define SINGELI_FILE arTables
|
||||||
|
#include "../../utils/includeSingeli.h"
|
||||||
|
|||||||
@ -189,4 +189,4 @@ andBytes{vw}(r: *u8, x: *u8, maskU64:u64, len:u64) : void = {
|
|||||||
|
|
||||||
'avx2_andBytes'=andBytes{256}
|
'avx2_andBytes'=andBytes{256}
|
||||||
'orSAc_f64_f64_f64'=arithSA{2,bqn_or,0,f64,f64,f64}
|
'orSAc_f64_f64_f64'=arithSA{2,bqn_or,0,f64,f64,f64}
|
||||||
include './../gen/arDefs'
|
include 'gen/arDefs'
|
||||||
|
|||||||
@ -19,7 +19,11 @@
|
|||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
|
#ifdef SINGELI_DIR
|
||||||
|
#include SINGELI_FILE1(../../build/obj2/SINGELI_DIR/SINGELI_FILE.c)
|
||||||
|
#else
|
||||||
#include SINGELI_FILE1(../singeli/gen/SINGELI_FILE.c)
|
#include SINGELI_FILE1(../singeli/gen/SINGELI_FILE.c)
|
||||||
|
#endif
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
#undef SINGELI_FILE
|
#undef SINGELI_FILE
|
||||||
Loading…
Reference in New Issue
Block a user