Artifact Cache
The artifact cache is the target-level cache layer in vix build.
Use this guide when you want to understand how Vix can reuse complete build outputs such as executables, libraries, compiled packages, and generated package artifacts.
The problem
Object caching avoids recompiling individual source files.
But C++ builds often spend time beyond compilation.
A project may still need to:
archive static libraries
link executables
copy resources
prepare generated outputs
rebuild dependency packages
produce final artifactsEven when object files are already available, the final target may still need work. The artifact cache solves a larger question:
Have we already built this target or package with the same build identity?If the answer is yes, Vix can restore or reuse the complete output instead of rebuilding it.
What the artifact cache does
The artifact cache stores larger reusable build outputs.
Examples:
executable binary
static library
shared library
compiled package prefix
generated install prefix
final linked target
package artifactFor example:
build-ninja/vix
build-ninja/lib/libvix_core.a
dist/app@1.0.0.vixpkgcan be treated as artifacts when their full build identity is known.
Object cache vs artifact cache
Object cache works at the source-file level:
src/server.cpp -> server.cpp.o
src/server.cpp -> server.cpp.dArtifact cache works at the target or package level:
object files + libraries + link options -> executable
package source + compiler + options -> compiled packageThe difference is:
ObjectCache
reuses compile outputs
ArtifactCache
reuses complete build outputsA strong build system needs both.
Why artifact caching matters
Artifact caching matters because repeated builds often rebuild outputs that are already known.
It helps with:
clean builds
CI builds
compiled dependencies
large libraries
final executables
local repeated builds
cross-project package reuseThe goal is not magic.
The goal is disciplined reuse:
same inputs
same build identity
same artifact
reuse safelyThe safety rule
The safety rule is:
reuse an artifact only when its full build identity matchesA target name is not enough. A file path is not enough. A previous successful build state is not enough. Vix must know that the current build identity matches the cached artifact identity. A false cache miss is acceptable. A false cache hit is dangerous.
What is an artifact?
An artifact is a reusable build output.
Examples:
binary executable
static library
shared library
compiled dependency
package install prefix
generated distribution folder
.vixpkg packageFor example:
build-ninja/bin/serveris an artifact.
So is:
build-ninja/lib/libauth.aA compiled registry package can also be an artifact.
Artifact identity
An artifact needs a stable identity.
That identity can include:
package name
package version
target name
target type
compiler identity
linker identity
build type
target triple
source fingerprint
dependency fingerprint
build options
link options
resource fingerprintA Debug binary is not the same as a Release binary. A GCC build is not the same as a Clang build. A Linux artifact is not the same as a Windows artifact.
Fingerprint
A fingerprint is a compact representation of build-relevant inputs. For an artifact, the fingerprint should include the inputs that can affect the final output.
Examples:
source file hashes
header file hashes
manifest hash
CMake configuration hash
compiler identity
compiler flags
linker identity
link options
target triple
build type
package versions
dependency artifact hashes
resourcesIf the fingerprint changes, the artifact must not be reused.
Basic flow
The artifact cache flow is:
1. Resolve target or package identity
2. Compute artifact fingerprint
3. Check artifact cache
4. If hit, verify cached output
5. Restore or reuse artifact
6. If miss, build normally
7. Store artifact after successful buildThe important part is verification. A cache entry must be complete and valid before Vix uses it.
Local build state vs artifact cache
Local build state and artifact cache answer different questions. Local build state answers:
Is this target already valid in this build directory?Artifact cache answers:
Do we have this complete output somewhere in the cache?Both are useful. Build state is fastest for no-op builds. Artifact cache is useful after clean builds, across projects, and in CI.
Relationship with fast target builds
Fast target builds use build state first. If the target is already valid, Vix can return early:
vix build --build-target vixExpected output shape:
Checking vix (dev)
✔ Up to date in 0.3sBut if the build directory is missing, build state alone cannot help. That is where artifact cache matters.
Clean build with warm artifact cache
Example:
vix build --build-target vix
rm -rf build-ninja
vix build --build-target vixIf the final target artifact is cached, Vix can restore it:
Restoring vix (dev)
✔ Artifact cache hit
✔ DoneThis avoids recompiling and relinking when the final output is already known.
Missing output safety
A state hit is not enough. If the target output is missing, Vix must not say the target is up to date.
Example:
vix build --build-target vix
rm -f build-ninja/vix
vix build --fast --build-target vixThe correct behavior is:
target output missing
rebuild or restore from artifact cacheNot:
Up to dateThe final output must still exist and be valid.
Layered build model
Artifact cache fits into the Vix build pipeline as a higher-level reuse layer.
The model is:
BuildState -> fastest no-op validation
ArtifactCache -> restore complete target
BuildGraph -> target-aware analysis
ObjectCache -> restore compile outputs
CMake/Ninja -> compatibility fallbackEach layer has a job.
BuildState
BuildState answers:
Can Vix prove this target is already valid right now?If yes, Vix returns immediately.
This is the fastest path.
ArtifactCache
ArtifactCache answers:
Can Vix restore the full target output?If yes, Vix can avoid compile and link work. This is especially useful after deleting the build directory.
BuildGraph
BuildGraph answers:
What does this target depend on?It gives Vix target awareness. When the artifact cache misses, the graph helps Vix decide what work is necessary.
ObjectCache
ObjectCache answers:
Can Vix restore individual compile outputs?If the final artifact cannot be reused, object cache can still avoid recompiling files that have not changed.
CMake and Ninja fallback
CMake and Ninja remain the compatibility fallback. If Vix cannot prove that an artifact is safe, it should delegate. The fallback is part of correctness.
if unsure, fallbackPackage artifacts
Package artifacts are one of the best use cases for artifact caching. Packages are often reused across projects.
Example:
project A builds package softadastra/json
project B uses the same package
project B reuses the cached compiled artifactThis can avoid repeated dependency builds.
Header-only packages
Header-only packages do not need compiled binaries. For header-only packages, the artifact may only contain:
include/
manifest.json
metadataNo library output is needed. This distinction matters. A header-only package should not be treated like a compiled package.
Compiled packages
Compiled packages can produce:
static libraries
shared libraries
headers
CMake config files
generated metadataA compiled package artifact can be stored as a reusable prefix:
include/
lib/
share/
manifest.jsonThen another project can reuse it when the identity matches.
CMAKE_PREFIX_PATH integration
For compiled package artifacts, Vix can expose the cached prefix to CMake.
If an artifact contains:
lib/cmake/package/packageConfig.cmakeVix can add the artifact prefix to:
CMAKE_PREFIX_PATHThis keeps artifact reuse compatible with normal CMake package discovery.
Source fallback
If no compiled artifact exists, Vix can fall back to source integration.
The fallback model is:
artifact cache hit
reuse compiled artifact
artifact cache miss
build package from source
store artifact after successThis gives immediate correctness and later speed.
Final target artifacts
A final executable can also be cached.
Example:
build-ninja/vixIf the full target identity matches, Vix can restore the executable. This is different from object cache. Object cache restores .o files. Artifact cache can restore the final binary.
Artifact metadata
Each artifact should have metadata.
Example shape:
{
"name": "vix",
"target": "vix",
"type": "executable",
"compiler": "g++",
"compiler_version": "13.3.0",
"linker": "mold",
"build_type": "Debug",
"target_triple": "x86_64-linux-gnu",
"fingerprint": "...",
"created_at": "...",
"outputs": ["build-ninja/vix"]
}The exact format can evolve. The goal is explainability. Vix should know what an artifact is and why it is valid.
Cache layout
A possible artifact cache layout is:
~/.vix/cache/build/
artifacts/
<target-or-package>/
<compiler>/
<build-type>/
<target-triple>/
<fingerprint>/
manifest.json
outputs/For package artifacts:
~/.vix/cache/build/
packages/
softadastra.json/
gcc-13.3.0/
release/
x86_64-linux-gnu/
<fingerprint>/
include/
lib/
share/
manifest.jsonThe exact layout can change.
The identity rule should not.
Artifact verification
Before using a cached artifact, Vix should verify:
metadata exists
expected files exist
artifact type matches
fingerprint matches
compiler identity matches
build type matches
target triple matches
outputs are completeIf verification fails, treat it as a cache miss. Do not use broken cache entries.
Atomic restore
Artifact restoration should avoid partial outputs.
A safe restore can use this model:
restore into temporary location
verify expected files
move into final location
update build stateThis prevents corrupted build directories when a restore fails halfway.
Resource files
Resources can affect runtime output.
Example vix.app resources:
resources = [
".env=.env",
"assets=assets",
]If resources are part of the final artifact, their content should be included in the artifact identity. If a resource changes, the artifact should not be reused without updating the restored output.
Artifact cache and vix.app
vix.app is a strong input for artifact caching because it is structured.
It can describe:
name
type
sources
include_dirs
defines
modules
deps
packages
links
resources
output_dirThis makes it easier to compute a stable artifact fingerprint. For vix.app projects, Vix has more direct knowledge than with arbitrary CMake.
Artifact cache and generated CMake
When a vix.app project generates internal CMake, the artifact cache can still work.
The identity can include:
vix.app hash
generated CMake hash
project inputs
build options
compiler identity
link optionsThis allows artifact caching before a fully native build path exists.
Artifact cache and CMake projects
For arbitrary CMake projects, Vix should be conservative. CMake can contain custom logic.
So Vix should base decisions on generated build outputs such as:
compile_commands.json
build.ninja
CMakeCache.txt
dependency files
build stateIf the artifact identity is incomplete, the cache should miss.
Artifact cache and CI
CI often starts from a clean workspace. That makes artifact caching useful. A CI workflow can restore:
~/.vix/cache/build/before running:
vix build --preset releaseThe CI cache key must include:
OS
compiler
compiler version
target triple
build type
dependency versions
Vix versionUnsafe CI cache keys can cause incorrect reuse.
Artifact cache and cross-compilation
Cross-compilation requires separate artifact identities.
An artifact built for:
x86_64-linux-gnucannot be reused for:
aarch64-linux-gnuTarget triple must be part of the artifact key. Sysroot and toolchain metadata may also need to be included.
Artifact cache and build type
Debug and Release artifacts are different. Debug may include:
debug symbols
assertions
different optimization levelRelease may include:
optimization
NDEBUG
different link behaviorBuild type must be part of the artifact identity.
Artifact cache and compiler identity
Artifacts depend on compiler and ABI.
Important compiler identity fields include:
compiler name
compiler path
compiler version
standard library
target triple
ABI-relevant flagsFor safety, Vix should separate artifacts by compiler identity.
Artifact cache and linker identity
The linker can also affect final outputs.
For linked artifacts, the identity can include:
linker name
linker version
link options
library order
runtime paths
static or shared modeIf link identity changes, the final artifact should miss.
Cache invalidation
Artifact cache invalidation happens naturally when fingerprints change.
Examples:
source changed
header changed
manifest changed
dependency changed
compiler changed
build type changed
target triple changed
link options changed
resource changedThe old artifact can remain in the cache. It just will not match the new identity.
Cache eviction
Artifact caches can become large.
Vix can eventually support eviction policies such as:
maximum cache size
least recently used
maximum age
per-target cleanup
per-package cleanup
manual cleanEviction should never affect correctness. It only affects whether future builds are cache hits or misses.
Explainable cache behavior
Artifact cache decisions should be visible.
Useful messages include:
artifact cache hit: vix
artifact cache miss: source fingerprint changed
artifact cache miss: compiler changed
artifact cache miss: target output missing
artifact restored: build-ninja/vix
artifact stored: vixA fast build that cannot be explained feels unsafe.
Vix should make cache behavior understandable.
--explain
Use --explain to understand build decisions:
vix build --explain --build-target vixExample output:
Restoring vix
reason: artifact cache hit
Skipping compile tasks
reason: final target restoredIf the artifact cannot be reused:
Artifact cache miss
reason: build fingerprint changed
Rebuilding BuildCommand.cpp
reason: source file changedThis helps developers trust the result.
Example workflow
Build a target:
vix build --build-target vixRemove the build directory:
rm -rf build-ninjaBuild the same target again:
vix build --build-target vixIf the artifact cache has a valid target artifact, Vix can restore it instead of rebuilding.
Example output shape
Restoring vix (dev)
✔ Artifact cache hit
✔ Restored target output
✔ DoneIf the artifact is not available:
Building vix (dev)
i Artifact cache miss
i Falling back to graph build
✔ BuiltBoth are valid.
A miss is not an error.
Recommended workflow
Use normal builds:
vix buildUse target builds for specific outputs:
vix build --build-target vixUse explain mode when diagnosing cache behavior:
vix build --explain --build-target vixUse clean build only when needed:
vix build --cleanUse vix info to inspect cache paths:
vix infoCommon workflows
# Build normally
vix build
# Build one target
vix build --build-target vix
# Explain cache decisions
vix build --explain --build-target vix
# Test artifact restoration after build directory removal
vix build --build-target vix
rm -rf build-ninja
vix build --build-target vix
# Inspect cache state
vix infoCommon mistakes
Thinking artifact cache replaces object cache
Artifact cache and object cache solve different problems. Artifact cache reuses complete outputs. Object cache reuses compile outputs.
Trusting a target name only
The target name is not enough.
The full build identity must match.
Reusing artifacts across compilers blindly
C++ artifacts are compiler and ABI sensitive. Compiler identity must be part of the cache key.
Ignoring resources
If resources affect the final output, they must be part of the artifact fingerprint.
Treating cache misses as errors
A cache miss is normal. It only means Vix must build normally.
Good first version
A practical first artifact cache can support:
local build state
target artifact metadata
final binary restore
compiled package prefix reuse
basic fingerprinting
safe verification
clear hit and miss logsIt does not need remote caching on day one. Correctness comes first.
Later improvements
Later improvements can include:
remote artifact cache
link result cache
artifact signing
cache eviction
CI cache helpers
team cache sharing
explainable miss reasons
native vix.app integration
artifact trust policiesThe system should grow in layers.
Security considerations
A build cache stores executable code. Local-only artifact cache has lower risk. Remote artifact cache needs stronger safety.
Possible mechanisms:
content hashes
signatures
trusted cache sources
metadata verification
sandboxed extractionFor Vix, the best path is:
local correctness first
remote sharing later
trust before speedRelated commands
| Command | Purpose |
|---|---|
vix build | Build a project or target |
vix build --explain | Explain rebuild and cache decisions |
vix info | Show cache paths and local state |
vix clean | Remove project-local generated state |
vix reset | Clean and reinstall dependencies |
vix pack | Create distributable package artifacts |
vix verify | Verify package artifacts |
vix cache | Store verified packages locally |
What you should remember
The artifact cache is the large-output reuse layer.
It can restore:
executables
libraries
compiled packages
package artifactsIts rule is:
reuse only when the full build identity matchesIt sits above the object cache. If the artifact cache hits, Vix can avoid compile and link work. If it misses, Vix can still use the build graph and object cache. If Vix is unsure, it falls back. The principle remains:
fast when safe
correct by default
fallback when needed