diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f018aff..b4c7b807 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,18 +22,32 @@ jobs: - gcc cmake: - true + vcvarsall: + - true include: - os: "windows-2022" compiler: "msvc" cmake: true + 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 exclude: - os: "windows-2022" compiler: "gcc" cmake: true + vcvarsall: true steps: - uses: actions/checkout@v2 - name: Cache @@ -54,7 +68,7 @@ jobs: uses: aminya/setup-cpp@v1 with: compiler: ${{ matrix.compiler }} - vcvarsall: ${{ contains(matrix.os, 'windows') }} + vcvarsall: ${{ contains(matrix.os, 'windows') && matrix.vcvarsall }} cmake: ${{ matrix.cmake }} ninja: true vcpkg: true diff --git a/README.md b/README.md index d1419893..95d17dc7 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,11 @@ cmake_minimum_required(VERSION 3.16) # If commented, the latest supported standard for your compiler is automatically set. # set(CMAKE_CXX_STANDARD 20) -# Add project_options v0.20.0 +# Add project_options v0.21.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.20.0.zip) +FetchContent_Declare(_project_options URL https://github.com/aminya/project_options/archive/refs/tags/v0.21.1.zip) FetchContent_MakeAvailable(_project_options) include(${_project_options_SOURCE_DIR}/Index.cmake) @@ -90,6 +90,7 @@ project_options( # ENABLE_USER_LINKER # ENABLE_BUILD_WITH_TIME_TRACE # ENABLE_UNITY + # CONAN_PROFILE ${profile_path} # passes a profile to conan: see https://docs.conan.io/en/latest/reference/profiles.html ) ``` @@ -214,7 +215,11 @@ It accepts the following named flags: It gets the following named parameters that can have different values in front of them: -- `DOXYGEN_THEME`: the name of the Doxygen theme to use. Supported themes: `awesome-sidebar` (default), `awesome` and `original`. +- `DOXYGEN_THEME`: the name of the Doxygen theme to use. Supported themes: + - `awesome-sidebar` (default) + - `awesome` + - `original` + - Alternatively you can supply a list of css files to be added to [DOXYGEN_HTML_EXTRA_STYLESHEET](https://www.doxygen.nl/manual/config.html#cfg_html_extra_stylesheet) - `PCH_HEADERS`: the list of the headers to precompile - `MSVC_WARNINGS`: Override the defaults for the MSVC warnings - `CLANG_WARNINGS`: Override the defaults for the CLANG warnings @@ -323,11 +328,11 @@ cmake_minimum_required(VERSION 3.16) # If commented, the latest supported standard for your compiler is automatically set. # set(CMAKE_CXX_STANDARD 20) -# Add project_options v0.20.0 +# Add project_options v0.21.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.20.0.zip) +FetchContent_Declare(_project_options URL https://github.com/aminya/project_options/archive/refs/tags/v0.21.1.zip) FetchContent_MakeAvailable(_project_options) include(${_project_options_SOURCE_DIR}/Index.cmake) diff --git a/cspell.config.yaml b/cspell.config.yaml index 5f277f89..d107cc6f 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -12,6 +12,7 @@ enableGlobDot: true words: - aarch - aminya + - Amnet - anotherproj - applellvm - ARGN @@ -73,6 +74,7 @@ words: - shlib - suppr - TOLOWER + - TOUPPER - ubsan - vcpkg - vcvarsall diff --git a/src/Common.cmake b/src/Common.cmake index c0979816..45f3265d 100644 --- a/src/Common.cmake +++ b/src/Common.cmake @@ -21,6 +21,38 @@ macro(common_project_options) "RelWithDebInfo") endif() + get_property(BUILDING_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(BUILDING_MULTI_CONFIG) + if(NOT CMAKE_BUILD_TYPE) + # Make sure that all supported configuration types have their + # associated conan packages available. You can reduce this + # list to only the configuration types you use, but only if one + # is not forced-set on the command line for VS + message(TRACE "Setting up multi-config build types") + set(CMAKE_CONFIGURATION_TYPES + Debug + Release + RelWithDebInfo + MinSizeRel + CACHE STRING "Enabled build types" FORCE) + else() + message(TRACE "User chose a specific build type, so we are using that") + set(CMAKE_CONFIGURATION_TYPES + ${CMAKE_BUILD_TYPE} + CACHE STRING "Enabled build types" FORCE) + endif() + endif() + + # Fix for Amnet/Colcon + if(NOT + "${AMENT_PREFIX_PATH}" + STREQUAL + "" + OR "$ENV{COLCON}" STREQUAL "1") + # these are used in order: + set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO "RelWithDebInfo;Release;None;NoConfig") + endif() + # Generate compile_commands.json to make it easier to work with clang based tools set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -50,6 +82,5 @@ macro(common_project_options) set_standards() # run vcvarsall when msvc is used - include("${ProjectOptions_SRC_DIR}/VCEnvironment.cmake") run_vcvarsall() endmacro() diff --git a/src/Conan.cmake b/src/Conan.cmake index 7a1ba303..9067a3eb 100644 --- a/src/Conan.cmake +++ b/src/Conan.cmake @@ -33,46 +33,63 @@ macro(run_conan) URL https://bincrafters.jfrog.io/artifactory/api/conan/public-conan) - # For multi configuration generators, like VS and XCode - if(NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Single configuration build!") - set(LIST_OF_BUILD_TYPES ${CMAKE_BUILD_TYPE}) + if(CONAN_EXPORTED) + # standard conan installation, in which deps will be defined in conanfile. It is not necessary to call conan again, as it is already running. + if(EXISTS "${CMAKE_BINARY_DIR}/../conanbuildinfo.cmake") + include(${CMAKE_BINARY_DIR}/../conanbuildinfo.cmake) + else() + message( + FATAL_ERROR "Could not set up conan because \"${CMAKE_BINARY_DIR}/../conanbuildinfo.cmake\" does not exist") + endif() + conan_basic_setup() else() - message(STATUS "Multi-configuration build: '${CMAKE_CONFIGURATION_TYPES}'!") - set(LIST_OF_BUILD_TYPES ${CMAKE_CONFIGURATION_TYPES}) - endif() + # For multi configuration generators, like VS and XCode + if(NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Single configuration build!") + set(LIST_OF_BUILD_TYPES ${CMAKE_BUILD_TYPE}) + else() + message(STATUS "Multi-configuration build: '${CMAKE_CONFIGURATION_TYPES}'!") + set(LIST_OF_BUILD_TYPES ${CMAKE_CONFIGURATION_TYPES}) + endif() - is_verbose(_is_verbose) - if(NOT ${_is_verbose}) - set(OUTPUT_QUIET "OUTPUT_QUIET") - else() - set(OUTPUT_QUIET OFF) - endif() + is_verbose(_is_verbose) + if(NOT ${_is_verbose}) + set(OUTPUT_QUIET "OUTPUT_QUIET") + else() + set(OUTPUT_QUIET OFF) + endif() - foreach(TYPE ${LIST_OF_BUILD_TYPES}) - message(STATUS "Running Conan for build type '${TYPE}'") + foreach(TYPE ${LIST_OF_BUILD_TYPES}) + message(STATUS "Running Conan for build type '${TYPE}'") - # Detects current build settings to pass into conan - conan_cmake_autodetect(settings BUILD_TYPE ${TYPE}) + if("${ProjectOptions_CONAN_PROFILE}" STREQUAL "") + # Detects current build settings to pass into conan + conan_cmake_autodetect(settings BUILD_TYPE ${TYPE}) + set(CONAN_SETTINGS SETTINGS ${settings}) + 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}) + # CONAN_ENV should be redundant, since the profile can set CC & CXX + endif() - # PATH_OR_REFERENCE ${CMAKE_SOURCE_DIR} is used to tell conan to process - # the external "conanfile.py" provided with the project - # Alternatively a conanfile.txt could be used - conan_cmake_install( - PATH_OR_REFERENCE - ${CMAKE_SOURCE_DIR} - BUILD - missing - # Pass compile-time configured options into conan - OPTIONS - ${ProjectOptions_CONAN_OPTIONS} - # Pass CMake compilers to Conan - ENV - "CC=${CMAKE_C_COMPILER}" - "CXX=${CMAKE_CXX_COMPILER}" - SETTINGS - ${settings} - ${OUTPUT_QUIET}) - endforeach() + # PATH_OR_REFERENCE ${CMAKE_SOURCE_DIR} is used to tell conan to process + # the external "conanfile.py" provided with the project + # Alternatively a conanfile.txt could be used + conan_cmake_install( + PATH_OR_REFERENCE + ${CMAKE_SOURCE_DIR} + BUILD + missing + # Pass compile-time configured options into conan + OPTIONS + ${ProjectOptions_CONAN_OPTIONS} + # Pass CMake compilers to Conan + ${CONAN_ENV} + # Pass either autodetected settings or a conan profile + ${CONAN_SETTINGS} + ${OUTPUT_QUIET}) + endforeach() + endif() endmacro() diff --git a/src/Doxygen.cmake b/src/Doxygen.cmake index 2f524bba..a0814398 100644 --- a/src/Doxygen.cmake +++ b/src/Doxygen.cmake @@ -42,8 +42,22 @@ function(enable_doxygen DOXYGEN_THEME) set(DOXYGEN_HTML_EXTRA_STYLESHEET ${DOXYGEN_HTML_EXTRA_STYLESHEET} "${_doxygen_theme_SOURCE_DIR}/doxygen-awesome-sidebar-only.css") endif() - else() + elseif("${DOXYGEN_THEME}" STREQUAL "original") # use the original doxygen theme + else() + # use custom doxygen theme + + # if any of the custom theme files are not found, the theme is reverted to original + set(OLD_DOXYGEN_HTML_EXTRA_STYLESHEET ${DOXYGEN_HTML_EXTRA_STYLESHEET}) + foreach(file ${DOXYGEN_THEME}) + if(NOT EXISTS ${file}) + message(WARNING "Could not find doxygen theme file '${file}'. Using original theme.") + set(DOXYGEN_HTML_EXTRA_STYLESHEET ${OLD_DOXYGEN_HTML_EXTRA_STYLESHEET}) + break() + else() + set(DOXYGEN_HTML_EXTRA_STYLESHEET ${DOXYGEN_HTML_EXTRA_STYLESHEET} "${file}") + endif() + endforeach() endif() # find doxygen and dot if available diff --git a/src/Index.cmake b/src/Index.cmake index b2a6828b..afc8db17 100644 --- a/src/Index.cmake +++ b/src/Index.cmake @@ -29,8 +29,13 @@ 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}/Vcpkg.cmake") +include("${ProjectOptions_SRC_DIR}/VCEnvironment.cmake") + +# find msvc on windows if required. Should be called before run_vcpkg and run_conan to be effective +find_msvc() + include("${ProjectOptions_SRC_DIR}/Conan.cmake") +include("${ProjectOptions_SRC_DIR}/Vcpkg.cmake") # # Params: @@ -86,8 +91,9 @@ macro(project_options) ENABLE_SANITIZER_UNDEFINED_BEHAVIOR ENABLE_SANITIZER_THREAD ENABLE_SANITIZER_MEMORY) - set(oneValueArgs DOXYGEN_THEME VS_ANALYSIS_RULESET) + set(oneValueArgs VS_ANALYSIS_RULESET CONAN_PROFILE) set(multiValueArgs + DOXYGEN_THEME MSVC_WARNINGS CLANG_WARNINGS GCC_WARNINGS diff --git a/src/PackageProject.cmake b/src/PackageProject.cmake index 566b019b..f272175c 100644 --- a/src/PackageProject.cmake +++ b/src/PackageProject.cmake @@ -82,7 +82,7 @@ function(package_project) set(_PackageProject_COMPATIBILITY "SameMajorVersion") endif() - # default to the build_directory/project_name + # default to the build_directory/project_name if("${_PackageProject_CONFIG_EXPORT_DESTINATION}" STREQUAL "") set(_PackageProject_CONFIG_EXPORT_DESTINATION "${CMAKE_BINARY_DIR}/${_PackageProject_NAME}") endif() diff --git a/src/VCEnvironment.cmake b/src/VCEnvironment.cmake index 561a1df2..a4502abc 100644 --- a/src/VCEnvironment.cmake +++ b/src/VCEnvironment.cmake @@ -2,10 +2,50 @@ include_guard() include("${ProjectOptions_SRC_DIR}/Utilities.cmake") +macro(find_msvc) + # Try finding MSVC + if(# if MSVC is not found by CMake yet, + NOT MSVC + AND # if the user has specified cl using -DCMAKE_CXX_COMPILER=cl or -DCMAKE_C_COMPILER=cl + ((CMAKE_CXX_COMPILER MATCHES "^cl(.exe)?$" AND CMAKE_C_COMPILER MATCHES "^cl(.exe)?$") + # if the user has specified cl using CC and CXX but not using -DCMAKE_CXX_COMPILER or -DCMAKE_C_COMPILER + OR (NOT CMAKE_CXX_COMPILER + AND NOT CMAKE_C_COMPILER + AND ("$ENV{CXX}" MATCHES "^cl(.exe)?$" AND "$ENV{CC}" MATCHES "^cl(.exe)?$")) + )) + message(STATUS "Finding MSVC cl.exe ...") + include(FetchContent) + FetchContent_Declare( + _msvc_toolchain + URL "https://github.com/MarkSchofield/Toolchain/archive/5fdd24e609cfb860c06ada86c9e64f43062e0866.zip") + FetchContent_MakeAvailable(_msvc_toolchain) + include("${_msvc_toolchain_SOURCE_DIR}/Windows.MSVC.toolchain.cmake") + message(STATUS "Setting CMAKE_CXX_COMPILER to ${CMAKE_CXX_COMPILER}") + set(ENV{CXX} ${CMAKE_CXX_COMPILER}) + set(ENV{CC} ${CMAKE_C_COMPILER}) + set(MSVC_FOUND TRUE) + run_vcvarsall() + endif() +endmacro() + # Run vcvarsall.bat and set CMake environment variables -function(run_vcvarsall) - # if MSVC but VSCMD_VER is not set, which means vcvarsall has not run - if(MSVC AND "$ENV{VSCMD_VER}" STREQUAL "") +macro(run_vcvarsall) + # detect the architecture + detect_architecture(VCVARSALL_ARCH) + + # If MSVC is being used, and ASAN is enabled, we need to set the debugger environment + # so that it behaves well with MSVC's debugger, and we can run the target from visual studio + if(MSVC) + string(TOUPPER "${VCVARSALL_ARCH}" VCVARSALL_ARCH_UPPER) + set(VS_DEBUGGER_ENVIRONMENT "PATH=\$(VC_ExecutablePath_${VCVARSALL_ARCH_UPPER});%PATH%") + + get_all_targets(all_targets) + set_target_properties(${all_targets} PROPERTIES VS_DEBUGGER_ENVIRONMENT "${VS_DEBUGGER_ENVIRONMENT}") + endif() + + # if msvc_found is set by find_msvc + # or if MSVC but VSCMD_VER is not set, which means vcvarsall has not run + if(MSVC_FOUND OR (MSVC AND "$ENV{VSCMD_VER}" STREQUAL "")) # find vcvarsall.bat get_filename_component(MSVC_DIR ${CMAKE_CXX_COMPILER} DIRECTORY) @@ -20,9 +60,6 @@ function(run_vcvarsall) PATH_SUFFIXES "VC/Auxiliary/Build" "Common7/Tools" "Tools") if(EXISTS ${VCVARSALL_FILE}) - # detect the architecture - detect_architecture(VCVARSALL_ARCH) - # run vcvarsall and print the environment variables message(STATUS "Running `${VCVARSALL_FILE} ${VCVARSALL_ARCH}` to set up the MSVC environment") execute_process( @@ -38,7 +75,6 @@ function(run_vcvarsall) # set the environment variables set_env_from_string("${VCVARSALL_ENV}") - else() message( WARNING @@ -46,4 +82,4 @@ function(run_vcvarsall) ") endif() endif() -endfunction() +endmacro() diff --git a/test_install/CMakeLists.txt b/test_install/CMakeLists.txt index 10b81cfc..837ca2dd 100644 --- a/test_install/CMakeLists.txt +++ b/test_install/CMakeLists.txt @@ -14,30 +14,32 @@ project( ### Initialize project_options project_options( -# ENABLE_CACHE + ENABLE_CACHE ENABLE_CONAN -# # WARNINGS_AS_ERRORS -# ENABLE_CPPCHECK -# ENABLE_CLANG_TIDY -# # ENABLE_INCLUDE_WHAT_YOU_USE -# # ENABLE_COVERAGE -# # ENABLE_PCH -# # PCH_HEADERS -# # ENABLE_DOXYGEN -# ENABLE_INTERPROCEDURAL_OPTIMIZATION -# ENABLE_NATIVE_OPTIMIZATION -# # ENABLE_USER_LINKER -# # ENABLE_BUILD_WITH_TIME_TRACE -# # ENABLE_UNITY -# # ENABLE_SANITIZER_ADDRESS -# # ENABLE_SANITIZER_LEAK -# # ENABLE_SANITIZER_UNDEFINED_BEHAVIOR -# # ENABLE_SANITIZER_THREAD -# # ENABLE_SANITIZER_MEMORY + # WARNINGS_AS_ERRORS + ENABLE_CPPCHECK + ENABLE_CLANG_TIDY + # ENABLE_INCLUDE_WHAT_YOU_USE + # ENABLE_COVERAGE + # ENABLE_PCH + # PCH_HEADERS + ENABLE_DOXYGEN + DOXYGEN_THEME + "${CMAKE_CURRENT_LIST_DIR}/css/my_custom_theme.css" + "${CMAKE_CURRENT_LIST_DIR}/css/my_custom_theme_extra.css" + ENABLE_INTERPROCEDURAL_OPTIMIZATION + # ENABLE_USER_LINKER + # ENABLE_BUILD_WITH_TIME_TRACE + # ENABLE_UNITY + # ENABLE_SANITIZER_ADDRESS + # ENABLE_SANITIZER_LEAK + # ENABLE_SANITIZER_UNDEFINED_BEHAVIOR + # ENABLE_SANITIZER_THREAD + # ENABLE_SANITIZER_MEMORY ) # add src, tests, etc here: -add_executable(another_main another_main.cpp) +add_executable(another_main "./src/another_main.cpp") target_link_libraries(another_main PRIVATE project_options project_warnings) ## dependencies diff --git a/test_install/css/my_custom_theme.css b/test_install/css/my_custom_theme.css new file mode 100644 index 00000000..eed82075 --- /dev/null +++ b/test_install/css/my_custom_theme.css @@ -0,0 +1,3 @@ +body { + background-color: lightblue; +} diff --git a/test_install/css/my_custom_theme_extra.css b/test_install/css/my_custom_theme_extra.css new file mode 100644 index 00000000..0a74149a --- /dev/null +++ b/test_install/css/my_custom_theme_extra.css @@ -0,0 +1,3 @@ +h1, h2, h3, h4, h5, h6 { + color: salmon; +} diff --git a/test_install/another_main.cpp b/test_install/src/another_main.cpp similarity index 100% rename from test_install/another_main.cpp rename to test_install/src/another_main.cpp