cmake学习笔记(二)
向项目中添加一个自己的库。将编写好的库文件放入名为MathFunctions的子目录中。此目录已包含头文件MathFunctions.h和源文件mysqrt.cxx。源文件有名为mysqrt的函数,它提供域编译器sqrt类似的的功能。
将包含以下代码的CMakeLists.txt文件添加到MathFunctions目录:
add_library(MathFunctions mysqrt.cxx)
在主目录下的CMakeLists.txt文件中添加以下代码:
# add the MathFunctions library
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC MathFunctions)
# 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}"
"${PROJECT_SOURCE_DIR}/MathFunctions"
)
将MathFunctions库设置为可选(这一步并非必要,但在大型项目中比较常见)。
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)
此选项将显示在cmake gui中,默认值ON,用户可以进行更改。编译后,此设置将会存储在缓存中,因此用户无需每次运行cmake时设置该值。
将和MathFunctions库的连接成为有条件的:
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}
)
使用变量EXTRA_LIBS添加可选库,使用EXTRA_INCLUDES添加可选头文件。
対源码的修改,在tutorial.cxx中包含MathFunctions.h标题:
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
根据USE_MYMATH选择不同的库函数:
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
由于源码中使用USE_MYMATH,因此在TutorialConfig.h.in文件中添加如下行:
#cmakedefine USE_MYMATH
在编译过程中使用以下选项配置USE_MYMATH ON/OFF:
cmake ../Step2 -D USE_MYMATH=OFF
后记:
list用法:
list(LENGTH <list><output variable>)
list(GET <list> <elementindex> [<element index> ...]<output variable>)
list(APPEND <list><element> [<element> ...])
list(FIND <list> <value><output variable>)
list(INSERT <list><element_index> <element> [<element> ...])
list(REMOVE_ITEM <list> <value>[<value> ...])
list(REMOVE_AT <list><index> [<index> ...])
list(REMOVE_DUPLICATES <list>)
list(REVERSE <list>)
list(SORT <list>)
- LENGTH:返回list的长度
- GET:返回list中index的element到value中
- APPEND:添加新element到list中
- FIND:返回list中element的index,没有找到返回-1
- INSERT:将element插入到list中index的位置
- REMOVE_ITEM:从list中删除某个element
- REMOVE_AT:从list中删除指定index的element
- REMOVE_DUPLICATES:从list中删除重复的element
- REVERSE:将list中的内容反转
- SORT:将list按字母顺序排序
LIST与SET命令类似,即使列表本身实在父域中定义的,LIST指令也只会在当前域创建新的变量,要想将这些操作的结果向上传递,需要通过SET PARENT_SCOPE,SET CACHE_INTERNAL或运用其他值域扩展的方法。
cmake中的list是以分号隔开的一组字符串。可以使用set命令创建一个新的列表。例:set(var a b c d e)
当指定index时,如果element index为大于或等于的值,它从列表的开始处索引,0代表列表的第一个元素。如果element index为小于或等于-1的值,则从列表的结束处开始索引,-1表示列表的最后一个元素。
target_link_libraries中属性PRIVATE、PUBLIC、INTERFACE含义:
- PRIVATE: 源文件(如cpp)中包含第三方头文件,但是头文件(如hpp)中不包含该第三方头文件
- PUBLIC: 源文件和头文件中都包含该第三方头文件
- INTERFACE: 头文件中包含第三方头文件,但是源文件中不包含