Skip to content

Commit d3acd72

Browse files
feat: major build system improvements with multi-compiler support and sanitizers
Completely overhaul the build system with production-quality features: Build System: - Add comprehensive warning flags (-Wall, -Wextra, -Wpedantic, etc.) - Enable -Werror for Debug builds, warnings-only for Release - Add ASAN, UBSAN, and TSAN support with proper CMake options - Make benchmarks opt-in (BUILD_BENCHMARKS) to save ~30-40% compile time - Disable sanitizers for GCC on macOS (not supported) Build Scripts: - Rewrite build.sh with automatic compiler detection - Support multiple compilers: gcc-15/14/13, clang-19/18/17, llvm, appleclang - Add --list-compilers flag to show available compilers - Generic compiler selection (gcc → latest available) - Show full version numbers (e.g., "GCC 15.2.0") - Save compiler preferences to .build_config - Auto-clean when switching compilers to avoid CMake cache issues - Improved error messages with suggestions ("Did you mean 'appleclang'?") Build Modes: - debug: ASAN + UBSAN, warnings as errors - debug-tsan: TSAN, warnings as errors - release: Optimized, no sanitizers, warnings enabled Scripts: - Update test.sh to default to debug mode (ASAN + UBSAN) - Update benchmark.sh to auto-enable BUILD_BENCHMARKS - Update run.sh to support all build modes CI: - Update to Debug builds with ASAN + UBSAN on all platforms - Test with GCC 14 and Clang on Linux - Test with AppleClang on macOS - Skip benchmarks in CI (unreliable on shared runners) Documentation: - Comprehensive README.md update with build modes, compiler selection - Update CONTRIBUTING.md with sanitizer info, build instructions - Add sanitizer support matrix This follows industry best practices from projects like Abseil, LLVM, and Google Benchmark.
1 parent 6ea69bb commit d3acd72

File tree

12 files changed

+767
-133
lines changed

12 files changed

+767
-133
lines changed

.github/workflows/ci.yml

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,25 @@ jobs:
2828
sudo apt-get update
2929
sudo apt-get install -y gcc-14 g++-14
3030
31-
- name: Configure CMake
31+
- name: Configure CMake (Debug with ASAN + UBSAN)
3232
run: |
3333
if [ "${{ matrix.compiler }}" = "gcc" ]; then
3434
export CC=gcc-14 CXX=g++-14
3535
else
3636
export CC=clang CXX=clang++
3737
fi
38-
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -G Ninja
38+
cmake -B build -S . \
39+
-DCMAKE_BUILD_TYPE=Debug \
40+
-DENABLE_ASAN=ON \
41+
-DENABLE_UBSAN=ON \
42+
-DENABLE_TSAN=OFF \
43+
-G Ninja
3944
4045
- name: Build
41-
run: cmake --build build --config Release
42-
43-
- name: Run tests
44-
run: cd build && ctest --output-on-failure -C Release
46+
run: cmake --build build --config Debug
4547

46-
- name: Run benchmarks (quick)
47-
run: ./build/benchmarks/hello_world_benchmark --benchmark_min_time=0.1s
48+
- name: Run tests with sanitizers
49+
run: cd build && ctest --output-on-failure -C Debug
4850

4951
build-macos:
5052
runs-on: macos-latest
@@ -53,26 +55,22 @@ jobs:
5355
- uses: actions/checkout@v4
5456

5557
- name: Install dependencies
56-
run: |
57-
brew install cmake ninja llvm
58+
run: brew install cmake ninja
5859

59-
- name: Configure CMake with Homebrew LLVM
60+
- name: Configure CMake (Debug with ASAN + UBSAN)
6061
run: |
61-
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
6262
cmake -B build -S . \
63-
-DCMAKE_BUILD_TYPE=Release \
64-
-DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang \
65-
-DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ \
63+
-DCMAKE_BUILD_TYPE=Debug \
64+
-DENABLE_ASAN=ON \
65+
-DENABLE_UBSAN=ON \
66+
-DENABLE_TSAN=OFF \
6667
-G Ninja
6768
6869
- name: Build
69-
run: cmake --build build --config Release
70-
71-
- name: Run tests
72-
run: cd build && ctest --output-on-failure -C Release
70+
run: cmake --build build --config Debug
7371

74-
- name: Run benchmarks (quick)
75-
run: ./build/benchmarks/hello_world_benchmark --benchmark_min_time=0.1s
72+
- name: Run tests with sanitizers
73+
run: cd build && ctest --output-on-failure -C Debug
7674

7775
coverage:
7876
runs-on: ubuntu-latest

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
# Build files
4444
build/
4545
cmake-build-*/
46+
.build_config
4647

4748
# CMake
4849
CMakeCache.txt

CMakeLists.txt

Lines changed: 92 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,28 @@ set(CMAKE_CXX_STANDARD 23)
99
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1010
set(CMAKE_CXX_EXTENSIONS OFF)
1111

12+
# Define warning flags for project targets only (not third-party dependencies)
13+
set(PROJECT_WARNING_FLAGS -Wall -Wextra -Wpedantic -Wshadow -Wuninitialized
14+
-Wconversion)
15+
16+
# Add compiler-specific warnings
17+
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
18+
list(APPEND PROJECT_WARNING_FLAGS -Wmost -Wthread-safety)
19+
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
20+
list(APPEND PROJECT_WARNING_FLAGS -Wduplicated-cond -Wlogical-op)
21+
endif()
22+
23+
# Add -Werror for Debug builds only
24+
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
25+
list(APPEND PROJECT_WARNING_FLAGS -Werror)
26+
endif()
27+
1228
# Only disable Apple-specific flags if using GCC on macOS
1329
if(APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
1430
message(STATUS "Using GCC on macOS - disabling Apple-specific flags")
1531
set(CMAKE_OSX_ARCHITECTURES "")
1632
set(CMAKE_OSX_SYSROOT "")
1733
set(CMAKE_OSX_DEPLOYMENT_TARGET "")
18-
# GCC on macOS doesn't support TSAN well, disable it
19-
set(ENABLE_TSAN
20-
OFF
21-
CACHE BOOL "TSAN not supported with GCC on macOS" FORCE)
22-
message(
23-
WARNING
24-
"Thread Sanitizer (TSAN) is not supported with GCC on macOS ARM64 - disabling"
25-
)
2634
endif()
2735

2836
# Configure Homebrew LLVM/Clang to use the correct libc++
@@ -49,7 +57,50 @@ endif()
4957
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
5058

5159
# Add sanitizer options
52-
option(ENABLE_TSAN "Enable Thread Sanitizer" ON)
60+
option(ENABLE_ASAN "Enable Address Sanitizer" OFF)
61+
option(ENABLE_UBSAN "Enable Undefined Behavior Sanitizer" OFF)
62+
option(ENABLE_TSAN "Enable Thread Sanitizer" OFF)
63+
64+
# GCC on macOS doesn't include sanitizer runtime libraries - disable them
65+
if(APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
66+
if(ENABLE_ASAN)
67+
message(
68+
WARNING
69+
"Address Sanitizer (ASAN) is not supported with GCC on macOS - disabling"
70+
)
71+
set(ENABLE_ASAN
72+
OFF
73+
CACHE BOOL "ASAN not supported with GCC on macOS" FORCE)
74+
endif()
75+
if(ENABLE_UBSAN)
76+
message(
77+
WARNING
78+
"Undefined Behavior Sanitizer (UBSAN) is not supported with GCC on macOS - disabling"
79+
)
80+
set(ENABLE_UBSAN
81+
OFF
82+
CACHE BOOL "UBSAN not supported with GCC on macOS" FORCE)
83+
endif()
84+
if(ENABLE_TSAN)
85+
message(
86+
WARNING
87+
"Thread Sanitizer (TSAN) is not supported with GCC on macOS - disabling"
88+
)
89+
set(ENABLE_TSAN
90+
OFF
91+
CACHE BOOL "TSAN not supported with GCC on macOS" FORCE)
92+
endif()
93+
endif()
94+
95+
if(ENABLE_ASAN)
96+
add_compile_options(-fsanitize=address)
97+
add_link_options(-fsanitize=address)
98+
endif()
99+
100+
if(ENABLE_UBSAN)
101+
add_compile_options(-fsanitize=undefined)
102+
add_link_options(-fsanitize=undefined)
103+
endif()
53104

54105
if(ENABLE_TSAN)
55106
add_compile_options(-fsanitize=thread)
@@ -78,38 +129,51 @@ set(gtest_force_shared_crt
78129
CACHE BOOL "" FORCE)
79130
FetchContent_MakeAvailable(googletest)
80131

81-
# Fetch Google Benchmark
82-
FetchContent_Declare(
83-
googlebenchmark
84-
GIT_REPOSITORY https://github.com/google/benchmark.git
85-
GIT_TAG v1.9.1)
86-
set(BENCHMARK_ENABLE_TESTING
87-
OFF
88-
CACHE BOOL "" FORCE)
89-
set(BENCHMARK_ENABLE_GTEST_TESTS
90-
OFF
91-
CACHE BOOL "" FORCE)
92-
set(HAVE_STD_REGEX
93-
ON
94-
CACHE BOOL "" FORCE)
95-
set(RUN_HAVE_STD_REGEX
96-
1
97-
CACHE STRING "" FORCE)
98-
FetchContent_MakeAvailable(googlebenchmark)
132+
# Benchmark support (opt-in, use ./scripts/benchmark.sh to enable)
133+
option(BUILD_BENCHMARKS "Build benchmark executables" OFF)
134+
135+
if(BUILD_BENCHMARKS)
136+
FetchContent_Declare(
137+
googlebenchmark
138+
GIT_REPOSITORY https://github.com/google/benchmark.git
139+
GIT_TAG v1.9.1)
140+
set(BENCHMARK_ENABLE_TESTING
141+
OFF
142+
CACHE BOOL "" FORCE)
143+
set(BENCHMARK_ENABLE_GTEST_TESTS
144+
OFF
145+
CACHE BOOL "" FORCE)
146+
set(HAVE_STD_REGEX
147+
ON
148+
CACHE BOOL "" FORCE)
149+
set(RUN_HAVE_STD_REGEX
150+
1
151+
CACHE STRING "" FORCE)
152+
FetchContent_MakeAvailable(googlebenchmark)
153+
endif()
99154

100155
# Main library
101156
add_library(hello_world STATIC src/hello_world.cpp)
102157
target_include_directories(
103158
hello_world PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
104159
$<INSTALL_INTERFACE:include>)
160+
target_compile_options(hello_world PRIVATE ${PROJECT_WARNING_FLAGS})
105161

106162
# Main executable
107163
add_executable(hello_world_demo src/main.cpp)
108164
target_link_libraries(hello_world_demo PRIVATE hello_world)
165+
target_compile_options(hello_world_demo PRIVATE ${PROJECT_WARNING_FLAGS})
109166

110167
# Enable testing
111168
enable_testing()
112169

113170
# Add subdirectories
114171
add_subdirectory(tests)
115-
add_subdirectory(benchmarks)
172+
173+
if(BUILD_BENCHMARKS)
174+
add_subdirectory(benchmarks)
175+
message(STATUS "Benchmarks enabled")
176+
else()
177+
message(
178+
STATUS "Benchmarks disabled (run ./scripts/benchmark.sh to build and run)")
179+
endif()

0 commit comments

Comments
 (0)