Ответ 1
Ваш подход был бы, как прокомментировал @Tsyvarev, абсолютно нормальным, поскольку ваш запрос о "новом" подходе в CMake будет следующим:
cmake_minimum_required(VERSION 3.8)
project(HelloWorld)
string(
APPEND _opts
"$<IF:$<CXX_COMPILER_ID:MSVC>,"
"/W4;$<$<CONFIG:RELEASE>:/O2>,"
"-Wall;-Wextra;-Werror;"
"$<$<CONFIG:RELEASE>:-O3>"
"$<$<CXX_COMPILER_ID:Clang>:-stdlib=libc++>"
">"
)
add_compile_options("${_opts}")
add_executable(HelloWorld "main.cpp")
target_compile_features(HelloWorld PUBLIC cxx_lambda_init_captures)
Вы берете add_compile_options()
и - как @Al.G. прокомментировал - "используйте грязные выражения генератора".
Есть несколько недостатков выражений генератора:
- Очень полезное выражение
$<IF:...,...,...>
доступно только в версии CMake> = 3.8 - Вы должны написать это в одну строку. Чтобы избежать этого, я использовал
string(APPEND ...)
, который вы также можете использовать для "оптимизации" ваших вызововset(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ...
. - Это трудно читать и понимать. Например. точки с запятой необходимы, чтобы сделать его списком параметров компиляции (в противном случае CMake процитирует его).
Поэтому лучше использовать более читаемый и обратно совместимый подход с add_compile_options()
:
if(MSVC)
add_compile_options("/W4" "$<$<CONFIG:RELEASE>:/O2>")
else()
add_compile_options("-Wall" "-Wextra" "-Werror" "$<$<CONFIG:RELEASE>:-O3>")
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options("-stdlib=libc++")
else()
# nothing special for gcc at the moment
endif()
endif()
И да, вы больше не указываете явно стандарт C++, вы просто называете функцию C++, от которой зависит ваш код/цель, с помощью вызовов target_compile_features()
.
Для этого примера я выбрал cxx_lambda_init_captures
, например, для старый компилятор GCC выдает следующую ошибку (например, что происходит, если компилятор не поддерживает эту функцию):
The compiler feature "cxx_lambda_init_captures" is not known to CXX compiler
"GNU"
version 4.8.4.
Кроме того, вам нужно написать скрипт-обертку для создания нескольких конфигураций с помощью генератора make файлов "с одной конфигурацией" или использовать "среду с несколькими конфигурациями" в качестве Visual Studio.
Вот ссылки на примеры:
- Всегда ли CMake генерирует конфигурации для всех возможных конфигураций проекта?
- Как сказать CMake использовать Clang в Windows?
- Как добавить компиляцию Linux в Cmake Project в Visual Studio
Итак, я протестировал следующее с поддержкой Open Folder
Visual Studio 2017 CMake, чтобы объединить в этом примере компиляторы cl, clang и mingw:
CMakeSettings.json
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"buildCommandArgs": "-m -v:minimal",
},
{
"name": "x86-Release",
"generator": "Visual Studio 15 2017",
"configurationType": "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"buildCommandArgs": "-m -v:minimal",
},
{
"name": "Clang-Debug",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-T\"LLVM-vs2014\"",
"buildCommandArgs": "-m -v:minimal",
},
{
"name": "Clang-Release",
"generator": "Visual Studio 15 2017",
"configurationType": "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-T\"LLVM-vs2014\"",
"buildCommandArgs": "-m -v:minimal",
},
{
"name": "GNU-Debug",
"generator": "MinGW Makefiles",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"variables": [
{
"name": "CMAKE_MAKE_PROGRAM",
"value": "${projectDir}\\mingw32-make.cmd"
}
]
},
{
"name": "GNU-Release",
"generator": "Unix Makefiles",
"configurationType": "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"variables": [
{
"name": "CMAKE_MAKE_PROGRAM",
"value": "${projectDir}\\mingw32-make.cmd"
}
]
}
]
}
mingw32-make.cmd
@echo off
mingw32-make.exe %~1 %~2 %~3 %~4
Таким образом, вы можете использовать любой генератор CMake из Visual Studio 2017, происходит нездоровое цитирование (как в сентябре 2017 года, может быть исправлено позже), для которого требуется mingw32-make.cmd
посредник (удаление кавычек).