Packages and Links
vix.app separates package discovery from linking.
This is important.
packages -> find_package(...)
links -> target_link_libraries(...)packages does not automatically link anything.
You use packages to ask CMake to find a package.
You use links to choose what targets or libraries your target should link against.
Basic rule
Correct:
packages = [
fmt:REQUIRED,
]
links = [
fmt::fmt,
]Incorrect:
packages = [
fmt:REQUIRED,
]The incorrect version finds fmt, but it does not link fmt::fmt.
packages
The packages field generates find_package(...) calls in the internal CMake project.
Example:
packages = [
Threads:REQUIRED,
fmt:REQUIRED,
]This means Vix generates something equivalent to:
find_package(Threads REQUIRED)
find_package(fmt REQUIRED)links
The links field generates target_link_libraries(...).
Example:
links = [
Threads::Threads,
fmt::fmt,
]This means Vix generates something equivalent to:
target_link_libraries(myapp PRIVATE
Threads::Threads
fmt::fmt
)Why packages and links are separate
CMake packages can expose different target names.
For example, a package can be found with:
find_package(fmt REQUIRED)but the target to link is usually:
fmt::fmtAnother package can be found with:
find_package(Boost REQUIRED COMPONENTS system filesystem)but the targets to link can be:
Boost::system
Boost::filesystemBecause package names and target names are not always the same, vix.app keeps them separate.
Supported package syntax
packages supports these forms:
<name>
<name>:REQUIRED
<name>:COMPONENTS=a,b
<name>:COMPONENTS=a,b:REQUIREDSimple package
packages = [
Threads,
]Generates:
find_package(Threads)Required package
packages = [
Threads:REQUIRED,
]Generates:
find_package(Threads REQUIRED)Package with components
packages = [
"Boost:COMPONENTS=system,filesystem",
]Generates:
find_package(Boost COMPONENTS system filesystem)Required package with components
packages = [
"Boost:COMPONENTS=system,filesystem:REQUIRED",
]Generates:
find_package(Boost REQUIRED COMPONENTS system filesystem)Why some package values are quoted
Values that contain commas should be quoted.
Correct:
packages = [
"Boost:COMPONENTS=system,filesystem:REQUIRED",
]If you do not quote a value containing commas, the manifest parser may treat it as multiple array items.
Threads example
Project layout:
threaded-app/
vix.app
src/
main.cppvix.app:
name = threaded_app
type = executable
standard = c++20
sources = [
src/main.cpp,
]
packages = [
Threads:REQUIRED,
]
links = [
Threads::Threads,
]src/main.cpp:
#include <vix.hpp>
#include <thread>
int main()
{
std::thread worker([] {
vix::print("Hello from a thread");
});
worker.join();
return 0;
}Build and run:
vix build
vix runfmt example
This example assumes fmt is available to CMake on your system.
vix.app:
name = fmt_app
type = executable
standard = c++20
sources = [
src/main.cpp,
]
packages = [
fmt:REQUIRED,
]
links = [
fmt::fmt,
]src/main.cpp:
#include <fmt/core.h>
int main()
{
fmt::print("Hello from fmt\n");
return 0;
}Build and run:
vix build
vix runBoost example
This example assumes Boost is installed and available to CMake.
vix.app:
name = boost_app
type = executable
standard = c++20
sources = [
src/main.cpp,
]
packages = [
"Boost:COMPONENTS=system,filesystem:REQUIRED",
]
links = [
Boost::system,
Boost::filesystem,
]src/main.cpp:
#include <vix.hpp>
#include <boost/filesystem.hpp>
int main()
{
boost::filesystem::path path = ".";
vix::print("Current path:", path.string());
return 0;
}Build and run:
vix build
vix runSystem libraries
You can link simple system libraries directly with links.
Example on Linux:
links = [
m,
]This links the math library.
Complete example:
name = math_app
type = executable
standard = c++20
sources = [
src/main.cpp,
]
links = [
m,
]src/main.cpp:
#include <vix.hpp>
#include <cmath>
int main()
{
vix::print("sqrt(25) =", std::sqrt(25.0));
return 0;
}Local CMake targets
If your generated project has access to a local target, you can list it under links.
Example:
links = [
my_local_lib,
]For vix.app V1, the recommended approach is still one manifest per target.
For multiple related targets, use either:
- one vix.app project per target
- or a normal CMakeLists.txt for full controlHeader-only libraries
Header-only libraries usually do not need linking.
They usually only need an include directory.
Example:
name = header_app
type = executable
standard = c++20
sources = [
src/main.cpp,
]
include_dirs = [
third_party/some_header_lib/include,
]No links field is needed if the library is truly header-only.
Package found but target not linked
A common mistake is to write:
packages = [
fmt:REQUIRED,
]and expect the target to link automatically.
This is not enough.
You still need:
links = [
fmt::fmt,
]Correct complete version:
packages = [
fmt:REQUIRED,
]
links = [
fmt::fmt,
]Imported target not found
If the build fails with an error similar to:
Target "myapp" links to:
fmt::fmt
but the target was not found.It usually means one of these things:
- the package was not found
- the package was found but does not export that target name
- the target name is different on your system
- you forgot to add the package under packagesCheck the package documentation to confirm the imported target name.
Package not found
If CMake cannot find a package, you may see an error like:
Could not find a package configuration file provided by "fmt"This means CMake cannot locate the package.
Possible fixes:
- install the package
- set CMAKE_PREFIX_PATH
- use your system package manager
- use a normal CMakeLists.txt if the dependency needs custom setupYou can pass extra CMake arguments after --:
vix build -- -DCMAKE_PREFIX_PATH=/path/to/prefixUsing CMAKE_PREFIX_PATH
Some packages are installed in custom locations.
Example:
vix build -- -DCMAKE_PREFIX_PATH=/opt/fmtor:
vix build -- -DCMAKE_PREFIX_PATH=$HOME/localThis helps CMake find packages installed outside the default system paths.
Multiple packages
You can list several packages:
packages = [
Threads:REQUIRED,
fmt:REQUIRED,
"Boost:COMPONENTS=system,filesystem:REQUIRED",
]And link their imported targets:
links = [
Threads::Threads,
fmt::fmt,
Boost::system,
Boost::filesystem,
]Complete example:
name = network_app
type = executable
standard = c++20
sources = [
src/main.cpp,
]
packages = [
Threads:REQUIRED,
fmt:REQUIRED,
"Boost:COMPONENTS=system,filesystem:REQUIRED",
]
links = [
Threads::Threads,
fmt::fmt,
Boost::system,
Boost::filesystem,
]Using link options
link_options is different from links.
Use links for libraries and targets:
links = [
fmt::fmt,
Threads::Threads,
]Use link_options for linker flags:
link_options = [
"-Wl,--as-needed",
]Complete example:
name = linked_app
type = executable
standard = c++20
sources = [
src/main.cpp,
]
packages = [
fmt:REQUIRED,
]
links = [
fmt::fmt,
]
link_options = [
"-Wl,--as-needed",
]Recommended pattern
For every external dependency, think in two steps.
Step 1: find the package.
packages = [
fmt:REQUIRED,
]Step 2: link the target.
links = [
fmt::fmt,
]Final:
packages = [
fmt:REQUIRED,
]
links = [
fmt::fmt,
]When to use CMakeLists.txt instead
Use a normal CMakeLists.txt when dependency setup requires complex CMake logic.
Examples:
- FetchContent
- CPM.cmake
- custom find modules
- generated dependency targets
- platform-specific package logic
- optional dependency graphs
- multiple dependency variantsvix.app is designed to keep common cases simple.
For advanced dependency control, CMake is still the right tool.
Summary
packages:
finds packages with find_package(...)
links:
links libraries or imported targets with target_link_libraries(...)
compile_options:
compiler flags
link_options:
linker flagsThe safest pattern is:
packages = [
SomePackage:REQUIRED,
]
links = [
SomePackage::SomeTarget,
]Next steps
Continue with: