diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 070ee77c..4097e9ad 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,17 +31,14 @@ jobs:
vcvarsall: true
- os: "windows-2022"
compiler: "msvc"
- cmake: 3.18.0
cmake_generator: "Ninja"
vcvarsall: true
- os: "windows-2022"
compiler: "msvc"
- cmake: 3.18.0
cmake_generator: "Ninja"
vcvarsall: false
- os: "windows-2022"
compiler: "msvc"
- cmake: 3.18.0
vcvarsall: false
steps:
- uses: actions/checkout@v2
diff --git a/README.md b/README.md
index 988aa012..12c8ba22 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,29 @@
# project_options
-A general-purpose CMake library that provides functions that improve the CMake experience.
-
-It provides different functions such as `project_options`, `package_project`, `dynamic_project_options`, `run_vcpkg`, `target_link_system_libraries`, etc.
+A general-purpose CMake library that provides functions that improve the CMake experience following the best practices.
+
+## Features
+
+- `project_options`:
+ - compiler warnings,
+ - compiler optimizations (intraprocedural, native),
+ - caching (ccache, sccache),
+ - sanitizers,
+ - static code analyzers (clang-tidy, cppcheck, visual studio, include-what-you-use),
+ - document generation (doxygen),
+ - test coverage analysis,
+ - precompiled headers,
+ - build time measurement,
+ - unity builds
+ - using custom linkers (e.g. lld)
+- `package_project`: automatic packaging/installation of the project for seamless usage via find_package/target_link through CMake's FetchContent, vcpkg, etc.
+- `run_vcpkg`: automatic installation of vcpkg and the project dependencies
+- `ENABLE_CONAN` in `project_options`: automatic installation of Conan and the project dependencies
+- `dynamic_project_options`: a wrapper around `project_options` to change the options on the fly dynamically
+- `target_link_system_libraries` and `target_include_system_directories`: linking/including external dependencies/headers without warnings
+- `target_link_cuda`: linking Cuda to a target
+
+[![ci](https://github.com/aminya/project_options/actions/workflows/ci.yml/badge.svg)](https://github.com/aminya/project_options/actions/workflows/ci.yml)
## Usage
@@ -11,17 +32,17 @@ See `project_options()` in action in [this template repository](https://github.c
Here is a full example:
```cmake
-cmake_minimum_required(VERSION 3.16)
+cmake_minimum_required(VERSION 3.20)
# set a default CXX standard for the tools and targets that do not specify them.
# If commented, the latest supported standard for your compiler is automatically set.
# set(CMAKE_CXX_STANDARD 20)
-# Add project_options v0.22.4
+# Add project_options v0.26.1
# https://github.com/aminya/project_options
# Change the version in the following URL to update the package (watch the releases of the repository for future updates)
include(FetchContent)
-FetchContent_Declare(_project_options URL https://github.com/aminya/project_options/archive/refs/tags/v0.22.4.zip)
+FetchContent_Declare(_project_options URL https://github.com/aminya/project_options/archive/refs/tags/v0.26.1.zip)
FetchContent_MakeAvailable(_project_options)
include(${_project_options_SOURCE_DIR}/Index.cmake)
@@ -221,6 +242,7 @@ It accepts the following named flags:
It gets the following named parameters that can have different values in front of them:
+- `PREFIX`: the optional prefix that is used to define `${PREFIX}_project_options` and `${PREFIX}_project_warnings` targets when the function is used in a multi-project fashion.
- `DOXYGEN_THEME`: the name of the Doxygen theme to use. Supported themes:
- `awesome-sidebar` (default)
- `awesome`
@@ -232,15 +254,32 @@ It gets the following named parameters that can have different values in front o
- `CLANG_WARNINGS`: Override the defaults for the CLANG warnings
- `GCC_WARNINGS`: Override the defaults for the GCC warnings
- `CUDA_WARNINGS`: Override the defaults for the CUDA warnings
-- `CPPCHECK_WARNINGS`: Override the defaults for the options passed to cppcheck
+- `CPPCHECK_OPTIONS`: Override the defaults for the options passed to cppcheck
- `VS_ANALYSIS_RULESET`: Override the defaults for the code analysis rule set in Visual Studio.
- `CONAN_OPTIONS`: Extra Conan options
## `run_vcpkg` function
+```cmake
+run_vcpkg()
+```
+
+Or by specifying the options
+
+```cmake
+run_vcpkg(
+ VCPKG_URL "https://github.com/microsoft/vcpkg.git"
+ VCPKG_REV "33c8f025390f8682811629b6830d2d66ecedcaa5"
+ ENABLE_VCPKG_UPDATE
+)
+```
+
Named Option:
-- `ENABLE_VCPKG_UPDATE`: (Disabled by default). If enabled, the vcpkg registry is updated before building (using `git pull`). As a result, if some of your vcpkg dependencies have been updated in the registry, they will be rebuilt.
+- `ENABLE_VCPKG_UPDATE`: (Disabled by default). If enabled, the vcpkg registry is updated before building (using `git pull`).
+
+ If `VCPKG_REV` is set to a specific commit sha, no rebuilds are triggered.
+ If `VCPKG_REV` is not specified or is a branch, enabling `ENABLE_VCPKG_UPDATE` will rebuild your updated vcpkg dependencies.
Named String:
@@ -249,6 +288,9 @@ Named String:
- `VCPKG_URL`: (Defaults to `https://github.com/microsoft/vcpkg.git`). This option allows setting the URL of the vcpkg repository. By default, the official vcpkg repository is used.
+- `VCPKG_REV`: This option allows checking out a specific branch name or a commit sha.
+If `VCPKG_REV` is set to a specific commit sha, the builds will become reproducible because that exact commit is always used for the builds. To make sure that this commit sha is pulled, enable `ENABLE_VCPKG_UPDATE`
+
## `target_link_system_libraries` function
A function that accepts the same arguments as `target_link_libraries`. It has the following features:
@@ -303,6 +345,20 @@ Other arguments that are automatically found and manually specifying them is not
- `CONFIG_INSTALL_DESTINATION`: the destination for installation of the configuration files. Defaults to `${CMAKE_INSTALL_DATADIR}/${NAME}`
+## Disabling static analysis for external targets
+
+This function disables static analysis for the given target:
+
+```cmake
+target_disable_static_analysis(some_external_target)
+```
+
+There is also individual functions to disable a specific analysis for the target:
+
+- `target_disable_cpp_check(target)`
+- `target_disable_vs_analysis(target)`
+- `target_disable_clang_tidy(target)`
+
## Changing the project_options dynamically
During the test and development, it can be useful to change options on the fly. For example, to enable sanitizers when running tests. You can include `DynamicOptions.cmake`, which imports the `dynamic_project_options` function.
@@ -329,17 +385,17 @@ See `dynamic_project_options()` in action in [this template repository](https://
👉 Click to show the example:
```cmake
-cmake_minimum_required(VERSION 3.16)
+cmake_minimum_required(VERSION 3.20)
# set a default CXX standard for the tools and targets that do not specify them.
# If commented, the latest supported standard for your compiler is automatically set.
# set(CMAKE_CXX_STANDARD 20)
-# Add project_options v0.22.4
+# Add project_options v0.26.1
# https://github.com/aminya/project_options
# Change the version in the following URL to update the package (watch the releases of the repository for future updates)
include(FetchContent)
-FetchContent_Declare(_project_options URL https://github.com/aminya/project_options/archive/refs/tags/v0.22.4.zip)
+FetchContent_Declare(_project_options URL https://github.com/aminya/project_options/archive/refs/tags/v0.26.1.zip)
FetchContent_MakeAvailable(_project_options)
include(${_project_options_SOURCE_DIR}/Index.cmake)
diff --git a/cspell.config.yaml b/cspell.config.yaml
index 0aa60cb0..d3fe0b48 100644
--- a/cspell.config.yaml
+++ b/cspell.config.yaml
@@ -22,12 +22,14 @@ words:
- ccmake
- choco
- cmake
+ - CMAKE
- cmakelint
- cmds
- cond
- CPATH
- Cppcheck
- cppcoreguidelines
+ - cppdbg
- CPPFLAGS
- cpprc
- ctest
@@ -45,6 +47,7 @@ words:
- gcovr
- Graphviz
- hwrap
+ - iwwu
- kcov
- LDFLAGS
- libc
@@ -62,6 +65,7 @@ words:
- myprogram
- myproj
- myproject
+ - mythirdpartylib
- nothrow
- nvcc
- Opencppcoverage
@@ -104,10 +108,3 @@ words:
- Wuseless
- xcrun
- Yahyaabadi
- - "ARGN"
- - "CMAKE"
- - "fargs"
- - "shlib"
- - "vcpkg"
- - cppdbg
- - mythirdpartylib
diff --git a/src/Common.cmake b/src/Common.cmake
index 499992fb..3deb3c9d 100644
--- a/src/Common.cmake
+++ b/src/Common.cmake
@@ -1,7 +1,17 @@
include_guard()
+# This function sets ProjectOptions_SRC_DIR using the current lists path
+macro(set_project_options_src_dir)
+ get_directory_property(LISTFILE_STACK LISTFILE_STACK)
+ list(POP_BACK LISTFILE_STACK _LIST_FILE)
+ cmake_path(GET _LIST_FILE PARENT_PATH ProjectOptions_SRC_DIR)
+endmacro()
+
# Common project settings run by default for all the projects that call `project_options()`
macro(common_project_options)
+ set_project_options_src_dir()
+ message(DEBUG "${ProjectOptions_SRC_DIR}")
+
include("${ProjectOptions_SRC_DIR}/PreventInSourceBuilds.cmake")
assure_out_of_source_builds()
diff --git a/src/CompilerWarnings.cmake b/src/CompilerWarnings.cmake
index b4fb252a..db895867 100644
--- a/src/CompilerWarnings.cmake
+++ b/src/CompilerWarnings.cmake
@@ -44,6 +44,7 @@ function(
set(CLANG_WARNINGS
-Wall
-Wextra # reasonable and standard
+ -Wextra-semi # Warn about semicolon after in-class function definition.
-Wshadow # warn the user if a variable declaration shadows one from a parent context
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
# catch hard to track down memory errors
diff --git a/src/Conan.cmake b/src/Conan.cmake
index 9067a3eb..b27200b0 100644
--- a/src/Conan.cmake
+++ b/src/Conan.cmake
@@ -56,7 +56,7 @@ macro(run_conan)
if(NOT ${_is_verbose})
set(OUTPUT_QUIET "OUTPUT_QUIET")
else()
- set(OUTPUT_QUIET OFF)
+ set(OUTPUT_QUIET)
endif()
foreach(TYPE ${LIST_OF_BUILD_TYPES})
@@ -69,7 +69,11 @@ macro(run_conan)
set(CONAN_ENV ENV "CC=${CMAKE_C_COMPILER}" "CXX=${CMAKE_CXX_COMPILER}")
else()
# Derive all conan settings from a conan profile
- set(CONAN_SETTINGS PROFILE ${ProjectOptions_CONAN_PROFILE})
+ set(CONAN_SETTINGS
+ PROFILE
+ ${ProjectOptions_CONAN_PROFILE}
+ SETTINGS
+ "build_type=${TYPE}")
# CONAN_ENV should be redundant, since the profile can set CC & CXX
endif()
diff --git a/src/Index.cmake b/src/Index.cmake
index 23fb5ba3..71c8f588 100644
--- a/src/Index.cmake
+++ b/src/Index.cmake
@@ -1,46 +1,39 @@
-if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.18.0")
- cmake_minimum_required(VERSION 3.18)
-else()
- cmake_minimum_required(VERSION 3.16)
- message(
- WARNING
- "Consider upgrading CMake to the latest version. CMake ${CMAKE_VERSION} might fail in the linking stage because of missing references."
- )
-endif()
+cmake_minimum_required(VERSION 3.20)
+# 3.20 is required by the windows toolchain and cmake_path. It also has a more reliable building functionality.
+# 3.18 required by package_project and interprocedural optimization. It also has a more reliable building functionality (no errors during the linking stage).
include_guard()
-set(ProjectOptions_SRC_DIR
- ${CMAKE_CURRENT_LIST_DIR}
- CACHE FILEPATH "")
+# only useable here
+set(ProjectOptions_SRC_DIR ${CMAKE_CURRENT_LIST_DIR})
# include the files to allow calling individual functions (including the files does not run any code.)
-include("${ProjectOptions_SRC_DIR}/Common.cmake")
-include("${ProjectOptions_SRC_DIR}/Utilities.cmake")
-include("${ProjectOptions_SRC_DIR}/Vcpkg.cmake")
-include("${ProjectOptions_SRC_DIR}/SystemLink.cmake")
-include("${ProjectOptions_SRC_DIR}/Cuda.cmake")
-include("${ProjectOptions_SRC_DIR}/PackageProject.cmake")
-include("${ProjectOptions_SRC_DIR}/Optimization.cmake")
-include("${ProjectOptions_SRC_DIR}/Cache.cmake")
-include("${ProjectOptions_SRC_DIR}/Linker.cmake")
-include("${ProjectOptions_SRC_DIR}/CompilerWarnings.cmake")
-include("${ProjectOptions_SRC_DIR}/Tests.cmake")
-include("${ProjectOptions_SRC_DIR}/Sanitizers.cmake")
-include("${ProjectOptions_SRC_DIR}/Doxygen.cmake")
-include("${ProjectOptions_SRC_DIR}/StaticAnalyzers.cmake")
-include("${ProjectOptions_SRC_DIR}/VCEnvironment.cmake")
-include("${ProjectOptions_SRC_DIR}/MinGW.cmake")
-include("${ProjectOptions_SRC_DIR}/DetectCompiler.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Common.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Utilities.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/SystemLink.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Cuda.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/PackageProject.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Optimization.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Cache.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Linker.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/CompilerWarnings.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Tests.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Sanitizers.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Doxygen.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/StaticAnalyzers.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/VCEnvironment.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/MinGW.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/DetectCompiler.cmake")
# Include msvc toolchain on windows if the generator is not visual studio. Should be called before run_vcpkg and run_conan to be effective
msvc_toolchain()
-include("${ProjectOptions_SRC_DIR}/Conan.cmake")
-include("${ProjectOptions_SRC_DIR}/Vcpkg.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Conan.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/Vcpkg.cmake")
#
# Params:
+# - PREFIX: the optional prefix to be prepended to the `project_options` and `project_warnings` targets when the function is used in a multi-project fashion.
# - WARNINGS_AS_ERRORS: Treat compiler warnings as errors
# - ENABLE_CPPCHECK: Enable static analysis with cppcheck
# - ENABLE_CLANG_TIDY: Enable static analysis with clang-tidy
@@ -94,7 +87,11 @@ macro(project_options)
ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
ENABLE_SANITIZER_THREAD
ENABLE_SANITIZER_MEMORY)
- set(oneValueArgs LINKER VS_ANALYSIS_RULESET CONAN_PROFILE)
+ set(oneValueArgs
+ PREFIX
+ LINKER
+ VS_ANALYSIS_RULESET
+ CONAN_PROFILE)
set(multiValueArgs
DOXYGEN_THEME
MSVC_WARNINGS
@@ -121,8 +118,26 @@ macro(project_options)
common_project_options()
- # Link this 'library' to set the c++ standard / compile-time options requested
- add_library(project_options INTERFACE)
+ # Add an interface library for the options
+ set(_options_target project_options)
+ set(_warnings_target project_warnings)
+ if(NOT
+ "${ProjectOptions_PREFIX}"
+ STREQUAL
+ "")
+ set(_options_target "${ProjectOptions_PREFIX}_project_options")
+ set(_warnings_target "${ProjectOptions_PREFIX}_project_warnings")
+ else()
+ if(TARGET project_options)
+ message(
+ FATAL
+ "Multiple calls to `project_options` in the same `project` detected, but the argument `PREFIX` that is prepended to `project_options` and `project_warnings` is not set."
+ )
+ endif()
+ endif()
+
+ add_library(${_options_target} INTERFACE)
+ add_library(${_warnings_target} INTERFACE)
# fix mingw
mingw_unicode()
@@ -135,33 +150,30 @@ macro(project_options)
set(ProjectOptions_ENABLE_INTERPROCEDURAL_OPTIMIZATION ${ProjectOptions_ENABLE_IPO})
endif()
if(${ProjectOptions_ENABLE_INTERPROCEDURAL_OPTIMIZATION})
- enable_interprocedural_optimization(project_options)
+ enable_interprocedural_optimization(${_options_target})
endif()
if(${ProjectOptions_ENABLE_NATIVE_OPTIMIZATION})
- enable_native_optimization(project_options)
+ enable_native_optimization(${_options_target})
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
if(ProjectOptions_ENABLE_BUILD_WITH_TIME_TRACE)
- target_compile_options(project_options INTERFACE -ftime-trace)
+ target_compile_options(${_options_target} INTERFACE -ftime-trace)
endif()
endif()
- # Link this 'library' to use the warnings specified in CompilerWarnings.cmake
- add_library(project_warnings INTERFACE)
-
if(${ProjectOptions_ENABLE_CACHE})
# enable cache system
enable_cache()
endif()
# use the linker
- configure_linker(project_options "${ProjectOptions_LINKER}")
+ configure_linker(${_options_target} "${ProjectOptions_LINKER}")
# standard compiler warnings
set_project_warnings(
- project_warnings
+ ${_warnings_target}
"${WARNINGS_AS_ERRORS}"
"${ProjectOptions_MSVC_WARNINGS}"
"${ProjectOptions_CLANG_WARNINGS}"
@@ -169,12 +181,12 @@ macro(project_options)
"${ProjectOptions_CUDA_WARNINGS}")
if(${ProjectOptions_ENABLE_COVERAGE})
- enable_coverage(project_options)
+ enable_coverage(${_options_target})
endif()
# sanitizer options if supported by compiler
enable_sanitizers(
- project_options
+ ${_options_target}
${ProjectOptions_ENABLE_SANITIZER_ADDRESS}
${ProjectOptions_ENABLE_SANITIZER_LEAK}
${ProjectOptions_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR}
@@ -211,7 +223,7 @@ macro(project_options)