vix.app
Experimental
vix.app is an experimental Vix feature.
It is available for testing and design feedback, but it is not production-ready yet. The file format, fields, generated CMake behavior, and registry dependency integration may change before stabilization.
vix.app is a simple application manifest for C++ projects built with Vix.
It lets small and medium C++ apps start without writing a visible CMakeLists.txt.
Vix reads vix.app, generates an internal CMake project, then uses CMake and Ninja underneath to build and run the app.
Goal
vix.app is designed for projects that need a simple entry point:
vix run
vix buildwithout requiring the user to write CMake manually.
The generated CMake project stays internal:
.vix/generated/app/CMakeLists.txtThis means the user gets a simple project format, while Vix keeps the power of the C++ build ecosystem underneath.
What vix.app does
vix.app describes:
- the application name
- the target type
- the C++ standard
- source files
- include directories
- compile definitions
- linked libraries or CMake targets
Example:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp",
"hello.cpp"
]
include_dirs = [
"include"
]
defines = [
"DEMO_APP=1"
]
links = [
"vix::core"
]Then run:
vix runVix generates CMake internally, builds the app, and runs the executable.
What vix.app does not replace
vix.app does not replace vix.json.
They have different roles.
| File | Role |
|---|---|
vix.app | Describes the C++ application target. |
vix.json | Describes project metadata, registry dependencies, tasks, and workflows. |
vix.lock | Stores resolved dependency versions. |
.vix/ | Stores generated files, installed dependencies, cache data, and internal metadata. |
The rule is simple:
vix.app= app build descriptionvix.json= registry, tasks, workflows, project metadata
Detection order
Vix keeps existing project behavior intact.
The resolution order is:
1. If CMakeLists.txt exists
-> use the existing CMake project
2. Else if vix.app exists
-> generate an internal CMake project
3. Else if a single .cpp file is passed
-> use single-file mode
4. Else
-> show a clear errorThis means vix.app is only used when there is no CMakeLists.txt.
Existing CMake projects keep working as before.
Minimal project
Project structure:
demo/
├── main.cpp
└── vix.appmain.cpp:
#include <iostream>
int main()
{
std::cout << "Hello from Vix app\n";
return 0;
}vix.app:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp"
]Run:
vix runExpected output:
Hello from Vix appMulti-file project
Project structure:
demo/
├── main.cpp
├── hello.cpp
├── include/
│ └── hello.hpp
└── vix.appinclude/hello.hpp:
#ifndef DEMO_HELLO_HPP
#define DEMO_HELLO_HPP
void say_hello();
#endifhello.cpp:
#include "hello.hpp"
#include <vix/print.hpp>
void say_hello()
{
vix::print("Hello from hello.cpp");
}main.cpp:
#include "hello.hpp"
#include <vix/print.hpp>
int main()
{
vix::print("Hello from main.cpp");
say_hello();
return 0;
}vix.app:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp",
"hello.cpp"
]
include_dirs = [
"include"
]Run:
vix runExpected output:
Hello from main.cpp
Hello from hello.cppGenerated CMake
For the previous example, Vix generates an internal file similar to this:
# Auto-generated by Vix from vix.app
# Do not edit this file directly.
cmake_minimum_required(VERSION 3.24)
project(demo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(demo
"/absolute/path/to/main.cpp"
"/absolute/path/to/hello.cpp"
)
target_include_directories(demo PRIVATE
"/absolute/path/to/include"
)The generated file is stored under:
.vix/generated/app/CMakeLists.txtUsers should not edit this file directly.
Edit vix.app instead.
Commands
Build the app
vix buildFor a vix.app project, Vix does this internally:
vix.app
-> .vix/generated/app/CMakeLists.txt
-> cmake -S .vix/generated/app -B build-ninja -G Ninja
-> cmake --build build-ninjaRun the app
vix runFor a vix.app project, Vix does this internally:
vix.app
-> generate CMake
-> build
-> run build-ninja/<target>Single-file mode still works
vix run main.cppThis keeps the existing script mode behavior.
Use this for quick experiments or one-file programs.
Use vix.app when the app has multiple source files or needs includes, definitions, links, or registry dependencies.
Fields
name
Required.
Defines the CMake project name and default target name.
name = "demo"Valid examples:
name = "api"
name = "hello"
name = "softadastra_agent"The name should be simple and filesystem-friendly.
type
Optional.
Default:
type = "executable"Supported values:
type = "executable"
type = "static"
type = "static-library"
type = "shared"
type = "shared-library"
type = "library"Recommended value for apps:
type = "executable"Example:
name = "demo"
type = "executable"standard
Optional.
Default:
standard = "c++20"Supported values:
standard = "c++11"
standard = "c++14"
standard = "c++17"
standard = "c++20"
standard = "c++23"
standard = "c++26"Recommended default:
standard = "c++20"sources
Required.
Lists source files for the app.
sources = [
"main.cpp",
"hello.cpp"
]Paths are relative to the project directory.
You can also use files inside src/:
sources = [
"src/main.cpp",
"src/server.cpp",
"src/routes.cpp"
]include_dirs
Optional.
Lists include directories.
include_dirs = [
"include"
]This generates:
target_include_directories(<target> PRIVATE ...)Example project:
demo/
├── include/
│ └── demo/server.hpp
├── src/
│ ├── main.cpp
│ └── server.cpp
└── vix.appvix.app:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"src/main.cpp",
"src/server.cpp"
]
include_dirs = [
"include"
]defines
Optional.
Lists preprocessor definitions.
defines = [
"DEMO_APP=1",
"VIX_USE_FAST_PATH"
]This generates:
target_compile_definitions(<target> PRIVATE ...)Example:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp"
]
defines = [
"APP_ENV=\"dev\"",
"ENABLE_LOGS=1"
]links
Optional.
Lists libraries or CMake targets linked by the app.
links = [
"vix::core",
"vix::json"
]This generates:
target_link_libraries(<target> PRIVATE ...)Use this field for:
- Vix modules
- registry package targets
- local CMake targets exposed through generated dependency files
- system libraries when appropriate
Example:
name = "api"
type = "executable"
standard = "c++20"
sources = [
"src/main.cpp"
]
links = [
"vix::core",
"vix::json"
]Registry dependencies
Registry dependencies stay in vix.json and vix.lock.
vix.app only consumes the targets after they are installed.
Typical flow:
vix add softadastra/kordex-runtime
vix install
vix runThe project keeps dependency metadata in:
vix.jsonvix.lock
The installed dependency files live under:
.vix/The generated CMake project can include dependency integration files from .vix/, then links can reference the exposed CMake targets.
Example vix.app:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"src/main.cpp"
]
links = [
"softadastra::kordex-runtime"
]The important separation is:
vix.jsonhandles dependency declaration.vix.lockhandles resolved versions.vix.applinks the final targets used by the app.
Recommended project layout
For a simple app:
demo/
├── src/
│ ├── main.cpp
│ └── app.cpp
├── include/
│ └── demo/
│ └── app.hpp
├── vix.app
├── vix.json
└── vix.lockRecommended vix.app:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"src/main.cpp",
"src/app.cpp"
]
include_dirs = [
"include"
]Full REST API example
Project structure:
rest-api/
├── src/
│ └── main.cpp
└── vix.appvix.app:
name = "rest_api"
type = "executable"
standard = "c++20"
sources = [
"src/main.cpp"
]
links = [
"vix::core"
]src/main.cpp:
#include <vix.hpp>
using namespace vix;
int main()
{
App app;
app.get("/", [](Request &, Response &res){
res.json({
"message", "Hello from Vix",
"framework", "Vix.cpp"
});
});
app.get("/health", [](Request &, Response &res){
res.json({
"ok", true,
"service", "rest_api"
});
});
app.run(8080);
return 0;
}Run:
vix runTest:
curl -i http://127.0.0.1:8080/
curl -i http://127.0.0.1:8080/healthvix.app vs CMakeLists.txt
Use vix.app when:
- the app is small or medium-sized
- you want a fast start
- you want to avoid writing CMake manually
- your app has a simple executable target
- your app has a few source files
- your app links registry dependencies through Vix
Use CMakeLists.txt when:
- the project has advanced build logic
- the project has many targets
- the project needs custom CMake functions
- the project needs advanced install rules
- the project needs custom toolchains or platform-specific build logic
- the project is a library intended for complex packaging
The rule is:
vix.appfor simple app description.CMakeLists.txtfor advanced build control.
If both files exist, CMakeLists.txt wins.
Generated files
A vix.app project may create:
.vix/generated/app/CMakeLists.txt
build-ninja/
build-dev/
build-release/These are internal or build output paths.
Recommended .gitignore:
build/
build-*/
.vix/generated/
.vix/cache/
.vix/runs/Depending on how the project handles dependencies, some .vix/ dependency files may be local build state and should not be committed.
Common workflows
Create a simple app manually
mkdir demo
cd demo
cat > main.cpp <<'CPP'
#include <vix/print.hpp>
int main()
{
vix::print("Hello from Vix app");
return 0;
}
CPP
cat > vix.app <<'EOF'
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp"
]
EOF
vix runAdd another source file
cat > hello.cpp <<'CPP'
#include <vix/print.hpp>
void say_hello()
{
vix::print("Hello from hello.cpp");
}
CPPUpdate main.cpp:
#include <iostream>
void say_hello();
int main()
{
vix::print("Hello from main.cpp");
say_hello();
return 0;
}Update vix.app:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp",
"hello.cpp"
]Run:
vix runAdd an include directory
demo/
├── include/
│ └── hello.hpp
├── main.cpp
├── hello.cpp
└── vix.appvix.app:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp",
"hello.cpp"
]
include_dirs = [
"include"
]Add registry dependencies
vix add namespace/package
vix installThen link the target exposed by the package:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"src/main.cpp"
]
links = [
"namespace::package"
]Run:
vix runError messages
Missing vix.app
If no CMakeLists.txt and no vix.app exist, Vix cannot resolve a project.
Fix:
vix run main.cppor create vix.app:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp"
]Missing sources
Invalid:
name = "demo"
type = "executable"
standard = "c++20"Fix:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp"
]Wrong source path
Invalid:
sources = [
"src/missing.cpp"
]Fix the path or create the file.
Unknown link target
Invalid:
links = [
"missing::target"
]Fix:
- install the dependency
- check
vix.lock - check the target name exposed by the package
- check
.vix/dependency integration files - update the
linksfield
Best practices
Keep vix.app small.
Recommended:
name = "api"
type = "executable"
standard = "c++20"
sources = [
"src/main.cpp",
"src/routes.cpp",
"src/server.cpp"
]
include_dirs = [
"include"
]
links = [
"vix::core"
]- Avoid turning
vix.appinto a full build system. - Do not put registry metadata in
vix.app. - Keep dependencies in
vix.json. - Keep resolved versions in
vix.lock. - Use
CMakeLists.txtwhen the app becomes advanced enough to need custom build logic.
Reference
Complete field reference:
| Field | Required | Default | Purpose |
|---|---|---|---|
name | yes | none | Target and project name. |
type | no | executable | Target type. |
standard | no | c++20 | C++ language standard. |
sources | yes | none | Source files. |
include_dirs | no | empty | Include directories. |
defines | no | empty | Compile definitions. |
links | no | empty | Libraries or CMake targets. |
Supported target types:
| Value | Meaning |
|---|---|
executable | Builds an executable app. |
static | Builds a static library. |
static-library | Builds a static library. |
shared | Builds a shared library. |
shared-library | Builds a shared library. |
library | Builds a static library by default. |
Supported standards:
| Value |
|---|
c++11 |
c++14 |
c++17 |
c++20 |
c++23 |
c++26 |
Summary
vix.app gives Vix a simple project-level entry point for C++ apps.
The user writes:
name = "demo"
type = "executable"
standard = "c++20"
sources = [
"main.cpp",
"hello.cpp"
]Then runs:
vix runVix handles:
- manifest parsing
- CMake generation
- configure
- build
- run
The result is a lighter first experience for C++ apps, while keeping CMake and Ninja underneath for the real build work.