Cmake用法
cmake
1.常见用法
cd some_software-1.4.2
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/opt/the/prefix
cmake --build .
cmake --build . --target install
cmake --build . --target myexe --config Release
2.构建变量
CMAKE_PREFIX_PATH 搜索路径 dependent packages
CMAKE_MODULE_PATH 搜索其他 CMake 模块的路径
CMAKE_BUILD_TYPE 构建配置,例如 Debug或Release,确定调试/优化标志。这仅与单配置构建系统(例如Makefile和Ninja)相关。多配置构建系统(例如 Visual Studio 和 Xcode 的构建系统)会忽略此设置。
CMAKE_INSTALL_PREFIX 使用 install构建目标安装软件的位置
CMAKE_TOOLCHAIN_FILE 包含交叉编译数据的文件,例如 toolchains and sysroots。
BUILD_SHARED_LIBS 是否构建共享库而不是静态库add_library() 不使用类型的命令
CMAKE_EXPORT_COMPILE_COMMANDS 生成一个compile_commands.json 用于基于 clang 的工具的文件
CMAKE_EXPORT_BUILD_DATABASE 生成一个build_database.json 用于基于 clang 的工具的文件
3.基本cmake包
# 需要的cmake版本声明
cmake_minimum_required(VERSION 3.15)
# 项目名称和版本
project(Tutorial VERSION 1.0)
# 生成可执行文件
add_executable(Tutorial tutorial.cxx)
#include <iostream>
int main(int argc, char* argv[])
{
std::cout << "hello" << std::endl;
return 0;
}
4.代码中使用项目版本号
TutorialConfig.h会生成到PROJECT_BINARY_DIR目录中
configure_file(TutorialConfig.h.in TutorialConfig.h)
#将PROJECT_BINARY_DIR添加到包含文件的搜索路径中
#这样我们就能找到TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#include <iostream>
#include <string>
#include "TutorialConfig.h"
int main(int argc, char* argv[])
{
// report version
std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
<< Tutorial_VERSION_MINOR << std::endl;
return 0;
}
5.创建动态库
// MathFunctions/CMakeLists.txt
# 声明动态库
add_library(MathFunctions MathFunctions.cxx)
# 声明动态库的接口目录(动态库用户需要使用的目录(生成时不需要))
target_include_directories(MathFunctions
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
CMakeLists.txt
add_subdirectory(MathFunctions)
6.链接动态库
CMakeLists.txt
# 链接动态库名称
target_link_libraries(Tutorial PUBLIC MathFunctions)
tutorial.cxx
#include "MathFunctions.h"
7.cmake 选项
MathFunctions/CMakeLists.txt
# 声明选项 默认为ON
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# 选项逻辑
if (USE_MYMATH)
# 产生编译宏
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
include(MakeTable.cmake) # generates Table.h
# library that just does sqrt
add_library(SqrtLibrary STATIC
mysqrt.cxx
${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
# state that we depend on our binary dir to find Table.h
target_include_directories(SqrtLibrary PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
# state that SqrtLibrary need PIC when the default is shared libraries
set_target_properties(SqrtLibrary PROPERTIES
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
)
# link SqrtLibrary to tutorial_compiler_flags
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()
MathFunctions/MathFunctions.cxx
//代码中的选项宏
#include <cmath>
#ifdef USE_MYMATH
# include "mysqrt.h"
#endif
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
8.设置 C++ 标准
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
9.向目标添加编译选项
CMakeLists.txt
# 设置变量
set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
# 向目标添加编译选项
# BUILD_INTERFACE限制该设置只有在构建时候生效
target_compile_options(tutorial_compiler_flags INTERFACE
"$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
10.安装
MathFunctions/CMakeLists.txt
# 安装动态库
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs}
EXPORT MathFunctionsTargets
DESTINATION lib)
# 安装头文件
install(FILES MathFunctions.h DESTINATION include)
CMakeLists.txt
# add the install targets
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include
)
11.测试
CMakeLists.txt
# 生成并安装测试程序
add_executable(Tutorial tutorial.cxx)
set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
# add the install targets
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include
)
# 启动测试功能
enable_testing()
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
# 检测打印输出是否包含指定正则表达式
add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(Usage
PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
)
# define a function to simplify adding tests
function(do_test target arg result)
add_test(NAME Comp${arg} COMMAND ${target} ${arg})
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
# 测试程序的输出语句
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;
12.测试仪表盘
CMakeLists.txt
include(CTest)
CTestConfig.cmake
set(CTEST_PROJECT_NAME "CMakeTutorial")
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
set(CTEST_DROP_SITE_CDASH TRUE)
ctest [-VV] -D Experimental
ctest [-VV] -C Debug -D Experimental
13.添加系统自检
在项目中添加一些依赖于目标平台可能没有的功能的代码
MathFunctions/CMakeLists.txt
#检查是否可以构建 C++ 源代码
include(CheckCXXSourceCompiles)
#检查是否可以构建特定 C++ 源代码
check_cxx_source_compiles("
#include <cmath>
int main() {
std::log(1.0);
return 0;
}
" HAVE_LOG)
check_cxx_source_compiles("
#include <cmath>
int main() {
std::exp(1.0);
return 0;
}
" HAVE_EXP)
#根据检查结果修改编译流程
if(HAVE_LOG AND HAVE_EXP)
target_compile_definitions(SqrtLibrary
PRIVATE "HAVE_LOG" "HAVE_EXP"
)
endif()
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()
MathFunctions/mysqrt.cxx
#include <cmath>
#if defined(HAVE_LOG) && defined(HAVE_EXP)
double result = std::exp(std::log(x) * 0.5);
std::cout << "Computing sqrt of " << x << " to be " << result
<< " using log and exp" << std::endl;
#else
double result = x;
// do ten iterations
for (int i = 0; i < 10; ++i) {
if (result <= 0) {
result = 0.1;
}
double delta = x - (result * result);
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
#endif
14.添加自定义命令和生成文件
MathFunctions/MakeTable.cmake
# 我们添加MakeTable的可执行文件
add_executable(MakeTable MakeTable.cxx)
target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags)
# 添加生成源代码的命令
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
)
MathFunctions/CMakeLists.txt
# 包含自定义命令文件
include(MakeTable.cmake)
#目标依赖于生成的文件
add_library(SqrtLibrary STATIC
mysqrt.cxx
${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
# 在CMAKE_CURRENT_BINARY_DIR查找头文件
target_include_directories(SqrtLibrary PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
15.打包安装程序
CMakeLists.txt
# setup installer
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
set(CPACK_GENERATOR "TGZ")
set(CPACK_SOURCE_GENERATOR "TGZ")
include(CPack)
打包命令
# 打包生成软件包
cpack
# -G选项选择生成器 -C多配置构建
cpack -G ZIP -C Debug
16.选择静态或共享库
CMakeLists.txt
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
MathFunctions/CMakeLists.txt
#设置目标库的属性(位置无关代码)
set_target_properties(SqrtLibrary PROPERTIES
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
)
#设置宏,用于windows程序库的生成
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
MathFunctions/MathFunctions.h
根据宏定义切换链接方式
#if defined(_WIN32)
# if defined(EXPORTING_MYMATH)
# define DECLSPEC __declspec(dllexport)
# else
# define DECLSPEC __declspec(dllimport)
# endif
#else // non windows
# define DECLSPEC
#endif
namespace mathfunctions {
double DECLSPEC sqrt(double x);
}
17.导出给其他cmake项目使用
17.1导出安装 *Targets.cmake文件
MathFunctions/CMakeLists.txt
# 这里应保证不导出当前计算机固有关联的路径(使用BUILD_INTERFACE、INSTALL_INTERFACE分别描述)
target_include_directories(MathFunctions
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
# install(TARGETS) 增加EXPORT关键字生成CMake文件MathFunctionsTargets.cmake
install(TARGETS MathFunctions
EXPORT MathFunctionsTargets
DESTINATION lib)
# 安装生成的MathFunctionsTargets.cmake文件
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
17.2导出安装两个Config cmake文件
Config.cmake.in
@PACKAGE_INIT@
include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )
CMakeLists.txt
include(CMakePackageConfigHelpers)
# 生成MathFunctionsConfig.cmake
# 根据Config.cmake.in生成包含导出的配置文件MathFunctionsConfig.cmake
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
INSTALL_DESTINATION "lib/cmake/MathFunctions"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
# 生成MathFunctionsConfigVersion.cmake
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}"
COMPATIBILITY AnyNewerVersion
)
# 安装两个config文件
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake
DESTINATION lib/cmake/MathFunctions
)
17.3 导出MathFunctionsTargets.cmake
通常,项目在被外部项目使用之前会先进行构建和安装。但是,在某些情况下,最好直接从构建树中导出目标。然后,引用构建树的外部项目可以使用这些目标,而无需进行安装。
CMakeLists.txt
export(EXPORT MathFunctionsTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake"
)
17.4 导出Targets文件NAMESPACE用法
此命令生成MathFunctionsTargets.cmake文件并安排将其安装到${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions。该文件包含适合下游使用的代码,用于从安装树导入安装命令中列出的所有目标。
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
NAMESPACE MathFunctions::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions
)
17.5 导入target文件
include(${INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions/MathFunctionsTargets.cmake)
add_executable(myexe src1.c src2.c )
target_link_libraries(myexe PRIVATE MathFunctions::MathFunctions)
18.打包debug和release
18.1区分调试库的后缀
CMakeLists.txt
set(CMAKE_DEBUG_POSTFIX d)
add_library(tutorial_compiler_flags INTERFACE)
add_executable(Tutorial tutorial.cxx)
set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
18.2 设置库版本
MathFunctions/CMakeLists.txt
set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
18.3 构建debug和release库
cd debug
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake --build .
cd ../release
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
18.4 debug+release打包
打包脚本
MultiCPackConfig.cmake
MultiCPackConfig.cmake
include("release/CPackConfig.cmake")
set(CPACK_INSTALL_CMAKE_PROJECTS
"debug;Tutorial;ALL;/"
"release;Tutorial;ALL;/"
)
打包命令
cpack --config MultiCPackConfig.cmake
19.导入cmake包
19.1一般导入
find package的用法
find_package(Catch2)
find_package(GTest REQUIRED)
find_package(Boost 1.79 COMPONENTS date_time)
find package完整使用方式
cmake_minimum_required(VERSION 3.10)
project(MyExeProject VERSION 1.0.0)
# Make project-provided Find modules available
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(SomePackage REQUIRED)
add_executable(MyExe main.cpp)
target_link_libraries(MyExe PRIVATE SomePrefix::LibName)
19.2导入并使用git包
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
FIND_PACKAGE_ARGS NAMES GTest
)
FetchContent_MakeAvailable(googletest)
add_executable(ThingUnitTest thing_ut.cpp)
target_link_libraries(ThingUnitTest GTest::gtest_main)
include(FetchContent)
FetchContent_Declare(
Catch2
URL https://intranet.mycomp.com/vendored/Catch2_2.13.4_patched.tgz
URL_HASH MD5=abc123...
OVERRIDE_FIND_PACKAGE
)
# The following is automatically redirected to FetchContent_MakeAvailable(Catch2)
find_package(Catch2)
19.3导入多种配置的库
find_library(math_REL NAMES m)
find_library(math_DBG NAMES md)
add_library(math STATIC IMPORTED GLOBAL)
set_target_properties(math PROPERTIES
IMPORTED_LOCATION "${math_REL}"
IMPORTED_LOCATION_DEBUG "${math_DBG}"
IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
)
add_executable(myexe src1.c src2.c)
target_link_libraries(myexe PRIVATE math)
20.导入其他
导入可执行文件
导入一个可生成源码的可执行文件,然后编译生成的源码
add_executable(myexe IMPORTED)
set_property(TARGET myexe PROPERTY
IMPORTED_LOCATION "../InstallMyExe/bin/myexe")
add_custom_command(OUTPUT main.cc COMMAND myexe)
add_executable(mynewexe main.cc)
导入动态库
add_library(foo STATIC IMPORTED)
set_property(TARGET foo PROPERTY
IMPORTED_LOCATION "/path/to/libfoo.a")
add_executable(myexe src1.c src2.c)
target_link_libraries(myexe PRIVATE foo)
windows 导入
add_library(bar SHARED IMPORTED)
set_property(TARGET bar PROPERTY
IMPORTED_LOCATION "c:/path/to/bar.dll")
set_property(TARGET bar PROPERTY
IMPORTED_IMPLIB "c:/path/to/bar.lib")
add_executable(myexe src1.c src2.c)
target_link_libraries(myexe PRIVATE bar)

浙公网安备 33010602011771号