Project Types
vix.app supports the most common C++ target types.
A target type tells Vix what kind of build output should be generated.
type = executabletype = statictype = sharedtype = libraryFor most projects, you will use either:
executable -> application
static -> static library
shared -> shared libraryDefault type
If type is not provided, Vix uses:
type = executableSo this:
name = hello
standard = c++20
sources = [
src/main.cpp,
]is equivalent to:
name = hello
type = executable
standard = c++20
sources = [
src/main.cpp,
]Executable projects
Use executable when your project builds an application.
name = hello
type = executable
standard = c++20
sources = [
src/main.cpp,
]This creates an executable target named:
helloTypical layout:
hello/
vix.app
src/
main.cppsrc/main.cpp:
#include <vix.hpp>
int main()
{
vix::print("Hello from vix.app");
return 0;
}Build and run:
vix build
vix runExecutable with multiple files
A real application usually has more than one source file.
myapp/
vix.app
include/
myapp/
app.hpp
src/
main.cpp
app.cppvix.app:
name = myapp
type = executable
standard = c++20
sources = [
src/main.cpp,
src/app.cpp,
]
include_dirs = [
include,
]include/myapp/app.hpp:
#pragma once
namespace myapp
{
int run();
}src/app.cpp:
#include <vix.hpp>
#include <myapp/app.hpp>
namespace myapp
{
int run()
{
vix::print("myapp running");
return 0;
}
}src/main.cpp:
#include <myapp/app.hpp>
int main()
{
return myapp::run();
}Static library projects
Use static when your project builds a static library.
name = mathlib
type = static
standard = c++20
sources = [
src/add.cpp,
src/mul.cpp,
]
include_dirs = [
include,
]This creates a static library target named:
mathlibTypical layout:
mathlib/
vix.app
include/
mathlib/
math.hpp
src/
add.cpp
mul.cppinclude/mathlib/math.hpp:
#pragma once
namespace mathlib
{
int add(int a, int b);
int mul(int a, int b);
}src/add.cpp:
#include <mathlib/math.hpp>
namespace mathlib
{
int add(int a, int b)
{
return a + b;
}
}src/mul.cpp:
#include <mathlib/math.hpp>
namespace mathlib
{
int mul(int a, int b)
{
return a * b;
}
}Build:
vix buildStatic library aliases
The following values are accepted for static libraries:
type = statictype = static-libraryUse static for shorter manifests.
Recommended:
type = staticShared library projects
Use shared when your project builds a shared library.
name = plugin
type = shared
standard = c++20
sources = [
src/plugin.cpp,
]
include_dirs = [
include,
]This creates a shared library target named:
pluginTypical layout:
plugin/
vix.app
include/
plugin/
plugin.hpp
src/
plugin.cppinclude/plugin/plugin.hpp:
#pragma once
namespace plugin
{
const char *name();
}src/plugin.cpp:
#include <plugin/plugin.hpp>
namespace plugin
{
const char *name()
{
return "plugin";
}
}Build:
vix buildShared library aliases
The following values are accepted for shared libraries:
type = sharedtype = shared-libraryUse shared for shorter manifests.
Recommended:
type = sharedLibrary projects
library is also supported.
name = core
type = library
standard = c++20
sources = [
src/core.cpp,
]
include_dirs = [
include,
]Use library when you want the default library behavior supported by Vix.
For clearer intent, prefer one of these when possible:
type = staticor:
type = sharedChoosing the right type
Use this rule:
executable -> the target has main()
static -> reusable code linked into another target
shared -> dynamic library loaded or linked at runtime
library -> generic library targetExecutable vs library
An executable usually has a main() function.
Example:
int main()
{
return 0;
}A library usually does not have main().
Example:
namespace mathlib
{
int add(int a, int b)
{
return a + b;
}
}If you put main() in a static or shared library target, it usually means your project structure should be changed.
Testing a library
For vix.app V1, use a separate test manifest.
Example:
mathlib/
vix.app
include/
mathlib/
math.hpp
src/
add.cpp
tests/
vix.app
test_add.cppRoot vix.app:
name = mathlib
type = static
standard = c++20
sources = [
src/add.cpp,
]
include_dirs = [
include,
]tests/vix.app:
name = mathlib_tests
type = executable
standard = c++20
sources = [
test_add.cpp,
../src/add.cpp,
]
include_dirs = [
../include,
]Run tests:
cd tests
vix runApplication with internal library-style code
For applications, it is better to keep main.cpp small.
Recommended:
myapp/
vix.app
include/
myapp/
app.hpp
src/
main.cpp
app.cppvix.app:
name = myapp
type = executable
standard = c++20
sources = [
src/main.cpp,
src/app.cpp,
]
include_dirs = [
include,
]src/main.cpp should only start the application:
#include <myapp/app.hpp>
int main()
{
return myapp::run();
}This makes your project easier to test.
Examples as separate targets
Since vix.app describes one target, the recommended approach is one folder per example.
examples/
hello/
vix.app
src/
main.cpp
threads/
vix.app
src/
main.cpp
resources/
vix.app
src/
main.cpp
assets/
config.jsonBuild one example:
cd examples/hello
vix runThis keeps each example independent and simple.
Multiple targets
vix.app is intentionally simple.
It describes one target.
For multiple targets, use one of these approaches:
- one folder with one vix.app per target
- a normal CMakeLists.txt for full multi-target controlRecommended for simple projects:
workspace/
apps/
server/
vix.app
src/
main.cpp
client/
vix.app
src/
main.cpp
libs/
mathlib/
vix.app
src/
add.cpp
include/
mathlib/
math.hppFor advanced multi-target projects, use CMakeLists.txt.
Type and output name
The name field defines the target name.
The type field defines what kind of target is generated.
Example:
name = hello
type = executableThis creates an executable target named:
helloExample:
name = mathlib
type = staticThis creates a static library target named:
mathlibType and vix run
vix run is mainly useful for executable targets.
For this manifest:
name = hello
type = executable
standard = c++20
sources = [
src/main.cpp,
]you can run:
vix runFor this manifest:
name = mathlib
type = static
standard = c++20
sources = [
src/add.cpp,
]vix build is the main command:
vix buildIf you want to run tests for a library, create a test executable under tests/vix.app.
Type and resources
Resources are usually useful for executables.
Example:
name = asset_app
type = executable
standard = c++20
output_dir = bin
sources = [
src/main.cpp,
]
resources = [
assets,
]For libraries, resources are less common.
Type and packages
All project types can use packages and links.
Executable:
name = threaded_app
type = executable
standard = c++20
sources = [
src/main.cpp,
]
packages = [
Threads:REQUIRED,
]
links = [
Threads::Threads,
]Static library:
name = core
type = static
standard = c++20
sources = [
src/core.cpp,
]
packages = [
Threads:REQUIRED,
]
links = [
Threads::Threads,
]Shared library:
name = plugin
type = shared
standard = c++20
sources = [
src/plugin.cpp,
]
packages = [
Threads:REQUIRED,
]
links = [
Threads::Threads,
]Common mistakes
Using executable for a library
Incorrect:
name = mathlib
type = executable
sources = [
src/add.cpp,
]If src/add.cpp does not provide main(), the link step will fail.
Correct:
name = mathlib
type = static
sources = [
src/add.cpp,
]Using static for an app
Incorrect:
name = hello
type = static
sources = [
src/main.cpp,
]If your target is meant to run, use:
type = executableTesting by adding main.cpp twice
Incorrect test manifest:
sources = [
test_app.cpp,
../src/main.cpp,
../src/app.cpp,
]This can cause duplicate main() errors.
Correct:
sources = [
test_app.cpp,
../src/app.cpp,
]Recommended patterns
CLI application
cli-tool/
vix.app
src/
main.cppname = cli_tool
type = executable
standard = c++20
sources = [
src/main.cpp,
]Application with internal logic
myapp/
vix.app
include/
myapp/
app.hpp
src/
main.cpp
app.cppname = myapp
type = executable
standard = c++20
sources = [
src/main.cpp,
src/app.cpp,
]
include_dirs = [
include,
]Static library
mathlib/
vix.app
include/
mathlib/
math.hpp
src/
add.cpp
mul.cppname = mathlib
type = static
standard = c++20
sources = [
src/add.cpp,
src/mul.cpp,
]
include_dirs = [
include,
]Shared library
plugin/
vix.app
include/
plugin/
plugin.hpp
src/
plugin.cppname = plugin
type = shared
standard = c++20
sources = [
src/plugin.cpp,
]
include_dirs = [
include,
]When to use CMakeLists.txt
Use CMakeLists.txt when you need:
- many targets in one project
- complex target dependencies
- generated source files
- custom commands
- CTest integration
- install rules
- advanced packaging
- platform-specific build logicvix.app is best for one clear target.
CMake is still the compatibility path for advanced build systems.
Summary
type = executable
build an application
type = static
build a static library
type = shared
build a shared library
type = library
build a generic library targetRecommended rule:
Use vix.app for one simple target.
Use CMakeLists.txt for complex multi-target projects.Next steps
Continue with: