Before you begin developing a database, it’s important to make sure you know why you’re building it. If you’re building it for fun, or as a miniature project to learn how databases work, that’s fair enough. However, if you are developing a database because you need one for your project, unless it is so niche that a database does not already exist for it, you should try to find an existing database instead of reinventing the wheel.
Getting the environment set up
Before we go any further, it’s important to get the environment set up. For this, you need to ensure that you have a C compiler installed (MSVC, gcc, etc), CMake, an editor of sorts, and git.
Make sure to create a repository, and get git set up so you can push changes. For this, we will be using a small .gitignore file, containing just 3 items:
# Build directories
build/**
lib/**
bin/**Build scripts
Now we need a few scripts, just to make it easier to compile the project. We have one for Window, and one for Linux:
@echo off
REM Windows build script
REM ---------------------------------------------------------
REM Options:
REM build_win.bat "path/to/build" Debug/Release
REM Example:
REM build_win.bat build Debug
if not exist %1 (
echo %1 does not exist, creating...
mkdir %1
)
if not %2 == Debug if not %2 == Release (
echo %2 is not a valid option
exit /B 1
)
cd %1
if %2 == Debug (
echo Building with Debug configuration
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Debug
) else if %2 == Release (
echo Building with Release configuration
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release
)
cd ..#!/usr/bin/env bash
# Linux build script
# -------------------------------------------------------
# Options:
# build_linux.sh "path/to/build" Debug/Release
# Example:
# build_linux.sh build Debug
set -e
if [ "$2" != "Debug" ] && [ "$2" != "Release" ]; then
echo "$2 must be either Debug or Release"
exit 1
fi
if [ ! -d "$1" ]; then
echo "Creating build path at $1"
mkdir -p "$1" || { echo "Failed to create directory at $1"; exit 1; }
fi
cd "$1" || exit 1
if [ "$2" = "Debug" ]; then
echo "Building with Debug configuration"
cmake .. -DCMAKE_BUILD_TYPE=Debug
cmake --build . -- -j$(nproc)
elif [ "$2" = "Release" ]; then
echo "Building with Release configuration"
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . -- -j$(nproc)
fi
cd ..These scripts can be run pretty easily with just build.bat/build.sh build Debug/Release.
CMake configuration
For this, we will be using 3.24 as the minimum CMake version, and C99 as the C standard. We first set the CMake minimum required version with the following:
cmake_minimum_required(VERSION 3.24)Then, we need to configure the project, you can name it what you’d like, just make sure that there are no spaces in the name (You can swap them for underscores however):
project(
custom_db
VERSION 1.0.0
DESCRIPTION "My custom database"
LANGUAGES C
)Now we set a few other details, like C configuration, and output directories:
set(CMAKE_C_STANDARD 99)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)Once all those are set, we can move on to actually setting up the executable, we use the GLOB_RECURSE option on file to select all C file within the source directory, and then put these into add_executable with the project name. After that, we can add target the include directory, so we split off the header file from the source files:
file(GLOB_RECURSE SRC_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
)
add_executable(${PROJECT_NAME} ${SRC_FILES})
target_include_directories(
${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)Once this is complete, we can set up some compiler optimisations options:
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(OPTIONS_OPTIMIZATION -O2)
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(OPTIONS_OPTIMIZATION -g)
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
set(OPTIONS_OPTIMIZATION -O2 -g)
elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
set(OPTIONS_OPTIMIZATION -Os)
endif()After all of that, your final CMakeLists.txt file should look like this:
cmake_minimum_required(VERSION 3.24)
project(
custom_db
VERSION 1.0.0
DESCRIPTION "My custom database"
LANGUAGES C
)
set(CMAKE_C_STANDARD 99)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
file(GLOB_RECURSE SRC_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
)
add_executable(${PROJECT_NAME} ${SRC_FILES})
target_include_directories(
${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(OPTIONS_OPTIMIZATION -O2)
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(OPTIONS_OPTIMIZATION -g)
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
set(OPTIONS_OPTIMIZATION -O2 -g)
elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
set(OPTIONS_OPTIMIZATION -Os)
endif()Series
Part 1: Environment set up (This)
Part 2: Architecture design
Part 3: What is SQL?
![]()
Discover more from WTDawson
Subscribe to get the latest posts sent to your email.
