Appearance
vix.app Registry Dependencies
vix.app can now declare dependencies from the Vix Registry directly in the application manifest.
The application stays simple. The dependency system stays explicit. The generated build keeps the native C++ integration underneath.
The problem
A C++ application often needs small external libraries. Without a higher-level manifest, the user usually has to manage several things manually:
text
where the dependency is installed
which include directory it exposes
which CMake target it exports
which transitive dependencies it needs
how the package is linked to the app targetThat is too much wiring for simple application projects. For vix.app, the user should describe the application. They should not have to maintain generated CMake glue by hand.
The new field
Registry dependencies are declared with deps.
Example:
text
name = api
type = executable
standard = c++20
sources = [
src/main.cpp,
]
deps = [
gk/email,
]This means:
text
the application depends on the Vix Registry package gk/emailThe user still installs dependencies with:
bash
vix installThen builds normally:
bash
vix buildField separation
vix.app now has several dependency-related fields, but they do not mean the same thing.
text
modules internal application modules created with vix modules
deps external packages from the Vix Registry
packages system or CMake packages resolved with find_package(...)
links raw CMake targets or libraries linked manuallyThis separation matters. A module is application code. A registry dependency is external package code. A package is a CMake discovery rule. A link is a target-level link instruction. Keeping these concepts separate makes the manifest predictable.
Example with modules and deps
A backend app can use both internal modules and registry dependencies:
text
name = api
type = executable
standard = c++20
output_dir = bin
sources = [
src/main.cpp,
src/api/app/AppBootstrap.cpp,
]
include_dirs = [
include,
src,
]
modules = [
User,
]
deps = [
gk/email,
]Here:
text
User is an internal application module
gk/email is an external registry dependencyThe generated CMake handles both, but the manifest keeps them visually separate.
The build flow
The dependency flow is:
text
vix.app
-> deps = [...]
-> vix.json / vix.lock
-> vix install
-> .vix/deps/
-> .vix/vix_deps.cmake
-> .vix/generated/app/CMakeLists.txt
-> CMake/Ninja buildvix.app declares the dependency. vix install installs the resolved packages. The generated vix_deps.cmake exposes CMake targets. The generated application CMake includes that file and links the declared dependencies.
Why vix install still matters
vix.app is declarative.
It does not fetch packages by itself. Dependency installation remains explicit:
bash
vix installThis keeps the build reproducible. It also keeps dependency installation separate from normal compilation. A missing dependency integration file gives a direct error:
text
vix.app dependencies are declared, but .vix/vix_deps.cmake was not found.
Run: vix installThat is better than letting CMake fail later with a confusing missing include or missing target.
Generated CMake integration
When deps is not empty, the generated application CMake includes:
cmake
include("/absolute/path/to/project/.vix/vix_deps.cmake")The path is absolute on purpose. The generated CMake project lives under:
text
.vix/generated/app/The dependency integration file lives under:
text
.vix/vix_deps.cmakeA relative include such as:
cmake
include(.vix/vix_deps.cmake)would be wrong because it would be resolved relative to the generated CMake directory, not the user project root. So Vix emits an absolute path.
Target convention
A registry dependency uses this canonical target convention:
text
namespace/name -> namespace::nameExample:
text
gk/email -> gk::emailSo this manifest:
text
deps = [
gk/email,
]is linked conceptually as:
cmake
target_link_libraries(api PRIVATE gk::email)The user does not need to write that manually in a vix.app project.
Header-only packages
Some registry packages are header-only. For those packages, Vix should not require a full CMake project. It can create an interface target:
cmake
add_library(gk::email INTERFACE)
target_include_directories(gk::email INTERFACE
/path/to/.vix/deps/gk.email/include
)The exact generated target may use an internal safe name and expose the public alias:
text
gk::emailThe important point is that the application can link the dependency by its canonical registry target.
Packages with CMakeLists.txt
Some packages include their own CMakeLists.txt. When the package is not header-only, Vix can load it with add_subdirectory(...). But header-only packages are handled differently. Even if a header-only package contains a CMakeLists.txt, Vix can safely expose it as an interface dependency. This avoids entering package CMake code that may be written for standalone builds.
Transitive dependencies
A registry package may depend on other registry packages.
Example:
text
gk/email
-> gk/jwt
-> gaspardkirira/hmacThe lock file contains the full resolved dependency graph. vix install installs all resolved dependencies and generates CMake integration for each one. That means the final project can have:
text
gk::email
gk::jwt
gaspardkirira::hmacavailable from .vix/vix_deps.cmake. The app manifest only needs to declare what the app uses directly:
text
deps = [
gk/email,
]The transitive packages are still installed and made available by the lock.
Why target fallback matters
A dependency can be installed correctly but still fail to link if no expected CMake target exists.
For example:
text
dependency: gk/email
expected target: gk::emailVix solves this by ensuring a stable target exists for header-only packages. That makes this work:
text
deps = [
gk/email,
]without asking the user to know the internal build details of gk/email.
Better errors
The generated CMake emits a stable Vix error marker when a declared dependency is not linkable. Instead of a generic CMake error like:
text
CMake configure failedVix can show:
text
error: vix.app dependency is not linkable
dependency: gk/email
target: gk::emailThis is important. The user should know that the dependency is installed, but the expected build target is missing. That is a Vix dependency integration problem, not a random CMake failure.
vix install output for vix.app projects
For a classic CMake project, vix install can tell the user to add:
cmake
include(.vix/vix_deps.cmake)
target_link_libraries(app PRIVATE ...)But for a vix.app project, that message is wrong.
The user should not edit CMakeLists.txt.
For vix.app, the correct next step is:
bash
vix buildSo the developer flow becomes:
bash
vix add @gk/email
vix install
vix buildNo manual CMake wiring is needed.
Example flow
A project starts with:
text
name = api
type = executable
standard = c++20
sources = [
src/main.cpp,
]
deps = [
gk/email,
]The user runs:
bash
vix installVix installs the dependencies:
text
gk/email
gk/jwt
gaspardkirira/hmacThen:
bash
vix buildThe app builds through the generated CMake project. The application manifest stays the source of truth.
Why this belongs in vix.app
The goal of vix.app is not to hide C++. The goal is to remove repetitive project wiring. Dependency declarations are application-level information. They belong in the application manifest. The user should be able to read one file and understand:
- what this app builds
- which sources it uses
- which internal modules it has
- which registry packages it depends on
- which system packages it needs
- which raw targets it links
That is the value of vix.app.
What stays explicit
vix.app does not remove explicitness.
It still keeps these concepts separate:
depsfor Vix Registry packagespackagesfor CMakefind_package(...)linksfor manual CMake targetsmodulesfor internal application modules
This avoids hidden magic.
If a dependency is from the Vix Registry, use deps. If it is a system dependency, use packages. If a target must be linked manually, use links. If it is application code, use modules.
Current design boundary
The current registry dependency integration still uses CMake underneath.
The flow is:
text
registry deps -> .vix/vix_deps.cmake -> generated CMake -> CMake/NinjaThis is still a compatibility layer. Later, Vix can use the same structured manifest and lockfile to build directly from a native build graph. The important part is that the manifest is now structured enough to support both paths.
Conclusion
vix.app can now describe registry dependencies directly.
The developer writes:
text
deps = [
gk/email,
]Vix installs the dependency graph. Vix generates the CMake integration. Vix links the declared dependency into the app target. The user does not edit generated CMake. This keeps the application manifest simple while still producing a normal native C++ build.