build: reduce overall build times - #93
Merged
Merged
Conversation
The build script cloned the entire falcosecurity/libs repository (~44MB of pack data) only to immediately check out one pinned SHA. Fetch just that commit instead (~4MB): init an empty repo, `fetch --depth=1` the pinned SHA, and detach onto FETCH_HEAD. Fetching by SHA is content-addressed, so the checked-out tree is still cryptographically pinned by LIBSCAP_CHECKOUT_SHA; this is also the pre-git-2.49 spelling of `git clone --revision=<sha>`, which not all runners and cross images ship yet. A failed fetch now also removes the partially-initialized repo directory, so a retry starts clean instead of building whatever half-state a previous attempt left in OUT_DIR (the old code could even build the wrong ref if the clone succeeded but the checkout failed). Measured on my dev box (cross build inside protect): the clone phase of the build script drops from ~5.8s to ~1.4s cold; the transfer shrinks about 10x regardless of network conditions. Signed-off-by: Steven Noonan <steven@edera.dev>
… libbpf
CMake-generated compile rules honor CMAKE_C_COMPILER_LAUNCHER
(sccache/ccache), but two libscap build steps never see it:
- the modern_bpf eBPF objects are compiled by ${MODERN_CLANG_EXE}
inside add_custom_command rules, which don't apply launchers
- libbpf builds via an ExternalProject BUILD_COMMAND that invokes raw
`make` with an unwrapped CC; raw `make` also can't inherit the
jobserver, so libbpf built single-threaded ("jobserver unavailable:
using -j1")
When a launcher is configured, write two one-line shim scripts into
OUT_DIR that exec the launcher around clang and cc, point
MODERN_CLANG_EXE at the clang shim (a user-provided MODERN_CLANG_EXE
still wins: the shim wraps it rather than replacing it), and patch the
checked-out libbpf.cmake BUILD_COMMAND to use `make -j$NUM_JOBS` with
CC set to the cc shim. The -j fix applies even without a launcher, and
if a future libscap bump changes the module text the patch degrades to
a cargo:warning instead of breaking the build.
Measured on my dev box (cross build inside protect, warm sccache):
sccache compile requests go from 124 to 320 for one cold build-script
run - the 191 previously-invisible libbpf and eBPF compiles now hit the
cache - taking the libbpf target from ~3.6s to ~1.3s, the eBPF objects
from ~5.4s to ~2.6s, and the whole cmake phase from ~16.8s to ~8s. The
first build after this change pays one-time cache-population misses.
Signed-off-by: Steven Noonan <steven@edera.dev>
The bpftool release archive download (~9.6MB) ran serially after the git fetch, but the two are independent network operations. Split fetch_bpftool() into spawn_bpftool_download(), which starts the download on a background thread (skipped when a previously downloaded archive with a good checksum is already present), and install_bpftool(), which lands the verified bytes and extracts the binary after the fetch completes. Checksum verification is unchanged: the archive is still validated against the pinned sha256 before anything is written or extracted. Measured on my dev machine (cross build inside protect): hides essentially the whole ~1s bpftool download behind the git fetch on a cold build-script run; more on slower networks. Signed-off-by: Steven Noonan <steven@edera.dev>
The full bindings pass had emit_clang_ast() enabled, a bindgen debugging aid that dumps the entire parsed clang AST for inc/libscap.h to the build script's stdout. That's pure overhead in normal builds: extra work in the largest of the three bindgen passes (~1.4s on my dev box, versus ~0.25s for each of the two filtered passes) and megabytes of noise captured into cargo's build output file. The generated bindings are unaffected. Signed-off-by: Steven Noonan <steven@edera.dev>
The build script only needs a single blocking HTTPS GET to fetch the bpftool release, but reqwest dragged an entire async stack — tokio, hyper, quinn — into build-dependencies, and since reqwest 0.13 defaults its rustls provider to aws-lc-rs, the heavy aws-lc-sys C library too. That whole subgraph was compiled on the host purely to run this build script. Switch to ureq with rustls + ring and bundled webpki roots (default-features off, "rustls" feature only). It is synchronous (no async runtime), uses ring instead of aws-lc-rs (aws-lc-sys leaves the build-dependency graph entirely), and bundles webpki roots so certificate validation does not depend on a system trust store in the build environment. The download remains SHA256-verified against the pinned per-arch checksum, so TLS here is defense in depth. ureq's read_to_vec() caps the body at 10 MiB by default and the bpftool tarball is already 10.0 MiB, so the limit is raised to 64 MiB explicitly. cargo audit over the build-dependency tree improves from 8 advisories to 5: the quinn-proto (x2) and rand advisories go away with the async/QUIC stack, and the remaining bytes + rustls-webpki advisories are unchanged from the reqwest tree (same rustls 0.23 stack) and awaiting upstream fixes. Signed-off-by: Steven Noonan <steven@edera.dev>
bleggett
approved these changes
Jul 24, 2026
Collaborator
There was a problem hiding this comment.
jesus, no kidding did that reduce the dep count. ty!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR is a set of build-script (
build.rs) improvements that makelibscap-bindingscompile faster and pull in far less on the host -- with the biggest real-world win being where this crate sits on the critical path of a larger build.Why this matters beyond a standalone
cargo buildThe headline change drops the
aws-lc-*build-dependencies (viareqwest->ureq). In theprotectbuild,aws-lc-sys(a heavy C library) was a critical-path dependency: it had to compile beforelibscap-bindingscould finish, which in turn blocked everything downstream oflibscap-bindings. So the payoff isn't just the ~1,500-lineCargo.lockshrink you see here -- it's a pipelining effect: removingaws-lc-*unblocks this crate and its dependents earlier in the graph, which a lonecargo buildoflibscap-bindingswon't reveal.Changes
Drop the async/
aws-lcbuild-dep stack (reqwest->ureq). The build script only needs one blocking HTTPS GET for the bpftool archive.reqwestdragged in tokio/hyper/quinn and (via rustls' default provider)aws-lc-rs+aws-lc-sys. Switching toureq(rustls +ring, bundled webpki roots) removesaws-lc-sysfrom the build graph entirely.cargo auditover build-deps goes 8 -> 5 advisories. Download stays SHA256-verified.Fetch only the pinned libscap commit instead of a full clone. Init an empty repo and
fetch --depth=1the pinned SHA (~4MB vs ~44MB, still content-addressed / cryptographically pinned). Clone phase ~5.8s -> ~1.4s cold, ~10x less transfer. Failed fetches now clean up so retries start fresh.Route launcher-bypassing compiles through sccache; parallelize libbpf. The modern_bpf eBPF objects and the libbpf ExternalProject previously never saw
CMAKE_C_COMPILER_LAUNCHER(and libbpf built-j1). Shim scripts now wrap clang/cc so those 191 compiles hit the cache, and libbpf builds-j$NUM_JOBS. cmake phase ~16.8s -> ~8s (warm sccache).Overlap the bpftool download with the git fetch. These are independent network ops; the ~9.6MB bpftool download now runs on a background thread, hiding ~1s behind the fetch. Checksum verification unchanged.
Stop emitting the clang AST during bindgen. A leftover debugging aid that dumped the full AST to build output -- ~1.4s -> ~0.25s on the largest bindgen pass, and removes megabytes of noise. Generated bindings unchanged.