Vix.cpp v2.9.0: clearer build ownership, reproducible dependencies, better networking, and mobile support
Vix.cpp v2.9.0 is out.
This release is less about adding more features and more about correcting boundaries that became less clear as Vix grew.
A recurring question during this release was:
Which layer should actually own this responsibility?
That question affected the build system, dependency management, HTTP networking, SDK packaging, and mobile support.
Build: stop duplicating the backend
Vix had gradually accumulated logic for scanning sources, headers, build state, and dependency information before invoking CMake and Ninja.
But Ninja already owns the concrete incremental compilation graph.
So in v2.9.0, the normal build path became simpler:
- Vix owns project intent, configuration, dependencies, toolchains, diagnostics, and CLI behavior
- CMake and Ninja own compilation, dependency tracking, and incremental execution
Ordinary vix build no longer prepares a second source/header graph before invoking the backend.
Options such as --verbose and --cmake-verbose also no longer affect configuration identity. Changing how much output you want should not create a different build configuration.
The principle is simple:
Vix should add value to the build, not add work to the build.
vix install can now work with ordinary CMake projects
This is one of the changes I find particularly important.
A project should not have to replace CMake just to get a better dependency workflow.
For example:
vix install https://github.com/vixcpp/async \
--tag v1.2.1 \
--target vix::async
Vix can record the dependency intent in vix.app:
[dependencies.async]
git = "https://github.com/vixcpp/async"
tag = "v1.2.1"
target = "vix::async"
and resolve it to an exact commit in vix.lock.
The project itself can remain completely normal CMake:
target_link_libraries(
my_project
PRIVATE
vix::async
)
Vix handles dependency intent, resolution, locking, integrity, and materialization.
CMake continues doing what CMake is good at.
We are already using this model in projects such as Vix Stress.
The distinction is important:
-
vix.appdescribes what the project wants -
vix.lockrecords exactly what was resolved
That gives us a reproducible dependency graph without forcing developers into a new build language.
vix::requests is more consistently asynchronous
An asynchronous API should not become synchronous halfway through an operation.
In v2.9.0, vix::requests keeps the asynchronous path asynchronous through:
- DNS resolution
- connection establishment
- TLS
- request writes
- response reads
Connection and request lifetimes were also hardened, and compatible HTTP/HTTPS connections can now be reused through an origin-scoped connection pool.
Responses can also stream decoded body bytes incrementally instead of always materializing the complete response in memory first.
This is already useful inside the Vix CLI, where large downloads can be written directly to disk.
We also moved more CLI networking away from external curl, wget, and PowerShell processes toward vix::requests.
Not because external tools are bad, but because Vix should not spawn another program for work its own networking layer can already perform.
SDK dependencies are becoming implementation details
Another question we asked was:
If a dependency exists only because a Vix module needs it internally, why should every user install and configure it separately?
Vix now bundles several dependencies with the relevant SDK capabilities:
- nlohmann-json
- fmt
- spdlog
- SQLite
- zlib
- Brotli
This makes the SDK contract much closer to what users actually consume.
OpenSSL is treated differently because it represents a platform capability for features that genuinely depend on it.
The broader rule is:
A capability that is not used should not impose a dependency.
SDK packaging is also driven more directly by the selected profile, rather than by whatever happened to be built for the CLI.
Android and iOS without replacing Android and iOS
vix::ui now includes Android and iOS project generation and build support.
Android projects still use Gradle and WebView.
iOS projects still use Xcode and WKWebView.
Vix provides a common application model and CLI experience, but it does not try to reimplement the native platform toolchains.
I think this distinction matters.
A useful abstraction should remove accidental complexity without pretending the underlying system no longer exists.
Testing the installed SDK, not only the repository
A source-tree build can hide packaging problems.
Users do not consume the Vix repository exactly as we do during development. They consume installed headers, libraries, exported CMake targets, transitive requirements, and SDK metadata.
So v2.9.0 expands validation around external consumer projects using the installed SDK.
This helped catch issues involving:
- exported target properties
- transitive dependencies
- platform-specific linkage
- public header contracts
- dependencies accidentally satisfied by the source tree
The installed SDK is increasingly treated as a first-class public contract.
What's next: Vix 3
v2.9.0 closes an important chapter for Vix 2.
The next step is Vix 3.
The goal is not to make Vix larger or to add another collection of modules.
It is an opportunity to revisit the foundations using everything we learned while building Vix 2.
That includes questions such as:
- how projects describe what they need
- how dependencies should be owned and distributed
- where the boundary between Vix and the C++ toolchain should live
- which common C++ workflows can be simplified without hiding C++ or the machine underneath
Some of that direction is already visible in v2.9.0.
The build has clearer ownership boundaries. vix install separates dependency intent from reproducible resolution. SDK dependencies are becoming capabilities instead of machine setup instructions. Installed artifacts are treated as part of the public contract.
Vix 3 will continue from those principles.
Full v2.9.0 release post:
https://www.vixcpp.com/blog/changelog/v2.9.0
GitHub:
Top comments (0)