From 8d87b2781b491418ebcf06ec121126c3c6991909 Mon Sep 17 00:00:00 2001 From: Yury Bayda Date: Fri, 31 Jul 2026 19:42:15 -0700 Subject: [PATCH 1/2] feat: streamline cross-platform kata setup Preserve Replit support and the example run target while removing forced Clang, Ninja, and system GoogleTest requirements. Add portable build paths, three-platform CI, ownership, dependency updates, and setup guidance. --- .cmake-format.yaml | 7 +++ .github/CODEOWNERS | 1 + .github/dependabot.yml | 6 ++ .github/workflows/main.yml | 30 +++------- .gitignore | 1 + CMakeLists.txt | 43 +++++++++++---- Makefile | 46 ++++++++++------ README.md | 110 ++++++++++++++++++++++++++++++++----- cmake/FetchGTest.cmake | 31 +++++++++++ 9 files changed, 214 insertions(+), 61 deletions(-) create mode 100644 .cmake-format.yaml create mode 100644 .github/CODEOWNERS create mode 100644 .github/dependabot.yml create mode 100644 cmake/FetchGTest.cmake diff --git a/.cmake-format.yaml b/.cmake-format.yaml new file mode 100644 index 0000000..8606e38 --- /dev/null +++ b/.cmake-format.yaml @@ -0,0 +1,7 @@ +format: + line_width: 100 + tab_size: 4 + use_tabchars: false + max_subgroups_hwrap: 3 + max_pargs_hwrap: 3 + dangle_parens: true 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 d11a83c..f4a77e1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,34 +11,22 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 + - uses: actions/checkout@v7 - name: Check formatting run: make format-check test: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + + env: + GTEST_COLOR: "1" steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install Ninja, GTest, and GMock - run: | - sudo apt-get update - sudo apt-get install \ - google-mock \ - googletest \ - libgmock-dev \ - libgtest-dev \ - ninja-build - - - name: Build - run: make build - - - name: Run main - run: make run + - uses: actions/checkout@v7 - name: Test run: make test diff --git a/.gitignore b/.gitignore index 8de37ca..ae1801a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build +cmake-build-* .cache .ccls-cache compile_commands.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fd44aa..cf83caa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,26 +1,47 @@ -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.24) project(bootstrap-cpp-kata CXX) -enable_testing() 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) + +include(FetchGTest) +fetch_gtest() + +include(GoogleTest) -find_package(GTest REQUIRED) +enable_testing() add_executable(main main.cpp) +add_custom_target( + run + COMMAND $ + DEPENDS main + COMMENT "Running the example executable" +) file(GLOB tests test_*.cpp) foreach(test ${tests}) get_filename_component(name ${test} NAME_WE) add_executable(${name} ${test}) - add_test(${name} ${name}) - target_link_libraries(${name} PRIVATE GTest::gmock GTest::gmock_main) + target_link_libraries(${name} PRIVATE GTest::gmock_main) + + gtest_discover_tests(${name}) endforeach() -add_custom_target( - copy-compile-commands ALL - ${CMAKE_COMMAND} -E copy_if_different - ${CMAKE_BINARY_DIR}/compile_commands.json - ${CMAKE_CURRENT_LIST_DIR} -) +if(UNIX) + add_custom_target( + copy-compile-commands ALL + ${CMAKE_COMMAND} + -E + 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 f268d8c..ec77c7a 100644 --- a/Makefile +++ b/Makefile @@ -1,37 +1,51 @@ -all: build test +COLOR_CYAN := \033[36m +COLOR_RESET := \033[0m -export CXX := clang++ -export GTEST_COLOR := 1 +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} -G Ninja . - cmake --build ${BUILDDIR} +build: ## Configure and build + cmake -S . -B ${BUILDDIR} -DCMAKE_BUILD_TYPE=${BUILDCONFIG} + cmake --build ${BUILDDIR} --config ${BUILDCONFIG} .PHONY: run -run: - cd ${BUILDDIR} && ./main +run: build ## Build and run the example executable + cmake --build ${BUILDDIR} --config ${BUILDCONFIG} --target run .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 2938a12..ab9c653 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Roman numerals kata in C++ [![CI](https://github.com/Coding-Cuddles/roman-numerals-cpp-kata/actions/workflows/main.yml/badge.svg)](https://github.com/Coding-Cuddles/roman-numerals-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) [![Replit](https://img.shields.io/badge/Try%20with%20Replit-black?logo=replit)](https://replit.com/new/github/Coding-Cuddles/roman-numerals-cpp-kata) ## Overview @@ -62,33 +64,115 @@ their corresponding Arabic digits. * If you do know an algorithm, evaluate if it can be implemented using strict TDD principles. -This is a bootstrap repository for clean code katas in C++17 using GTest. +This is a C++17 kata using GoogleTest. Setup is complete when CTest reports +`100% tests passed`. -## Usage +## Prerequisites -You can import this project into [Replit](https://replit.com), and it will -handle all dependencies automatically. +Required: -### Prerequisites +- [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) -* [CMake 3.19+](https://cmake.org) -* [Ninja](https://ninja-build.org) -* [GTest](https://github.com/google/googletest) +Optional: -### Build +- [GNU Make](https://www.gnu.org/software/make/), for shorter commands. Every + required task also has direct CMake and CTest commands. Make may be + unavailable on Windows. + +You do not need to install GoogleTest separately. CMake finds an installed +copy or downloads the pinned release when needed. + +## Set up the kata + +You can also import the project into [Replit](https://replit.com), which +provides the required dependencies. + +1. Clone the repository: + + ```console + git clone https://github.com/Coding-Cuddles/roman-numerals-cpp-kata.git + ``` + +2. Enter the repository directory: + + ```console + cd roman-numerals-cpp-kata + ``` + +3. Build and run the tests. 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. CTest should report +`100% tests passed`. If a command reports a missing compiler or CMake, install +that prerequisite and run the setup commands again. Setup is complete when +CTest reports `100% tests passed`. + +## Work on the kata + +Add one test at a time to `test_roman_numerals.cpp`, then implement enough code +in `roman_numerals.h` to make the test pass. Keep the existing exercises and +constraints above as the target behavior. + +After each change, use Make when it is installed: ```console -make build +make test ``` -### Run main +Otherwise, use CMake and CTest directly: + +```console +cmake --build build --config Debug +ctest --test-dir build --build-config Debug --output-on-failure +``` + +Continue when CTest reports `100% tests passed`. + +## Run the example + +Use Make when it is installed: ```console make run ``` -### Run tests +Otherwise, use the CMake run target: ```console -make test +cmake --build build --config Debug --target run ``` + +The executable prints `Hello World!`. + +## Make command reference + +Make is optional. Run `make` or `make help` to list these commands in the +terminal. + +| Command | Result | +| ------------------- | ----------------------------------------- | +| `make all` | Build and run the test suite | +| `make help` | List public Make targets | +| `make build` | Configure and build without running tests | +| `make run` | Build and run the example executable | +| `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 new file mode 100644 index 0000000..c801e16 --- /dev/null +++ b/cmake/FetchGTest.cmake @@ -0,0 +1,31 @@ +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 ${gtest_url} + URL_HASH SHA256=${gtest_sha256} + DOWNLOAD_EXTRACT_TIMESTAMP + FALSE + FIND_PACKAGE_ARGS + NAMES + 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() From 205b641c30914f440fdaa8e5abebd64933c27fbe Mon Sep 17 00:00:00 2001 From: Yury Bayda Date: Fri, 31 Jul 2026 19:45:54 -0700 Subject: [PATCH 2/2] docs: qualify Replit setup guidance --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ab9c653..a36a9b0 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,8 @@ copy or downloads the pinned release when needed. ## Set up the kata -You can also import the project into [Replit](https://replit.com), which -provides the required dependencies. +The tracked Replit configuration is retained. The local setup below is the +validated development path. 1. Clone the repository: