This document provides detailed build instructions for NoisePQC++ across different platforms.
Recommended: Before building from source, try the pre-configured Docker images. They include the exact compiler, CMake, Ninja, and Python analysis stack used to develop and test NoisePQC++, so you can build, test, and benchmark without installing any toolchain locally. See the Docker Image Usage Guide. Building from scratch is documented below for users who need a native toolchain or are working on an unsupported platform.
- CMake 4.0 or higher (required for C++ module support, tested with 4.0.4)
Note: For
import stdsupport make sure to use a CMake version that includes the necessary C++23 module detection features. CMake 4.0.4 is recommended and has been tested with the specified toolchains. With other versions, you will have to get the right experimental ID. Refer to CMake's documentation for the version you are using to find the correctCMAKE_EXPERIMENTAL_CXX_IMPORT_STDvalue if you are not using 4.0.4.
- Ninja build system (required for C++ modules)
- C++23-compatible compiler:
- Clang 18+ (recommended, tested on macOS and Linux with 18.1.8)
- GCC 15.2+ (with C++ modules support, tested on Linux x86_64 with 15.2.x)
- MSVC 19.44+ (Visual Studio 2022 17.12+, tested on Windows x86_64)
- Catch2 v3.11.0 for testing (automatically downloaded via CMake FetchContent if not found)
- Botan 3.10.0 cryptographic library (pre-downloaded Botan minimized build source in
third_party/) - Google Benchmark for benchmarking (automatically downloaded via CMake FetchContent if not found). See Benchmarking Guide for complete benchmarking instructions.
- Git for version control
Important:
- C++ modules require the Ninja generator. The Unix Makefiles generator is not supported.
- On first CMake run, Catch2 and Google Benchmark (when
NOISEPQC_BUILD_BENCHMARKSis set toON, the default) will be automatically downloaded if not found system-wide. - Botan 3.11.1 minimized build source is provided for macOS (x86_64, ARM64), Linux (x86_64, ARM64), and Windows (x86_64).
Supported Architectures: x86_64 and ARM64 (tested on Debian Trixie/Ubuntu 24.04 x86_64 and Raspberry Pi 5)
Botan Version: 3.10.0 (pre-downloaded source included in third_party/)
Compilers: Clang 18+ and GCC 15.2+
# Install dependencies. See cmake note above for experimental import std module support.
sudo apt update
sudo apt install cmake ninja-build clang-18 libc++-18-dev libc++abi-18-dev
# Configure with the Linux Clang toolchain file
# The toolchain file handles: compiler paths, libc++, headers, and linker flags
# Run cmake command below from inside the repository root directory (where CMakeLists.txt is located)
cmake -B build -S . -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/clang18-linux-toolchain.cmake
# Build
cmake --build build -j$(nproc)
# Run tests
ctest --test-dir build --output-on-failureWhat the toolchain file does:
- Sets Clang 18 compiler (
/usr/bin/clang++-18) - Configures libc++ standard library
- Sets proper include paths for LLVM 18 headers
- Configures linker flags with rpath for libc++
- Enables
import std;support
Note: GCC 15.2+ required for full C++23 modules support with import std;
# Install dependencies. See cmake note above for experimental import std module support.
# Note: GCC 15.2 may need to be built from source
# Ensure GCC 15.2 is installed to /opt/gcc-15 (or adjust toolchain file)
sudo apt update
sudo apt install cmake ninja-build gcc-15 g++-15
# Configure with the GCC 15 toolchain file
# The toolchain file handles: compiler paths, libstdc++, headers, and linker flags
# Run cmake command below from inside the repository root directory (where CMakeLists.txt is located)
cmake -B build -S . -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/gcc15-linux-toolchain.cmake
# Build
cmake --build build -j$(nproc)
# Run tests
ctest --test-dir build --output-on-failureWhat the toolchain file does:
- Sets GCC 15 compiler (
/opt/gcc-15/bin/g++-15) - Configures libstdc++ standard library
- Sets proper include paths for GCC 15 headers
- Configures linker flags with rpath for libstdc++
- Enables
import std;support
# Install dependencies. See cmake note above for experimental import std module support.
sudo apt update
sudo apt install cmake ninja-build clang-18 libc++-18-dev libc++abi-18-dev
# Configure with the Raspberry Pi toolchain file
# The toolchain file handles: compiler paths, libc++, headers, and linker flags
# Run cmake command below from inside the repository root directory (where CMakeLists.txt is located)
cmake -B build -S . -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/clang18-rasPi-toolchain.cmake
# Build (use fewer jobs on Pi to avoid memory issues)
cmake --build build -j2
# Run tests
ctest --test-dir build --output-on-failureWhat the toolchain file does:
- Sets Clang 18 compiler (
/usr/bin/clang++-18) - Configures libc++ standard library
- Sets proper include paths for LLVM 18 headers
- Configures linker flags with rpath for libc++
- Enables
import std;support - Optimized for ARM64 architecture
Supported Architectures: Intel (x86_64) and Apple Silicon (ARM64)
Botan Version: 3.10.0 (pre-downloaded source included in third_party/)
For Homebrew Clang on macOS, review the import std; / libc++.modules.json note below before building.
# Install dependencies. See cmake note above for experimental import std module support.
brew install cmake ninja llvm@18
# Configure with the macOS toolchain file
# The toolchain file handles: compiler paths, libc++, headers, and linker flags
# Run cmake command below from inside the repository root directory (where CMakeLists.txt is located)
cmake -B build -S . -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/clang18-macOS-toolchain.cmake
# Build
cmake --build build -j$(sysctl -n hw.ncpu)
# Run tests
ctest --test-dir build --output-on-failureWhat the toolchain file does:
- Sets Clang 18 compiler from Homebrew (
/usr/local/opt/llvm@18/bin/clang++on Intel macOS or/opt/homebrew/opt/llvm@18/bin/clang++on Apple Silicon) - Configures libc++ standard library
- Sets proper include paths for LLVM 18 headers
- Configures linker flags for libc++ and libunwind
- Enables
import std;support
When building NoisePQC++ with CMake 4.0.x and Homebrew Clang 18.1.x on macOS, CMake may fail to enable import std; because Homebrew Clang can report a bad, relative, or incomplete path for libc++.modules.json during compiler detection.
Typical configure-time errors include:
The "CXX_MODULE_STD" property on the target "<target>" requires that the "__CMAKE::CXX23" target exist, but it was not provided by the toolchain.
or:
Reason: `libc++.modules.json` resource does not exist
This is a macOS/Homebrew toolchain discovery issue rather than a NoisePQC++ source issue. The specific path-resolution problem described here is not expected for the Linux build paths documented below. In particular:
- the Linux Clang toolchain does not use Homebrew's macOS libc++ layout
- the Linux GCC 15.2 toolchain uses
libstdc++rather thanlibc++.modules.json
Recommended fix (project-local and persistent for this repository)
Note: The fixes below are based on research and have not yet been fully tested. If you encounter issues, please report them.
The preferred fix is to add a Clang resource-directory hint to the macOS toolchain file so CMake sees the correct libc++ layout during compiler detection.
Open:
cmake/clang18-macOS-toolchain.cmake
and add one of the following lines after the compiler definitions.
For Intel macOS:
set(CMAKE_CXX_COMPILER_ID_ARG1
"-resource-dir=/usr/local/opt/llvm@18/lib/c++"
CACHE STRING "Extra argument used when CMake probes Clang for import std" FORCE)For Apple Silicon:
set(CMAKE_CXX_COMPILER_ID_ARG1
"-resource-dir=/opt/homebrew/opt/llvm@18/lib/c++"
CACHE STRING "Extra argument used when CMake probes Clang for import std" FORCE)Then do a clean configure:
rm -rf build
cmake -B build -S . -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/clang18-macOS-toolchain.cmakeOne-shot configure workaround
Instead of editing the toolchain file, pass the same hint on the CMake command line:
cmake -B build -S . -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/clang18-macOS-toolchain.cmake \
-DCMAKE_CXX_COMPILER_ID_ARG1="-resource-dir=$(brew --prefix llvm@18)/lib/c++"Alternate machine-local workaround: patch the installed CMake compiler module for Homebrew Clang 18.x
Note: The fix below are based on research and have been fully tested to work. If you encounter issues, please report them.
If you are building on macOS with Homebrew Clang 18.x and CMake 4.0.x, and import std; still fails because CMake cannot locate libc++.modules.json, you can patch the installed CMake compiler module as a machine-local workaround.
This workaround is specifically for Clang 18.x. It is different from the newer Clang 19+ workaround that uses -print-library-module-manifest-path.
-
Find CMake's module root:
cmake --system-information | grep CMAKE_ROOT -
Open this file under that root:
${CMAKE_ROOT}/Modules/Compiler/Clang-CXX-CXXImportStd.cmakeOn Homebrew CMake this is typically one of:
/opt/homebrew/Cellar/cmake/4.0.4/share/cmake/Modules/Compiler/Clang-CXX-CXXImportStd.cmake /usr/local/Cellar/cmake/4.0.4/share/cmake/Modules/Compiler/Clang-CXX-CXXImportStd.cmake -
Back up the file before editing it.
-
Find the compiler probe that looks like this:
COMMAND "${CMAKE_CXX_COMPILER}" ${CMAKE_CXX_COMPILER_ID_ARG1} -print-file-name=libc++.modules.json
-
Replace that last line with:
-print-file-name=../../c++/libc++.modules.jsonSo the patched block becomes:
COMMAND "${CMAKE_CXX_COMPILER}" ${CMAKE_CXX_COMPILER_ID_ARG1} -print-file-name=../../c++/libc++.modules.json
-
Remove your build directory and reconfigure:
rm -rf build cmake -B build -S . -G Ninja \ -DCMAKE_TOOLCHAIN_FILE=cmake/clang18-macOS-toolchain.cmake
This patch is a machine-local workaround and will apply to other CMake projects on that Mac, but it is not permanent across CMake upgrades or reinstalls. It should be treated as a last resort after the project-local toolchain-file fix.
This issue is specific to the macOS/Homebrew Clang + libc++ module discovery path. It is not the expected path for the Linux toolchains documented in this guide, and the Linux GCC 15.2 build path uses libstdc++ rather than libc++.modules.json.
Supported Architecture: x86_64
Botan Version: 3.10.0 (pre-downloaded source included in third_party/)
Compiler: MSVC 19.44+ (Visual Studio 2022 17.12+)
Performance Note: MSVC's C++ modules implementation is currently slower than Clang/GCC, so Windows builds may take significantly longer to compile. For development on Windows, consider using the Docker image with Clang 18 for faster iteration. Use "Release" build configuration to reduce compile times and testing times, as "Debug" builds with MSVC modules can be particularly slow.
Install Visual Studio 2022 (17.12 or later) with these workloads/components:
- Desktop development with C++
- C++ CMake tools for Windows
- C++ Modules for v143 build tools
Catch2 and Google Benchmark are fetched automatically via CMake FetchContent — no manual installation needed.
CMake auto-detects MSVC, but only when cl.exe and the MSVC INCLUDE/LIB environment variables are on PATH. A regular Command Prompt does not have these set up.
Open Start Menu → "Developer Command Prompt for VS 2022".
Verify MSVC is on PATH before continuing:
clYou should see a line similar to:
Microsoft (R) C/C++ Optimizing Compiler Version 19.44.xxxxx for x64
If cl is not recognized, you are still in a regular Command Prompt — go back to Start Menu and look for "Developer Command Prompt for VS 2022".
Run from the repository root (where CMakeLists.txt lives):
cmake -DCMAKE_BUILD_TYPE=Release -S . -B build-release
cmake --build build-release --config Release
ctest --test-dir build-release --output-on-failureNote: A separate toolchain file is not needed on Windows — the active Developer Command Prompt session is what selects MSVC. This differs from Linux/macOS, where cmake/clang18-*-toolchain.cmake or cmake/gcc15-linux-toolchain.cmake must be passed via -DCMAKE_TOOLCHAIN_FILE.
Pre-configured Docker images are available for building and testing on Linux without setting up a local toolchain. The Dockerfiles are located in the docker/ directory.
Available images:
- Clang 18 (
docker/clang18-linux/Dockerfile): Debian Trixie with Clang 18.1.8, CMake 4.0.4, Ninja - GCC 15 (
docker/gcc15-linux/Dockerfile): Debian Trixie with GCC 15.2.0 (built from source), CMake 4.0.4, Ninja
Both images include a Python environment with analysis tools (pandas, matplotlib, seaborn, JupyterLab) for benchmark post-processing.
For detailed instructions on pulling images, building inside containers, and running benchmarks, see the Docker Image Usage Guide.
To enable comprehensive debug logging showing handshake state transitions:
cmake -B build-debug -S . -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/clang18-macOS-toolchain.cmake \
-DNOISE_DEBUG_BUILD=ONThis enables color-coded, detailed logging of:
- Token processing (e, s, ee, es, se, ss, psk)
- State transitions (plaintext → encrypted)
- Key exchanges and DH operations
- Message flows and sizes
- Role identification (Initiator/Responder)
For complete information, see Logging and Debugging Guide.
Benchmarks require a Release build configuration. They are enabled by default (NOISEPQC_BUILD_BENCHMARKS=ON) and Google Benchmark v1.9.1 is automatically downloaded via FetchContent on first configure.
With single-config generators (Ninja), benchmarks are only built when CMAKE_BUILD_TYPE=Release. With multi-config generators (Ninja Multi-Config, MS Visual Studio), build with --config Release.
For complete information, see Benchmarking Guide.
# Debug build
cmake -B build -S . -G Ninja -DCMAKE_BUILD_TYPE=Debug
# Release build (optimized)
cmake -B build -S . -G Ninja -DCMAKE_BUILD_TYPE=Release
# RelWithDebInfo (optimized with debug symbols)
cmake -B build -S . -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo
# Specify C++ standard (23 is default)
cmake -B build -S . -G Ninja -DCMAKE_CXX_STANDARD=23Problem: Compiler cannot find C++ module files or "Unsupported generator" error
Solution:
- Ensure you're using Clang 18+ or GCC 15+
- Check that CMake is version 4.0+
- Must use Ninja generator: Add
-G Ninjato cmake command - Install Ninja:
brew install ninja(macOS) orsudo apt install ninja-build(Linux) - Try a clean rebuild:
rm -rf build && cmake -B build -S . -G Ninja
Problem: CMake fails during configure with __CMAKE::CXX23, CXX_MODULE_STD, or libc++.modules.json errors when using Homebrew Clang and import std;.
Solution: See the detailed Homebrew Clang import std; Note in the macOS section above for causes and fixes.
Problem: Cannot find botan_all.h or linking errors
Solution:
- Verify
third_party/botan/directory exists - Check that the correct platform directory is being used
- CMake should automatically select based on your system
Problem: Tests fail during execution
Solution:
- Run tests individually to isolate failures:
./build/test_cipher -s - Check for missing runtime dependencies
- Verify platform-specific Botan library is correct
Problem: Linker cannot find libc++ or module files
Solution:
# Add LLVM to PATH
# Intel macOS:
export PATH="/usr/local/opt/llvm@18/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/llvm@18/lib"
export CPPFLAGS="-I/usr/local/opt/llvm@18/include"
# Apple Silicon macOS:
export PATH="/opt/homebrew/opt/llvm@18/bin:$PATH"
export LDFLAGS="-L/opt/homebrew/opt/llvm@18/lib"
export CPPFLAGS="-I/opt/homebrew/opt/llvm@18/include"
# Reconfigure with the toolchain file (recommended over manual compiler flags)
cmake -B build -S . -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/clang18-macOS-toolchain.cmakeProblem: cmake -B build -S . fails immediately with:
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:2 (project):
No CMAKE_CXX_COMPILER could be found.
Cause: You are running from a regular Command Prompt. MSVC's cl.exe is not on PATH, so CMake cannot find a C++ compiler.
Solution: Launch "Developer Command Prompt for VS 2022" from the Start Menu (see Windows (x86_64) → Step 1). Then run cl to confirm MSVC is detected before re-running cmake.
Note: Adding -DCMAKE_TOOLCHAIN_FILE=... will not fix this — there is no Windows toolchain file in cmake/ by design. The MSVC environment is set up by the shell, not by a CMake toolchain file.
Problem: MSVC cannot compile C++ modules
Solution:
- Update to Visual Studio 2022 version 17.12 or later
- Ensure the C++ Modules for v143 build tools component is installed via the Visual Studio Installer
- Verify MSVC version is 19.44+: run
clin a Developer Command Prompt and check the version line
cd build
ctest --output-on-failure# Run with default output
./build/tests/test_handshakestate
# Run with verbose output (Catch2)
./build/tests/test_handshakestate -s
# Run specific test case
./build/tests/test_handshakestate "XX handshake"
# List all test cases
./build/tests/test_handshakestate --list-testsThe project includes comprehensive tests (200+ test cases, 500+ assertions):
- test_cipher: Cipher module (ChaCha20-Poly1305, AES-GCM)
- test_hash: Hash module (SHA256, SHA512, BLAKE2b, BLAKE2s)
- test_dh: DH and KEM module (X25519, X448, ML-KEM-512/768/1024)
- test_cipherstate: CipherState module
- test_symmetricstate: SymmetricState module
- test_protocol: Protocol module (classical, PQ, and HFS protocols)
- test_handshakestate: Complete handshake flows for all 57 classical patterns
- test_noise_pq: Post-Quantum pattern tests (pqXX, pqNK, etc.)
- test_hfs: Hybrid Forward Secrecy pattern tests (XXhfs, NKhfs, etc.)
- test_vectors: Noise specification test vectors
- test_example: End-to-end demonstration
- Docker Image Usage Guide - Building and testing with Docker containers
- Pattern Guide - Complete guide to all Noise patterns (classical, PQ, HFS) with use cases
- Architecture Documentation - System architecture and design principles
- API Reference - Complete API documentation with examples
- Noise Protocol Specification - Official specification