This guide provides instructions for building, testing, and benchmarking the Ada URL parser library using CMake.
Quick Reference
# Build library only (no tests, no benchmarks)
cmake -B build && cmake --build build
# Build with tests (development checks ENABLED)
cmake -B build -DADA_TESTING=ON && cmake --build build
ctest --output-on-failure --test-dir build
# Build with benchmarks (development checks DISABLED for accurate performance)
cmake -B build -DADA_BENCHMARKS=ON -DADA_USE_UNSAFE_STD_REGEX_PROVIDER=ON -DCMAKE_BUILD_TYPE=Release && cmake --build build
./build/benchmarks/benchdata # Run main benchmark
# FASTER BUILDS: Use Ninja instead of Make
cmake -B build -G Ninja -DADA_TESTING=ON && cmake --build build
cmake -B build -G Ninja -DADA_BENCHMARKS=ON -DADA_USE_UNSAFE_STD_REGEX_PROVIDER=ON -DCMAKE_BUILD_TYPE=Release && cmake --build build
Requirements
- C++20 compatible compiler (GCC 12+, LLVM 14+, MSVC 2022+)
- CMake 3.15+
- Git (for fetching test dependencies)
- Ninja (optional, for faster builds): sudo apt install ninja-build on Ubuntu
Building the Library
Basic Build (Library Only)
For a minimal build with just the library:
cmake -B build
cmake --build build
This creates the Ada library without tests or benchmarks.
Build with Tests
To build with tests enabled:
cmake -B build -DADA_TESTING=ON
cmake --build build
Important: When ADA_TESTING=ON, development checks are automatically enabled unless you explicitly build in Release mode with NDEBUG defined. Development checks include assertions (ADA_ASSERT_TRUE, ADA_ASSERT_EQUAL) that validate internal state.
Build with Benchmarks
To build benchmarks for performance testing:
cmake -B build -DADA_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build
Critical: Always build benchmarks in Release mode (-DCMAKE_BUILD_TYPE=Release) to disable development checks. Development assertions significantly impact performance and will give misleading benchmark results.
Using Local Packages
If you have dependencies (like GoogleTest, Google Benchmark) already installed locally:
cmake -B build -DADA_TESTING=ON -DCPM_USE_LOCAL_PACKAGES=ON
cmake --build build
CMake Build Options
| Option | Default | Description |
| ADA_TESTING | OFF | Enable building tests |
| ADA_BENCHMARKS | OFF | Enable building benchmarks (requires 64-bit) |
| ADA_TOOLS | OFF | Enable building command-line tools |
| ADA_BUILD_SINGLE_HEADER_LIB | OFF | Build from single-header amalgamated files |
| ADA_USE_SIMDUTF | OFF | Enable SIMD-accelerated Unicode via simdutf |
| CMAKE_BUILD_TYPE | - | Set to Release for optimized builds, Debug for development |
Running Tests
After building with -DADA_TESTING=ON:
# Run all tests
ctest --output-on-failure --test-dir build
# Run specific test executable
./build/tests/basic_tests
# Run tests with verbose output
ctest --verbose --test-dir build
Development Checks in Tests
Tests run with development checks enabled by default (unless built with -DCMAKE_BUILD_TYPE=Release -DNDEBUG). This means:
This is the recommended mode for development.
Running Benchmarks
After building with -DADA_BENCHMARKS=ON:
# Main benchmark comparing against competitors
./build/benchmarks/benchdata
# Specific benchmarks
./build/benchmarks/bench # Basic URL parsing benchmarks
./build/benchmarks/bbc_bench # BBC URLs benchmark
./build/benchmarks/wpt_bench # Web Platform Tests benchmark
./build/benchmarks/percent_encode # Percent encoding benchmarks
Development Checks in Benchmarks
Always disable development checks for benchmarks by building in Release mode:
# CORRECT: Benchmarks with development checks disabled
cmake -B build -DADA_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build
./build/benchmarks/benchdata
# WRONG: Don't benchmark with development checks enabled
cmake -B build -DADA_BENCHMARKS=ON # Missing Release mode!
Development checks add significant overhead that skews performance measurements. The ADA_DEVELOPMENT_CHECKS macro is automatically disabled when:
Complete Development Workflow
1. Initial Setup
# Clone and enter directory
cd /path/to/ada
# Create build directory for tests
cmake -B build -DADA_TESTING=ON
cmake --build build
2. Development Cycle (with tests)
# Make code changes...
# Rebuild (only rebuilds changed files)
cmake --build build
# Run tests to verify correctness
ctest --output-on-failure --test-dir build
# Or run specific test
./build/tests/basic_tests
3. Performance Validation (with benchmarks)
# Create separate benchmark build
cmake -B build-release -DADA_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build-release
# Run benchmarks
./build-release/benchmarks/benchdata
# Compare before/after optimizations
# (stash changes, rebuild, run benchmark, restore, rebuild, run again)
4. Clean Rebuild
# Remove build directory and start fresh
rm -rf build
cmake -B build -DADA_TESTING=ON
cmake --build build
Understanding Development Checks
What are Development Checks?
Development checks are compile-time assertions that validate:
- Function preconditions and postconditions
- Internal invariants (e.g., validate() on URL objects)
- Argument validity
When are they Enabled?
Automatically enabled when:
- ADA_TESTING=ON (unless overridden with Release mode)
- Debug build (CMAKE_BUILD_TYPE=Debug)
- NDEBUG is not defined
Automatically disabled when:
- CMAKE_BUILD_TYPE=Release
- NDEBUG is defined
- Production builds
Manual Control
# Force enable development checks (even in Release)
cmake -B build -DADA_DEVELOPMENT_CHECKS=1
# Force disable development checks (even in Debug)
cmake -B build -DNDEBUG=1
Running Clang-Tidy
Clang-tidy is used for static analysis. There are two ways to run it:
During Build (Recommended)
Run clang-tidy automatically during compilation:
cmake -B build -DADA_TESTING=ON \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_CXX_CLANG_TIDY=clang-tidy \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build build
Important: You must use clang++ as the compiler when running clang-tidy during build. Using GCC will cause errors because clang-tidy doesn't understand GCC-specific flags like -mno-avx256-split-unaligned-load.
Standalone with compile_commands.json
First, generate the compilation database:
cmake -B build -DADA_TESTING=ON \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build build
Then run clang-tidy on specific files:
clang-tidy -p build src/ada.cpp
clang-tidy -p build src/ada_idna.cpp
The -p build flag tells clang-tidy to use the compile_commands.json from the build directory.
Clang-Tidy Configuration
The .clang-tidy file in the project root configures which checks are enabled. Current configuration enables:
- bugprone-* checks (with some exclusions)
- clang-analyzer-* checks
All warnings are treated as errors (WarningsAsErrors: '*').
Platform-Specific Notes
Windows
Specify configuration during build:
cmake -B build -DADA_TESTING=ON
cmake --build build --config Release
ctest --output-on-failure --test-dir build --config Release
macOS/Linux
Standard commands work as documented above.
Troubleshooting
Benchmarks are unexpectedly slow
Cause: Development checks are enabled.
Solution: Rebuild with Release mode:
cmake -B build -DADA_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build
Tests are failing with assertion errors
Expected behavior - development checks are catching bugs. Review the assertion message and fix the underlying issue.
Can't find benchmark executable
Cause: Benchmarks not built (32-bit system or not enabled).
Solution:
cmake -B build -DADA_BENCHMARKS=ON
cmake --build build
ls build/benchmarks/ # Check what was built
Additional Resources
- README.md: General project overview and API usage
- docs/cli.md: Command-line interface documentation
- benchmarks/: Benchmark source code
- tests/: Test source code
- include/ada/: Library headers
Summary
| Task | Command | Development Checks |
| Library only | cmake -B build && cmake --build build | N/A |
| Testing | cmake -B build -DADA_TESTING=ON && cmake --build build | ✅ Enabled |
| Benchmarking | cmake -B build -DADA_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release && cmake --build build | ❌ Disabled |
| Development | cmake -B build -DADA_TESTING=ON -DCMAKE_BUILD_TYPE=Debug && cmake --build build | ✅ Enabled |