How vix run Resolves Targets
vix run is the command that turns a source file or project into something executable, then runs it.
It looks simple from the outside:
vix runor:
vix run main.cppBut internally, vix run has to answer several questions:
Is this a single C++ file?
Is this a project?
Is the project using CMakeLists.txt?
Is the project using vix.app?
What target should be built?
Where is the executable?
Which arguments belong to Vix?
Which arguments belong to the program?Target resolution is the part of vix run that answers these questions.
Two main modes
vix run has two major modes:
script mode
project modeScript mode runs a single C++ file.
Project mode runs a CMake or vix.app project.
Example script mode:
vix run main.cppExample project mode:
vix runfrom inside a project directory.
Script mode
Script mode is used when the input is a C++ source file.
Example:
vix run main.cppIn this mode, Vix treats the file as the entry point.
The target identity comes from the source file.
Conceptually:
input file: main.cpp
script target: mainVix can compile the file, link the required libraries, then execute the produced binary.
Project mode
Project mode is used when Vix detects a project root.
A project root contains one of these files:
CMakeLists.txt
vix.appResolution order:
1. CMakeLists.txt
2. vix.appIf a CMakeLists.txt exists, Vix uses the CMake project.
If no CMakeLists.txt exists but vix.app exists, Vix uses the vix.app project.
Why target resolution matters
Running a project is not only about building.
After building, Vix needs to find the executable.
That requires a target name.
For example:
name = hello
type = executable
standard = c++20
sources = [
src/main.cpp,
]The executable target is:
helloSo vix run should build and search for:
hellonot necessarily the folder name.
The old simple assumption
For many CMake projects, Vix can guess the target from the project folder.
Example:
hello/
CMakeLists.txt
src/
main.cppFolder name:
helloTarget name:
helloIn this case, guessing from the folder works.
But this assumption breaks when the target name differs from the directory name.
vix.app makes target identity explicit
With vix.app, the manifest declares the target name directly:
name = serverThe folder could be named:
backend-app/But the target is:
serverSo vix run must use the resolved target name from the manifest.
It should not guess from:
project directory name
generated CMake directory nameProject resolution result
A good project resolver returns enough metadata for vix run.
For a CMake project:
kind = CMake
userProjectDir = project/
cmakeSourceDir = project/
cmakeListsPath = project/CMakeLists.txt
targetName = project folder name or resolved target
generated = falseFor a vix.app project:
kind = vix.app
userProjectDir = project/
cmakeSourceDir = project/.vix/generated/app/
cmakeListsPath = project/.vix/generated/app/CMakeLists.txt
appManifestPath = project/vix.app
targetName = manifest.name
generated = truevix run should use this resolved result instead of duplicating project detection logic.
userProjectDir
userProjectDir is the real project root.
It contains:
CMakeLists.txtor:
vix.app
src/
include/
assets/For vix.app, this remains the user project root even though the generated CMake file lives elsewhere.
vix run should use userProjectDir for:
working directory decisions
watch mode
project-relative operations
calling vix build
user-facing diagnosticscmakeSourceDir
cmakeSourceDir is the directory passed to CMake configure.
For CMake projects:
cmakeSourceDir = project/For vix.app projects:
cmakeSourceDir = project/.vix/generated/app/vix run usually should not treat this as the user project root.
It is only the active CMake source directory.
targetName
targetName is the target to build and run.
For vix.app, this comes from:
name = ...Example:
name = api_serverThen vix run should build:
api_serverand search for an executable named:
api_serveror platform equivalent:
api_server.exeon Windows.
generated
The generated flag tells Vix whether the active CMake project came from vix.app.
This helps diagnostics.
For example, vix run can show different context:
Project directory:
app/
Generated CMake source:
app/.vix/generated/app/It also helps avoid using generated directories for user-facing operations.
Running a CMake project
For a normal CMake project:
hello/
CMakeLists.txt
src/
main.cppvix run can do:
resolve project
build target
find executable
run executableConceptually:
vix build --dir hello
./build-ninja/helloThe actual implementation may call internal build functions or invoke the build pipeline directly, but the logic is the same.
Running a vix.app project
For a vix.app project:
hello/
vix.app
src/
main.cppwith:
name = hello
type = executable
standard = c++20
sources = [
src/main.cpp,
]vix run should do:
resolve vix.app
generate internal CMake if needed
build target hello
find executable hello
run executableThe generated CMake directory should not become the user project root.
Build before run
vix run should ensure the target is built before execution.
Conceptually:
vix run
-> resolve project
-> build selected target
-> resolve executable path
-> execute binaryThis is why vix run depends on correct vix build planning.
If vix build builds the wrong target, vix run will search for the wrong executable.
Executable lookup
After building, vix run needs to find the executable.
Common locations include:
build-ninja/<target>
build-ninja/bin/<target>
build-ninja/src/<target>For Windows, the executable may include:
.exeSo for target:
helloVix may search for:
hello
hello.exedepending on platform.
output_dir and executable lookup
vix.app supports:
output_dir = binThis means the executable may be under:
build-ninja/bin/Example:
name = server
type = executable
standard = c++20
output_dir = bin
sources = [
src/main.cpp,
]After build, Vix should search:
build-ninja/bin/serveras well as other common locations.
Why recursive fallback exists
Some build systems place outputs in less obvious directories.
A fallback recursive search can help when the executable is not in the expected locations.
However, recursive search should still be guided by:
targetNameIt should not run a random executable just because it exists.
Target name keeps the search safe and predictable.
Running libraries
vix run is mainly for executable targets.
If a project is:
name = mathlib
type = staticthere may be no executable to run.
The correct command is:
vix buildTo run something for a library, use a test or example executable:
tests/vix.app
examples/basic/vix.appThen run:
cd tests
vix runor:
cd examples/basic
vix runRuntime arguments
vix run must separate Vix arguments from program arguments.
For example:
vix run main.cpp --run --name Gaspardor for project mode:
vix run -- --name GaspardThe exact boundary depends on the command design, but the principle is important:
arguments before the boundary configure Vix
arguments after the boundary go to the programWithout a clear boundary, Vix may consume arguments intended for the user program.
Script mode target resolution
In script mode:
vix run main.cppVix can derive the target name from the file:
mainThe compiled output can be stored in a Vix build/cache directory.
The exact path is an implementation detail.
What matters is:
the source file is the entry point
the output is executable
the program receives runtime argumentsProject mode target resolution
In project mode:
vix runVix must resolve a project first.
Then it uses the project target.
For CMake:
targetName = project default targetFor vix.app:
targetName = manifest.nameThis is the main difference.
Explicit build target
A user may provide an explicit build target.
Example:
vix run --build-target serverIn that case, the explicit target should take priority over the default target.
Resolution rule:
if --build-target is provided:
use --build-target
else:
use resolved targetNameThis is useful for CMake projects with multiple targets.
For vix.app, there is normally one target, so the manifest name is usually enough.
Watch mode
Watch mode should watch the real project directory.
For CMake projects:
watch project/For vix.app projects:
watch project/It should not watch only:
project/.vix/generated/app/because that directory contains generated files, not the user’s real source code.
For vix.app, watch mode should observe:
vix.app
src/
include/
assets/Generated CMake and run
For a vix.app project, generated CMake is part of the build process.
But vix run should still think in terms of the user project.
The important values are:
userProjectDir -> where the project lives
cmakeSourceDir -> where generated CMake lives
targetName -> what to build and runThis keeps vix run aligned with vix build.
CMake presets
For normal CMake projects, vix run may use CMake presets when available.
For vix.app, presets are less relevant because the CMake project is generated internally.
The important rule is:
normal CMake project -> can use project CMake presets
vix.app project -> use generated CMake and Vix build planningError: project not found
If Vix cannot find:
CMakeLists.txtor:
vix.appproject mode cannot run.
Example error:
Unable to determine the project directory.
Missing CMakeLists.txt or vix.app.Fix:
run vix from a project directory
or create vix.app
or create CMakeLists.txtError: executable not found
This can happen when:
the target is a library
the build failed
the target name is wrong
output_dir is unexpected
the executable was not producedFor vix.app, check:
name = ...
type = executable
output_dir = ...If the type is:
type = staticthen vix run has no executable to run.
Error: wrong target name
This can happen if the build system guesses from the folder name instead of using the manifest name.
Example:
folder: hello-project
manifest name: helloCorrect target:
helloWrong target:
hello-projectThe fix is to use the resolved target name from project resolution.
Error: generated directory used as project root
For vix.app, this is wrong:
project root = .vix/generated/appThat can break:
watch mode
runtime working directory
target guessing
exports
diagnosticsThe project root should be:
userProjectDirThe generated directory should be:
cmakeSourceDirRuntime working directory
The runtime working directory affects relative file access.
If the program opens:
std::ifstream file("config/app.json");then it depends on where the process starts.
For apps with resources, this matters.
A vix.app project may copy resources next to the executable:
build-ninja/bin/config/app.jsonbut the program may run from the project root unless Vix changes the working directory.
This is a design choice vix run should make deliberately.
Running with resources
If the manifest says:
output_dir = bin
resources = [
"data/config.json=config/config.json",
]then the resource may be copied to:
build-ninja/bin/config/config.jsonvix run should either:
run from the executable directoryor document the runtime working directory clearly.
The important point is predictability.
Project mode should not duplicate build logic
vix run should not reinvent vix build.
It should reuse the same project resolution and build planning rules.
The flow should be:
resolve project
call build pipeline with target
resolve executable
run executableIf vix run and vix build resolve projects differently, bugs appear.
Especially with vix.app.
Shared resolver
A shared resolver should answer:
kind
userProjectDir
cmakeSourceDir
targetName
generated
cmakeListsPath
appManifestPathBoth vix build and vix run should use this same model.
That keeps behavior consistent.
Good output
When verbose mode is enabled, vix run can show:
Project:
kind: vix.app
root: /path/to/project
generated CMake: /path/to/project/.vix/generated/app
target: hello
Build:
preset: dev-ninja
directory: build-ninja
Run:
executable: build-ninja/bin/helloThis makes target resolution visible.
Why this matters
Most command-line tools feel simple because the hard decisions are hidden.
But hidden decisions still need to be correct.
vix run should feel like:
vix runBut internally it must correctly handle:
single-file scripts
CMake projects
vix.app projects
generated CMake
output directories
runtime arguments
watch modeThat is why target resolution matters.
Future native vix.app builds
In the future, vix.app may build natively:
vix.app
-> BuildGraph
-> ObjectCache
-> Scheduler
-> Linkvix run should not need a major redesign for that.
If the resolver still provides:
targetName
buildDir
output path
project rootthen the execution step stays similar.
Only the build engine changes underneath.
Conclusion
vix run resolves targets by first deciding whether it is running a single file or a project.
For projects, it resolves either:
CMakeLists.txtor:
vix.appFor vix.app, the manifest name is the target name.
That target name must drive both the build step and the executable lookup.
The key rule is:
do not guess from the generated directory
do not guess from the folder when the manifest gives a nameA clean vix run model uses shared project resolution, builds the correct target, finds the executable, and runs it with a clear argument boundary.