diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 00000000..ef2747ec --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,73 @@ +# Building MobilityDuck + +MobilityDuck is a DuckDB extension. One CMake project builds DuckDB itself +(~1300 source files), the bundled `spatial` and `icu` extensions, and +MobilityDuck (~36 source files). The MEOS, GEOS, PROJ, GDAL and GSL +dependencies are built by vcpkg and cached. + +## One-time full build + +```bash +make # release into build/release (use GEN=ninja for Ninja) +make debug # debug into build/debug +``` + +The first run compiles DuckDB and the vcpkg dependencies from source and is the +slow one. The result is `build/release/extension/mobilityduck/mobilityduck.duckdb_extension` +and a `build/release/duckdb` shell with the extension linked in. + +## Fast iteration on MobilityDuck + +After the one-time build, rebuild only the extension: + +```bash +make ext # rebuild build/release extension only +make ext_debug # rebuild build/debug extension only +``` + +`make ext` recompiles only the changed MobilityDuck translation units and +relinks the `.duckdb_extension`. DuckDB, `spatial`, `icu`, `parquet` and the +vcpkg packages are not recompiled, because they are unchanged in the build tree. + +Two settings cut the per-change cost further and apply automatically: + +- A precompiled header (`src/include/mobilityduck_pch.hpp`) parses the heavy + DuckDB and MEOS headers once instead of in every translation unit. +- When `mold` is installed it is used to link the extension; the relink + dominates a single-file change and mold is much faster than the default + linker (`apt install mold`, or the equivalent for your platform). The build + falls back to the default linker when mold is absent. + +Keep the build tree in sync with the checked-out branch: switching branches (or +building a different worktree) against a tree configured for another state makes +CMake detect changed headers and recompile broadly. A persistent, path-independent +`ccache` keeps those recompiles cheap (see below). + +## ccache across branches and worktrees + +`ccache` caches compiled objects. Making it path-independent lets a fresh +worktree or a branch switch reuse DuckDB's unchanged objects instead of +recompiling them: + +```bash +export CCACHE_DIR="$HOME/.ccache" +export CCACHE_BASEDIR="$PWD" +ccache -M 30G +ccache -o hash_dir=false -o sloppiness=locale,time_macros +``` + +## vcpkg dependency cache + +vcpkg stores built packages in `~/.cache/vcpkg/archives` and reuses them across +clean build trees. MEOS, GEOS, PROJ and GDAL are rebuilt only when their version +or the MEOS pin in `vcpkg_ports/meos/portfile.cmake` changes — ordinary +MobilityDuck edits reuse the cache. + +## Installing without building + +End users do not build the extension. They install the distributed binary: + +```sql +INSTALL mobilityduck FROM ''; +LOAD mobilityduck; +``` diff --git a/CMakeLists.txt b/CMakeLists.txt index 47640ba4..3963be86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,25 @@ target_link_libraries(${LOADABLE_EXTENSION_NAME} OpenSSL::Crypto ) +# ----------------------------- +# Developer build speed +# ----------------------------- +# Parse the heavy, stable DuckDB and MEOS headers once per build instead of in +# every translation unit. +target_precompile_headers(${EXTENSION_NAME} PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/src/include/mobilityduck_pch.hpp") +target_precompile_headers(${LOADABLE_EXTENSION_NAME} PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/src/include/mobilityduck_pch.hpp") + +# Link the extension with mold when it is installed: relinking the extension +# dominates the cost of a single-file change, and mold relinks far faster than +# the default linker. Falls back to the default linker when mold is absent. +find_program(MOLD_LINKER mold) +if(MOLD_LINKER) + target_link_options(${EXTENSION_NAME} PRIVATE -fuse-ld=mold) + target_link_options(${LOADABLE_EXTENSION_NAME} PRIVATE -fuse-ld=mold) +endif() + # ----------------------------- # Install (static & loadable) # ----------------------------- diff --git a/Makefile b/Makefile index 6ee08484..9e7941b7 100644 --- a/Makefile +++ b/Makefile @@ -51,4 +51,16 @@ test_debug_internal: ./build/debug/$(TEST_PATH) "$(PROJ_DIR)test/*" test_reldebug_internal: $(call stage_icu,reldebug) - ./build/reldebug/$(TEST_PATH) "$(PROJ_DIR)test/*" \ No newline at end of file + ./build/reldebug/$(TEST_PATH) "$(PROJ_DIR)test/*" + +# Fast developer iteration: rebuild ONLY the MobilityDuck extension against the +# already-configured DuckDB build and vcpkg dependencies. Run a full `make` +# (release) / `make debug` once; thereafter `make ext` / `make ext_debug` +# recompiles just the changed MobilityDuck translation units and relinks +# build//extension/mobilityduck/mobilityduck.duckdb_extension without +# rebuilding DuckDB, spatial, icu, parquet or the vcpkg packages. See BUILDING.md. +.PHONY: ext ext_debug +ext: + cmake --build build/release --target mobilityduck_loadable_extension --parallel +ext_debug: + cmake --build build/debug --target mobilityduck_loadable_extension --parallel diff --git a/src/include/mobilityduck_pch.hpp b/src/include/mobilityduck_pch.hpp new file mode 100644 index 00000000..47aa02e4 --- /dev/null +++ b/src/include/mobilityduck_pch.hpp @@ -0,0 +1,17 @@ +// Precompiled header: the heavy, stable third-party headers shared by every +// MobilityDuck translation unit. Compiling these once per build instead of in +// each translation unit cuts incremental compile time. Only third-party +// headers belong here — adding a MobilityDuck header would rebuild the whole +// precompiled header whenever that header changes. +#pragma once + +extern "C" { +#include +#include +} + +#include "duckdb/common/exception.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/main/extension/extension_loader.hpp" +#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp" diff --git a/vcpkg_ports/meos/portfile.cmake b/vcpkg_ports/meos/portfile.cmake index 82619e3a..9aeff5d5 100644 --- a/vcpkg_ports/meos/portfile.cmake +++ b/vcpkg_ports/meos/portfile.cmake @@ -1,8 +1,8 @@ vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO estebanzimanyi/MobilityDB - REF a8178dc9d56d841d0eb5025a7e8717c8d25a1d0f - SHA512 030a144bb3247695702dd2de11f4c389ed28c6eb0186e6988a489e2b00e9801179ba8f27bcbcd81ae89e398a7277ed7f9ff7058dbf15f5db322ae4644365c560 + REF 3db47f887c61f049a6a03db55c48bedf6d10eee4 + SHA512 b73123bca036813c43937f90f0d0ce45af5cb9e39d6a597304199d21ae854212319a3a7b58ecd075eb5678d89d6d5990b9faf63dd29bd8c9a4e2ed83282b94c5 ) vcpkg_replace_string(