CMake添加库

时间:2025-05-09 09:18:31

尝试给项目添加一个库,还是以上一篇的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的内容。

相关代码