Building from Source
This content is for v0.9.3. Switch to the latest version for up-to-date documentation.
This guide covers building the GraphQLite SQLite extension and CLI from source, running tests, checking code quality, and installing the result for use with the Rust crate.
Prerequisites
Section titled “Prerequisites”| Tool | Minimum Version | macOS | Linux (Debian/Ubuntu) | Windows (MSYS2) |
|---|---|---|---|---|
| GCC or Clang | 9 / 11 | Xcode CLI tools | build-essential |
mingw-w64-x86_64-gcc |
| Bison | 3.0+ | brew install bison |
bison |
bison |
| Flex | 2.6+ | brew install flex |
flex |
flex |
| SQLite dev headers | 3.35+ | brew install sqlite |
libsqlite3-dev |
mingw-w64-x86_64-sqlite3 |
| CUnit | 2.1+ | brew install cunit |
libcunit1-dev |
(optional) |
| make | 4.0+ | Xcode CLI tools | make |
make |
xcode-select --installbrew install bison flex sqlite cunit
# Homebrew Bison must precede the system Bison on PATHexport PATH="$(brew --prefix bison)/bin:$PATH"Add the PATH export to your shell profile (~/.zshrc or ~/.bash_profile) to make it persistent.
Linux (Debian/Ubuntu)
Section titled “Linux (Debian/Ubuntu)”sudo apt-get updatesudo apt-get install build-essential bison flex libsqlite3-dev libcunit1-devWindows (MSYS2)
Section titled “Windows (MSYS2)”pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-sqlite3 bison flex makeRun all commands from the MSYS2 MinGW 64-bit shell.
Clone and Build
Section titled “Clone and Build”git clone https://github.com/your-org/graphqlitecd graphqlitemake extensionThis produces:
| Platform | Output file |
|---|---|
| macOS | build/graphqlite.dylib |
| Linux | build/graphqlite.so |
| Windows | build/graphqlite.dll |
Debug vs. Release
Section titled “Debug vs. Release”The default build includes debug symbols and C assertions. For a production build:
make extension RELEASE=1RELEASE=1 adds -O2 optimization and strips assertions. Always use release builds for benchmarking.
Build Targets
Section titled “Build Targets”Run make help to see all available targets. The most commonly used ones are:
Core Targets
Section titled “Core Targets”| Target | Description |
|---|---|
make extension |
Build the SQLite extension (.dylib/.so/.dll) |
make extension RELEASE=1 |
Build optimized release extension |
make graphqlite |
Build the gqlite interactive CLI |
make graphqlite RELEASE=1 |
Build optimized release CLI |
make all |
Build everything (extension + CLI) |
Test Targets
Section titled “Test Targets”| Target | Description |
|---|---|
make test unit |
Run CUnit unit tests (770 tests) |
make test functional |
Run SQL-based functional tests |
make test python |
Run Python binding tests |
make test rust |
Build and run Rust binding tests |
make test-all |
Run all test suites |
Quality Targets
Section titled “Quality Targets”| Target | Description |
|---|---|
make lint |
Strict C11 compliance check |
make coverage |
Build with coverage instrumentation and run unit tests |
make performance |
Run performance benchmarks |
make performance-quick |
Quick performance smoke test |
Install Targets
Section titled “Install Targets”| Target | Description |
|---|---|
make install-bundled |
Copy extension into the Rust crate’s source tree |
Running Tests
Section titled “Running Tests”Unit Tests
Section titled “Unit Tests”make test unitBuilds and runs the CUnit test suite. Output shows pass/fail counts per suite. All 770 tests must pass on a clean build.
Functional Tests
Section titled “Functional Tests”make test functionalRuns SQL script tests against the built extension. Each test file is a .sql script in tests/functional/ that exercises a specific feature:
# Run a single functional test manuallysqlite3 :memory: < tests/functional/01_create_match.sqlPython Tests
Section titled “Python Tests”make test pythonRequires Python 3.8+ and pip install graphqlite[dev] (or install the dev dependencies from requirements-dev.txt).
Rust Tests
Section titled “Rust Tests”make test rustThis target first calls make install-bundled to copy the freshly-built extension into the Rust crate, then runs cargo test.
All Tests
Section titled “All Tests”make test-allRuns unit, functional, CLI, and binding tests in sequence. All suites must pass before a release.
Linting
Section titled “Linting”make lintThe lint target compiles all C source files with strict C11 flags:
-std=c11 -Wall -Wextra -Wpedantic -Werror -Wshadow -Wformat=2Zero warnings are permitted (-Werror). Fix all lint warnings before submitting changes. The lint target does not link the extension; it only checks the source.
Coverage
Section titled “Coverage”make coverageBuilds the unit test runner with --coverage instrumentation (GCC gcov/lcov) and runs the tests. Coverage data appears in build/coverage/. Open build/coverage/index.html in a browser to browse line-by-line coverage.
Requirements: lcov must be installed (brew install lcov / sudo apt-get install lcov).
Performance Benchmarks
Section titled “Performance Benchmarks”# Full benchmark suitemake performance
# Quick smoke test (faster, fewer iterations)make performance-quick
# Extended benchmark with larger graphsmake performance-fullBenchmark results are printed to stdout. Run with RELEASE=1 for meaningful numbers:
make performance RELEASE=1Installing for Rust Bundled Builds
Section titled “Installing for Rust Bundled Builds”The Rust crate defaults to the bundled-extension feature, which embeds the extension binary at compile time. After building from source, copy the extension into the Rust crate:
make install-bundledThis copies build/graphqlite.{dylib,so,dll} into the correct location inside bindings/rust/ so that cargo build picks it up. Run this after every source change when developing the Rust crate.
Platform-Specific Notes
Section titled “Platform-Specific Notes”-
The system
bison(in/usr/bin) is version 2.x, which is too old. Always install via Homebrew and prepend it toPATH. -
If you see
library not loaded: libsqlite3.dylibwhen loading the built extension, setDYLD_LIBRARY_PATH:Terminal window export DYLD_LIBRARY_PATH="$(brew --prefix sqlite)/lib:$DYLD_LIBRARY_PATH" -
On Apple Silicon (M1/M2), the Homebrew prefix is
/opt/homebrewrather than/usr/local.
-
The
libcunit1-devpackage is only needed for unit tests. The extension itself (make extension) does not require CUnit. -
On systems without
lcov,make coveragewill fail at the report generation step. Install lcov or skip coverage. -
On Alpine Linux (musl libc), replace
apt-getwithapk add:Terminal window apk add build-base bison flex sqlite-dev
Windows (MSYS2)
Section titled “Windows (MSYS2)”- All commands must be run from the MSYS2 MinGW 64-bit shell, not the default MSYS shell. The MinGW shell sets the correct compiler paths.
- Python tests require a Windows Python 3.8+ installation accessible from the MSYS2 PATH.
- The extension output is
build/graphqlite.dll.
Build Directory Layout
Section titled “Build Directory Layout”After a full build:
build/├── graphqlite.dylib # SQLite extension (macOS)├── gqlite # Interactive CLI binary├── test_runner # CUnit test runner binary├── parser/ # Compiled parser objects├── transform/ # Compiled transform objects├── executor/ # Compiled executor objects└── coverage/ # Coverage HTML report (after make coverage)Troubleshooting
Section titled “Troubleshooting”bison: syntax error during build
Section titled “bison: syntax error during build”The system Bison is too old. Confirm the version:
bison --versionIf it shows 2.x, install Homebrew Bison (brew install bison) and prepend it to PATH.
flex: command not found
Section titled “flex: command not found”Install flex: brew install flex / sudo apt-get install flex.
cannot open shared object file: libcunit.so
Section titled “cannot open shared object file: libcunit.so”CUnit is not installed or not on LD_LIBRARY_PATH. Install it (libcunit1-dev) or run make extension (which does not need CUnit) instead of make test unit.
Python tests fail with No module named graphqlite
Section titled “Python tests fail with No module named graphqlite”Install the Python package in development mode:
pip install -e bindings/python/or install it from PyPI and use GRAPHQLITE_EXTENSION_PATH to point to your locally built extension:
export GRAPHQLITE_EXTENSION_PATH=$(pwd)/build/graphqlite.dylibmake test python