CMake使用教程二:CMake依赖外部库
1. 概述
此教程旨在说明通过CMake
构建时,对外部库的处理方式,同时此教程会涉及以下主要点:
- 通过
CMake
定义C++
的宏 - 子模块构建
2. 源码
目录结构:
.
├── CMakeLists.txt
├── MathFunctions
│ ├── CMakeLists.txt
│ ├── MathFunctions.h
│ └── mysqrt.cpp
├── TutorialConfig.h.in
└── tutorial.cpp
-
tutorial.cpp
// A simple program that computes the square root of a number #include <cmath> #include <iostream> #include <string> #include "TutorialConfig.h" // should we include the MathFunctions header? #ifdef USE_MYMATH #include "MathFunctions.h" #endif int main(int argc, char* argv[]) { if (argc < 2) { // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } // convert input to double const double inputValue = std::stod(argv[1]); // which square root function should we use? #ifdef USE_MYMATH const double outputValue = mysqrt(inputValue); #else const double outputValue = sqrt(inputValue); #endif std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; return 0; }
-
TutorialConfig.h.in
// the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ #cmakedefine USE_MYMATH
-
mysqrt.cpp
#include <iostream> #include "MathFunctions.h" // a hack square root calculation using simple operations double mysqrt(double x) { if (x <= 0) { return 0; } 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; } return result; }
-
MathFunctions.h
double mysqrt(double x);
3. CMakeLists.txt
-
./CMakeLists.txt
cmake_minimum_required(VERSION 3.10) # set the project name and version project(Tutorial VERSION 1.0) # specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) # should we use our own math functions # 类似于C语言中的宏条件编译,可以使TutorialConfig.h.in中的#cmakedefine USE_MYMATH生效,也可以通过 cmake -B ./bin -S ./ -DUSE_MYMATH=ON 方式使其生效 option(USE_MYMATH "Use tutorial provided math implementation" ON) # configure a header file to pass some of the CMake settings to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library if(USE_MYMATH) # 添加子模块的构建 add_subdirectory(MathFunctions) # 将要链接的库名添加到 EXTRA_LIBS 列表变量中 list(APPEND EXTRA_LIBS MathFunctions) # 将头文件的包含目录添加到 EXTRA_INCLUDES 列表变量中 list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions") endif() # add the executable add_executable(Tutorial tutorial.cpp) # 链接依赖库 target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) # 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}" ${EXTRA_INCLUDES} )
-
./MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cpp)
4. CMake文件解析
add_subdirectory(source_dir [binary_dir])
向这个build
中添加子目录
source_dir
指定源CMakeLists.txt
和代码文件所在的目录,通常是一个相对路径也可以是绝对路径
binary_dir
指定输出文件的目录,若未设置,则输出到source_dir
所在目录#cmakedefine
#cmakedefine
的作用是通过CMake
定义C++
的宏,在configure_file()
调用后,会将其进行替换。
在CMake
中通过option(USE_MYMATH "Use tutorial provided math implementation" ON)
进行设置,或在构建时指定cmake -B ./bin -S ./ -DUSE_MYMATH=ON
,可以设置ON
或OFF
5. 优化
由于每个依赖MathFunctions
的目标,都需要包含MathFunctions
的目录,所以最好可以在./MathFunctions/CMakeLists.txt
将这个事情处理,这样依赖MathFunctions
的目标就不需要进行其他处理。
- 修改
./MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cpp)
# INTERFACE 指定的是使用者(依赖此库的目标)需要的东西,因此其他使用者就不用额外添加这个库的包含目录
target_include_directories(MathFunctions INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
- 修改
./CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# should we use our own math functions
# 类似于C语言中的宏条件编译,可以使TutorialConfig.h.in中的#cmakedefine USE_MYMATH生效,也可以通过 cmake -B ./bin -S ./ -DUSE_MYMATH=ON 方式使其生效
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
# 添加子模块的构建
add_subdirectory(MathFunctions)
# 将要链接的库名添加到 EXTRA_LIBS 列表变量中
list(APPEND EXTRA_LIBS MathFunctions)
endif()
# add the executable
add_executable(Tutorial tutorial.cpp)
# 链接依赖库
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# 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}"
)