vix.app Project Resolution
vix.app project resolution is the step where Vix decides what kind of project it is working with.
Before Vix can build or run anything, it needs to answer a few questions:
Where is the project root?
Is this a CMake project?
Is this a vix.app project?
What source directory should CMake use?
What target name should be built?
Where should build directories be created?This resolution step is small, but it is important.
If project resolution is wrong, the build system can use the wrong directory, the wrong target name, or the wrong generated CMake source.
The resolution rule
Vix uses this rule:
1. If CMakeLists.txt exists, use CMakeLists.txt.
2. Otherwise, if vix.app exists, use vix.app.This keeps existing CMake projects safe.
A project like this is resolved as a CMake project:
myapp/
CMakeLists.txt
vix.app
src/
main.cppA project like this is resolved as a vix.app project:
myapp/
vix.app
src/
main.cppCMake has priority because it is the full-control path.
vix.app is used only when there is no CMakeLists.txt.
Why CMake has priority
CMake projects can contain arbitrary build logic.
If a CMakeLists.txt exists, Vix should not ignore it.
That file may define:
custom targets
generated sources
install rules
CTest integration
toolchains
package exports
platform branches
dependency setupUsing vix.app instead would risk breaking the project.
The safe rule is:
CMakeLists.txt is explicit full control.
vix.app is the simple project path.The project root
The project root is the directory that contains one of these files:
CMakeLists.txt
vix.appWhen Vix starts from a directory, it can search upward until it finds a project root.
Example:
myapp/
vix.app
src/
main.cpp
features/
auth.cppIf the user runs Vix from:
myapp/src/features/Vix can walk upward and find:
myapp/vix.appThe resolved project root is:
myapp/CMake project resolution
For a normal CMake project:
myapp/
CMakeLists.txt
src/
main.cppthe resolved model is simple:
project kind: CMake
user project dir: myapp/
CMake source dir: myapp/
CMakeLists path: myapp/CMakeLists.txt
target name: usually myapp
generated: falseIn this case, the user project directory and the CMake source directory are the same.
Vix can configure CMake with:
cmake -S myapp -B myapp/build-ninjavix.app project resolution
For a vix.app project:
myapp/
vix.app
src/
main.cppVix resolves the project differently.
The user project directory is still:
myapp/But the CMake source directory is generated:
myapp/.vix/generated/app/The resolved model becomes:
project kind: vix.app
user project dir: myapp/
CMake source dir: myapp/.vix/generated/app/
CMakeLists path: myapp/.vix/generated/app/CMakeLists.txt
target name: manifest name
generated: trueSo if vix.app contains:
name = hello
type = executable
standard = c++20
sources = [
src/main.cpp,
]then the default target name is:
hellonot necessarily the project folder name.
Why target name matters
The target name is important because it is used by:
vix build
vix run
CMake target selection
executable lookup
diagnostics
artifact identityIf the project folder is called:
hello-project/but the manifest says:
name = hellothen Vix should build and run:
hellonot:
hello-projectThis is why vix.app resolution must expose the manifest target name.
The important separation
For vix.app, there are two different directories:
userProjectDir
cmakeSourceDirThey must not be confused.
The user project directory is where the real project lives:
myapp/It contains:
vix.app
src/
include/
assets/
tests/The CMake source directory is internal:
myapp/.vix/generated/app/It contains the generated:
CMakeLists.txtThese two paths serve different purposes.
userProjectDir
userProjectDir should be used for user-facing project operations.
Examples:
build directories
.env lookup
.vix metadata
resources
source path resolution
snapshots
local cache state
exported binaries
watch modeFor a vix.app project:
userProjectDir = myapp/That should remain true even though the generated CMake file is somewhere else.
cmakeSourceDir
cmakeSourceDir should be used for CMake configuration.
Examples:
cmake -S
generated CMake diagnostics
CMakeLists.txt path
CMake configure source directoryFor a vix.app project:
cmakeSourceDir = myapp/.vix/generated/app/So Vix configures CMake with:
cmake -S myapp/.vix/generated/app -B myapp/build-ninjanot with:
cmake -S myapp -B myapp/build-ninjabecause the original project root does not contain a CMakeLists.txt.
The bug this separation avoids
A common mistake is to store only one projectDir.
For CMake projects, that works because:
projectDir = user project dir = CMake source dirBut for vix.app, that breaks down.
If projectDir is changed to:
myapp/.vix/generated/app/then other systems may accidentally treat the generated directory as the real project.
That can break:
target name detection
build directory placement
export paths
input snapshots
watch mode
resource paths
.env lookup
cache keysThe correct model is to keep both paths.
A better build plan model
A build plan should distinguish:
userProjectDir
cmakeSourceDir
defaultTargetName
generatedFromVixAppFor a CMake project:
userProjectDir = myapp/
cmakeSourceDir = myapp/
defaultTargetName = myapp
generatedFromVixApp = falseFor a vix.app project:
userProjectDir = myapp/
cmakeSourceDir = myapp/.vix/generated/app/
defaultTargetName = manifest.name
generatedFromVixApp = trueThis makes the rest of the build system simpler.
Each operation can choose the correct path.
Configure uses cmakeSourceDir
CMake configure should use:
cmakeSourceDirFor CMake projects:
cmake -S myapp -B myapp/build-ninjaFor vix.app projects:
cmake -S myapp/.vix/generated/app -B myapp/build-ninjaThis is the only path that should be passed to cmake -S.
Build directories use userProjectDir
Build directories should be created under the user project directory.
For example:
myapp/build-ninja/
myapp/build-dev/
myapp/build-release/Not under:
myapp/.vix/generated/app/build-ninja/The generated CMake directory is internal source metadata.
It should not become the visible project root.
Default target uses manifest name
For vix.app, the default target should come from:
name = helloSo vix build should build:
cmake --build build-ninja --target hellonot:
cmake --build build-ninja --target appThe generated directory is named app, but that is not the target name.
The target name belongs to the manifest.
vix build project resolution
For vix build, project resolution should produce a build plan.
The build plan should contain:
userProjectDir
cmakeSourceDir
buildDir
configureLog
buildLog
defaultTargetName
generatedFromVixAppThen the build command can do:
configure:
cmake -S cmakeSourceDir -B buildDir
build:
cmake --build buildDir --target defaultTargetName
cache/snapshot/export:
use userProjectDirThis keeps CMake integration and user project handling separate.
vix run project resolution
vix run also needs the same resolved project metadata.
It needs to know:
where to configure
where to build
which target to build
which executable to run
where the real project livesFor vix.app, it should use:
resolved.userProjectDir
resolved.cmakeSourceDir
resolved.targetName
resolved.generatedThen it can build the correct target and search for the executable by manifest name.
Executable lookup
After building, vix run needs to find the executable.
For a vix.app project:
name = hello
output_dir = binVix should search common locations such as:
build-ninja/hello
build-ninja/bin/hello
build-ninja/src/helloThe lookup should use:
targetName = hellonot the folder name and not the generated directory name.
Watch mode
Watch mode should watch the real project directory.
For CMake projects:
watch myapp/For vix.app projects:
watch myapp/It should not watch only:
myapp/.vix/generated/app/The generated directory does not contain the user’s real source files.
Watch mode belongs to the user project directory.
Diagnostics
Project resolution also affects diagnostics.
For a generated vix.app project, build errors may involve:
generated CMakeLists.txt
real source files
manifest fieldsA good diagnostic should show the correct context.
Examples:
Project directory:
myapp/
Generated CMake source:
myapp/.vix/generated/app/
Build directory:
myapp/build-ninja/This helps engineers understand which layer failed.
Generated CMake path
When configure fails for a vix.app project, the relevant CMake file is:
.vix/generated/app/CMakeLists.txtSo CMake diagnostics should point there.
But source validation errors should point back to:
vix.app
src/main.cpp
include/The diagnostic layer should not confuse generated files with user-authored files.
Why AppProjectResolver exists
A dedicated project resolver makes this logic reusable.
Both vix build and vix run need the same answer:
What project is this?
Where is the real root?
Where is the CMake source?
What target should I build?
Was this generated from vix.app?If each command implements its own resolution logic, they can drift.
A shared resolver keeps behavior consistent.
Resolver result
A useful resolver result contains:
kind
userProjectDir
cmakeSourceDir
cmakeListsPath
appManifestPath
targetName
generated
errorFor a CMake project:
kind = CMake
userProjectDir = project/
cmakeSourceDir = project/
cmakeListsPath = project/CMakeLists.txt
targetName = project folder name
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 = trueSearch behavior
The resolver can start from:
current directory
a file path
a directory passed with --dirThen it searches upward for:
CMakeLists.txt
vix.appThe first directory containing either file becomes the project root.
Inside that root, CMake has priority.
Example: current directory
Project:
hello/
vix.app
src/
main.cppCommand:
cd hello
vix buildResolved result:
kind = vix.app
userProjectDir = hello/
cmakeSourceDir = hello/.vix/generated/app/
targetName = manifest.nameExample: nested directory
Project:
hello/
vix.app
src/
features/
auth.cppCommand:
cd hello/src/features
vix buildThe resolver walks upward and finds:
hello/vix.appResolved root:
hello/Example: CMake wins
Project:
hello/
CMakeLists.txt
vix.app
src/
main.cppResolved result:
kind = CMake
userProjectDir = hello/
cmakeSourceDir = hello/
generated = falseThe vix.app file is ignored for project resolution.
Failure cases
Resolution can fail when neither file exists.
Example:
empty-folder/
src/
main.cppCommand:
vix buildError:
Unable to determine the project directory.
Missing CMakeLists.txt or vix.app.The fix is to add either:
CMakeLists.txtor:
vix.appManifest load failure
For vix.app, resolution includes loading the manifest.
This can fail when:
name is missing
sources are missing
type is invalid
standard is invalid
array syntax is malformed
unknown field is presentIn that case, project resolution should return a structured error.
The command should display that error clearly and stop before CMake runs.
Generated CMake failure
After the manifest is loaded, Vix generates the internal CMake project.
Generation can fail when:
source files do not exist
resource paths are invalid
output paths are invalid
package syntax is invalid
target name is invalidThese are still manifest-level or generation-level errors.
They should be reported before the configure/build stage when possible.
Why this is important for native builds
Project resolution is also the foundation for future native vix.app builds.
The future build path may be:
vix.app
-> native BuildGraph
-> ObjectCache
-> Scheduler
-> LinkThat path still needs the same resolved metadata:
userProjectDir
targetName
sources
include_dirs
defines
output_dir
resourcesSo clean project resolution is not only about generated CMake.
It is also preparation for a native build engine.
The clean architecture
A clean architecture has three layers:
Project resolution
decides what project this is
Build planning
decides what to configure, build, cache, and run
Execution
runs CMake, Ninja, native tasks, or the final executablevix.app should enter the system at the resolution layer.
It should not be patched into every command separately.
Practical rule for engineers
When changing Vix project resolution, keep this rule in mind:
CMake source directory is not always the user project directory.
Target name is not always the project folder name.This is the core lesson from vix.app.
For normal CMake projects, those values often look the same.
For generated projects, they are different.
Conclusion
vix.app project resolution is about keeping identities separate.
A vix.app project has:
a real user project directory
a generated CMake source directory
a manifest-defined target name
a generated flagCMake projects remain the full-control path.
vix.app projects become the simple path.
The resolver connects both models through one consistent result.
That consistency lets vix build, vix run, diagnostics, caching, and future native builds all reason about the project the same way.