add target_from_cc=1 option

This commit is contained in:
dzaima 2024-10-01 21:04:48 +03:00
parent 7774d8ba5e
commit d24031a125
4 changed files with 128 additions and 87 deletions

View File

@ -37,31 +37,32 @@ For native builds, targeted extensions are determined by `/proc/cpuinfo` (or `sy
### Build flags
`notui=1` - display build progress in a plain-text format
`version=...` - specify the version to report in `--version` (default is commit hash)
`nogit=1` - error if something attempts to use `git`
`CC=...` - choose a different C compiler (default is `clang`, or `cc` if unavailable; CBQN is more tuned for clang, but gcc also works)
`CXX=...` - choose a different C++ compiler; needed only for REPLXX (default is `c++`)
`OUTPUT=path/to/somewhere` - change output location; for `emcc-o3` it will be the destination folder for `BQN.js` and `BQN.wasm`, for everything else - the filename
`target_arch=(x86-64|aarch64|generic)` - target architecture. Inferred from `uname` by default. Used for deciding target optimizations.
`target_os=(linux|bsd|macos|windows)` - target OS. Inferred from `uname` by default. Used for determining default output names and slight configuration changes.
`j=8` - override the default parallel job count (default is the output of `nproc`)
`has=...` - assume specified architecture extensions/properties (x86-64-only). Takes a comma-separated list which, beyond what is architecturally guaranteed, infer additional extensions as noted which hold on existing hardware (at least as of the time of writing):
- `notui=1` - display build progress in a plain-text format
- `version=...` - specify the version to report in `--version` (default is commit hash)
- `nogit=1` - error if something attempts to use `git`
- `CC=...` - choose a different C compiler (default is `clang`, or `cc` if unavailable; CBQN is more tuned for clang, but gcc also works)
- `CXX=...` - choose a different C++ compiler; needed only for REPLXX (default is `c++`)
- `j=8` - override the default parallel job count (default is the output of `nproc`)
- `OUTPUT=path/to/somewhere` - change output location; for `emcc-o3` it will be the destination folder for `BQN.js` and `BQN.wasm`, for everything else - the filename
- `target_arch=(x86-64|aarch64|generic)` - target architecture; if abscent, inferred from `uname`, or `CC` if `target_from_cc=1`; used for enabling architecture-specific optimizations
- `target_os=(linux|bsd|macos|windows)` - target OS; if abscent, inferred from `uname`, or `CC` if `target_from_cc=1`; used for determining default output names and slight configuration changes
- `target_from_cc=1` - infer the target architecture and OS from C macros that `CC` defines via `-dM -E`; additionally infers available extensions, allowing e.g. `make f=-march=x86-64-v3 - target_from_cc=1` to optimize assuming AVX2, which would otherwise need `has=avx2`
- `has=...` - assume specified architecture extensions/properties (x86-64-only); takes a comma-separated list which, beyond what is architecturally guaranteed, infer additional extensions as noted which hold on existing hardware (at least as of the time of writing):
- `pclmul` (implies SSE4.2)
- `avx2` (implies `pclmul`, POPCNT, BMI1)
- `bmi2` (implies `pclmul`, AVX1)
- `slow-pdep` (specifies Zen 1 & Zen 2's slow `pdep`/`pext`)
`REPLXX=0` - disable REPLXX
`singeli=0` - disable usage of Singeli
`FFI=0` - disable `•FFI`, thus not depending on libffi
`usz=64` - support arrays with length over 2<sup>32</sup>
`f=...` - add extra C compiler flags for CBQN file compilation
`lf=...` - add extra linking flags (`LDFLAGS` is a synonym)
`CCFLAGS=...` - add flags for all CC/CXX/linking invocations
`REPLXX_FLAGS=...` - override replxx build flags (default is `-std=c++11 -Os`)
`CXXFLAGS=...` - add additional CXX flags
- `bmi2` (implies `avx2`)
- `slow-pdep` (implies `bmi2`; specifies Zen 1 & Zen 2's slow `pdep`/`pext`)
<!-- separator -->
- `REPLXX=0` - disable REPLXX
- `singeli=0` - disable usage of Singeli
- `FFI=0` - disable `•FFI`, thus not depending on libffi
- `usz=64` - support arrays with length over 2<sup>32</sup>
<!-- separator -->
- `f=...` - add extra C compiler flags for CBQN file compilation
- `lf=...` - add extra linking flags (`LDFLAGS` is a synonym)
- `CCFLAGS=...` - add flags for all CC/CXX/linking invocations
- `REPLXX_FLAGS=...` - override replxx build flags (default is `-std=c++11 -Os`)
- `CXXFLAGS=...` - add additional CXX flags
Alternatively, `build/build` (aka build.bqn) can be invoked manually, though note that it has slightly different argument naming (see `build/build --help`) and doesn't have predefined build types (i.e. `make o3ng` is done as `build/build replxx singeli native g`)
@ -113,12 +114,11 @@ AArch64 ARMv8-A (within Termux on Android 8):
```
Additionally, CBQN is known to compile as-is on macOS. Windows builds can be made by cross-compilation ([Docker setup](https://github.com/vylsaz/cbqn-win-docker-build)).
The build will attempt to use `pkg-config` to find libffi, `uname` to determine `target_arch` & `target_os`, and `nproc` for parallel job count, with defaults if unavailable (`-lffi` for linking libffi (+ `-ldl` on non-BSD), `target_arch=generic`, `target_os=linux`, `j=4`; these can of course also be specified manually).
The build will attempt to use `pkg-config` to find libffi, `uname` to determine `target_arch` & `target_os` if not using `target_from_cc`, and `nproc` for parallel job count, with defaults if unavailable (`-lffi` for linking libffi (+ `-ldl` on non-BSD), `target_arch=generic`, `target_os=linux`, `j=4`; these can of course also be specified manually).
Furthermore, `git` is used to determine the version to present for `--version` (override with `version=...`), and to update submodules.
Submodules are used for Singeli, replxx, and precompiled bytecode. To avoid automatic usage of `git`, link local copies to `build/singeliLocal`, `build/replxxLocal`, and `build/bytecodeLocal`.
Git submodules are used for Singeli, replxx, and precompiled bytecode. To avoid automatic usage of `git` here, link local copies to `build/singeliLocal`, `build/replxxLocal`, and `build/bytecodeLocal`.
Furthermore, `git` is used to determine the version that `--version` should display (override with `version=...`). Use `nogit=1` to disallow automatic `git` usage.
### Precompiled bytecode
@ -145,7 +145,9 @@ Note that, after either of those, the compiled bytecode may become desynchronize
You must manually set up a cross-compilation environment. It's possible to pass flags to all CC/CXX/linking invocations via `CCFLAGS=...`, and `LDFLAGS=...` to pass ones to the linking step specifically (more configuration options [above](#build-flags)).
A `target_arch=(x86-64|aarch64|generic)` make argument must be present (`generic` will work always, but a more specific argument will enable significant optimizations), as otherwise it'll choose based on `uname`. Similarly, `target_os=(linux|bsd|macos|windows)` should be present if the target OS differs from the host.
A `target_arch=(x86-64|aarch64|generic)` make argument should be added (`generic` will work always, but a more specific argument will enable significant optimizations), as otherwise it'll choose based on `uname`. Similarly, `target_os=(linux|bsd|macos|windows)` should be present if the target OS differs from the host.
Alternatively, the `target_from_cc=1` make argument can be used, replacing the need of `target_arch` and `target_os` (although they can be still set, overriding the values inferred from CC).
Furthermore, all build targets (except `-makeonly` ones) will need a non-cross-compiled version of CBQN at build time to run build.bqn and Singeli. For those, a `make for-build` will need to be ran before the primary build, configured to not cross-compile. (this step only needs a C compiler (default is `CC=cc` here), and doesn't need libffi, nor a C++ compiler).

@ -1 +1 @@
Subproject commit 5ae2e77d7d4704bf7440eabc9146dedf7c8a902d
Subproject commit b43f3999b0c5a40b43ceee258fbe6bb8245d06af

View File

@ -34,6 +34,7 @@ opts ← ⟨
1, "color", @, "Whether to enable colored diagnostics; default based on notui"
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 selecting Singeli target
1, "target-from-cc",0, "Detect arch, OS, and target-supported extensions from CC"
1, "pie", @, "Position-independent executable; default based on OS & arch"@+10
0, "OUTPUT", "", "Output location; defaults to ./BQN for regular builds"
@ -51,14 +52,14 @@ opts ← ⟨
1, "static-bin", 0, "Statically link the executable"
1, "wasi", 0, "Build with WASI; default output name is BQN.wasm"
1, "emcc", 0, "Build with emscripten; outputs two files - BQN.wasm and BQN.js"
1, "clangd", 0, "Don't build, instead generate a compile_commands.json for clangd"@+10
1, "clangd", 0, "Generate a compile_commands.json for clangd"@+10
1, "FFI", @, "Enable FFI through libffi; On by default for linux, BSD, macos"
1, "FFI", @, "Enable FFI through libffi; off by default for Windows"
1, "pkgconfig", 1, "Whether to attempt to use pkg-config to find libffi flags"
1, "singeli", 0, "Enable compilation with Singeli"
1, "singeli", 0, "Enable Singeli usage"
1, "replxx", 0, "Enable REPLXX"@+10
0, "usz", "32", "Size of array length fields in bits; default 32, can be 32 or 64"
0, "usz", "32", "Size of array length fields in bits; 32 or 64 (default: 32)"
1, "c", 0, "Disable some default flags"
1, "O3", @, "Use '-O3'; On by default unless 'c=1'"
1, "native", @, "Use '-march=native'"
@ -182,10 +183,12 @@ po ← { # parsed options
emcc, wasm, replxx, singeli, staticLib,
usz, ffi, o3, debug, rtverify, heapverify,
bytecodeDir, replxxDir, singeliDir,
CBQNc, ccColor, singeliFlags, siCFlags, singeliArch, REPLXXc, Linker
CBQNc, ccColor, singeliFlags, singeliCFlags, singeliArch, REPLXXc, Linker
compat GetOpt "from-makefile"
compatTgt compat/"target_"
custom GetOpt "c"
clangd GetOpt "clangd"
DOpt {@,𝕨 GetOpt 𝕩}
@ -194,6 +197,7 @@ po ← { # parsed options
warnStored GetOpt "stored-warn"
loud ¬GetOpt "quiet"
nogit GetOpt "nogit"
truecc GetOpt "target-from-cc"
dry GetOpt "dry-run"
CacheList {
@ -234,12 +238,10 @@ po ← { # parsed options
cc {emcc? "emcc"; "clang"} DOpt "CC"
ccClang {
clangd? 1;
TryVersion {𝕩 SH cc"--version"}
vs TryVersion {@GetOpt"CC"? ¯1; @}
{𝕊: cc"cc" Log "Note: default CC 'clang' wasn't found; building with 'cc'; add a `CC=cc` argument to hide" vsTryVersion@} vs¯1
{𝕊: Logloud "Note: default CC '"cc"' wasn't found; using 'cc'; add 'CC=cc' to hide" cc"cc" vsTryVersion@} vs¯1
´"clang"vs
}
@ -250,31 +252,83 @@ po ← { # parsed options
ubsan GetOpt "ubsan"
o3 (¬custom) DOpt "O3"
uname ""{𝕊: Lowercase "" TrySH "uname""-sm"} ´ (@GetOpt)¨ "os""arch"
InUname {𝕊: ´ 𝕩uname}
allFlags GetOpt "CCFLAGS"
minCCFlags allFlags GetOpt "f"
os Lowercase {InUname"linux"? "linux"; InUname"darwin"? "macos"; InUname"bsd"? "bsd"; "linux"} DOpt "os"
linuxbsdmacoswindows os¨ {𝕊: "Error: Unsupported OS; options:"1", "¨𝕩}_assert_(os<) "linux""bsd""macos""windows"
CDefines {𝕊: cDefines (@+10) Split SH cc minCCFlags "-dM", "-E", "-"}
arch {'-'¨(('_'=𝕩)/)𝕩} Lowercase {InUname"x86_64"? "x86-64"; ´InUname¨"aarch64""arm64"? "aarch64"; "generic"} DOpt "arch"
{𝕊: arch "generic"} wasm
{𝕊: "Error: Unsupported arch; options:"1", "¨𝕩}_assert_(arch<) "x86-64""aarch64""generic"
Uname {𝕊: uname Lowercase "" TrySH "uname""-sm"}
InUname {𝕊: ´ 𝕩Uname@}
ffi ((¬windows)¬wasm) DOpt "FFI"
singeli GetOpt "singeli"
replxx GetOpt "REPLXX"
SubmoduleDir "build"•file.At(@) {𝕨0?@; •file.Exists rAtRoot "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
arch {'-'¨(('_'=𝕩)/)𝕩} Lowercase {trueccwasm? "generic"; InUname"x86_64"? "x86-64"; ´InUname¨"aarch64""arm64"? "aarch64"; "generic"} DOpt "arch"
{𝕊: "Error: Unsupported arch; options:"1", "¨𝕩}_assert_(arch<) "x86-64""aarch64""riscv64""generic"
arch {"riscv64": "RV64"; "generic": "NONE"; Uppercase {'_'¨(('-'=𝕩)/)𝕩} 𝕩} # translate to Singeli
has ','Split¨Lowercase GetOpt "has"
has has ("slow-pdep"<has)/"bmi2"
{𝕊: "Error: Unsupported 'has' options; options:"1", "¨𝕩}_assert_(´has) "ssse3""sse4.1""sse4.2""avx2""bmi2""pclmul""slow-pdep"
{𝕊: "Error: Cannot have 'has' options on architecture '"arch"'; remove 'has=...' or add an argument of "compat"arch=x86-64""target_arch=x86-64"}_assert_¬ (arch"x86-64") 0has
has has ("slow-pdep"< has) / "bmi2"
{𝕊: "Error: Invalid 'has' value; options:"1", "¨𝕩}_assert_(´has) "ssse3""sse4.1""sse4.2""avx2""bmi2""pclmul""slow-pdep"
"Error: Cannot use 'has=...' if Singeli isn't enabled"_assert_ singeli has
singeliArch ({"x86-64":"X86_64"; "aarch64":"AARCH64"; "none"} arch) < Uppercase "ssse3""sse4.1""sse4.2""avx2""bmi2""pclmul"/ has
{𝕊: has (´(("#define __tune_znver""__ 1")¨ "12")CDefines@) / "slow-pdep"} truecc
{𝕊: "Target: "os" "arch 1 ", "¨ hasnative/"native"} _verboseLog@
singeliArch @
singeliCFlags
pie {(¬sharedLibstaticLib)linuxarch"x86-64"? 0; 1} DOpt "pie"
{𝕊: pie 0} wasm
{
¬singeli? @;
UpdateSubmodule singeliDir
SingeliUtil {𝕨 •Import AtRoot singeliDir •file.At 𝕩}
singeliArch {
truecc @GetOpt"arch"?
archutil SingeliUtil "archutil.bqn"
foundArch archutil.ParseCDefines CDefines@
arch foundArch
foundArch
;
Uppercase arch
}
{
arch"X86_64"?
singeliArch Uppercase "ssse3""sse4.1""sse4.2""avx2""bmi2""pclmul"/ has
ArchInfo {({native? ; singeliArch}, 𝕩 SingeliUtil "arch.bqn").GetCFlags @}
singeliCFlags ArchInfo 1
{𝕊: Log "Note: inferred the following C flags:"' '¨𝕩}(loud ×) singeliCFlags (¬/) ArchInfo 0
;@
}
}
{𝕊: "Error: Cannot have 'has' options on architecture '"arch"'; remove 'has=...' or use '"compatTgt"arch=x86-64'"}_assert_¬ (arch"X86_64") 0has
os GetOpt "os"
{
os@?
os Lowercase ;
¬truecc?
os {InUname"linux"? "linux"; InUname"darwin"? "macos"; InUname"bsd"? "bsd"; "linux"};
osKeysosVals <˘>
"_WIN32", "windows"
"__FreeBSD__", "bsd"
"__OpenBSD__", "bsd"
"__APPLE__", "macos"
"__MACH__", "macos"
"__linux", "linux"
osOpts osVals /˜ osKeys{𝕩˜𝕩' '}¨ 8¨ ("#define "8)¨/ CDefines@
{𝕊: "Error: Couldn't detect OS from C-defined macros; add explicit '"compatTgt"os=...'"} _assert_ 1=osOpts
os osOpts
}
linuxbsdmacoswindows os¨ {𝕊: "Error: Unsupported OS; options:"1", "¨𝕩}_assert_(os<) "linux""bsd""macos""windows"
{𝕊: "Target: ", os, " ", Lowercase arch, 1 ", "¨ hasnative/"native"} _verboseLog@
output GetOpt "OUTPUT"
output •wdpath•file.At {𝕊:
@ -285,6 +339,12 @@ po ← { # parsed options
windows? "BQN.exe";
"BQN"
}("") output
{𝕊: "Output location: "𝕩}_verboseLog output
pie {(¬sharedLibstaticLib)linuxarch"X86_64"? 0; 1} DOpt "pie"
{𝕊: pie 0} wasm
ffi ((¬windows)¬wasm) DOpt "FFI"
exportSymbols ffilib
@ -298,21 +358,6 @@ po ← { # parsed options
}
}
SubmoduleDir "build"•file.At(@) {𝕨0?@; •file.Exists rAtRoot "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
siCFlags {
¬singeli? @;
UpdateSubmodule singeliDir
({native? ; singeliArch}, 1 •Import AtRoot singeliDir •file.At "arch.bqn").GetCFlags@
}
allFlags GetOpt "CCFLAGS"
allFlags ubsan/"-fsanitize=undefined", "-fno-sanitize=float-cast-overflow", "-fno-sanitize=vla-bound"
ccColor ((¬clangd) tui DOpt "color") / ccClang"-fdiagnostics-color=always""-fcolor-diagnostics"
cbqnc {
@ -334,12 +379,11 @@ po ← { # parsed options
args 0GetLibs@
args GetOpt "f"
args allFlags
args (singeli arch "x86-64") / "-DSINGELI_X86_64" {singeli? "-mssse3""-mavx2" siCFlags; 0} / "-DSINGELI_SSSE3""-DSINGELI_AVX2"
args (singeli arch"aarch64") / "-DSINGELI_NEON"
args (singeli arch<"x86-64""aarch64") / "-DSINGELI_SIMD"
args minCCFlags
args ubsan / "-fsanitize=undefined", "-fno-sanitize=float-cast-overflow", "-fno-sanitize=vla-bound"
args (singeli arch "X86_64") / "-DSINGELI_X86_64" {singeli? "-mavx2" singeliCFlags; 0} / "-DSINGELI_AVX2"
args (singeli arch"AARCH64") / "-DSINGELI_NEON"
args (singeli arch<"X86_64""AARCH64") / "-DSINGELI_SIMD"
args ( wasm) / "-DWASM"
args ( wasi) / "-DWASI", "-DNO_MMAP", "-DUSE_SETJMP=0", "-D_WASI_EMULATED_MMAN", "--target=wasm32-wasi"
args ( emcc) / "-DEMCC", "-O3"
@ -358,13 +402,8 @@ po ← { # parsed options
args (replxx windows) / "-DUSE_REPLXX_IO"
args ( @versionName) / "-DHAS_VERSION"
args ( usz64) / "-DUSZ_64"
args (´"slow-pdep"¨ has) / "-DSLOW_PDEP"
args {
native? "-march=native";
: ;
"Error: Cannot use has=... if Singeli isn't enabled"_assert_ singeli
siCFlags
} has
args ("slow-pdep"< has) / "-DSLOW_PDEP"
args {native? "-march=native"; singeliCFlags}
args args (¬/) GetOpt "rm_f"
{"CBQN C compiler: "•Repr 𝕩} _verboseLog args
args
@ -694,7 +733,7 @@ cachedBin‿linkerCache ← {
"src/utils/", "ryu.c", "utf.c", "hash.c", "file.c", "mut.c", "each.c", "bits.c"
cbqnSrc cbqnSrc clangd.Files "src"
singeliMap 1¨ ({´ (po.arch) 𝕩}¨ ¨)/
singeliMap 1¨ ({ ({"X86_64":'x'; "AARCH64":'a'; "RV64":'g'; "NONE":'g'} po.arch) 𝕩}¨ ¨)/
"xa.""src/builtins/arithm.c""monarith", "xa.""src/builtins/compare.c""equal",
"xa.""src/builtins/arithd.c""dyarith", "xa.""src/builtins/cmp.c""cmp",
"xa.""src/builtins/squeeze.c""squeeze", "xa.""src/utils/mut.c""copy",
@ -722,7 +761,7 @@ cachedBin‿linkerCache ← {
singeliObjs @
singeliCache {
¬po.singeli? @;
singeliCache GetCache "singeli", "Singeli generated code location", po.native, po.arch, po.usz, po.has, po.singeliFlags, po.singeliDir
singeliCache GetCache "singeli", "Singeli generated code location", po.native, po.singeliArch, po.arch, po.usz, po.has, po.singeliFlags, po.singeliDir
# genArithTables
ga "src/singeli/src/genArithTables.bqn"
@ -742,7 +781,7 @@ cachedBin‿linkerCache ← {
{po.native? ; "-a" 1 ','¨ po.singeliArch}
{𝕊: "Singeli args: "•Repr singeliArgs} _verboseLog @
{𝕊: "Singeli-required C args: "•Repr po.siCFlags; @} _verboseLog @
{𝕊: "Singeli-determined C arch: "•Repr po.singeliCFlags; @} _verboseLog @
singeliObjs {MakeSingeliInv singeliArgs, {𝕊:UpdateSubmodule po.singeliDir}, singeliCache, 𝕩, "src/singeli/src/"•file.At 𝕩".singeli", (𝕩"dyarith")/gaRule}¨ 1¨singeliMap
singeliCache

View File

@ -86,7 +86,7 @@ endif
@build/build from-makefile CC="$(CC)" CXX="$(CXX)" PIE="$(ENABLE_PIE)" OUTPUT="$(OUTPUT)" j="$(j)" \
verbose="$(verbose)" notui="$(notui)" v="$(version)" stored-warn="$(stored-warn)" \
f="$(f)" lf="$(lf)" CCFLAGS="$(CCFLAGS)" LDFLAGS="$(LDFLAGS)" REPLXX_FLAGS="$(REPLXX_FLAGS)" CXXFLAGS="$(CXXFLAGS)" \
LD_LIBS="$(LD_LIBS)" NO_LDL="$(NO_LDL)" no_fPIC="$(no_fPIC)" \
LD_LIBS="$(LD_LIBS)" NO_LDL="$(NO_LDL)" no_fPIC="$(no_fPIC)" target-from-cc="$(target_from_cc)" \
c="$(build_c)" debug="$(debug)" $(i_build_opts) $(build_opts) \
os="$(target_os)" arch="$(target_arch)" has="$(has)" usz="$(usz)" nogit="$(nogit)" \
shared="$(i_SHARED)" singeli="$(i_singeli_1)" replxx="$(i_REPLXX_1)" FFI="$(FFI)"