diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da89879a..5c6a12c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,13 +87,16 @@ jobs: - {os: {name: ubuntu-latest, type: linux}, compiler: {name: gcc-11, type: gcc}} - {os: {name: ubuntu-latest, type: linux}, compiler: {name: llvm, type: llvm}} - {os: {name: ubuntu-latest, type: mingw-dynamic-linux}, compiler: {name: mingw, type: mingw}} + - {os: {name: ubuntu-latest, type: mingw-static-linux}, compiler: {name: mingw, type: mingw}} - {os: {name: macos-latest, type: osx}, compiler: {name: applellvm, type: llvm}} - {os: {name: macos-latest, type: osx}, compiler: {name: llvm, type: llvm}} # setup-cpp doesn't support mingw on macOS yet # - {os: {name: macos-latest, type: mingw-dynamic-darwin}, compiler: {name: mingw, type: mingw}} + # - {os: {name: macos-latest, type: mingw-static-darwin}, compiler: {name: mingw, type: mingw}} - {os: {name: windows-latest, type: windows}, compiler: {name: msvc, type: msvc}} - {os: {name: windows-latest, type: windows}, compiler: {name: llvm, type: llvm}} - - {os: {name: windows-latest, type: mingw-dynamic-windows}, compiler: {name: mingw, type: mingw-gcc}} + - {os: {name: windows-latest, type: mingw-dynamic-windows}, compiler: {name: mingw, type: mingw}} + - {os: {name: windows-latest, type: mingw-static-windows}, compiler: {name: mingw, type: mingw}} arch: - {name: x64, type: x64} vcpkg: diff --git a/CMakePresets.json b/CMakePresets.json index 5f1e39d4..c21bd1ef 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -8,9 +8,12 @@ "include": [ "cmake/presets/x64-linux-llvm.json", "cmake/presets/x64-linux-gcc.json", - "cmake/presets/x64-mingw-dynamic-windows-mingw-gcc.json", + "cmake/presets/x64-mingw-dynamic-windows-mingw.json", "cmake/presets/x64-mingw-dynamic-darwin-mingw.json", "cmake/presets/x64-mingw-dynamic-linux-mingw.json", + "cmake/presets/x64-mingw-static-windows-mingw.json", + "cmake/presets/x64-mingw-static-darwin-mingw.json", + "cmake/presets/x64-mingw-static-linux-mingw.json", "cmake/presets/x64-osx-gcc.json", "cmake/presets/x64-osx-llvm.json", "cmake/presets/x64-windows-llvm.json", diff --git a/cmake/build_configuration.md b/cmake/build_configuration.md index 112c1850..5d106fda 100644 --- a/cmake/build_configuration.md +++ b/cmake/build_configuration.md @@ -1,15 +1,15 @@ # Build Congfiguration -Based on vcpkg and CMake, we can seamlessly creat, build, and test our projects on different platforms and configurations. Here are some tips and tricks to make things easier. +Based on vcpkg and CMake, we can seamlessly create, build, and test our projects on different platforms and configurations. Here are some tips and tricks to make things easier. ## Triplet Presets -The triplet presets are used to specify the target platform and build configuration for the project.It consists of three parts: architecture, target-compiling-os/toolchain, and distribution. +The triplet presets are used to specify the target platform and build configuration for the project.It consists of three parts: Architecture, Target-Compiling-Os/Toolchain, Distribution and Compiler. - Architecture: x86, x64, arm, arm64, ppc64le, s390x, wasm32, etc. - Target-Compiling-OS/Toolchain: windows, linux, macos, freebsd, android, ios, mingw, etc. - Distribution: dynamic, static, release, etc. -- Compiler(Optional): MSVC, GCC, Clang, MinGW +- Compiler: MSVC, GCC, Clang, MinGW. More about triplets, see: @@ -28,12 +28,11 @@ ctest --preset= # test the desired test preset ## Building without presets(Not Recommended) -If you don't want to use presets, you can still build the project by specifying the target platform and build configuration. It's not recommended as it's more complex and error-prone because you need to specify the correct triplet and toolchain for each platform and configuration. - +You can also build the project without using presets. It's not recommended as it's more complex and error-prone because you need to specify the correct triplet and toolchain for each platform and configuration. But it is documented here for reference to reveal the underlying mechanism. Here are some necessary variables to configure the project: -- `CMAKE_TOOLCHAIN_FILE(Required)`: specify the path to the project's toolchain file(cmake/vcpkg/vcpkg.toolchain.cmake). It contains steps to set the correct triplet and initialize the vcpkg environment. +- `CMAKE_TOOLCHAIN_FILE(Required)`: specify the path to the project's toolchain file(cmake/vcpkg/vcpkg.toolchain.cmake). It contains steps to set the correct triplet and initialize the vcpkg environment. More importantly, it also loads triplet variables and chainload toolchain according to `VCPKG_TARGET_TRIPLET`. - `CMAKE_BUILD_TYPE(Required)`: specify the build configuration, such as "Debug", "Release", "RelWithDebInfo", "MinSizeRel", etc. - `CMAKE_GENERATOR(Required)`: specify the generator for the build system, such as "Ninja", "Unix Makefiles", "Visual Studio 16 2019", etc. And it's recommended to use Ninja for cross-platform builds. - `VCPKG_ROOT(Optional)`: specify the path to the toolchain file for the target platform. Normally it's in the vcpkg installation directory. If not specified, cmake/vcpkg/vcpkg.toolchain.cmake will automatically create one for you. @@ -46,7 +45,14 @@ Here's an example of building the project with the specified variables: ```bash # Configure -cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=cmake/vcpkg/vcpkg.toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -G Ninja -DVCPKG_TARGET_TRIPLET=x64-linux -DVCPKG_HOST_TRIPLET=x64-linux -DVCPKG_OVERLAY_TRIPLETS=cmake/vcpkg/triplets -DVCPKG_OVERLAY_PORTS=cmake/vcpkg/ports +cmake -S . -B build \ + -DCMAKE_TOOLCHAIN_FILE=cmake/vcpkg/vcpkg.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -G Ninja \ + -DVCPKG_TARGET_TRIPLET=x64-linux \ + -DVCPKG_HOST_TRIPLET=x64-linux \ + -DVCPKG_OVERLAY_TRIPLETS=cmake/vcpkg/triplets \ + -DVCPKG_OVERLAY_PORTS=cmake/vcpkg/ports # Build cmake --build build --config Debug # Testing diff --git a/cmake/presets/compilers/llvm.json b/cmake/presets/compilers/llvm.json index f673547f..5172325a 100644 --- a/cmake/presets/compilers/llvm.json +++ b/cmake/presets/compilers/llvm.json @@ -13,8 +13,8 @@ "name": "llvm-cl", "hidden": true, "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl" + "CMAKE_C_COMPILER": "clang-cl.exe", + "CMAKE_CXX_COMPILER": "clang-cl.exe" } } ] diff --git a/cmake/presets/triplets/x64-mingw-dynamic.json b/cmake/presets/triplets/x64-mingw-dynamic.json index d4060956..849b15f7 100644 --- a/cmake/presets/triplets/x64-mingw-dynamic.json +++ b/cmake/presets/triplets/x64-mingw-dynamic.json @@ -12,8 +12,7 @@ ], "cacheVariables": { "VCPKG_TARGET_TRIPLET": "x64-mingw-dynamic", - "VCPKG_HOST_TRIPLET": "x64-mingw-dynamic", - "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/cmake/vcpkg/scripts/toolchains/mingw.cmake" + "VCPKG_HOST_TRIPLET": "x64-mingw-dynamic" } } ] diff --git a/cmake/presets/triplets/x64-mingw-static.json b/cmake/presets/triplets/x64-mingw-static.json new file mode 100644 index 00000000..1caf05bd --- /dev/null +++ b/cmake/presets/triplets/x64-mingw-static.json @@ -0,0 +1,19 @@ +{ + "version": 6, + "include": [ + "../arch/x64.json" + ], + "configurePresets": [ + { + "name": "x64-mingw-static", + "hidden": true, + "inherits": [ + "x64" + ], + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-mingw-static", + "VCPKG_HOST_TRIPLET": "x64-mingw-static" + } + } + ] +} diff --git a/cmake/presets/x64-mingw-dynamic-windows-mingw-gcc.json b/cmake/presets/x64-mingw-dynamic-windows-mingw.json similarity index 57% rename from cmake/presets/x64-mingw-dynamic-windows-mingw-gcc.json rename to cmake/presets/x64-mingw-dynamic-windows-mingw.json index 85aa2fb0..0d9c996a 100644 --- a/cmake/presets/x64-mingw-dynamic-windows-mingw-gcc.json +++ b/cmake/presets/x64-mingw-dynamic-windows-mingw.json @@ -8,7 +8,7 @@ ], "configurePresets": [ { - "name": "x64-mingw-dynamic-windows-mingw-gcc", + "name": "x64-mingw-dynamic-windows-mingw", "inherits": [ "base", "windows", @@ -22,33 +22,33 @@ ], "buildPresets": [ { - "name": "x64-mingw-dynamic-windows-mingw-gcc", + "name": "x64-mingw-dynamic-windows-mingw", "inherits": "base", - "configurePreset": "x64-mingw-dynamic-windows-mingw-gcc" + "configurePreset": "x64-mingw-dynamic-windows-mingw" } ], "testPresets": [ { - "name": "x64-mingw-dynamic-windows-mingw-gcc", + "name": "x64-mingw-dynamic-windows-mingw", "inherits": "base", - "configurePreset": "x64-mingw-dynamic-windows-mingw-gcc" + "configurePreset": "x64-mingw-dynamic-windows-mingw" } ], "workflowPresets": [ { - "name": "x64-mingw-dynamic-windows-mingw-gcc", + "name": "x64-mingw-dynamic-windows-mingw", "steps": [ { "type": "configure", - "name": "x64-mingw-dynamic-windows-mingw-gcc" + "name": "x64-mingw-dynamic-windows-mingw" }, { "type": "build", - "name": "x64-mingw-dynamic-windows-mingw-gcc" + "name": "x64-mingw-dynamic-windows-mingw" }, { "type": "test", - "name": "x64-mingw-dynamic-windows-mingw-gcc" + "name": "x64-mingw-dynamic-windows-mingw" } ] } diff --git a/cmake/presets/x64-mingw-static-darwin-mingw.json b/cmake/presets/x64-mingw-static-darwin-mingw.json new file mode 100644 index 00000000..c40a5be2 --- /dev/null +++ b/cmake/presets/x64-mingw-static-darwin-mingw.json @@ -0,0 +1,53 @@ +{ + "version": 6, + "include": [ + "base.json", + "os/darwin.json", + "compilers/mingw.json", + "triplets/x64-mingw-static.json" + ], + "configurePresets": [ + { + "name": "x64-mingw-static-darwin-mingw", + "inherits": [ + "base", + "darwin", + "mingw", + "x64-mingw-static" + ] + } + ], + "buildPresets": [ + { + "name": "x64-mingw-static-darwin-mingw", + "inherits": "base", + "configurePreset": "x64-mingw-static-darwin-mingw" + } + ], + "testPresets": [ + { + "name": "x64-mingw-static-darwin-mingw", + "inherits": "base", + "configurePreset": "x64-mingw-static-darwin-mingw" + } + ], + "workflowPresets": [ + { + "name": "x64-mingw-static-darwin-mingw", + "steps": [ + { + "type": "configure", + "name": "x64-mingw-static-darwin-mingw" + }, + { + "type": "build", + "name": "x64-mingw-static-darwin-mingw" + }, + { + "type": "test", + "name": "x64-mingw-static-darwin-mingw" + } + ] + } + ] +} diff --git a/cmake/presets/x64-mingw-static-linux-mingw.json b/cmake/presets/x64-mingw-static-linux-mingw.json new file mode 100644 index 00000000..15355f53 --- /dev/null +++ b/cmake/presets/x64-mingw-static-linux-mingw.json @@ -0,0 +1,56 @@ +{ + "version": 6, + "include": [ + "base.json", + "os/linux.json", + "compilers/mingw.json", + "triplets/x64-mingw-static.json" + ], + "configurePresets": [ + { + "name": "x64-mingw-static-linux-mingw", + "inherits": [ + "base", + "linux", + "mingw", + "x64-mingw-static" + ], + "cacheVariables": { + "USE_SANITIZER": "FALSE" + } + } + ], + "buildPresets": [ + { + "name": "x64-mingw-static-linux-mingw", + "inherits": "base", + "configurePreset": "x64-mingw-static-linux-mingw" + } + ], + "testPresets": [ + { + "name": "x64-mingw-static-linux-mingw", + "inherits": "base", + "configurePreset": "x64-mingw-static-linux-mingw" + } + ], + "workflowPresets": [ + { + "name": "x64-mingw-static-linux-mingw", + "steps": [ + { + "type": "configure", + "name": "x64-mingw-static-linux-mingw" + }, + { + "type": "build", + "name": "x64-mingw-static-linux-mingw" + }, + { + "type": "test", + "name": "x64-mingw-static-linux-mingw" + } + ] + } + ] +} diff --git a/cmake/presets/x64-mingw-static-windows-mingw.json b/cmake/presets/x64-mingw-static-windows-mingw.json new file mode 100644 index 00000000..76201727 --- /dev/null +++ b/cmake/presets/x64-mingw-static-windows-mingw.json @@ -0,0 +1,56 @@ +{ + "version": 6, + "include": [ + "base.json", + "os/windows.json", + "compilers/mingw.json", + "triplets/x64-mingw-static.json" + ], + "configurePresets": [ + { + "name": "x64-mingw-static-windows-mingw-gcc", + "inherits": [ + "base", + "windows", + "mingw", + "x64-mingw-static" + ], + "cacheVariables": { + "USE_SANITIZER": "FALSE" + } + } + ], + "buildPresets": [ + { + "name": "x64-mingw-static-windows-mingw-gcc", + "inherits": "base", + "configurePreset": "x64-mingw-static-windows-mingw-gcc" + } + ], + "testPresets": [ + { + "name": "x64-mingw-static-windows-mingw-gcc", + "inherits": "base", + "configurePreset": "x64-mingw-static-windows-mingw-gcc" + } + ], + "workflowPresets": [ + { + "name": "x64-mingw-static-windows-mingw-gcc", + "steps": [ + { + "type": "configure", + "name": "x64-mingw-static-windows-mingw-gcc" + }, + { + "type": "build", + "name": "x64-mingw-static-windows-mingw-gcc" + }, + { + "type": "test", + "name": "x64-mingw-static-windows-mingw-gcc" + } + ] + } + ] +} diff --git a/cmake/vcpkg/bootstrap/vcpkg-config.cmake b/cmake/vcpkg/bootstrap/vcpkg-config.cmake index 3dc8bca4..0bc81a68 100644 --- a/cmake/vcpkg/bootstrap/vcpkg-config.cmake +++ b/cmake/vcpkg/bootstrap/vcpkg-config.cmake @@ -14,4 +14,6 @@ set(__vcpkg_bootstrap_list_dir "${CMAKE_CURRENT_LIST_DIR}") include(${__vcpkg_bootstrap_list_dir}/vcpkg_skip_install_on_reconfigure.cmake) include(${__vcpkg_bootstrap_list_dir}/vcpkg_bootstrap.cmake) +include(${__vcpkg_bootstrap_list_dir}/vcpkg_chainload_toolchain.cmake) +include(${__vcpkg_bootstrap_list_dir}/vcpkg_load_triplet.cmake) include(${__vcpkg_bootstrap_list_dir}/vcpkg_configure.cmake) diff --git a/cmake/vcpkg/bootstrap/vcpkg_chainload_toolchain.cmake b/cmake/vcpkg/bootstrap/vcpkg_chainload_toolchain.cmake new file mode 100644 index 00000000..0a38f875 --- /dev/null +++ b/cmake/vcpkg/bootstrap/vcpkg_chainload_toolchain.cmake @@ -0,0 +1,41 @@ +#[[ +SPDX-License-Identifier: MIT +SPDX-FileCopyrightText: Copyright 2024 msclock +]] + +# configure VCPKG_CHAINLOAD_TOOLCHAIN_FILE based on VCPKG_TARGET_TRIPLET and +# VCPKG_TARGET_ARCHITECTURE +function(_vcpkg_chainload_toolchain) + if(DEFINED VCPKG_CHAINLOAD_TOOLCHAIN_FILE) + return() + endif() + + if(NOT DEFINED VCPKG_TARGET_TRIPLET OR NOT DEFINED VCPKG_TARGET_ARCHITECTURE) + message( + FATAL_ERROR + "VCPKG_TARGET_TRIPLET and VCPKG_TARGET_ARCHITECTURE must be set before calling _vcpkg_chainload_toolchain()" + ) + endif() + + string(LENGTH "${VCPKG_TARGET_ARCHITECTURE}-" _prefix_len) + string(SUBSTRING ${VCPKG_TARGET_TRIPLET} ${_prefix_len} -1 _stripped_string) + string(REPLACE "-" ";" _triplet_parts "${_stripped_string}") + list(GET _triplet_parts 0 _chainload_toolchain_name) + + set(_toolchain "scripts/toolchains/${_chainload_toolchain_name}.cmake") + + if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${_toolchain}") + set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE + "${CMAKE_CURRENT_LIST_DIR}/${_toolchain}" + CACHE INTERNAL "vcpkg chainload") + elseif(EXISTS "${_VCPKG_ROOT}/${_toolchain}") + set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE + "${_VCPKG_ROOT}/${_toolchain}" + CACHE INTERNAL "vcpkg chainload") + else() + message( + WARNING + "Could not find toolchain file for ${_chainload_toolchain_name}, skipping chainload" + ) + endif() +endfunction() diff --git a/cmake/vcpkg/bootstrap/vcpkg_configure.cmake b/cmake/vcpkg/bootstrap/vcpkg_configure.cmake index 206cf2da..3ea5f810 100644 --- a/cmake/vcpkg/bootstrap/vcpkg_configure.cmake +++ b/cmake/vcpkg/bootstrap/vcpkg_configure.cmake @@ -5,7 +5,9 @@ SPDX-FileCopyrightText: Copyright 2024 msclock ]] # bootstrap and configure vcpkg -function(vcpkg_configure) +macro(vcpkg_configure) _vcpkg_bootstrap(${ARGN}) _vcpkg_skip_install_on_reconfigure() -endfunction() + _vcpkg_load_triplet() + _vcpkg_chainload_toolchain() +endmacro() diff --git a/cmake/vcpkg/bootstrap/vcpkg_load_triplet.cmake b/cmake/vcpkg/bootstrap/vcpkg_load_triplet.cmake new file mode 100644 index 00000000..072def56 --- /dev/null +++ b/cmake/vcpkg/bootstrap/vcpkg_load_triplet.cmake @@ -0,0 +1,34 @@ +#[[ +SPDX-License-Identifier: MIT +SPDX-FileCopyrightText: Copyright 2024 msclock +]] + +# load the triplet by VCPKG_TARGET_TRIPLET +macro(_vcpkg_load_triplet) + if(NOT DEFINED VCPKG_TARGET_TRIPLET) + message( + FATAL_ERROR + "VCPKG_TARGET_TRIPLET is not defined, please set it to the desired triplet" + ) + endif() + + set(_triplet "triplets/${VCPKG_TARGET_TRIPLET}.cmake") + set(_community_triplet "triplets/community/${VCPKG_TARGET_TRIPLET}.cmake") + + if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${_triplet}") + include("${CMAKE_CURRENT_LIST_DIR}/${_triplet}") + elseif(EXISTS "${_VCPKG_ROOT}/${_triplet}") + include("${_VCPKG_ROOT}/${_triplet}") + elseif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${_community_triplet}") + include("${CMAKE_CURRENT_LIST_DIR}/${_community_triplet}") + elseif(EXISTS "${_VCPKG_ROOT}/${_community_triplet}") + include("${_VCPKG_ROOT}/${_community_triplet}") + else() + message( + FATAL_ERROR + "Triplet ${VCPKG_TARGET_TRIPLET} not found at ${CMAKE_CURRENT_LIST_DIR}/${_triplet} or ${_VCPKG_ROOT}/${_triplet}" + ) + endif() + unset(_triplet) + unset(_community_triplet) +endmacro(_vcpkg_load_triplet) diff --git a/docs/development/index.md b/docs/development/index.md index 0e1e1f0a..bb51a0d2 100644 --- a/docs/development/index.md +++ b/docs/development/index.md @@ -1,7 +1,11 @@ # Development +This sections covers the development process of the project. + ```{toctree} :maxdepth: 1 +:titlesonly: +:caption: For Developers build_configuration ``` diff --git a/template/CMakePresets.json b/template/CMakePresets.json index 5f1e39d4..c21bd1ef 100644 --- a/template/CMakePresets.json +++ b/template/CMakePresets.json @@ -8,9 +8,12 @@ "include": [ "cmake/presets/x64-linux-llvm.json", "cmake/presets/x64-linux-gcc.json", - "cmake/presets/x64-mingw-dynamic-windows-mingw-gcc.json", + "cmake/presets/x64-mingw-dynamic-windows-mingw.json", "cmake/presets/x64-mingw-dynamic-darwin-mingw.json", "cmake/presets/x64-mingw-dynamic-linux-mingw.json", + "cmake/presets/x64-mingw-static-windows-mingw.json", + "cmake/presets/x64-mingw-static-darwin-mingw.json", + "cmake/presets/x64-mingw-static-linux-mingw.json", "cmake/presets/x64-osx-gcc.json", "cmake/presets/x64-osx-llvm.json", "cmake/presets/x64-windows-llvm.json", diff --git a/template/[% if docs_type == 'sphinx' %]docs[% endif %]/development/index.md b/template/[% if docs_type == 'sphinx' %]docs[% endif %]/development/index.md index 0e1e1f0a..bb51a0d2 100644 --- a/template/[% if docs_type == 'sphinx' %]docs[% endif %]/development/index.md +++ b/template/[% if docs_type == 'sphinx' %]docs[% endif %]/development/index.md @@ -1,7 +1,11 @@ # Development +This sections covers the development process of the project. + ```{toctree} :maxdepth: 1 +:titlesonly: +:caption: For Developers build_configuration ``` diff --git a/template/[% if repo_host_type == 'github.com' %].github[% endif %]/workflows/ci.yml b/template/[% if repo_host_type == 'github.com' %].github[% endif %]/workflows/ci.yml index da89879a..5c6a12c8 100644 --- a/template/[% if repo_host_type == 'github.com' %].github[% endif %]/workflows/ci.yml +++ b/template/[% if repo_host_type == 'github.com' %].github[% endif %]/workflows/ci.yml @@ -87,13 +87,16 @@ jobs: - {os: {name: ubuntu-latest, type: linux}, compiler: {name: gcc-11, type: gcc}} - {os: {name: ubuntu-latest, type: linux}, compiler: {name: llvm, type: llvm}} - {os: {name: ubuntu-latest, type: mingw-dynamic-linux}, compiler: {name: mingw, type: mingw}} + - {os: {name: ubuntu-latest, type: mingw-static-linux}, compiler: {name: mingw, type: mingw}} - {os: {name: macos-latest, type: osx}, compiler: {name: applellvm, type: llvm}} - {os: {name: macos-latest, type: osx}, compiler: {name: llvm, type: llvm}} # setup-cpp doesn't support mingw on macOS yet # - {os: {name: macos-latest, type: mingw-dynamic-darwin}, compiler: {name: mingw, type: mingw}} + # - {os: {name: macos-latest, type: mingw-static-darwin}, compiler: {name: mingw, type: mingw}} - {os: {name: windows-latest, type: windows}, compiler: {name: msvc, type: msvc}} - {os: {name: windows-latest, type: windows}, compiler: {name: llvm, type: llvm}} - - {os: {name: windows-latest, type: mingw-dynamic-windows}, compiler: {name: mingw, type: mingw-gcc}} + - {os: {name: windows-latest, type: mingw-dynamic-windows}, compiler: {name: mingw, type: mingw}} + - {os: {name: windows-latest, type: mingw-static-windows}, compiler: {name: mingw, type: mingw}} arch: - {name: x64, type: x64} vcpkg: diff --git a/template/cmake/build_configuration.md b/template/cmake/build_configuration.md index 112c1850..5d106fda 100644 --- a/template/cmake/build_configuration.md +++ b/template/cmake/build_configuration.md @@ -1,15 +1,15 @@ # Build Congfiguration -Based on vcpkg and CMake, we can seamlessly creat, build, and test our projects on different platforms and configurations. Here are some tips and tricks to make things easier. +Based on vcpkg and CMake, we can seamlessly create, build, and test our projects on different platforms and configurations. Here are some tips and tricks to make things easier. ## Triplet Presets -The triplet presets are used to specify the target platform and build configuration for the project.It consists of three parts: architecture, target-compiling-os/toolchain, and distribution. +The triplet presets are used to specify the target platform and build configuration for the project.It consists of three parts: Architecture, Target-Compiling-Os/Toolchain, Distribution and Compiler. - Architecture: x86, x64, arm, arm64, ppc64le, s390x, wasm32, etc. - Target-Compiling-OS/Toolchain: windows, linux, macos, freebsd, android, ios, mingw, etc. - Distribution: dynamic, static, release, etc. -- Compiler(Optional): MSVC, GCC, Clang, MinGW +- Compiler: MSVC, GCC, Clang, MinGW. More about triplets, see: @@ -28,12 +28,11 @@ ctest --preset= # test the desired test preset ## Building without presets(Not Recommended) -If you don't want to use presets, you can still build the project by specifying the target platform and build configuration. It's not recommended as it's more complex and error-prone because you need to specify the correct triplet and toolchain for each platform and configuration. - +You can also build the project without using presets. It's not recommended as it's more complex and error-prone because you need to specify the correct triplet and toolchain for each platform and configuration. But it is documented here for reference to reveal the underlying mechanism. Here are some necessary variables to configure the project: -- `CMAKE_TOOLCHAIN_FILE(Required)`: specify the path to the project's toolchain file(cmake/vcpkg/vcpkg.toolchain.cmake). It contains steps to set the correct triplet and initialize the vcpkg environment. +- `CMAKE_TOOLCHAIN_FILE(Required)`: specify the path to the project's toolchain file(cmake/vcpkg/vcpkg.toolchain.cmake). It contains steps to set the correct triplet and initialize the vcpkg environment. More importantly, it also loads triplet variables and chainload toolchain according to `VCPKG_TARGET_TRIPLET`. - `CMAKE_BUILD_TYPE(Required)`: specify the build configuration, such as "Debug", "Release", "RelWithDebInfo", "MinSizeRel", etc. - `CMAKE_GENERATOR(Required)`: specify the generator for the build system, such as "Ninja", "Unix Makefiles", "Visual Studio 16 2019", etc. And it's recommended to use Ninja for cross-platform builds. - `VCPKG_ROOT(Optional)`: specify the path to the toolchain file for the target platform. Normally it's in the vcpkg installation directory. If not specified, cmake/vcpkg/vcpkg.toolchain.cmake will automatically create one for you. @@ -46,7 +45,14 @@ Here's an example of building the project with the specified variables: ```bash # Configure -cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=cmake/vcpkg/vcpkg.toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -G Ninja -DVCPKG_TARGET_TRIPLET=x64-linux -DVCPKG_HOST_TRIPLET=x64-linux -DVCPKG_OVERLAY_TRIPLETS=cmake/vcpkg/triplets -DVCPKG_OVERLAY_PORTS=cmake/vcpkg/ports +cmake -S . -B build \ + -DCMAKE_TOOLCHAIN_FILE=cmake/vcpkg/vcpkg.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -G Ninja \ + -DVCPKG_TARGET_TRIPLET=x64-linux \ + -DVCPKG_HOST_TRIPLET=x64-linux \ + -DVCPKG_OVERLAY_TRIPLETS=cmake/vcpkg/triplets \ + -DVCPKG_OVERLAY_PORTS=cmake/vcpkg/ports # Build cmake --build build --config Debug # Testing diff --git a/template/cmake/presets/compilers/llvm.json b/template/cmake/presets/compilers/llvm.json index f673547f..5172325a 100644 --- a/template/cmake/presets/compilers/llvm.json +++ b/template/cmake/presets/compilers/llvm.json @@ -13,8 +13,8 @@ "name": "llvm-cl", "hidden": true, "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl" + "CMAKE_C_COMPILER": "clang-cl.exe", + "CMAKE_CXX_COMPILER": "clang-cl.exe" } } ] diff --git a/template/cmake/presets/triplets/x64-mingw-dynamic.json b/template/cmake/presets/triplets/x64-mingw-dynamic.json index d4060956..849b15f7 100644 --- a/template/cmake/presets/triplets/x64-mingw-dynamic.json +++ b/template/cmake/presets/triplets/x64-mingw-dynamic.json @@ -12,8 +12,7 @@ ], "cacheVariables": { "VCPKG_TARGET_TRIPLET": "x64-mingw-dynamic", - "VCPKG_HOST_TRIPLET": "x64-mingw-dynamic", - "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/cmake/vcpkg/scripts/toolchains/mingw.cmake" + "VCPKG_HOST_TRIPLET": "x64-mingw-dynamic" } } ] diff --git a/template/cmake/presets/triplets/x64-mingw-static.json b/template/cmake/presets/triplets/x64-mingw-static.json new file mode 100644 index 00000000..1caf05bd --- /dev/null +++ b/template/cmake/presets/triplets/x64-mingw-static.json @@ -0,0 +1,19 @@ +{ + "version": 6, + "include": [ + "../arch/x64.json" + ], + "configurePresets": [ + { + "name": "x64-mingw-static", + "hidden": true, + "inherits": [ + "x64" + ], + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-mingw-static", + "VCPKG_HOST_TRIPLET": "x64-mingw-static" + } + } + ] +} diff --git a/template/cmake/presets/x64-mingw-dynamic-windows-mingw-gcc.json b/template/cmake/presets/x64-mingw-dynamic-windows-mingw.json similarity index 57% rename from template/cmake/presets/x64-mingw-dynamic-windows-mingw-gcc.json rename to template/cmake/presets/x64-mingw-dynamic-windows-mingw.json index 85aa2fb0..0d9c996a 100644 --- a/template/cmake/presets/x64-mingw-dynamic-windows-mingw-gcc.json +++ b/template/cmake/presets/x64-mingw-dynamic-windows-mingw.json @@ -8,7 +8,7 @@ ], "configurePresets": [ { - "name": "x64-mingw-dynamic-windows-mingw-gcc", + "name": "x64-mingw-dynamic-windows-mingw", "inherits": [ "base", "windows", @@ -22,33 +22,33 @@ ], "buildPresets": [ { - "name": "x64-mingw-dynamic-windows-mingw-gcc", + "name": "x64-mingw-dynamic-windows-mingw", "inherits": "base", - "configurePreset": "x64-mingw-dynamic-windows-mingw-gcc" + "configurePreset": "x64-mingw-dynamic-windows-mingw" } ], "testPresets": [ { - "name": "x64-mingw-dynamic-windows-mingw-gcc", + "name": "x64-mingw-dynamic-windows-mingw", "inherits": "base", - "configurePreset": "x64-mingw-dynamic-windows-mingw-gcc" + "configurePreset": "x64-mingw-dynamic-windows-mingw" } ], "workflowPresets": [ { - "name": "x64-mingw-dynamic-windows-mingw-gcc", + "name": "x64-mingw-dynamic-windows-mingw", "steps": [ { "type": "configure", - "name": "x64-mingw-dynamic-windows-mingw-gcc" + "name": "x64-mingw-dynamic-windows-mingw" }, { "type": "build", - "name": "x64-mingw-dynamic-windows-mingw-gcc" + "name": "x64-mingw-dynamic-windows-mingw" }, { "type": "test", - "name": "x64-mingw-dynamic-windows-mingw-gcc" + "name": "x64-mingw-dynamic-windows-mingw" } ] } diff --git a/template/cmake/presets/x64-mingw-static-darwin-mingw.json b/template/cmake/presets/x64-mingw-static-darwin-mingw.json new file mode 100644 index 00000000..c40a5be2 --- /dev/null +++ b/template/cmake/presets/x64-mingw-static-darwin-mingw.json @@ -0,0 +1,53 @@ +{ + "version": 6, + "include": [ + "base.json", + "os/darwin.json", + "compilers/mingw.json", + "triplets/x64-mingw-static.json" + ], + "configurePresets": [ + { + "name": "x64-mingw-static-darwin-mingw", + "inherits": [ + "base", + "darwin", + "mingw", + "x64-mingw-static" + ] + } + ], + "buildPresets": [ + { + "name": "x64-mingw-static-darwin-mingw", + "inherits": "base", + "configurePreset": "x64-mingw-static-darwin-mingw" + } + ], + "testPresets": [ + { + "name": "x64-mingw-static-darwin-mingw", + "inherits": "base", + "configurePreset": "x64-mingw-static-darwin-mingw" + } + ], + "workflowPresets": [ + { + "name": "x64-mingw-static-darwin-mingw", + "steps": [ + { + "type": "configure", + "name": "x64-mingw-static-darwin-mingw" + }, + { + "type": "build", + "name": "x64-mingw-static-darwin-mingw" + }, + { + "type": "test", + "name": "x64-mingw-static-darwin-mingw" + } + ] + } + ] +} diff --git a/template/cmake/presets/x64-mingw-static-linux-mingw.json b/template/cmake/presets/x64-mingw-static-linux-mingw.json new file mode 100644 index 00000000..15355f53 --- /dev/null +++ b/template/cmake/presets/x64-mingw-static-linux-mingw.json @@ -0,0 +1,56 @@ +{ + "version": 6, + "include": [ + "base.json", + "os/linux.json", + "compilers/mingw.json", + "triplets/x64-mingw-static.json" + ], + "configurePresets": [ + { + "name": "x64-mingw-static-linux-mingw", + "inherits": [ + "base", + "linux", + "mingw", + "x64-mingw-static" + ], + "cacheVariables": { + "USE_SANITIZER": "FALSE" + } + } + ], + "buildPresets": [ + { + "name": "x64-mingw-static-linux-mingw", + "inherits": "base", + "configurePreset": "x64-mingw-static-linux-mingw" + } + ], + "testPresets": [ + { + "name": "x64-mingw-static-linux-mingw", + "inherits": "base", + "configurePreset": "x64-mingw-static-linux-mingw" + } + ], + "workflowPresets": [ + { + "name": "x64-mingw-static-linux-mingw", + "steps": [ + { + "type": "configure", + "name": "x64-mingw-static-linux-mingw" + }, + { + "type": "build", + "name": "x64-mingw-static-linux-mingw" + }, + { + "type": "test", + "name": "x64-mingw-static-linux-mingw" + } + ] + } + ] +} diff --git a/template/cmake/presets/x64-mingw-static-windows-mingw.json b/template/cmake/presets/x64-mingw-static-windows-mingw.json new file mode 100644 index 00000000..76201727 --- /dev/null +++ b/template/cmake/presets/x64-mingw-static-windows-mingw.json @@ -0,0 +1,56 @@ +{ + "version": 6, + "include": [ + "base.json", + "os/windows.json", + "compilers/mingw.json", + "triplets/x64-mingw-static.json" + ], + "configurePresets": [ + { + "name": "x64-mingw-static-windows-mingw-gcc", + "inherits": [ + "base", + "windows", + "mingw", + "x64-mingw-static" + ], + "cacheVariables": { + "USE_SANITIZER": "FALSE" + } + } + ], + "buildPresets": [ + { + "name": "x64-mingw-static-windows-mingw-gcc", + "inherits": "base", + "configurePreset": "x64-mingw-static-windows-mingw-gcc" + } + ], + "testPresets": [ + { + "name": "x64-mingw-static-windows-mingw-gcc", + "inherits": "base", + "configurePreset": "x64-mingw-static-windows-mingw-gcc" + } + ], + "workflowPresets": [ + { + "name": "x64-mingw-static-windows-mingw-gcc", + "steps": [ + { + "type": "configure", + "name": "x64-mingw-static-windows-mingw-gcc" + }, + { + "type": "build", + "name": "x64-mingw-static-windows-mingw-gcc" + }, + { + "type": "test", + "name": "x64-mingw-static-windows-mingw-gcc" + } + ] + } + ] +} diff --git a/template/cmake/vcpkg/bootstrap/vcpkg-config.cmake b/template/cmake/vcpkg/bootstrap/vcpkg-config.cmake index 3dc8bca4..0bc81a68 100644 --- a/template/cmake/vcpkg/bootstrap/vcpkg-config.cmake +++ b/template/cmake/vcpkg/bootstrap/vcpkg-config.cmake @@ -14,4 +14,6 @@ set(__vcpkg_bootstrap_list_dir "${CMAKE_CURRENT_LIST_DIR}") include(${__vcpkg_bootstrap_list_dir}/vcpkg_skip_install_on_reconfigure.cmake) include(${__vcpkg_bootstrap_list_dir}/vcpkg_bootstrap.cmake) +include(${__vcpkg_bootstrap_list_dir}/vcpkg_chainload_toolchain.cmake) +include(${__vcpkg_bootstrap_list_dir}/vcpkg_load_triplet.cmake) include(${__vcpkg_bootstrap_list_dir}/vcpkg_configure.cmake) diff --git a/template/cmake/vcpkg/bootstrap/vcpkg_chainload_toolchain.cmake b/template/cmake/vcpkg/bootstrap/vcpkg_chainload_toolchain.cmake new file mode 100644 index 00000000..0a38f875 --- /dev/null +++ b/template/cmake/vcpkg/bootstrap/vcpkg_chainload_toolchain.cmake @@ -0,0 +1,41 @@ +#[[ +SPDX-License-Identifier: MIT +SPDX-FileCopyrightText: Copyright 2024 msclock +]] + +# configure VCPKG_CHAINLOAD_TOOLCHAIN_FILE based on VCPKG_TARGET_TRIPLET and +# VCPKG_TARGET_ARCHITECTURE +function(_vcpkg_chainload_toolchain) + if(DEFINED VCPKG_CHAINLOAD_TOOLCHAIN_FILE) + return() + endif() + + if(NOT DEFINED VCPKG_TARGET_TRIPLET OR NOT DEFINED VCPKG_TARGET_ARCHITECTURE) + message( + FATAL_ERROR + "VCPKG_TARGET_TRIPLET and VCPKG_TARGET_ARCHITECTURE must be set before calling _vcpkg_chainload_toolchain()" + ) + endif() + + string(LENGTH "${VCPKG_TARGET_ARCHITECTURE}-" _prefix_len) + string(SUBSTRING ${VCPKG_TARGET_TRIPLET} ${_prefix_len} -1 _stripped_string) + string(REPLACE "-" ";" _triplet_parts "${_stripped_string}") + list(GET _triplet_parts 0 _chainload_toolchain_name) + + set(_toolchain "scripts/toolchains/${_chainload_toolchain_name}.cmake") + + if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${_toolchain}") + set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE + "${CMAKE_CURRENT_LIST_DIR}/${_toolchain}" + CACHE INTERNAL "vcpkg chainload") + elseif(EXISTS "${_VCPKG_ROOT}/${_toolchain}") + set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE + "${_VCPKG_ROOT}/${_toolchain}" + CACHE INTERNAL "vcpkg chainload") + else() + message( + WARNING + "Could not find toolchain file for ${_chainload_toolchain_name}, skipping chainload" + ) + endif() +endfunction() diff --git a/template/cmake/vcpkg/bootstrap/vcpkg_configure.cmake b/template/cmake/vcpkg/bootstrap/vcpkg_configure.cmake index 206cf2da..3ea5f810 100644 --- a/template/cmake/vcpkg/bootstrap/vcpkg_configure.cmake +++ b/template/cmake/vcpkg/bootstrap/vcpkg_configure.cmake @@ -5,7 +5,9 @@ SPDX-FileCopyrightText: Copyright 2024 msclock ]] # bootstrap and configure vcpkg -function(vcpkg_configure) +macro(vcpkg_configure) _vcpkg_bootstrap(${ARGN}) _vcpkg_skip_install_on_reconfigure() -endfunction() + _vcpkg_load_triplet() + _vcpkg_chainload_toolchain() +endmacro() diff --git a/template/cmake/vcpkg/bootstrap/vcpkg_load_triplet.cmake b/template/cmake/vcpkg/bootstrap/vcpkg_load_triplet.cmake new file mode 100644 index 00000000..072def56 --- /dev/null +++ b/template/cmake/vcpkg/bootstrap/vcpkg_load_triplet.cmake @@ -0,0 +1,34 @@ +#[[ +SPDX-License-Identifier: MIT +SPDX-FileCopyrightText: Copyright 2024 msclock +]] + +# load the triplet by VCPKG_TARGET_TRIPLET +macro(_vcpkg_load_triplet) + if(NOT DEFINED VCPKG_TARGET_TRIPLET) + message( + FATAL_ERROR + "VCPKG_TARGET_TRIPLET is not defined, please set it to the desired triplet" + ) + endif() + + set(_triplet "triplets/${VCPKG_TARGET_TRIPLET}.cmake") + set(_community_triplet "triplets/community/${VCPKG_TARGET_TRIPLET}.cmake") + + if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${_triplet}") + include("${CMAKE_CURRENT_LIST_DIR}/${_triplet}") + elseif(EXISTS "${_VCPKG_ROOT}/${_triplet}") + include("${_VCPKG_ROOT}/${_triplet}") + elseif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${_community_triplet}") + include("${CMAKE_CURRENT_LIST_DIR}/${_community_triplet}") + elseif(EXISTS "${_VCPKG_ROOT}/${_community_triplet}") + include("${_VCPKG_ROOT}/${_community_triplet}") + else() + message( + FATAL_ERROR + "Triplet ${VCPKG_TARGET_TRIPLET} not found at ${CMAKE_CURRENT_LIST_DIR}/${_triplet} or ${_VCPKG_ROOT}/${_triplet}" + ) + endif() + unset(_triplet) + unset(_community_triplet) +endmacro(_vcpkg_load_triplet)