Skip to content

Building from Source

This guide covers building pgraft from source for development and contributing.

Prerequisites

Ensure you have all required dependencies:

  • PostgreSQL 17+: With development headers
  • Go 1.21+: For Raft implementation
  • GCC: C compiler
  • Make: Build system

See Installation for system-specific installation instructions.

Build Process

1. Clone Repository

git clone https://github.com/pgelephant/pgraft.git cd pgraft 

2. Build

make clean make 

The build process:

  1. Compiles C sources (src/*.c) to object files
  2. Builds Go library (src/pgraft_go.go) to shared library
  3. Links everything into final pgraft.dylib (or .so on Linux)
  4. Creates extension SQL from pgraft--1.0.sql

3. Install

# Find PostgreSQL paths PG_LIB=$(pg_config --libdir) PG_SHARE=$(pg_config --sharedir)  # Install files cp pgraft.dylib $PG_LIB/ cp src/pgraft_go.dylib $PG_LIB/ cp pgraft.control $PG_SHARE/extension/ cp pgraft--1.0.sql $PG_SHARE/extension/ 

Build Targets

Clean Build

make clean make 

Install After Build

make install 

Build with Debugging

make clean CFLAGS="-g -O0" make 

This builds with: - -g: Debug symbols - -O0: No optimization

Verifying Build

Check for Errors

# Should have no errors make 2>&1 | grep -i error  # Should have no warnings make 2>&1 | grep -i warning 

Check Binary

# macOS otool -L pgraft.dylib  # Linux ldd pgraft.so  # Should show dependencies on libpq, PostgreSQL, etc. 

Test Extension

# Start PostgreSQL with extension psql -c "CREATE EXTENSION pgraft;" psql -c "SELECT pgraft_test();" 

Development Workflow

Edit-Compile-Test Cycle

# 1. Edit source files vim src/pgraft_core.c  # 2. Rebuild make clean && make  # 3. Reinstall make install  # 4. Restart PostgreSQL pg_ctl restart -D /path/to/data  # 5. Test psql -c "SELECT pgraft_test();" 

Incremental Builds

For faster development, you can rebuild only changed files:

# Rebuild only C files (if Go unchanged) make pgraft.dylib  # Rebuild only Go (if C unchanged) cd src go build -buildmode=c-shared -o pgraft_go.dylib pgraft_go.go 

Code Organization

C Source Files (src/)

File Purpose
pgraft.c Main extension entry point, background worker
pgraft_core.c Core Raft interface to Go layer
pgraft_sql.c SQL function implementations
pgraft_guc.c GUC (configuration) parameters
pgraft_state.c State management, shared memory
pgraft_log.c Log replication functions
pgraft_kv.c Key-value store implementation
pgraft_kv_sql.c KV SQL interface
pgraft_util.c Utility functions
pgraft_go.c CGO wrapper for Go library

Header Files (include/)

File Purpose
pgraft_core.h Core function declarations
pgraft_go.h Go library interface
pgraft_guc.h GUC declarations
pgraft_sql.h SQL function declarations
pgraft_state.h State structures
pgraft_log.h Log function declarations
pgraft_kv.h KV store declarations

Go Implementation

  • src/pgraft_go.go - Complete Raft implementation (2900+ lines)

Coding Standards

pgraft follows PostgreSQL C coding standards:

C89/C90 Compliance

/* Correct: Variables at function start */ void my_function(void) {  int result;  char *message;   result = 0;  message = "Hello";  /* ... function code ... */ }  /* Wrong: Variables declared in middle */ void bad_function(void) {  int result = 0;  /* some code */  char *message = "Hello"; /* NOT at start */ } 

Comments

/* Correct: C-style comments */ /* This is a proper comment */  // Wrong: C++ style comments // This is not allowed 

Indentation

  • Tabs only (not spaces)
  • Tab width: 4 spaces
  • Opening brace on same line:
/* Correct */ if (condition) {  /* code */ }  /* Wrong */ if (condition) {  /* code */ } 

Testing

Unit Tests

cd examples ./run.sh --destroy ./run.sh --init ./run.sh --status 

Manual Testing

-- Test basic functionality SELECT pgraft_test(); SELECT pgraft_init(); SELECT pgraft_is_leader();  -- Test cluster operations SELECT pgraft_add_node(2, '127.0.0.1', 7002); SELECT * FROM pgraft_get_cluster_status(); 

Debugging

Enable Debug Output

SELECT pgraft_set_debug(true); 

Check Logs

tail -f $PGDATA/log/postgresql-*.log | grep pgraft 

Use GDB

# Start PostgreSQL with gdb gdb --args postgres -D /path/to/data  # Set breakpoints (gdb) break pgraft_init (gdb) run  # When breakpoint hit (gdb) backtrace (gdb) print variable_name 

Common Debug Points

/* Add logging in C code */ elog(LOG, "pgraft: Debug point reached, value=%d", value);  /* Add error logging */ elog(ERROR, "pgraft: Error occurred: %s", error_message); 

Contributing

See Contributing for guidelines on: - Code style - Pull request process - Testing requirements - Documentation

Performance Profiling

CPU Profiling

# Use perf on Linux perf record -g postgres perf report  # Use Instruments on macOS instruments -t "Time Profiler" postgres 

Memory Profiling

# Valgrind valgrind --leak-check=full postgres -D /path/to/data  # macOS Instruments instruments -t "Leaks" postgres 

Troubleshooting Build Issues

PostgreSQL Headers Not Found

# Set PG_CONFIG explicitly export PG_CONFIG=/usr/local/pgsql/bin/pg_config make clean && make 

Go Build Fails

# Ensure Go modules are downloaded cd src go mod download go mod tidy 
# Check library paths export DYLD_LIBRARY_PATH=/usr/local/pgsql/lib # macOS export LD_LIBRARY_PATH=/usr/local/pgsql/lib # Linux 

Build System Details

The Makefile uses PostgreSQL's PGXS build system:

PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) 

This automatically handles: - Finding PostgreSQL headers - Setting correct compiler flags - Linking with PostgreSQL libraries - Installing to correct directories