Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ WarningsAsErrors: >
bugprone-use-after-move,
bugprone-dangling-handle

HeaderFilterRegex: 'src/.*\.(hpp|h)$'
HeaderFilterRegex: '.*/src/.*\.(hpp|h)$'

FormatStyle: file

Expand Down
37 changes: 23 additions & 14 deletions .github/workflows/cpp-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,52 @@ on:
pull_request:
branches: ["main"]

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
format-check:
name: Format Check
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Check out repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Check format
run: |
clang-format --version
find src tests \( -name "*.hpp" -o -name "*.cpp" -o -name "*.h" \) | \
xargs clang-format --dry-run --Werror
cmake \
-DCLANG_FORMAT_EXECUTABLE=clang-format \
-DCLAVIS_SOURCE_DIR="$PWD" \
-DCLAVIS_FORMAT_CHECK=ON \
-P cmake/RunClangFormat.cmake

build-and-test:
name: Build and Test
runs-on: ubuntu-24.04
needs: format-check
timeout-minutes: 15
steps:
- name: Check out repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtest-dev
sudo apt-get install --no-install-recommends -y libgtest-dev ninja-build

- name: Show tool versions
run: |
cmake --version
g++ --version

- name: Configure
run: cmake --preset ci

- name: Build
run: cmake --build --preset ci

- name: Test
run: ctest --preset ci
- name: Build and test
run: cmake --workflow --preset ci
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@
*.out
*.app

# Debug files
build/
# CMake build artifacts and local presets
build/
CMakeUserPresets.json
125 changes: 47 additions & 78 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,93 +2,48 @@ cmake_minimum_required(VERSION 3.25)

project(CLAVIS LANGUAGES CXX)

# Set build type (default is Debug)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()

# NOTE: file(GLOB) is not recommended by CMake official docs.
# Consider listing source files explicitly for reliable rebuilds.
# See: https://cmake.org/cmake/help/latest/command/file.html#glob
file(GLOB CORE_SOURCES
src/*.cpp
src/graph/*.hpp
src/data_structure/*.hpp
src/sorting/*.hpp
src/math/*.hpp
)

# Collect test files
file(GLOB TEST_SOURCES
tests/*.cpp
tests/graph/*.cpp
tests/data_structure/*.cpp
tests/sorting/*.cpp
tests/math/*.cpp
)
set(CMAKE_CXX_EXTENSIONS OFF)

# Combine all sources
set(SOURCES ${CORE_SOURCES})

# Create library
add_library(clavis_algorithm ${SOURCES})
function(clavis_enable_warnings target)
target_compile_options(${target} PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-Wall -Wextra>
)
endfunction()

# Set C++ standard (modern target-based approach)
add_library(clavis_algorithm)
target_compile_features(clavis_algorithm PUBLIC cxx_std_20)

# Set compiler warnings (target-based, not global CMAKE_CXX_FLAGS)
target_compile_options(clavis_algorithm PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-Wall -Wextra>
)

# Set include directories
target_include_directories(clavis_algorithm PUBLIC
${CMAKE_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src
)
clavis_enable_warnings(clavis_algorithm)

# Google Test configuration
find_package(GTest REQUIRED)
enable_testing()
add_executable(clavis_sorting_example)
target_link_libraries(clavis_sorting_example PRIVATE clavis_algorithm)
clavis_enable_warnings(clavis_sorting_example)

# Test executable
add_executable(clavis_algorithm_test ${TEST_SOURCES})
add_subdirectory(src)

# Set include directories for tests
target_include_directories(clavis_algorithm_test PRIVATE
${CMAKE_SOURCE_DIR}/src
)
include(CTest)
if(BUILD_TESTING)
find_package(GTest REQUIRED)

target_link_libraries(clavis_algorithm_test clavis_algorithm GTest::GTest GTest::Main)
add_executable(clavis_algorithm_test)
target_link_libraries(clavis_algorithm_test PRIVATE
clavis_algorithm
GTest::gtest_main
)
clavis_enable_warnings(clavis_algorithm_test)

# Set compiler warnings for tests
target_compile_options(clavis_algorithm_test PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-Wall -Wextra>
)
add_subdirectory(tests)

# Discover and register tests
include(GoogleTest)
gtest_discover_tests(clavis_algorithm_test)
include(GoogleTest)
gtest_discover_tests(clavis_algorithm_test)
endif()

# =============================================================================
# Code Quality Tools
# =============================================================================

# Collect all C++ files for formatting
file(GLOB_RECURSE ALL_CXX_FILES
${CMAKE_SOURCE_DIR}/src/*.hpp
${CMAKE_SOURCE_DIR}/src/*.cpp
${CMAKE_SOURCE_DIR}/src/*.h
${CMAKE_SOURCE_DIR}/tests/*.cpp
)

# Collect source files only for linting (exclude tests)
file(GLOB_RECURSE SRC_CXX_FILES
${CMAKE_SOURCE_DIR}/src/*.hpp
${CMAKE_SOURCE_DIR}/src/*.cpp
${CMAKE_SOURCE_DIR}/src/*.h
)

# clang-format targets
find_program(CLANG_FORMAT clang-format
HINTS
$ENV{LLVM_DIR}/bin
Expand All @@ -98,21 +53,36 @@ find_program(CLANG_FORMAT clang-format
)
if(CLANG_FORMAT)
add_custom_target(format
COMMAND ${CLANG_FORMAT} -i ${ALL_CXX_FILES}
COMMAND ${CMAKE_COMMAND}
-DCLANG_FORMAT_EXECUTABLE=${CLANG_FORMAT}
-DCLAVIS_SOURCE_DIR=${PROJECT_SOURCE_DIR}
-P ${PROJECT_SOURCE_DIR}/cmake/RunClangFormat.cmake
COMMENT "Running clang-format on all files"
VERBATIM
)

add_custom_target(format-check
COMMAND ${CLANG_FORMAT} --dry-run --Werror ${ALL_CXX_FILES}
COMMAND ${CMAKE_COMMAND}
-DCLANG_FORMAT_EXECUTABLE=${CLANG_FORMAT}
-DCLAVIS_SOURCE_DIR=${PROJECT_SOURCE_DIR}
-DCLAVIS_FORMAT_CHECK=ON
-P ${PROJECT_SOURCE_DIR}/cmake/RunClangFormat.cmake
COMMENT "Checking code format"
VERBATIM
)
else()
message(STATUS "clang-format not found. Format targets disabled.")
endif()

# clang-tidy target
# Lint production targets only; formatting separately covers every C++ file
# under src/ and tests/, including files not yet registered with a target.
get_target_property(CLAVIS_LIBRARY_SOURCES clavis_algorithm SOURCES)
get_target_property(CLAVIS_EXAMPLE_SOURCES clavis_sorting_example SOURCES)
set(CLAVIS_SOURCE_FILES
${CLAVIS_LIBRARY_SOURCES}
${CLAVIS_EXAMPLE_SOURCES}
)

find_program(CLANG_TIDY clang-tidy
HINTS
$ENV{LLVM_DIR}/bin
Expand All @@ -123,13 +93,12 @@ find_program(CLANG_TIDY clang-tidy
if(CLANG_TIDY)
add_custom_target(lint
COMMAND ${CLANG_TIDY}
-p ${CMAKE_BINARY_DIR}
-header-filter=${CMAKE_SOURCE_DIR}/src/.*
${SRC_CXX_FILES}
--quiet
${CLAVIS_SOURCE_FILES}
--
-x c++
-std=c++20
-I${CMAKE_SOURCE_DIR}/src
-I${PROJECT_SOURCE_DIR}/src
COMMENT "Running clang-tidy on source files"
VERBATIM
)
Expand Down
39 changes: 26 additions & 13 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"$schema": "https://cmake.org/cmake/help/latest/_downloads/3e2d73bff478d88a7de0de736ba5e361/schema.json",
"version": 8,
"version": 6,
"cmakeMinimumRequired": {
"major": 3,
"minor": 25,
Expand All @@ -13,8 +12,6 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_CXX_STANDARD": "20",
"CMAKE_CXX_STANDARD_REQUIRED": "ON",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
Expand All @@ -38,11 +35,17 @@
"name": "ci",
"displayName": "CI",
"inherits": "base",
"generator": "Unix Makefiles",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "quality",
"displayName": "Code Quality",
"inherits": "base",
"cacheVariables": {
"BUILD_TESTING": "OFF"
}
}
],
"buildPresets": [
Expand All @@ -56,8 +59,22 @@
},
{
"name": "ci",
"configurePreset": "ci",
"jobs": 4
"configurePreset": "ci"
},
{
"name": "format",
"configurePreset": "quality",
"targets": ["format"]
},
{
"name": "format-check",
"configurePreset": "quality",
"targets": ["format-check"]
},
{
"name": "lint",
"configurePreset": "quality",
"targets": ["lint"]
}
],
"testPresets": [
Expand Down Expand Up @@ -86,11 +103,7 @@
{
"name": "ci",
"configurePreset": "ci",
"inherits": "base",
"output": {
"outputOnFailure": true,
"verbosity": "verbose"
}
"inherits": "base"
}
],
"workflowPresets": [
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Welcome to Clavis! Here, efficient algorithms and unnecessarily complex C++ code
| CMake | 3.25+ | `brew install cmake` |
| Ninja | any | `brew install ninja` |
| GTest | any | `brew install googletest` |
| LLVM | any | `brew install llvm` |
| LLVM | 16+ | `brew install llvm` |

### Quick Setup (macOS)

Expand Down Expand Up @@ -39,17 +39,21 @@ ctest --preset debug --verbose
|--------|-----------|----------|
| `debug` | Ninja | Local development |
| `release` | Ninja | Production build |
| `ci` | Unix Makefiles | GitHub Actions |
| `ci` | Ninja | GitHub Actions |
| `quality` | Ninja | Code-quality tools |

## Code Quality

```bash
# Configure code-quality tools without requiring GTest
cmake --preset quality

# Format
cmake --build build/debug -t format
cmake --build --preset format

# Format check
cmake --build build/debug -t format-check
cmake --build --preset format-check

# Lint
cmake --build build/debug -t lint
cmake --build --preset lint
```
Loading