Skip to content

elide-dev/cflags

Repository files navigation

Elide's C Flags

Tree of simple text files which compound into final clang and LLD flags when building Elide. On Unix-like platforms, Elide and related repos may consult this one to build with a uniform suite of flags across compilation units.

Flag files allow comments which start with #. Comments are thus inline explaining the purpose of most flags.

There are two classes of profile:

  • Compile profiles (base, linux, darwin, linux-amd64, …) apply to every translation unit and link stage in the dependency-build pipeline (Netty C, BoringSSL, autoconf conftests, …). Anything here must be safe at intermediate link stages.
  • Binary profiles (*-bin) apply only at the consuming project's final executable / shared-library / dylib link. They hold flags — section stripping, undefined-symbol rejection, debug compression, fatal warnings — that would break a dependency's intermediate conftest or test-binary link if applied earlier. The chain mirrors the compile side: an OS-level linux-bin / darwin-bin carries the OS-wide final-link flags, and a leaf *-arch-bin layers any arch-specific final-link flags on top. The full rollup for linux-amd64-bin is base → linux → linux-amd64 → linux-bin → linux-amd64-bin.

Toolchain & deployment floor

These flags assume the following floor; downstream consumers should match or override per-profile.

Layer Floor
Compiler mainline LLVM clang 22.x (Polly-enabled), on every platform
Linker lld (ld.lld on Linux, ld64.lld on Darwin)
Linux libc musl 1.2.x primary; glibc 2.36+ for any glibc consumers
Linux libc++ Vendored libc++ (Linux/amd64); _LIBCPP_HARDENING_MODE honored
macOS macOS 12+ (dyld 4 / chained-fixups format)
Linux/amd64 ISA x86-64-v3 + aes/pclmul/sha/vaes/gfni/rdrand → Ice Lake / Zen 3+
Darwin/amd64 ISA x86-64-v3 + aes/pclmul/rdrand → Haswell+ (2013); covers every Intel Mac supported by macOS 12+
Linux/arm64 ISA armv8.2-a + crypto/crc/dotprod → Graviton 2+, Neoverse N1+, Altra
Darwin/arm64 ISA apple-m1 (ARMv8.5-A) — every shipping Apple Silicon Mac

Features

Compiler features activated or facilitated by these flags:

Feature Platforms Description
Thin LTO All Emits and optimizes as LLVM bitcode, program-wide
Function/Data Sections All -f{data,function}-sections (collected at final link, see below)
Constant merging All -fmerge-all-constants for smaller binary + fewer relocs at load
Stack Hardening Linux -fstack-clash-protection (canaries are parked, see "Phasing in")
Async Unwind Tables All -fasynchronous-unwind-tables for profilers + crash collectors
LLD as linker All -fuse-ld=lld required for Thin LTO
Full RELRO + -fno-plt Linux -z relro -z now plus PLT-less call lowering
No semantic interposition Linux -fno-semantic-interposition for intra-DSO inlining
DT_RELR relative relocations Linux -z pack-relative-relocs shrinks PIE relocation tables
LLD ICF (safe) Linux --icf=safe folds identical address-not-taken functions
GNU-hash dyn-symbol table Linux --hash-style=gnu (smaller, ~2× faster lookup at load)
LLD link optimization Linux -Wl,-O3 aggressive string/section merging at link time
Relative C++ ABI vtables Linux Enables relative vtable references program-wide
Propeller-ready BB sections Linux amd64 -fbasic-block-sections=all (awaiting symbol-ordering file)
Microarch tuning Linux amd64 -mtune=znver3 (mirrors Rust -Ztune-cpu=znver3)
PAC + BTI arm64 (both) -mbranch-protection=standard; -z force-bti on Linux
Mach-O fixup chains Darwin -bind_at_load, -fixup_chains, -no_data_in_code_info

Phasing in

Some hardening flags are temporarily disabled in the live profiles to prioritise startup time. They are tracked verbatim in labs.disabled.txt with a re-enable plan per flag. Currently parked, with the exact spelling needed when cut-and-pasting back into the live profile:

  • -fstack-protector-strong
  • -fzero-call-used-regs=used-gpr
  • -fcf-protection=full
  • -U_FORTIFY_SOURCE
  • -D_FORTIFY_SOURCE=2
  • -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST

The file is not consumed by the rollup or by cli/cflags.{sh,ts} — it is a parking lot, not a profile.

Important

Section-stripping and similar "no further link" flags live in *-bin, not in the per-OS or per-arch compile profiles. The compile profiles are applied to dependency builds (Netty, BoringSSL TCNative, autoconf conftests, …) where intermediate links still reference symbols that -Wl,--gc-sections / -Wl,-dead_strip would otherwise drop. The compiler still emits per-function/data sections via -ffunction-sections / -fdata-sections, so the consuming project picks up the full DCE win by selecting the corresponding *-bin profile (e.g. linux-amd64-bin) at its own final link step.

Note

-Wconversion is intentionally not enabled — it's too noisy across Netty's JNI glue and BoringSSL's x86 intrinsics to be useful as a blanket warning. Re-enable selectively per-target if needed.

Flag Profiles

Compile profiles

Applied to every translation unit and every link in the dependency-build pipeline. Roll-up: e.g. linux-amd64 = base.txt + linux.txt + linux-amd64.txt.

Profile OS Arch Description
base (All) (All) Baseline flags.
linux Linux (All) Linux-only flags.
linux-amd64 Linux amd64 Linux x86-64 flags.
linux-arm64 Linux aarch64 Linux ARM64 flags.
darwin macOS (All) macOS-only flags.
darwin-amd64 Darwin amd64 macOS Intel flags.
darwin-arm64 Darwin aarch64 macOS M-series flags.

Binary profiles

Applied only at the consuming project's final executable / shared-library / dylib link step. Holds flags that would break intermediate dependency-build links (autoconf conftests, BoringSSL test binaries, …). Roll-up: a *-bin profile inherits its compile-profile chain first, then adds the OS-wide *-bin layer, then the per-arch *-arch-bin layer. The full rollup for linux-amd64-bin is base → linux → linux-amd64 → linux-bin → linux-amd64-bin.

Profile OS Arch Adds
linux-bin Linux (All) --gc-sections, -z defs, --compress-debug-sections=zstd, --fatal-warnings
linux-amd64-bin Linux amd64 (placeholder for x86_64-only leaf-link flags)
linux-arm64-bin Linux aarch64 (placeholder for aarch64-only leaf-link flags)
darwin-bin Darwin (All) -dead_strip, -dead_strip_dylibs
darwin-amd64-bin Darwin amd64 (placeholder for Intel-Mac-only leaf-link flags)
darwin-arm64-bin Darwin aarch64 (placeholder for Apple-Silicon-only leaf-link flags)

Note

Windows is not covered here because we do not (yet) compile with clang on Windows.

CLI

Two equivalent scripts in cli/ emit the resolved, comment-stripped flag list as a single whitespace-separated line, suitable for use directly with shell command substitution.

Script Runtime
cli/cflags.sh Bash
cli/cflags.ts Bun

Both share the same surface:

cflags[.sh|.ts] [<os> <arch>] [--bin]
  • <os>linux | darwin — defaults to the host
  • <arch>amd64 | arm64 — defaults to the host
  • --bin — switch from the compile rollup (base → os → os-arch) to the binary rollup (base → os → os-arch → os-bin → os-arch-bin)

Examples:

# host compile flags
export CFLAGS="$(./cli/cflags.sh)"

# host final-link flags
export LDFLAGS="$(./cli/cflags.sh --bin)"

# explicit cross-target
export CFLAGS="$(bun run ./cli/cflags.ts linux arm64)"
export LDFLAGS="$(bun run ./cli/cflags.ts linux arm64 --bin)"

CI

.github/workflows/ci.yml runs on every push and PR; it resolves the flag set with both cli/cflags.sh and cli/cflags.ts, asserts they emit byte-identical output, and then compiles + links the tests/probe.c translation unit against the full compile and binary profiles for every supported target. The matrix covers:

Target GitHub runner
linux-amd64 ubuntu-24.04
linux-arm64 ubuntu-24.04-arm
darwin-arm64 macos-14

(darwin-amd64 is not covered: GitHub no longer offers an Intel-Mac runner. The profile is exercised locally before tagged releases.)

Downstream Projects

So far, the following projects consume these flags:

About

Central source for C compiler flags

Resources

Stars

Watchers

Forks

Contributors