Skip to content

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.

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
Terminal window
xcode-select --install
brew install bison flex sqlite cunit
# Homebrew Bison must precede the system Bison on PATH
export PATH="$(brew --prefix bison)/bin:$PATH"

Add the PATH export to your shell profile (~/.zshrc or ~/.bash_profile) to make it persistent.

Terminal window
sudo apt-get update
sudo apt-get install build-essential bison flex libsqlite3-dev libcunit1-dev
Terminal window
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-sqlite3 bison flex make

Run all commands from the MSYS2 MinGW 64-bit shell.

Terminal window
git clone https://github.com/your-org/graphqlite
cd graphqlite
make extension

This produces:

Platform Output file
macOS build/graphqlite.dylib
Linux build/graphqlite.so
Windows build/graphqlite.dll

The default build includes debug symbols and C assertions. For a production build:

Terminal window
make extension RELEASE=1

RELEASE=1 adds -O2 optimization and strips assertions. Always use release builds for benchmarking.

Run make help to see all available targets. The most commonly used ones are:

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)
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
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
Target Description
make install-bundled Copy extension into the Rust crate’s source tree
Terminal window
make test unit

Builds and runs the CUnit test suite. Output shows pass/fail counts per suite. All 770 tests must pass on a clean build.

Terminal window
make test functional

Runs SQL script tests against the built extension. Each test file is a .sql script in tests/functional/ that exercises a specific feature:

Terminal window
# Run a single functional test manually
sqlite3 :memory: < tests/functional/01_create_match.sql
Terminal window
make test python

Requires Python 3.8+ and pip install graphqlite[dev] (or install the dev dependencies from requirements-dev.txt).

Terminal window
make test rust

This target first calls make install-bundled to copy the freshly-built extension into the Rust crate, then runs cargo test.

Terminal window
make test-all

Runs unit, functional, CLI, and binding tests in sequence. All suites must pass before a release.

Terminal window
make lint

The lint target compiles all C source files with strict C11 flags:

-std=c11 -Wall -Wextra -Wpedantic -Werror -Wshadow -Wformat=2

Zero warnings are permitted (-Werror). Fix all lint warnings before submitting changes. The lint target does not link the extension; it only checks the source.

Terminal window
make coverage

Builds 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).

Terminal window
# Full benchmark suite
make performance
# Quick smoke test (faster, fewer iterations)
make performance-quick
# Extended benchmark with larger graphs
make performance-full

Benchmark results are printed to stdout. Run with RELEASE=1 for meaningful numbers:

Terminal window
make performance RELEASE=1

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:

Terminal window
make install-bundled

This 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.

  • The system bison (in /usr/bin) is version 2.x, which is too old. Always install via Homebrew and prepend it to PATH.

  • If you see library not loaded: libsqlite3.dylib when loading the built extension, set DYLD_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/homebrew rather than /usr/local.

  • The libcunit1-dev package is only needed for unit tests. The extension itself (make extension) does not require CUnit.

  • On systems without lcov, make coverage will fail at the report generation step. Install lcov or skip coverage.

  • On Alpine Linux (musl libc), replace apt-get with apk add:

    Terminal window
    apk add build-base bison flex sqlite-dev
  • 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.

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)

The system Bison is too old. Confirm the version:

Terminal window
bison --version

If it shows 2.x, install Homebrew Bison (brew install bison) and prepend it to PATH.

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:

Terminal window
pip install -e bindings/python/

or install it from PyPI and use GRAPHQLITE_EXTENSION_PATH to point to your locally built extension:

Terminal window
export GRAPHQLITE_EXTENSION_PATH=$(pwd)/build/graphqlite.dylib
make test python