尝试给项目添加一个库,还是以上一篇的CalculateSqrt为例。
1、新建库
新建一个子目录,命名为MathFunctions。在该目录下新建和,为函数声明,为实现文件, 不调用中的sqrt()函数,自己实现平方根的计算。当然为了检验方便,可以直接返回形参两倍值。
同样,MathFunctions目录下也需要构建,将其设定为库,并添加源文件:
add_library(MathFunctions )
2、顶层调用
为了使用这个新库,我们将在*CMakeLists中使用add_subdirectory()添加库调用。
# 添加库
add_subdirectory(MathFunctions)
然后将新库添加到可执行文件中,并将MathFunctions库添加到包含目录中,以便能够找到头文件。
target_link_libraries(CalculateSqrt PUBLIC MathFunctions)
#包含头文件
target_include_directories(
CalculateSqrt
PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/MathFunctions"
)
修改文件,添加文件的包含并调用该函数
#include ""
这样就简单地添加了MathFunctions库
3、尝试使用开关项
对于我们设计的MySqrt()函数,功能比较简单,很容易就能检测出是否正确,但有些情况下可能会涉及与库函数比较;或者,当头文件无法找到,只能使用。此时,需要设计一个开关项,用户可以设置是否使用MySqrt()函数。
设置开关项:
# 设置开关项默认为ON
option(USE_MYMATH "Use MySqrt provided math implementation" ON)
设置开关项ON、OFF时相应的操作。如果为USE_MYMATH为ON,需要添加MathFunctions库;为OFF,则不用。后续的包含头文件也是类似的操作。使用list语句(相当于构建了一个类似与python中的list数据结构),
list(APPEND <list> [<element> ...])
创建一个变量名为的变量,并将添加append(附加)到list中。如已有,则只执行append操作。
整体语句如下:
# 设置开关项相应操作
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
# 添加文件
add_executable(CalculateSqrt )
target_link_libraries(CalculateSqrt PUBLIC ${EXTRA_LIBS})
#包含头文件
target_include_directories(
CalculateSqrt
PUBLIC
"${PROJECT_BINARY_DIR}"
"${EXTRA_INCLUDES}")
相应地,要将该变量传递到源文件中,中定义USE_MYMATH:
#cmakedefine USE_MYMATH
在中加入:
#ifdef USE_MYMATH
#include ""
#endif
// 在调用处加入
#ifdef USE_MYMATH
const int outputValue = MySqrt(inputValue);
#else
const int outputValue = sqrt(inputValue);
#endif
定义了开关项之后,在命令行中设置开关项:
cmake .. -D USE_MYMATH=ON
cmake --build .
./CalculateSqrt 9
为了验证USE_MYMATH有没有起作用,可以将MySqrt()函数先设置为2倍值。
4、问题
尝试过程中出现报错,找不到MySqrt()函数,后续发现是由于中将
#ifdef USE_MYMATH
#include ""
#endif
放在
#include ""
之前,还没定义就开始使用导致的。
5、拓展
(1)除了在中定义开关项之外,也可以在文件中用以下命令定义:
target_compile_definitions(CalculateSqrt PRIVATE USE_MYMATH)
(2)像这种标准库函数的开关项,其实也可以用cmake中的CheckSymbolExists检查库函数是否可以使用,如果不能使用再设置使用自定义函数。
6、补充Usage requirement
Usage requirement(使用需求)会让使用者在链接库添加库当前路径,而设计者不需要。个人理解(不知道对不对)相当于给库设计函数接口,生成执行文件的时候自动链接库路径,不需要手动包含。
在Mathfunctions路径下的中添加
target_include_directories(
MathFunctions
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
在上级路径下的中删除有关EXTRA_INCLUDES的内容。
相关代码