diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..e656eab --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Coding-Cuddles/kata-maintainers diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ca79ca5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 255c5f4..f4a77e1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Check formatting run: make format-check @@ -22,11 +22,11 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 + env: + GTEST_COLOR: "1" - - name: Build - run: make build + steps: + - uses: actions/checkout@v7 - name: Test run: make test diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 9ed5ca3..b64ae0d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -17,8 +17,7 @@ "group": { "kind": "test", "isDefault": true - }, - "dependsOn": "Build" + } }, { "label": "Format", @@ -30,4 +29,4 @@ "problemMatcher": [] } ] -} \ No newline at end of file +} diff --git a/CMakeLists.txt b/CMakeLists.txt index ce4f254..b4380e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,12 @@ -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.24) project(bootstrap-cpp-kata CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_COLOR_DIAGNOSTICS ON) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) @@ -32,5 +34,6 @@ if(UNIX) copy_if_different ${CMAKE_BINARY_DIR}/compile_commands.json ${CMAKE_CURRENT_LIST_DIR} + COMMENT "Copying compile commands to the source directory" ) endif() diff --git a/Makefile b/Makefile index 1bd5a45..c4edc25 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,47 @@ -all: build test +COLOR_CYAN := \033[36m +COLOR_RESET := \033[0m + +CLICOLOR ?= 1 +GTEST_COLOR ?= 1 +export CLICOLOR GTEST_COLOR BUILDDIR ?= build -SRCS := $(shell git ls-files *.cpp *.h) +BUILDCONFIG ?= Debug +SRCS := $(shell git ls-files '*.cpp' '*.h' '*.hpp') + +.DEFAULT_GOAL := help + +.PHONY: all +all: test ## Build and run tests + +.PHONY: help +help: ## Show this help message + @awk 'BEGIN {FS = ":.*##"; printf "Usage: make [options] $(COLOR_CYAN)[target] ...$(COLOR_RESET)\n\n"} \ + /^[a-zA-Z_-]+:.*##/ {printf " $(COLOR_CYAN)%-20s$(COLOR_RESET) %s\n", $$1, $$2}' \ + $(MAKEFILE_LIST) .PHONY: build -build: - cmake -B ${BUILDDIR} . - cmake --build ${BUILDDIR} +build: ## Configure and build + cmake -S . -B ${BUILDDIR} -DCMAKE_BUILD_TYPE=${BUILDCONFIG} + cmake --build ${BUILDDIR} --config ${BUILDCONFIG} .PHONY: test -test: - ctest --output-on-failure --test-dir ${BUILDDIR} +test: build ## Build and run tests + ctest --test-dir ${BUILDDIR} --build-config ${BUILDCONFIG} --output-on-failure .PHONY: format -format: +format: ## Format C++ sources in place clang-format -i -style=file $(SRCS) .PHONY: format-check -format-check: +format-check: ## Fail if C++ sources require formatting clang-format -style=file --dry-run -Werror $(SRCS) \ || (echo "Some files require formatting. Run 'make format' to fix." && exit 1) .PHONY: clean -clean: - rm -rf ${BUILDDIR} +clean: ## Remove generated build artifacts + rm -rf ${BUILDDIR} compile_commands.json -ifndef VERBOSE +ifneq ($(VERBOSE),1) .SILENT: endif diff --git a/README.md b/README.md index 588fd8d..f5cd427 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,95 @@ # Bootstrap for C++ coding kata [![CI](https://github.com/Coding-Cuddles/bootstrap-cpp-kata/actions/workflows/main.yml/badge.svg)](https://github.com/Coding-Cuddles/bootstrap-cpp-kata/actions/workflows/main.yml) +[![C++17](https://img.shields.io/badge/C%2B%2B-17-blue.svg)](https://en.cppreference.com/w/cpp/17) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -## Overview - -This is a bootstrap repository for clean code katas in C++17 using GoogleTest. +Start a C++17 coding kata with GoogleTest. Setup is complete when the starter +test passes. ## Prerequisites -- A compatible C++ compiler that supports at least C++17 -- [CMake](https://cmake.org) -- [GoogleTest](https://github.com/google/googletest) +Required: + +- [Git](https://git-scm.com/downloads) +- A compiler with C++17 support. Choose one: + - [GCC](https://gcc.gnu.org/) 10+ on Linux + - [LLVM Clang](https://llvm.org/) 14+ on Linux + - [Apple Clang](https://developer.apple.com/xcode/) 17+ on macOS + - [MSVC](https://visualstudio.microsoft.com/) 2022 on Windows +- [CMake 3.24 or later](https://cmake.org) + +Optional: + +- [GNU Make](https://www.gnu.org/software/make/), for shorter commands. Every + required task also has direct CMake and CTest commands. + +You do not need to install GoogleTest separately. CMake finds an installed +copy or downloads the pinned release when needed. + +## Set up the kata + +1. Clone the repository: + + ```console + git clone https://github.com/Coding-Cuddles/bootstrap-cpp-kata.git + ``` + +2. Enter the repository directory: + + ```console + cd bootstrap-cpp-kata + ``` + +3. Run the starter test. Use Make when it is installed: + + ```console + make test + ``` + + Otherwise, use CMake and CTest directly: + + ```console + cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug + cmake --build build --config Debug + ctest --test-dir build --build-config Debug --output-on-failure + ``` + +The first run may download and build GoogleTest. Setup is complete when CTest reports +`100% tests passed`. + +If a command reports a missing compiler or CMake, install that prerequisite +and run the setup commands again. + +## Work on the kata + +1. Replace the starter assertions in `test_something.cpp` with the first kata test. + +2. Run the tests after each change. Use Make when it is installed: + + ```console + make test + ``` + + Otherwise, use CMake and CTest directly: -## Usage + ```console + cmake --build build --config Debug + ctest --test-dir build --build-config Debug --output-on-failure + ``` -### Build + Continue when CTest reports `100% tests passed`. -```console -make build -``` +## Make command reference -### Run tests +Make is optional. Run `make` or `make help` to list these commands in the +terminal. -```console -make test -``` +| Command | Result | +| ------------------- | ----------------------------------------- | +| `make all` | Build and run the test suite | +| `make build` | Configure and build without running tests | +| `make test` | Build and run the test suite | +| `make format` | Format tracked C++ and header files | +| `make format-check` | Check formatting without changing files | +| `make clean` | Remove generated build artifacts | diff --git a/cmake/FetchGTest.cmake b/cmake/FetchGTest.cmake index f3778ae..c801e16 100644 --- a/cmake/FetchGTest.cmake +++ b/cmake/FetchGTest.cmake @@ -1,10 +1,22 @@ include(FetchContent) +# Find an installed GoogleTest package or fetch and verify the pinned release function(fetch_gtest) + string( + CONCAT + gtest_url + "https://github.com/google/googletest/releases/download/" + "v1.17.0/googletest-1.17.0.tar.gz" + ) + set( + gtest_sha256 + 65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c + ) + FetchContent_Declare( googletest - URL https://github.com/google/googletest/releases/download/v1.16.0/googletest-1.16.0.tar.gz - URL_HASH MD5=9a75eb2ac97300cdb8b65b1a5833f411 + URL ${gtest_url} + URL_HASH SHA256=${gtest_sha256} DOWNLOAD_EXTRACT_TIMESTAMP FALSE FIND_PACKAGE_ARGS @@ -13,6 +25,7 @@ function(fetch_gtest) ) # Prevent overriding parent project's compiler/linker settings on Windows + # cmake-lint: disable=C0103 set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) endfunction()