Update: Using C++26 with contracts enabled
This commit is contained in:
@@ -12,6 +12,22 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"GCC 16+ is required (found ${CMAKE_CXX_COMPILER_VERSION}). "
|
||||||
|
"Use the 'default' CMake preset or cmake/toolchains/gcc-16.cmake."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"This project requires GCC 16+. Found compiler: ${CMAKE_CXX_COMPILER_ID}. "
|
||||||
|
"Select the GCC 16 toolchain / default CMake preset in CLion."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
option(COURSE_BUILD_TESTS "Build Google Test exercise targets" ON)
|
option(COURSE_BUILD_TESTS "Build Google Test exercise targets" ON)
|
||||||
option(COURSE_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF)
|
option(COURSE_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF)
|
||||||
option(COURSE_ENABLE_CONTRACTS "Enable C++26 contracts on GCC 16+" ON)
|
option(COURSE_ENABLE_CONTRACTS "Enable C++26 contracts on GCC 16+" ON)
|
||||||
@@ -37,3 +53,6 @@ if(COURSE_BUILD_TESTS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(modules)
|
add_subdirectory(modules)
|
||||||
|
|
||||||
|
include(Cppcheck)
|
||||||
|
course_add_cppcheck_targets()
|
||||||
|
|||||||
+17
-3
@@ -10,11 +10,21 @@
|
|||||||
"name": "default",
|
"name": "default",
|
||||||
"displayName": "GCC 16 + C++26",
|
"displayName": "GCC 16 + C++26",
|
||||||
"generator": "Unix Makefiles",
|
"generator": "Unix Makefiles",
|
||||||
"binaryDir": "${sourceDir}/build",
|
"binaryDir": "${sourceDir}/cmake-build-debug-gcc-16-cpp26",
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/gcc-16.cmake",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "Debug",
|
"CMAKE_BUILD_TYPE": "Debug",
|
||||||
"CMAKE_C_COMPILER": "/opt/homebrew/bin/gcc-16",
|
"COURSE_ENABLE_CONTRACTS": "ON"
|
||||||
"CMAKE_CXX_COMPILER": "/opt/homebrew/bin/g++-16",
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release",
|
||||||
|
"displayName": "GCC 16 + C++26 (Release)",
|
||||||
|
"generator": "Unix Makefiles",
|
||||||
|
"binaryDir": "${sourceDir}/cmake-build-release-gcc-16-cpp26",
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/gcc-16.cmake",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release",
|
||||||
"COURSE_ENABLE_CONTRACTS": "ON"
|
"COURSE_ENABLE_CONTRACTS": "ON"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,6 +33,10 @@
|
|||||||
{
|
{
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"configurePreset": "default"
|
"configurePreset": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release",
|
||||||
|
"configurePreset": "release"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"testPresets": [
|
"testPresets": [
|
||||||
|
|||||||
@@ -17,37 +17,40 @@ brew install gcc@16
|
|||||||
|
|
||||||
## Quick Start (CLion)
|
## Quick Start (CLion)
|
||||||
|
|
||||||
1. Open this folder in CLion (`File → Open…`).
|
1. Open this folder in CLion.
|
||||||
2. Use the **`default`** CMake profile (`GCC 16 + C++26` from `CMakePresets.json`).
|
2. **Settings → Build, Execution, Deployment → CMake**
|
||||||
3. Set the toolchain to **GCC 16** (`/opt/homebrew/bin/g++-16`).
|
3. Enable profile **`default`** (display name **GCC 16 + C++26** from `CMakePresets.json`).
|
||||||
4. **Disable Clang-based analysis** (this project targets GCC only):
|
4. Disable old profiles that use Apple Clang (e.g. custom profiles without the preset toolchain).
|
||||||
- **Settings → Languages & Frameworks → C/C++ → Clangd** → disable, **or**
|
5. Click **Reload CMake Project**.
|
||||||
- **Settings → Editor → Inspections → C/C++ → General → Clang-Tidy** → disable
|
|
||||||
5. Reload CMake, pick an exercise target (e.g. `02_control_flow_loops`), implement TODOs, run tests.
|
If configure fails with *"This project requires GCC 16+"*, CLion is still using Apple Clang. Enable the **`default`** preset or set the toolchain C++ compiler to `g++-16`.
|
||||||
|
|
||||||
|
If configure fails with *"generator does not match"*, delete the build folder (`cmake-build-debug-gcc-16-cpp26`) and reload CMake.
|
||||||
|
|
||||||
|
6. Pick an exercise target (e.g. `02_control_flow_loops`) and run tests.
|
||||||
|
|
||||||
## Quick Start (Terminal)
|
## Quick Start (Terminal)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake --preset default
|
cmake --preset default
|
||||||
cmake --build build
|
cmake --build cmake-build-debug-gcc-16-cpp26
|
||||||
ctest --test-dir build --output-on-failure
|
ctest --test-dir cmake-build-debug-gcc-16-cpp26 --output-on-failure
|
||||||
```
|
```
|
||||||
|
|
||||||
Run a single exercise:
|
Run a single exercise:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake --build build --target 02_control_flow_loops
|
cmake --build cmake-build-debug-gcc-16-cpp26 --target 02_control_flow_loops
|
||||||
./build/modules/02_control_flow/02_control_flow_loops
|
./cmake-build-debug-gcc-16-cpp26/modules/02_control_flow/02_control_flow_loops
|
||||||
```
|
```
|
||||||
|
|
||||||
Manual configure (without presets):
|
Manual configure (without presets):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake -S . -B build \
|
cmake -S . -B cmake-build-debug-gcc-16-cpp26 \
|
||||||
-DCMAKE_CXX_COMPILER=/opt/homebrew/bin/g++-16 \
|
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/gcc-16.cmake \
|
||||||
-DCMAKE_C_COMPILER=/opt/homebrew/bin/gcc-16 \
|
|
||||||
-DCOURSE_ENABLE_CONTRACTS=ON
|
-DCOURSE_ENABLE_CONTRACTS=ON
|
||||||
cmake --build build
|
cmake --build cmake-build-debug-gcc-16-cpp26
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
@@ -143,10 +146,43 @@ auto factorial(const int n) -> long long
|
|||||||
|
|
||||||
- Use the **GCC 16** toolchain, not Apple Clang.
|
- Use the **GCC 16** toolchain, not Apple Clang.
|
||||||
- Disable **Clangd** and **Clang-Tidy** inspections — they use the Clang frontend and do not support GCC C++26 contracts.
|
- Disable **Clangd** and **Clang-Tidy** inspections — they use the Clang frontend and do not support GCC C++26 contracts.
|
||||||
- Use CLion’s built-in **GCC** parser/inspections, or rely on compiler errors from the build.
|
- **Cppcheck plugin:** disable inline analysis for this project (see [Cppcheck](#cppcheck) below).
|
||||||
- Use **Run | Run…** and filter by module prefix (e.g. `02_control_flow`).
|
- Use **Run | Run…** and filter by module prefix (e.g. `02_control_flow`).
|
||||||
- Enable **Google Test** integration to see individual tests in the tree view.
|
- Enable **Google Test** integration to see individual tests in the tree view.
|
||||||
|
|
||||||
|
## Cppcheck
|
||||||
|
|
||||||
|
Cppcheck **does not understand GCC C++26 contracts** (`pre(...)`) or GCC 16 libstdc++ when the CLion plugin analyzes headers in isolation. That produces false IDE errors such as:
|
||||||
|
|
||||||
|
- `Include file: <contracts> not found`
|
||||||
|
- `failed to evaluate #elif condition` in libstdc++ headers
|
||||||
|
- parse errors on `pre(...)`
|
||||||
|
|
||||||
|
### Recommended: disable the plugin, use the CMake target
|
||||||
|
|
||||||
|
1. **Settings → Editor → Inspections → C/C++ → Cppcheck** → **disable**
|
||||||
|
2. Configure and build once:
|
||||||
|
```bash
|
||||||
|
cmake --preset default
|
||||||
|
cmake --build build
|
||||||
|
```
|
||||||
|
3. Run Cppcheck from CLion or terminal:
|
||||||
|
```bash
|
||||||
|
cmake --build build --target cppcheck_modules
|
||||||
|
```
|
||||||
|
|
||||||
|
This uses `compile_commands.json` from your **GCC 16** build and suppresses known false positives (`cppcheck/suppressions.txt`).
|
||||||
|
|
||||||
|
### If you keep the plugin anyway
|
||||||
|
|
||||||
|
**Settings → Cppcheck configuration → Options:**
|
||||||
|
|
||||||
|
```
|
||||||
|
--language=c++ --std=c++26 --max-configs=1 --suppress=missingIncludeSystem --suppress=syntaxError
|
||||||
|
```
|
||||||
|
|
||||||
|
Expect remaining false positives on contract syntax. The plugin is not a good fit for this codebase.
|
||||||
|
|
||||||
## Notes on C++26
|
## Notes on C++26
|
||||||
|
|
||||||
All exercises build with **C++26**. Module READMEs describe the language feature each exercise teaches (C++11, C++17, etc.), but the toolchain baseline is C++26 throughout.
|
All exercises build with **C++26**. Module READMEs describe the language feature each exercise teaches (C++11, C++17, etc.), but the toolchain baseline is C++26 throughout.
|
||||||
|
|||||||
@@ -21,7 +21,20 @@ function(course_apply_warnings target_name)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(course_set_cxx_standard target_name standard)
|
function(course_set_cxx_standard target_name standard)
|
||||||
target_compile_features(${target_name} PRIVATE cxx_std_${standard})
|
# Use explicit -std flags so older CLion/CMake builds still get C++26.
|
||||||
|
if(standard GREATER_EQUAL 26)
|
||||||
|
target_compile_options(${target_name} PRIVATE -std=c++26)
|
||||||
|
elseif(standard GREATER_EQUAL 23)
|
||||||
|
target_compile_options(${target_name} PRIVATE -std=c++23)
|
||||||
|
elseif(standard GREATER_EQUAL 20)
|
||||||
|
target_compile_options(${target_name} PRIVATE -std=c++20)
|
||||||
|
elseif(standard GREATER_EQUAL 17)
|
||||||
|
target_compile_options(${target_name} PRIVATE -std=c++17)
|
||||||
|
elseif(standard GREATER_EQUAL 14)
|
||||||
|
target_compile_options(${target_name} PRIVATE -std=c++14)
|
||||||
|
else()
|
||||||
|
target_compile_options(${target_name} PRIVATE -std=c++11)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(course_enable_contracts target_name)
|
function(course_enable_contracts target_name)
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
# Use GCC 16 for C++26 contracts support on macOS (Homebrew).
|
# GCC 16 toolchain for C++26 and contracts.
|
||||||
set(CMAKE_C_COMPILER "/opt/homebrew/bin/gcc-16" CACHE FILEPATH "C compiler")
|
find_program(
|
||||||
set(CMAKE_CXX_COMPILER "/opt/homebrew/bin/g++-16" CACHE FILEPATH "C++ compiler")
|
COURSE_GCC16_C
|
||||||
|
NAMES gcc-16
|
||||||
|
HINTS /opt/homebrew/bin /usr/local/bin /opt/local/bin
|
||||||
|
)
|
||||||
|
find_program(
|
||||||
|
COURSE_GCC16_CXX
|
||||||
|
NAMES g++-16
|
||||||
|
HINTS /opt/homebrew/bin /usr/local/bin /opt/local/bin
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT COURSE_GCC16_CXX)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"g++-16 not found. Install GCC 16, e.g. 'brew install gcc@16', "
|
||||||
|
"then ensure g++-16 is on your PATH."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER "${COURSE_GCC16_C}" CACHE FILEPATH "C compiler" FORCE)
|
||||||
|
set(CMAKE_CXX_COMPILER "${COURSE_GCC16_CXX}" CACHE FILEPATH "C++ compiler" FORCE)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
add_library(course_contract_support STATIC contract_handler.cpp)
|
add_library(course_contract_support STATIC contract_handler.cpp)
|
||||||
target_compile_features(course_contract_support PUBLIC cxx_std_26)
|
target_compile_options(course_contract_support PUBLIC -std=c++26)
|
||||||
set_target_properties(course_contract_support PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
set_target_properties(course_contract_support PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND COURSE_ENABLE_CONTRACTS)
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND COURSE_ENABLE_CONTRACTS)
|
||||||
|
|||||||
Reference in New Issue
Block a user