我们目的是将MathFunctions/
文件夹内的头文件MathFunctions.h
和源代码mysqrt.cxx
编译成一个库,外部的tutorial.cxx
再使用这个库的功能。
在包含要编译成库的源码的路径下添加一个CMakeLists.txt:
add_library(MathFunctions mysqrt.cxx)# 把当前文件夹下的mysqrt.cxx 编译名为MathFunctions的库。
为了这个编译好的库能被顶层的CMakeLists.txt 找到 ,需要在顶层的CMakeList.txt 内添加一些语句并修改一些语句确保编译后的库可以被引用,
add_subdirectory(子文件夹名)
在 add_executable(工程名 主程序源代码文件)
之前;add_executable()
之后指定目标要链接的库 target_link_libraries()
,目标需要由add_library()
或者add_executable()
生成;target_include_directories()
指定目标包含的头文件路径,包含子目录文件夹;target_include_directories() :
target_link_directories( [BEFORE]
[items1...]
[ [items2...] ...])
其中INTERFACE|PUBLIC|PRIVATE
#add the mathfunction library
add_subdirectory(MathFunctions)
#add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC MathFunctions)
#add the include directories
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_BINARY_DIR}/MathFunctions"
)
在大型工程项目中可能需要添加一些是否必要选用自己写的库还是其他库,即需要在顶层CMakeLists.txt给出一个可选择的编译选项开关。
其中option(
给出一个选项。如果[value]
这个参数没有给定,缺省的值为OFF
.
添加在 configure_file()
命令之前。
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)
当使用ccmake或者gui的时候会弹出该选项。
(make it conditional)
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
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}
)
其中,list()
命令主要用于对列表进行操作,如下:
Reading
list(LENGTH )
list(GET [ ...] )
list(JOIN )
list(SUBLIST )
Search
list(FIND )
Modification
list(APPEND [...])
list(FILTER {INCLUDE | EXCLUDE} REGEX )
list(INSERT [...])
list(POP_BACK [...])
list(POP_FRONT [...])
list(PREPEND [...])
list(REMOVE_ITEM ...)
list(REMOVE_AT ...)
list(REMOVE_DUPLICATES )
list(TRANSFORM [...])
Ordering
list(REVERSE )
list(SORT [...])
list 的子命令APPEND
,INSERT
等等这些都是列表的操作
需要注意的是cmake的列表是由 ;
隔开的字符串。例如可以用 set()
来生成cmake的列表:
set (var a b c d e)
会生成一个list有5个元素:a;b;c;d;e
set(var "a b c d e")
会生成一个list或一个字符串,其中有1个元素。
对于APPEND
即在list尾部加上该元素。在这里使用EXTRA_
LIBS 变量来包含所有后续可供选择的,会被链接到主程序的库们,使用EXTRA_INCLUDES
变量同理包含上述库所在的路径。这是一个很经典(老式)方法,后面tutorial会介绍更现代(新式)的方法。
使用EXTRA_LIBS
和EXTRA_INCLUDES
包含了要添加的库名和库源码所在路径之后相应的 target_link_libraries()
和target_include_directories()
中使用对EXTRA_LIBS和
EXTRA_INCLUDES的引用。
配置文件都修改完之后修改源码主程序中对库的依赖,
其中需要修改头文件包含和函数部分,使用宏来完成:
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
...
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
#cmakedefine USE_MYMATH
新建build文件夹在其中进行编译:
mkdir build
cd build
cmake ../ #若想要关闭自编库的引入,cmake ../ -DUSE_MYMATH=OFF
cmake --build .
./Tutorial 9
Note:
我在测试时使用命令行可以关掉USE_MYMATH,但是ccmake的时候没能看到这个选项。