CMake Help 系列基于CMake Tutorial 本文基于Step 2: Adding a Library Rather than placing all of the source files in one directory, we can organize our project with one or more subdirectories. In this case, we will create a subdirectory specifically for our library. Here, we can add a new CMakeLists.txt file and one or more source files. In the top level CMakeLists.txt file, we will use the add_subdirectory() command to add the subdirectory to the build. Once the library is created, it is connected to our executable target with target_include_directories() and target_link_libraries().
创建生成一个静态库 考虑,我们需要一个数学库的开方运算。自建一个数学库。目录结构如下
1 2 3 4 5 6 7 8 9 10 11 12 13 . ├── CMakeLists.txt ├── MyProject.h.in ├── include │ └── hello.h ├── libs │ └── mathFunctions │ ├── CMakeLists.txt │ ├── mathfunctions.h │ └── mysqrt.cpp └── src ├── hello.cpp └── main.cpp
在mathfunctions.h
声明方法,写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #ifndef _MATHFUNCTIONS_H_ #define _MATHFUNCTIONS_H_ namespace mymath {int mySqrt (int x) ;} #endif
在mysqrt.cpp
实现开方运算这个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include "mathfunctions.h" int mymath::mySqrt (int x) { int l = 0 , r = x, ans = -1 ; while (l <= r) { int mid = l + (r - l) / 2 ; if ( static_cast <long long >(mid * mid) <= x) { ans = mid; l = mid + 1 ; } else { r = mid - 1 ; } } return ans; }
编辑libs/mathFunctions/CMakeList.txt
文件。
我们要告知CMake
创建一个库目标,向其添加文件。
1 2 add_library (MathFunctions STATIC mysqrt.cpp)
这里我们定义了一个库MathFunctions
,向其添加mysqrt.cpp
文件。
在程序中链接静态库 我们返回MyProject
项目的目录。修改CMakeList.txt
文件。
为了使用我们自定义的MathFunctions
库,我们需要告知CMake
这个库的位置在哪。 库MathFunctions
定义在libs/mathFunctions/CMakeList.txt
中。
1 2 add_subdirectory (libs/mathFunctions)
而后我们在告知CMake
在生成可执行文件target1
前要将库MathFunctions
链接进来。
1 2 target_link_libraries (target1 PUBLIC MathFunctions)
最后我们需要告知库MathFunctions
的头文件在哪。
1 2 3 4 5 target_include_directories (target1 PUBLIC "${PROJECT_BINARY_DIR}" "include" "libs/mathFunctions" )
最后的CMakelists.txt
文件为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 cmake_minimum_required (VERSION 3.25 .0 )project (MyProject VERSION 1.0 .0 )configure_file ("MyProject.h.in" "MyProject.h" ) set (CMAKE_CXX_STANDARD 17 )set (CMAKE_CXX_STANDARD_REQUIRED on )set (CMAKE_EXPORT_COMPILE_COMMANDS ON )add_subdirectory (libs/mathFunctions)aux_source_directory (${PROJECT_SOURCE_DIR} /src sources)add_executable (target1)target_link_libraries (target1 PUBLIC MathFunctions)target_include_directories (target1 PUBLIC "${PROJECT_BINARY_DIR}" "include" "libs/mathFunctions" ) target_sources (target1 PUBLIC ${sources} )
修改./src/main.cpp
文件,调用自定义库中的库函数。
1 2 3 4 5 6 7 8 9 #include "hello.h" #include <mathfunctions.h> #include <iostream> int main () { printHelloWorld(); std ::cout << "100的算数平方根为" << mymath::mySqrt(100 ) << "\n" ; }
执行命令,构建target1
并运行。
1 cmake -B build && cmake --build build && ./build/target1
Hello World! 100的算数平方根为10
Exercise 2 - Making Our Library Optional
Now let us make the MathFunctions library optional. While for the tutorial there really isn’t any need to do so, for larger projects this is a common occurrence.
CMake can do this using the option()
command. This gives users a variable which they can change when configuring their cmake build. This setting will be stored in the cache so that the user does not need to set the value each time they run CMake on a build directory.
我们为自定义的库创建一个宏定义USE_MYMATH
去控制是否导入这个库。
修改CMakeLists.txt
文件,添加
1 2 3 4 5 6 7 8 9 10 11 option (USE_MYMATH "Use tutorial provided math implementation" ON )if (USE_MYMATH) add_subdirectory (libs/mathFunctions) list (APPEND EXTRA_LIBS MathFunctions) list (APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/libs/mathFunctions" ) endif ()
修改
1 2 3 4 5 6 7 8 9 target_link_libraries (target1 PUBLIC ${EXTRA_LIBS} )target_include_directories (target1 PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES} )
最后的CMakeLists.txt
文件为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 cmake_minimum_required (VERSION 3.25 .0 )project (MyProject VERSION 1.0 .0 )configure_file ("MyProject.h.in" "MyProject.h" ) set (CMAKE_CXX_STANDARD 17 )set (CMAKE_CXX_STANDARD_REQUIRED on )set (CMAKE_EXPORT_COMPILE_COMMANDS ON )option (USE_MYMATH "Use tutorial provided math implementation" ON )if (USE_MYMATH) add_subdirectory (libs/mathFunctions) list (APPEND EXTRA_LIBS MathFunctions) list (APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/libs/mathFunctions" ) endif ()include_directories (${PROJECT_SOURCE_DIR} /include )aux_source_directory (${PROJECT_SOURCE_DIR} /src sources)add_executable (target1)target_link_libraries (target1 PUBLIC ${EXTRA_LIBS} )target_include_directories (target1 PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES} ) target_sources (target1 PUBLIC ${sources} )
将USE_MYMATH
加入配置文件MyProject.h.in
中
1 2 3 4 #define MyProject_VERSION_MAJOR @MyProject_VERSION_MAJOR@ #define MyProject_VERSION_MINOR @MyProject_VERSION_MINOR@ #define MyProject_VERSION_PATCH @MyProject_VERSION_PATCH@ #cmakedefine USE_MYMATH
在项目中使用USE_MYMATH
控制,修改src/main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "MyProject.h" #include "hello.h" #ifdef USE_MYMATH #include <mathfunctions.h> #endif #include <cmath> #include <iostream> int main () { printHelloWorld(); #ifdef USE_MYMATH std ::cout << "100的算数平方根为" << mymath::mySqrt(100 ) << "\n" ; #else std ::cout << "使用标准库函数。100的算数平方根为" << sqrt (100 ) << "\n" ; #endif }