8. Building and Integration

8.1. CMake options

Package options

Option

Default

Purpose

XMLIO_BUILD_TESTS

Top-level builds

Build and register the unit tests.

XMLIO_BUILD_EXAMPLES

Top-level builds

Build the examples included in this manual.

XMLIO_BUILD_DOCUMENTATION

Off

Add Doxygen, HTML, and PDF documentation targets.

XMLIO_BUILD_PDF_DOCUMENTATION

On

Include the PDF target when documentation is enabled.

XMLIO_WARNINGS_AS_ERRORS

Off

Promote compiler warnings from xmlio targets to errors.

Tests and examples default on when xmlio is configured directly and off when it is included with add_subdirectory.

8.2. Complete developer build

The package script creates a fresh build, compiles with warnings as errors, runs all tests and examples, installs the package into a temporary staging prefix, and verifies that a separate CMake project can consume it:

./scripts/build.sh

Documentation is intentionally optional so a routine build does not require Doxygen, Sphinx, or LaTeX. Pass --docs to perform the same checks and also generate both manuals:

./scripts/build.sh --docs

In documentation mode, the script maintains a package-local Python environment for Sphinx. Set PYTHON to select the interpreter used to create .venv-docs. This environment is not inspected or created by a normal build. Use ./scripts/build.sh --help for the concise command summary. Select a different build tree with --build-dir:

./scripts/build.sh --build-dir build-clang

XMLIO_BUILD_DIR provides the equivalent environment setting. The command-line option takes precedence when both are present.

The generated manuals are:

build/docs/html/index.html
build/docs/latex/xmlio.pdf

The paths above are refreshed only by a --docs build. Individual xmlio_docs_html and xmlio_docs_pdf targets are available after documentation has been enabled when only one format is needed.

8.3. Choosing a compiler and build directory

The compiler and build directory are independent choices. CXX selects the C++ compiler, while XMLIO_BUILD_DIR selects where CMake places generated files, object files, executables, tests, and manuals. Neither changes where the library is eventually installed.

For example, build with Clang in a directory named build-clang:

CXX=clang++ XMLIO_BUILD_DIR=build-clang ./scripts/build.sh

Or build with an installed GNU compiler in a separate directory:

CXX=g++-VERSION XMLIO_BUILD_DIR=build-gcc ./scripts/build.sh

Replace g++-VERSION with the executable available on the system, such as a versioned compiler installed by a package manager. On macOS, the unversioned g++ command may invoke Apple Clang rather than GNU GCC. The CMake configure output reports The CXX compiler identification and should always be checked when comparing compilers.

Separate build directories allow Clang and GCC builds to coexist without overwriting one another. The package script configures with cmake --fresh, so each invocation selects the compiler from scratch. For a manual CMake build, the equivalent configuration is:

cmake --fresh -S . -B build-clang \
  -DCMAKE_CXX_COMPILER=clang++
cmake --build build-clang --parallel

Without --fresh, CMake retains the compiler previously selected for an existing build directory. Starting with a new build directory is therefore the simplest and least surprising way to change compilers.

8.4. HTML-only builds

Hosted documentation does not need a LaTeX installation. Configure an HTML-only build with:

cmake -S . -B build \
  -DXMLIO_BUILD_DOCUMENTATION=ON \
  -DXMLIO_BUILD_PDF_DOCUMENTATION=OFF
cmake --build build --target xmlio_docs_html

This mode remains useful for hosts that build the HTML manual directly. The Publish Documentation GitHub Actions workflow instead builds both the HTML and PDF manuals, copies xmlio.pdf beside the HTML files, and force-updates a generated docs-site branch after each push to main. Static hosting services should publish that branch without another framework build step. For Cloudflare Pages, set the build command to exit 0 and the output directory to ..

8.5. Example programs

The examples are ordinary clients linked only to xmlio::xmlio:

Compiled examples

Source

Focus

quick_start.cpp

Minimal in-memory write and read.

custom_types.cpp

Argument-dependent serialization of records.

xpath_queries.cpp

Predicates, namespaces, attributes, and optional values.

catalog_merge.cpp

Explicit map collision policies.

composition.cpp

Deferred groups and input provenance.

error_handling.cpp

Schema versions and typed exceptions.

streaming_output.cpp

Incremental output for documents that should not be retained in memory.

When tests are enabled, CTest also executes every example.

8.6. Installation

The install prefix is different from the build directory. The build directory contains intermediate and generated files; the install prefix receives the finished library, headers, CMake package files, and source documentation.

After building in the default build directory, choose an install prefix with:

cmake --install build --prefix "$HOME/.local"

The package helper presents these locations as a build directory and an install directory. With no options, it uses build/ and $HOME/.local:

./scripts/install.sh

If the selected build contains a compiled XMLIO library from this source tree, the helper installs it immediately without rebuilding or rerunning tests. If the build is absent or incomplete, the helper first runs the complete build.sh workflow and only installs after that succeeds.

Select both locations explicitly with:

./scripts/install.sh \
  --build-dir build-clang \
  --install-dir "$HOME/.local/xmlio"

XMLIO_BUILD_DIR and XMLIO_INSTALL_DIR provide equivalent environment settings. Command-line options take precedence. Use ./scripts/install.sh --help for a concise summary.

Match the install command to a custom build directory when one was used:

cmake --install build-clang --prefix "$HOME/.local/xmlio"

--prefix applies only to this installation and overrides the configured CMAKE_INSTALL_PREFIX. Installing into a system-owned location may require administrator permission; a directory below $HOME generally does not.

When the optional documentation targets have been built, installation also includes the generated HTML and PDF manuals.

8.7. Consuming the package

An installed-package consumer uses:

find_package(xmlio CONFIG REQUIRED)
target_link_libraries(my_program PRIVATE xmlio::xmlio)

Add the chosen prefix to CMAKE_PREFIX_PATH when CMake cannot otherwise find xmlioConfig.cmake.

For a source-tree dependency:

add_subdirectory(path/to/xmlio)
target_link_libraries(my_program PRIVATE xmlio::xmlio)

The public target requests C++23 and exports the required include paths. libxml2 remains an implementation detail of the C++ interface.

While xmlio is below version 1.0, CMake package compatibility follows the minor version: a request for 0.1 accepts compatible 0.1.x releases but does not silently accept 0.2. This leaves room for deliberate API changes between pre-1.0 minor releases. After a stable 1.0 release, this policy can be revisited for normal same-major-version compatibility.

The repository’s tests/package_consumer directory is a deliberately separate miniature CMake project. The complete build script and CI install xmlio into a temporary prefix, then configure this project with find_package(xmlio CONFIG REQUIRED). This catches incomplete exports, missing transitive dependencies, and install-tree include problems that an in-tree example cannot detect.