Repository navigation
Building vgl
This page explains how to build vgl from source: what you need installed, how to clone the
repository, the CMake presets, every VGL_* CMake option, where each dependency comes from,
static and shared builds, builds without exceptions and RTTI, running the tests, and notes for
Windows, Linux and macOS. For consuming a built or packaged vgl from your own project, see
Installing vgl. Builds for browsers and phones have pages of their own:
Web builds and Mobile platforms.
This page describes vgl 1.0. To use vgl without building it, see Installing vgl: release archives, vcpkg and Conan.
| Tool | Version | Notes |
|---|---|---|
| CMake | 3.24 or later | 3.25 or later to use CMakePresets.json (preset schema version 6, workflow presets) |
| C++ compiler | C++20 | A current MSVC, GCC, Clang or Apple Clang, the Android NDK's Clang, or Emscripten. CI uses the compilers of the windows-2025, ubuntu-24.04 and macos-15 runners |
| C compiler | C99 | vgl compiles stb_image and Zstandard as C; the C API headers are C99 |
| Ninja | any recent | Used by the Linux, macOS, Android, iOS and Emscripten presets (Ninja Multi-Config) |
| Network access | at configure time | Only for dependencies that are not installed (see Dependencies); turn VGL_FETCH_DEPENDENCIES off to forbid downloads |
Optional, depending on what you build:
-
Windows SDK
fxcfor the Direct3D 11 backend, which compiles its HLSL at build time. It ships with the Windows SDK that Visual Studio installs. If CMake cannot find it, the backend is skipped with a warning. -
libcurl for the defaults module's HTTP reader (
VGL_DEFAULTS_HTTP), or network access to let CMake download and build curl. -
GDAL 3.7 or later for the baker (
VGL_BUILD_BAKER). It is never downloaded. -
Ogre 14 for the Ogre backend (
VGL_BACKEND_OGRE), or network access to let CMake download and build Ogre 14.6.1. - X11 and Wayland development headers on Linux, when CMake downloads GLFW for the samples.
The library itself uses only the C and C++ standard libraries (design document, section 4). The runtime dependencies are stb_image and Zstandard, both compiled into vgl when they are downloaded.
git clone https://github.com/3dgep/vgl.git
cd vglThe repository has one submodule, wiki, which is this GitHub wiki checked out next to the
code so that its pages can be edited alongside it. It is not needed to build vgl, and a
plain git clone (without --recurse-submodules) is all you need. Contributors who edit the
wiki fetch it with git submodule update --init wiki.
The sample data in samples/data (about 30 MB of small packs baked by vgl's baker) is part of
the repository as ordinary files, so the samples and tests work offline after the clone.
Without presets, any generator works:
cmake -S . -B build
cmake --build build --config Release
ctest --test-dir build -C ReleaseWith presets, a workflow preset configures, builds and tests in one step:
cmake --list-presets=all
cmake --workflow --preset windows-msvc-static-release # on Windows
cmake --workflow --preset linux-gcc-static-release # on Linux
cmake --workflow --preset macos-clang-static-release # on macOSCMakePresets.json has the configurations CI builds. Every configure preset writes its build
tree to build/<preset> and installs to install/<preset>, exports compile_commands.json,
and turns VGL_WARNINGS_AS_ERRORS on. The multi-config generators put executables and DLLs in
build/<preset>/bin/<Config>, for example build/linux-gcc-static/bin/Release/vgl-headless.
Presets are only listed on the host they apply to (a condition on the host system, or on an
environment variable for the cross builds).
| Preset | Host | Generator | What it sets |
|---|---|---|---|
windows-msvc-static |
Windows | Newest Visual Studio | BUILD_SHARED_LIBS=OFF |
windows-msvc-shared |
Windows | Newest Visual Studio |
BUILD_SHARED_LIBS=ON, VGL_DEFAULTS_HTTP=ON
|
windows-msvc-noexcept |
Windows | Newest Visual Studio | VGL_DISABLE_EXCEPTIONS=ON |
windows-msvc-baker |
Windows | Newest Visual Studio | Static, VGL_BUILD_BAKER=ON, VGL_DEFAULTS_HTTP=ON, CMAKE_PREFIX_PATH=$env{CONDA_PREFIX}/Library (activate the conda-forge environment first) |
linux-gcc-static |
Linux | Ninja Multi-Config | GCC, BUILD_SHARED_LIBS=OFF
|
linux-gcc-shared |
Linux | Ninja Multi-Config | GCC, BUILD_SHARED_LIBS=ON, VGL_DEFAULTS_HTTP=ON
|
linux-gcc-noexcept |
Linux | Ninja Multi-Config | GCC, VGL_DISABLE_EXCEPTIONS=ON
|
linux-gcc-baker |
Linux | Ninja Multi-Config | GCC, static, VGL_BUILD_BAKER=ON, VGL_DEFAULTS_HTTP=ON
|
linux-clang-static |
Linux | Ninja Multi-Config | Clang, BUILD_SHARED_LIBS=OFF
|
linux-clang-shared |
Linux | Ninja Multi-Config | Clang, BUILD_SHARED_LIBS=ON, VGL_DEFAULTS_HTTP=ON
|
linux-clang-noexcept |
Linux | Ninja Multi-Config | Clang, VGL_DISABLE_EXCEPTIONS=ON
|
macos-clang-static |
macOS | Ninja Multi-Config | Apple Clang, BUILD_SHARED_LIBS=OFF
|
macos-clang-shared |
macOS | Ninja Multi-Config | Apple Clang, BUILD_SHARED_LIBS=ON
|
android-arm64 |
any, with ANDROID_NDK set |
Ninja Multi-Config | NDK toolchain, arm64-v8a, API 24, static; see Mobile platforms |
ios-arm64 |
macOS | Ninja Multi-Config | iOS arm64, deployment target 15.0, static; see Mobile platforms |
emscripten |
any, with EMSDK set |
Ninja Multi-Config | Emscripten toolchain, static, -pthread, VGL_DEFAULTS_HTTP=ON; see Web builds
|
Each configure preset has build and test presets named <preset>-debug and
<preset>-release (the baker presets and the cross builds have -release only), and a
workflow preset of the same name that runs configure, build and test in order. The Android and
iOS workflows configure and build only, since their tests need a device, emulator or
simulator.
# Configure once, then build and test separately.
cmake --preset linux-clang-shared
cmake --build --preset linux-clang-shared-release
ctest --preset linux-clang-shared-release
# Or all in one.
cmake --workflow --preset linux-clang-shared-releaseThe test presets show the output of failing tests and fail if no tests were found.
vgl's options all start with VGL_. Options that default to "top level" are on when vgl is
the top-level project and off when it is added to another project with add_subdirectory or
FetchContent, so that embedding vgl builds only the library.
| Option | Default | Meaning |
|---|---|---|
BUILD_SHARED_LIBS |
OFF |
Standard CMake option: build vgl, vgl-defaults, vgl-gl and vgl-d3d11 as shared libraries. The Ogre backend is always static |
VGL_BUILD_DEFAULTS |
ON |
Build the defaults module, vgl::defaults: a thread pool, a file reader, a disk cache and, with VGL_DEFAULTS_HTTP, an HTTP reader. The samples need it (Defaults module) |
VGL_DEFAULTS_HTTP |
OFF |
Give the defaults module an HTTP reader. Natively it uses libcurl (installed, or downloaded); with Emscripten it uses the browser's fetch and needs no library. Without it, vgl_http_reader_create returns VGL_RESULT_NOT_SUPPORTED
|
VGL_BACKEND_GL |
ON |
Build the OpenGL 3.3 / OpenGL ES 3.0 backend, vgl::gl (OpenGL backend) |
VGL_BACKEND_D3D11 |
ON on Windows |
Build the Direct3D 11 backend, vgl::d3d11 (Direct3D 11 backend). Not available elsewhere; skipped with a warning if fxc is not found |
VGL_BACKEND_OGRE |
OFF |
Build the Ogre backend, vgl::ogre, for classic Ogre 14 (Ogre backend) |
VGL_BUILD_BAKER |
OFF |
Build the baking tool vgl-bake (needs GDAL 3.7 or later) (Baker) |
VGL_BUILD_SAMPLES |
top level | Build the samples (Samples) |
VGL_BUILD_TESTS |
top level | Build the tests |
VGL_INSTALL |
top level | Generate install rules, the CMake package and the pkg-config files (Installing vgl) |
| Option | Default | Meaning |
|---|---|---|
VGL_DISABLE_EXCEPTIONS |
OFF |
Build the library targets without exceptions and RTTI (see below) |
VGL_WARNINGS_AS_ERRORS |
OFF |
Treat compiler warnings as errors (/WX or -Werror). Every preset turns it on |
| Option | Default | Meaning |
|---|---|---|
VGL_FETCH_DEPENDENCIES |
ON |
Download, at a pinned version with a checked hash, each dependency that is not installed. Off, a missing runtime dependency is a configure error, and parts that need a missing optional one (Ogre, GLFW, Dear ImGui) are skipped |
VGL_ZSTD_PROVIDER |
AUTO |
Where Zstandard comes from: AUTO (installed, else downloaded), SYSTEM (installed only; an error if none is found) or BUNDLED (always downloaded and compiled into vgl) |
| Option | Default | Meaning |
|---|---|---|
VGL_TEST_GL |
OFF |
Add the checks of the OpenGL, pure-C and Ogre samples as tests (gl, gl_es, gl_c, ogre_gl, ogre_d3d11). They need a display and an OpenGL driver; CI runs them under Xvfb with Mesa |
VGL_TEST_BROWSER |
OFF |
Emscripten builds only: add the browser test, which serves the OpenGL sample's page with Caddy and checks it in headless Chrome. VGL_CHROME and VGL_CADDY name the programs if they are not on the path |
Each dependency is looked for as an installed package first (system packages, vcpkg, conda or
anything on CMAKE_PREFIX_PATH), and otherwise downloaded with FetchContent at a pinned
version with a checked hash, unless VGL_FETCH_DEPENDENCIES is off. The configure output says
which was used, in lines that start with vgl:.
| Dependency | Used by | Installed package | Download |
|---|---|---|---|
| Zstandard | Runtime (decompression), baker (compression) | find_package(zstd 1.4 CONFIG) |
1.5.7, compiled into vgl with hidden symbols, no assembly, no multithreading |
| stb_image | Runtime (JPEG and PNG imagery tiles) |
stb_image.h found with find_path (for example Debian's libstb-dev or vcpkg's stb) |
2.30 at a pinned commit, compiled into vgl |
| libcurl | Defaults module's HTTP reader (VGL_DEFAULTS_HTTP), vgl-bake check
|
find_package(CURL) |
curl 8.11.1, static, HTTP and HTTPS only, on Schannel (Windows), Secure Transport (Apple) or OpenSSL (elsewhere) |
| Ogre | Ogre backend and sample (VGL_BACKEND_OGRE) |
find_package(OGRE 14 CONFIG), through OGRE_DIR or CMAKE_PREFIX_PATH
|
14.6.1, static, with only the OpenGL 3+ render system (and Direct3D 11 on Windows), RTSS, Bites, the overlay with Dear ImGui and the stb codec |
| GDAL | Baker only | find_package(GDAL 3.7) |
Never downloaded |
| nlohmann/json | Baker only | find_package(nlohmann_json 3.10 CONFIG) |
3.11.3 (headers) |
| GLFW | OpenGL, pure-C and Ogre samples | find_package(glfw3 3.3 CONFIG) |
3.4, static. With Emscripten, its GLFW port is used instead |
| Dear ImGui | Interactive samples' overlay | Never looked for | 1.92.9b; without VGL_FETCH_DEPENDENCIES, the OpenGL and Direct3D 11 samples are skipped |
Notes:
-
Zstandard. With an installed Zstandard, a static vgl passes the dependency on to its
consumers (
find_dependency(zstd CONFIG)in the package,Requires.private: libzstdinvgl.pc). A downloaded one is compiled in, and consumers need nothing. UseVGL_ZSTD_PROVIDER=BUNDLEDfor self-contained binaries (the release archives and the cross-build presets do) andSYSTEMfor package managers that must not download anything. -
libcurl. A downloaded curl is linked into
vgl-defaultsand not installed. An installed staticvgl-defaultswith the HTTP reader therefore needs an installed libcurl, which its CMake package finds withfind_dependency(CURL). On Linux, installlibcurl4-openssl-dev(Debian, Ubuntu) to avoid building curl. -
Ogre. Building Ogre the first time takes a while. A downloaded Ogre is part of vgl's build
tree and is not installed, so
vgl::ogreis installed only when vgl was built against an installed Ogre (Installing vgl). -
GDAL. On Linux, install it from the system packages (
libgdal-dev); on Windows, from conda-forge with the environment intools/baker/environment.yml. See Baker and the baker's README. -
Offline builds. Install Zstandard and stb_image (and libcurl, GLFW, Ogre as needed), then
configure with
-DVGL_FETCH_DEPENDENCIES=OFF. The interactive samples need Dear ImGui, which is only ever downloaded, so they are skipped; the headless sample still builds.
vgl builds as a static library by default, and as a shared one with BUILD_SHARED_LIBS=ON.
The core, the defaults module and the OpenGL and Direct3D 11 backends follow that setting; the
Ogre backend is always static, so that it shares the host's Ogre instead of holding a second
copy of Ogre's singletons.
A shared vgl exports only the C API (symbols are hidden by default, VGL_API marks the
exports). The macro VGL_SHARED tells the headers that the library is shared: on Windows
the declarations become __declspec(dllimport), elsewhere they get default visibility.
Consumers get it automatically:
- through CMake,
vgl::vglcarriesVGL_SHAREDin its interface compile definitions; - through pkg-config,
vgl.pchas-DVGL_SHAREDin itsCflags; - through Conan, the package defines it for shared builds.
If you link a shared vgl without any of those, define VGL_SHARED yourself before including
any vgl header. Never define it for a static vgl.
Things to know about each kind:
-
Static vgl is C++, so a C program that links it with the C linker also needs the C++
runtime. On Linux the
vgltarget linksstdc++andmfor you, andvgl.pclists them inLibs.private(usepkg-config --static). Apple's and Android's toolchains link libc++ themselves. -
Shared vgl on Windows puts
vgl.dll,vgl-defaults.dll,vgl-gl.dllandvgl-d3d11.dllnext to the executables in a top-level build (build/<preset>/bin/<Config>). Your own executables need the DLLs next to them; see Installing vgl. - The library version is
1.0.0, withSOVERSION1: the C ABI stays compatible within a major version, so the shared libraries arelibvgl.so.1andlibvgl.1.dylib. (Before 1.0, theSOVERSIONwas the major and minor version.)
vgl never lets an exception cross the API boundary, and its library targets build without
exceptions and RTTI when VGL_DISABLE_EXCEPTIONS is on (the *-noexcept presets). This is for
engines that compile everything with exceptions off.
cmake -S . -B build-noexcept -DVGL_DISABLE_EXCEPTIONS=ON
cmake --build build-noexcept --config ReleaseWhat it changes:
-
vgl,vgl-defaults,vgl-glandvgl-d3d11are compiled with/EHs-c- /GR-and_HAS_EXCEPTIONS=0on MSVC, or-fno-exceptions -fno-rttion GCC and Clang. - The tests, samples and the baker may still use exceptions; they are not affected.
- The Ogre backend keeps exceptions, because Ogre throws. It catches them at its interface, so nothing escapes into the host.
- The header-only C++ wrapper reports errors with
vgl::expected(std::expectedwhere the standard library has it, otherwise a minimal substitute that never throws), so it works in code built without exceptions too (C++ wrapper).
Tests are built when VGL_BUILD_TESTS is on (the default at the top level). Run them with
CTest, naming the configuration for multi-config generators. The Release tests are about four
times faster than Debug:
ctest --test-dir build/windows-msvc-static -C Release --output-on-failure
# or with a test preset
ctest --preset windows-msvc-static-release
# a subset, by name
ctest --preset windows-msvc-static-release -R "geodesy|tiling"| Test | What it covers | Built when |
|---|---|---|
foundation, common, geodesy, tiling, selection, mesh, image, pack, context, render
|
Internal unit tests (geodesy against GeographicLib reference values) | Always |
defaults |
Thread pool, file reader, disk cache | VGL_BUILD_DEFAULTS |
http |
HTTP reader against a small server on the loopback address |
VGL_DEFAULTS_HTTP, not Emscripten |
api_c, api_cpp
|
The C headers compile as C99 and the C++ wrapper as C++20, and both link against the library | Always |
headless |
The headless sample's --check on samples/data: loading, selection and frames without a GPU |
VGL_BUILD_SAMPLES |
d3d11 |
The Direct3D 11 sample's check, offscreen, on the hardware device or WARP | Windows, VGL_BUILD_SAMPLES
|
gl, gl_es, gl_c, ogre_gl, ogre_d3d11
|
Sample checks that need a display | VGL_TEST_GL |
baker, host_check
|
Baker on synthetic surfaces; vgl-bake check against a local server (needs libcurl) |
VGL_BUILD_BAKER |
browser |
The web page in headless Chrome | Emscripten, VGL_TEST_BROWSER
|
On Linux without a GPU, the OpenGL checks run on Mesa's software renderer under a virtual X server, as CI does:
sudo apt-get install xvfb libgl1-mesa-dri libglx-mesa0 libegl-mesa0
cmake --preset linux-gcc-shared -DVGL_TEST_GL=ON
cmake --build --preset linux-gcc-shared-release
LIBGL_ALWAYS_SOFTWARE=1 xvfb-run -a ctest --test-dir build/linux-gcc-shared -C Release --output-on-failureThe samples' checks expect the sample set in samples/data, which their tests name
explicitly.
-
Visual Studio with the "Desktop development with C++" workload, which includes the Windows SDK (for
fxc) and CMake. The Windows presets leave the generator out, so CMake uses the newest installed Visual Studio. Ninja works too, from a developer command prompt. -
The Direct3D 11 backend targets feature level 11_0 and links only
d3d11.lib. Its sample and test use WARP, the software rasterizer every Windows machine has, when there is no GPU. -
A static library from MSVC links only into builds with the same runtime (Debug or Release); build the configuration you link, or use a shared build.
-
The baker on Windows takes GDAL from conda-forge. Create and activate the environment, so that
CONDA_PREFIXis set, then use the baker preset:micromamba create -p D:\vgl-env -f tools\baker\environment.yml micromamba activate D:\vgl-env cmake --workflow --preset windows-msvc-baker-release
Keep that environment off
PATHfor ordinary builds: a re-configure can otherwise pick up its packages (such as its Zstandard DLL), and executables then fail to start.
-
The presets use Ninja Multi-Config with GCC (
linux-gcc-*) or Clang (linux-clang-*). -
The packages CI installs on Ubuntu 24.04 cover everything except the baker:
sudo apt-get install ninja-build libzstd-dev libcurl4-openssl-dev \ libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libwayland-dev libxkbcommon-devThe X11 and Wayland headers are for the GLFW that CMake downloads for the samples; with an installed GLFW (
libglfw3-dev) they are not needed. For the baker addlibgdal-devandnlohmann-json3-dev, and uselinux-gcc-baker. -
The minimum target is the glibc of Ubuntu 22.04, on x86_64 and aarch64 (design document, section 4).
-
Install the Xcode command line tools and Ninja (
brew install ninja), then usemacos-clang-staticormacos-clang-shared. -
The OpenGL backend runs on Apple's OpenGL 4.1 core profile. Apple ships no clip control, so the logarithmic depth convention applies. The Direct3D 11 backend is not built. The Ogre backend is not supported on macOS in version 1 (Ogre's Metal render system follows, as milestone M3b).
-
The supported minimum is macOS 11, as universal binaries (arm64 and x86_64). The macOS presets set
CMAKE_OSX_ARCHITECTUREStoarm64;x86_64andCMAKE_OSX_DEPLOYMENT_TARGETto11.0, and compile Zstandard in (VGL_ZSTD_PROVIDER=BUNDLED), since a universal build needs every library it links as a universal binary and Homebrew's have one architecture only. To build for the host's architecture alone, override the variable:cmake --preset macos-clang-static -DCMAKE_OSX_ARCHITECTURES=arm64 cmake --build --preset macos-clang-static-release
The HTTP reader links libcurl, so a universal build with
VGL_DEFAULTS_HTTPneeds a universal libcurl (or the downloaded one); this is not checked in CI.
vgl can be built as part of your own CMake project with add_subdirectory or FetchContent.
Tests, samples and install rules are then off by default, and the targets vgl::vgl,
vgl::defaults, vgl::gl, vgl::d3d11 and vgl::ogre are available under the same names as
in the installed package. See Installing vgl
for an example.
- Getting started: from a clone to a globe on screen
-
Installing vgl: packages,
find_package, pkg-config - Web builds and Mobile platforms
- Samples and Troubleshooting
- Design document, section 12.1
Getting vgl
Using the library
Rendering
Data
Reference
Specifications