Skip to content

Commit 55adbb3

Browse files
author
Pierre-Luc Gagné
committed
Refactor project layout: build presets, CMake modules, and script organization
1 parent 19fbd5e commit 55adbb3

17 files changed

Lines changed: 179 additions & 159 deletions

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
build/
2-
build-coverage/
3-
build_clang/
42
.env
53
compile_commands.json
64
*.o

CMakeLists.txt

Lines changed: 3 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -14,115 +14,12 @@ if(EXISTS "${CMAKE_SOURCE_DIR}/.githooks")
1414
)
1515
endif()
1616

17-
# Set C++23 standard
18-
set(CMAKE_CXX_STANDARD 23)
19-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
20-
set(CMAKE_CXX_EXTENSIONS OFF)
21-
22-
# Export compile commands for IDEs
23-
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
24-
25-
# Set default build type if not specified
26-
if(NOT CMAKE_BUILD_TYPE)
27-
set(CMAKE_BUILD_TYPE Release)
28-
endif()
29-
30-
# Build options
31-
option(BUILD_EXAMPLES "Build examples" ON)
32-
option(ENABLE_COVERAGE "Enable code coverage" OFF)
33-
option(SKIP_DOCKER_MANAGEMENT "Skip Docker container lifecycle in CTest (use when DB is externally provided, e.g. CI)" OFF)
34-
option(BUILD_INTEGRATION_TESTS "Build integration tests" ON)
35-
36-
# Compiler options
37-
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
38-
add_compile_options(
39-
-Wall
40-
-Wextra
41-
-Wpedantic
42-
-Werror
43-
)
44-
elseif(MSVC)
45-
add_compile_options(
46-
/W4 # High warning level
47-
/WX # Warnings as errors
48-
/permissive- # Strict standards conformance
49-
/Zc:preprocessor # Enable standards-conforming preprocessor (__VA_OPT__)
50-
)
51-
endif()
52-
53-
# Coverage flags
54-
if(ENABLE_COVERAGE)
55-
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
56-
add_compile_options(--coverage)
57-
add_link_options(--coverage)
58-
message(STATUS "Coverage enabled with --coverage flags")
59-
else()
60-
message(WARNING "Coverage is not supported with ${CMAKE_CXX_COMPILER_ID}")
61-
endif()
62-
endif()
63-
64-
# Include FetchContent for dependency management
65-
include(FetchContent)
66-
6717
# Make local CMake helper modules available early (needed by fetched deps).
6818
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
6919

70-
# MySQL client library
71-
if(WIN32)
72-
# On Windows, search common MySQL Server installation paths.
73-
# Override by passing -DMYSQL_ROOT_DIR=<path> to cmake.
74-
set(MYSQL_ROOT_DIR "" CACHE PATH "MySQL installation root (e.g. C:/Program Files/MySQL/MySQL Server 8.0)")
75-
if(NOT MYSQL_ROOT_DIR)
76-
file(GLOB _mysql_dirs "C:/Program Files/MySQL/MySQL Server *")
77-
if(_mysql_dirs)
78-
list(SORT _mysql_dirs ORDER DESCENDING)
79-
list(GET _mysql_dirs 0 MYSQL_ROOT_DIR)
80-
set(MYSQL_ROOT_DIR "${MYSQL_ROOT_DIR}" CACHE PATH "" FORCE)
81-
else()
82-
message(FATAL_ERROR "MySQL not found. Set -DMYSQL_ROOT_DIR=<path> to the MySQL installation directory.")
83-
endif()
84-
endif()
85-
86-
find_path(MYSQL_INCLUDE_DIR mysql.h PATHS "${MYSQL_ROOT_DIR}/include" NO_DEFAULT_PATH REQUIRED)
87-
find_library(MYSQL_LIBRARY libmysql PATHS "${MYSQL_ROOT_DIR}/lib" NO_DEFAULT_PATH REQUIRED)
88-
set(MYSQL_INCLUDE_DIRS "${MYSQL_INCLUDE_DIR}")
89-
set(MYSQL_LIBRARIES "${MYSQL_LIBRARY}")
90-
message(STATUS "MySQL found at: ${MYSQL_ROOT_DIR}")
91-
else()
92-
find_package(PkgConfig REQUIRED)
93-
pkg_check_modules(MYSQL REQUIRED mysqlclient)
94-
endif()
95-
96-
# Note: Boost.PFR is header-only and doesn't have a standard CMake config package yet,
97-
# so we fetch it directly without find_package. Once Boost.PFR is officially integrated
98-
# into Boost's CMake build system, we can use: find_package(Boost REQUIRED COMPONENTS pfr CONFIG)
99-
100-
# Boost.PFR (header-only, for compile-time reflection without macros)
101-
# We only need the headers; FetchContent_Populate avoids processing Boost.PFR's own
102-
# CMake build system, whose tests require Boost::core which is unavailable here.
103-
FetchContent_Declare(
104-
boost_pfr_headers
105-
GIT_REPOSITORY https://github.com/boostorg/pfr.git
106-
GIT_TAG master
107-
GIT_SHALLOW TRUE
108-
)
109-
# CMP0169 OLD: suppress the single-arg FetchContent_Populate deprecation warning.
110-
# This is intentional — we want headers only, not add_subdirectory behaviour.
111-
cmake_policy(PUSH)
112-
if(POLICY CMP0169)
113-
cmake_policy(SET CMP0169 OLD)
114-
endif()
115-
FetchContent_Populate(boost_pfr_headers)
116-
cmake_policy(POP)
117-
118-
# Create Boost.PFR target if not already provided by Boost.PFR's own CMake
119-
if(NOT TARGET Boost::pfr)
120-
add_library(Boost::pfr INTERFACE IMPORTED)
121-
set_target_properties(Boost::pfr PROPERTIES
122-
INTERFACE_INCLUDE_DIRECTORIES "${boost_pfr_headers_SOURCE_DIR}/include"
123-
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${boost_pfr_headers_SOURCE_DIR}/include"
124-
)
125-
endif()
20+
include(ProjectOptions)
21+
include(CompilerOptions)
22+
include(Dependencies)
12623

12724
# Auto-create .env from .env.example in tests/integration if missing
12825
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/tests/integration/.env")

CMakePresets.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"name": "default",
1111
"displayName": "Default (Release)",
1212
"generator": "Ninja",
13-
"binaryDir": "${sourceDir}/build",
13+
"binaryDir": "${sourceDir}/build/default",
1414
"cacheVariables": {
1515
"CMAKE_POLICY_DEFAULT_CMP0175": "OLD",
1616
"CMAKE_BUILD_TYPE": "Release",
@@ -22,7 +22,7 @@
2222
"name": "debug",
2323
"displayName": "Debug",
2424
"generator": "Ninja",
25-
"binaryDir": "${sourceDir}/build",
25+
"binaryDir": "${sourceDir}/build/debug",
2626
"cacheVariables": {
2727
"CMAKE_POLICY_DEFAULT_CMP0175": "OLD",
2828
"CMAKE_BUILD_TYPE": "Debug",
@@ -34,7 +34,7 @@
3434
"name": "release",
3535
"displayName": "Release",
3636
"generator": "Ninja",
37-
"binaryDir": "${sourceDir}/build",
37+
"binaryDir": "${sourceDir}/build/release",
3838
"cacheVariables": {
3939
"CMAKE_POLICY_DEFAULT_CMP0175": "OLD",
4040
"CMAKE_BUILD_TYPE": "Release",
@@ -46,7 +46,7 @@
4646
"name": "coverage",
4747
"displayName": "Coverage",
4848
"generator": "Ninja",
49-
"binaryDir": "${sourceDir}/build-coverage",
49+
"binaryDir": "${sourceDir}/build/coverage",
5050
"cacheVariables": {
5151
"CMAKE_POLICY_DEFAULT_CMP0175": "OLD",
5252
"CMAKE_BUILD_TYPE": "Debug",
@@ -59,7 +59,7 @@
5959
"name": "ci",
6060
"displayName": "CI (externally-managed DB)",
6161
"generator": "Ninja",
62-
"binaryDir": "${sourceDir}/build-ci",
62+
"binaryDir": "${sourceDir}/build/ci",
6363
"cacheVariables": {
6464
"CMAKE_POLICY_DEFAULT_CMP0175": "OLD",
6565
"CMAKE_BUILD_TYPE": "Release",

README.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ git clone https://github.com/DisciplinedSoftware/DSMySQL.git
9494
cd DSMySQL
9595
9696
cmake --preset release
97-
cmake --build build -j$(nproc)
97+
cmake --build build/release -j$(nproc)
9898
ctest --preset release
9999
```
100100

@@ -112,14 +112,23 @@ ctest --preset release
112112
```bash
113113
# Unit tests only, skip integration tests
114114
cmake --preset release -DBUILD_INTEGRATION_TESTS=OFF
115-
cmake --build build -j$(nproc)
115+
cmake --build build/release -j$(nproc)
116116
ctest --preset release
117117

118118
# Debug build
119119
cmake --preset debug
120-
cmake --build build -j$(nproc)
120+
cmake --build build/debug -j$(nproc)
121121
```
122122

123+
## Scripts Layout
124+
125+
Project automation scripts are grouped by purpose:
126+
127+
- `scripts/ci/act-ci.sh` — run `tests-gcc` job locally with `act`
128+
- `scripts/ci/act-ci-full.sh` — run Linux CI jobs locally in sequence with `act`
129+
- `scripts/release/release.sh` — bump version, update changelog, commit, and tag
130+
- `scripts/release/act-release.sh` — dry-run release workflow locally with `act`
131+
123132
## Using as a Dependency
124133

125134
Since DSMySQL is header-only, integrate it with CMake FetchContent:
@@ -141,8 +150,8 @@ Optional install/package flow:
141150

142151
```bash
143152
cmake --preset release -DDSMYSQL_ENABLE_INSTALL=ON
144-
cmake --build build -j$(nproc)
145-
cmake --install build --prefix /usr/local
153+
cmake --build build/release -j$(nproc)
154+
cmake --install build/release --prefix /usr/local
146155
```
147156

148157
```cmake
@@ -260,9 +269,9 @@ Integration tests connect to a real MySQL 8.0 instance managed via Docker Compos
260269
ctest --preset release
261270
262271
# Manual container management
263-
cmake --build build --target docker_integration_up
272+
cmake --build build/release --target docker_integration_up
264273
ctest --preset release -R tests_integration_ds_mysql
265-
cmake --build build --target docker_integration_down
274+
cmake --build build/release --target docker_integration_down
266275
```
267276

268277
See [docs/INTEGRATION_TESTS.md](docs/INTEGRATION_TESTS.md) for full details.

cmake/CompilerOptions.cmake

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Shared compiler warnings and instrumentation flags.
2+
3+
# Compiler options
4+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
5+
add_compile_options(
6+
-Wall
7+
-Wextra
8+
-Wpedantic
9+
-Werror
10+
)
11+
elseif(MSVC)
12+
add_compile_options(
13+
/W4 # High warning level
14+
/WX # Warnings as errors
15+
/permissive- # Strict standards conformance
16+
/Zc:preprocessor # Enable standards-conforming preprocessor (__VA_OPT__)
17+
)
18+
endif()
19+
20+
# Coverage flags
21+
if(ENABLE_COVERAGE)
22+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
23+
add_compile_options(--coverage)
24+
add_link_options(--coverage)
25+
message(STATUS "Coverage enabled with --coverage flags")
26+
else()
27+
message(WARNING "Coverage is not supported with ${CMAKE_CXX_COMPILER_ID}")
28+
endif()
29+
endif()

cmake/Dependencies.cmake

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Shared third-party dependency resolution.
2+
3+
include(FetchContent)
4+
5+
# MySQL client library
6+
if(WIN32)
7+
# On Windows, search common MySQL Server installation paths.
8+
# Override by passing -DMYSQL_ROOT_DIR=<path> to cmake.
9+
set(MYSQL_ROOT_DIR "" CACHE PATH "MySQL installation root (e.g. C:/Program Files/MySQL/MySQL Server 8.0)")
10+
if(NOT MYSQL_ROOT_DIR)
11+
file(GLOB _mysql_dirs "C:/Program Files/MySQL/MySQL Server *")
12+
if(_mysql_dirs)
13+
list(SORT _mysql_dirs ORDER DESCENDING)
14+
list(GET _mysql_dirs 0 MYSQL_ROOT_DIR)
15+
set(MYSQL_ROOT_DIR "${MYSQL_ROOT_DIR}" CACHE PATH "" FORCE)
16+
else()
17+
message(FATAL_ERROR "MySQL not found. Set -DMYSQL_ROOT_DIR=<path> to the MySQL installation directory.")
18+
endif()
19+
endif()
20+
21+
find_path(MYSQL_INCLUDE_DIR mysql.h PATHS "${MYSQL_ROOT_DIR}/include" NO_DEFAULT_PATH REQUIRED)
22+
find_library(MYSQL_LIBRARY libmysql PATHS "${MYSQL_ROOT_DIR}/lib" NO_DEFAULT_PATH REQUIRED)
23+
set(MYSQL_INCLUDE_DIRS "${MYSQL_INCLUDE_DIR}")
24+
set(MYSQL_LIBRARIES "${MYSQL_LIBRARY}")
25+
message(STATUS "MySQL found at: ${MYSQL_ROOT_DIR}")
26+
else()
27+
find_package(PkgConfig REQUIRED)
28+
pkg_check_modules(MYSQL REQUIRED mysqlclient)
29+
endif()
30+
31+
# Note: Boost.PFR is header-only and doesn't have a standard CMake config package yet,
32+
# so we fetch it directly without find_package. Once Boost.PFR is officially integrated
33+
# into Boost's CMake build system, we can use: find_package(Boost REQUIRED COMPONENTS pfr CONFIG)
34+
35+
# Boost.PFR (header-only, for compile-time reflection without macros)
36+
# We only need the headers; FetchContent_Populate avoids processing Boost.PFR's own
37+
# CMake build system, whose tests require Boost::core which is unavailable here.
38+
FetchContent_Declare(
39+
boost_pfr_headers
40+
GIT_REPOSITORY https://github.com/boostorg/pfr.git
41+
GIT_TAG master
42+
GIT_SHALLOW TRUE
43+
)
44+
# CMP0169 OLD: suppress the single-arg FetchContent_Populate deprecation warning.
45+
# This is intentional — we want headers only, not add_subdirectory behaviour.
46+
cmake_policy(PUSH)
47+
if(POLICY CMP0169)
48+
cmake_policy(SET CMP0169 OLD)
49+
endif()
50+
FetchContent_Populate(boost_pfr_headers)
51+
cmake_policy(POP)
52+
53+
# Create Boost.PFR target if not already provided by Boost.PFR's own CMake
54+
if(NOT TARGET Boost::pfr)
55+
add_library(Boost::pfr INTERFACE IMPORTED)
56+
set_target_properties(Boost::pfr PROPERTIES
57+
INTERFACE_INCLUDE_DIRECTORIES "${boost_pfr_headers_SOURCE_DIR}/include"
58+
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${boost_pfr_headers_SOURCE_DIR}/include"
59+
)
60+
endif()

cmake/ProjectOptions.cmake

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Shared project-level build options and defaults.
2+
3+
# Set C++23 standard
4+
set(CMAKE_CXX_STANDARD 23)
5+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6+
set(CMAKE_CXX_EXTENSIONS OFF)
7+
8+
# Export compile commands for IDEs
9+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
10+
11+
# Set default build type if not specified
12+
if(NOT CMAKE_BUILD_TYPE)
13+
set(CMAKE_BUILD_TYPE Release)
14+
endif()
15+
16+
# Build options
17+
option(BUILD_EXAMPLES "Build examples" ON)
18+
option(ENABLE_COVERAGE "Enable code coverage" OFF)
19+
option(SKIP_DOCKER_MANAGEMENT "Skip Docker container lifecycle in CTest (use when DB is externally provided, e.g. CI)" OFF)
20+
option(BUILD_INTEGRATION_TESTS "Build integration tests" ON)

docs/BUILD.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
```bash
1414
cmake --preset release
15-
cmake --build build -j$(nproc)
15+
cmake --build build/release -j$(nproc)
1616
ctest --preset release
1717
```
1818

@@ -30,8 +30,8 @@ DSMySQL/
3030
## Configure + Build Manually
3131

3232
```bash
33-
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-15
34-
cmake --build build -j$(nproc)
33+
cmake -S . -B build/release -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-15
34+
cmake --build build/release -j$(nproc)
3535
```
3636

3737
## Build Options
@@ -55,16 +55,16 @@ ctest --preset release
5555

5656
# Skip integration tests
5757
cmake --preset release -DBUILD_INTEGRATION_TESTS=OFF
58-
cmake --build build -j$(nproc)
58+
cmake --build build/release -j$(nproc)
5959
ctest --preset release
6060
```
6161

6262
## Code Coverage
6363

6464
```bash
6565
cmake --preset coverage
66-
cmake --build build-coverage -j$(nproc)
66+
cmake --build build/coverage -j$(nproc)
6767
ctest --preset coverage
68-
./scripts/generate_coverage.sh build-coverage
69-
# Report: build-coverage/html/index.html
68+
./scripts/generate_coverage.sh build/coverage
69+
# Report: build/coverage/html/index.html
7070
```

0 commit comments

Comments
 (0)