引入头文件
- include_directories (path)
将头文件路径添加到全局编译器搜索路径中,因此所有的编译器目标都可以访问该路径下的头文件
- taregt_include_directories()
是将头文件路径添加到特定的目标中,只有该目标可以访问该路径下的头文件。因此,推荐使用target_include_directories()
函数。
# 使用 include_directories() 函数引入头文件
include_directories(${PROJECT_SOURCE_DIR}/include)
# 使用 target_include_directories() 函数引入头文件
target_include_directories(my_lib PUBLIC ${PROJECT_SOURCE_DIR}/include)
# PROJECT_SOURCE_DIR是CMake内置的变量,表示工程的根目录路径
# 添加一个库
add_library(my_lib STATIC my_source.cpp)
# 当前target需要包含的头文件目录
target_include_directories(my_lib
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/public
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/interface
)
# 链接另一个库,并使用其头文件
target_link_libraries(my_lib PUBLIC other_lib)
# 另一个库也可以使用当前库的头文件
add_library(other_lib STATIC other_source.cpp)
target_link_libraries(other_lib PUBLIC my_lib)
PRIVATE
:表示只在当前target内部可见。PUBLIC
:表示在当前target内部和其他依赖该target的target中可见。INTERFACE
:表示只在其他依赖该target的target中可见。
引入源文件
1、使用 add_executable
或 add_library
命令,直接将所有需要编译的源文件列举出来,例如
add_executable(my_app main.cpp helper.cpp utils.cpp)
2、使用 file
命令或 aux_source_directory
命令来动态扫描指定目录下的所有源文件,例如:
file(GLOB SOURCES "src/*.cpp")
add_executable(my_app ${SOURCES})
或者
aux_source_directory(src SOURCES)
add_executable(my_app ${SOURCES})
引入外部库
find_package()
一般而言,使用find_package()
函数需要提供以下信息:
- 库的名称:在CMake模块中用来标识库的名称;
- 找到库的模块名称:通常是库的名称加上一个前缀"Find",例如在找OpenCV库时使用的模块名称为"FindOpenCV.cmake";
- 最低版本要求:一些库的模块会在最低版本要求上进行检查,如果不满足要求则不会被导入;
- 变量名称:如果找到了库,将库的相关信息存储在该变量中**。**
CMAKE_MODULE_PATH
CMAKE_MODULE_PATH是一个CMake内置的变量,它用于指定CMake在哪里搜索模块文件(即Find*.cmake)。当使用find_package函数查找第三方库时,CMake会搜索CMAKE_MODULE_PATH中指定的路径,以查找Find*.cmake文件。如果找到了对应的Find*.cmake文件,则使用它来查找库的头文件、库文件等信息。可以使用set命令来设置CMAKE_MODULE_PATH变量的值
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} /path/to/custom/module/files)
链接外部库
target_link_libraries
# 指定要生成的可执行文件
add_executable(my_app main.cpp)
# 指定my_app需要链接的库文件
target_link_libraries(my_app
PRIVATE
foo # 链接名为foo的库文件
bar # 链接名为bar的库文件
)
使用target_link_libraries
命令的PRIVATE
关键字表示my_app
只需要链接foo
和bar
库文件,其他的库文件不需要链接。如果使用PUBLIC
关键字,则表示链接的库文件会同时适用于my_app
及其依赖项,而如果使用INTERFACE
关键字,则表示链接的库文件只适用于my_app
的依赖项,不适用于my_app
本身。
注意 target_link_directories
只写 target_link_directories
是无法将库链接到目标中的,它只是告诉编译器在哪里查找库文件。还需要使用 target_link_libraries
函数指定具体要链接的库
target_link_directories(my_target PRIVATE /path/to/lib)
target_link_libraries(my_target PRIVATE my_lib)
编写.CMAKE文件
find_package_handle_standard_args
find_package_handle_standard_args(<Package> REQUIRED_VARS <Var1> [Var2...] [QUIET] [NO_DEFAULT_PATH] [HINTS path1 [path2...]] [PATHS path1 [path2...]])
find_package_handle_standard_args(
TensorRT DEFAULT_MSG TensorRT_INCLUDE_DIRS TensorRT_LIBS TensorRT_SOURCE)
#find_package_handle_standard_args 是一个 CMake 函数,用于处理一个 find_package 命令所找到的软件包,并根据其结果设置变量或报告错误信息。
在这个例子中,find_package_handle_standard_args 会检查是否找到了 TensorRT 软件包,并在找到之后将 TensorRT_INCLUDE_DIRS、TensorRT_LIBS 和 TensorRT_SOURCE 这三个变量设置为对应的路径和文件。如果没找到 TensorRT,它会打印出 DEFAULT_MSG 所指定的错误信息。
可以将 find_package_handle_standard_args 看作是一个由 CMake 提供的标准函数,用于处理软件包查找过程中的错误处理和变量设置。
常用其他函数
file()
file
函数是CMake中常用的一个函数,用于对文件和目录进行操作,包括创建、删除、复制、移动、比较等操作。下面是一些常用的file
函数及其用法:
-
file(GLOB var globbing_expression)
:用于获取指定模式的文件列表,将结果保存到变量var
中。例如:file(GLOB SOURCES src/*.cpp)
上面的命令会将
src
目录下所有以.cpp
结尾的文件名保存到变量SOURCES
中。 -
file(COPY source_dir DESTINATION dest_dir)
:用于复制文件或目录,将源目录或文件夹复制到目标位置。例如:file(COPY data DESTINATION ${PROJECT_BINARY_DIR})
上面的命令会将项目中的
data
文件夹复制到构建目录中。 -
file(MAKE_DIRECTORY dir)
:用于创建目录。例如:file(MAKE_DIRECTORY output)
上面的命令会在当前目录下创建一个名为
output
的目录。 -
file(REMOVE_RECURSE dir)
:用于删除目录或文件。例如:file(REMOVE_RECURSE output)
上面的命令会删除当前目录下的
output
目录及其所有子目录和文件。 -
file(STRINGS filename variable)
:用于读取文件中的字符串并保存到变量中。例如:file(STRINGS config.ini CONFIG_CONTENT)
上面的命令会将文件
config.ini
中的所有行保存到变量CONFIG_CONTENT
中。 -
file(WRITE filename content)
:用于将字符串写入文件。例如:file(WRITE output.txt "Hello, world!")
上面的命令会在当前目录下创建一个名为
output.txt
的文件,并写入字符串Hello, world!
。 -
file(EXISTS path/to/file_or_directory)
命令来判断指定路径下的文件或目录是否存在。如果存在,则该命令返回TRUE
,否则返回FALSE
。if (file(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/data)) message("Data directory exists.") else() message(FATAL_ERROR "Data directory not found.") endif()
还有很多其他的file
函数可以用于操作文件和目录,可以参考CMake官方文档中的说明。
find_path
find_path(<VAR> name1 [path1 path2 ...]
[DOC "docstring"]
[HINTS path1 path2 ...]
[PATH_SUFFIXES suffix1 suffix2 ...]
[NO_DEFAULT_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_SYSTEM_PATH]
[CMAKE_FIND_ROOT_PATH_BOTH|ONLY|NEVER]
[CMAKE_FIND_ROOT_PATH_MODE_[BOTH|ONLY|NEVER]])
其中,<VAR>
是变量名,name1
表示要查找的文件或目录名称,path1 path2 ...
表示查找的路径,HINTS
表示查找路径的提示,PATH_SUFFIXES
表示要添加到路径后面的后缀名,NO_DEFAULT_PATH
表示不要添加默认的查找路径,NO_CMAKE_ENVIRONMENT_PATH
表示不要添加 CMAKE_
前缀的环境变量路径,NO_SYSTEM_ENVIRONMENT_PATH
表示不要添加系统环境变量路径,NO_CMAKE_PATH
表示不要添加 CMAKE_
前缀的路径,NO_CMAKE_SYSTEM_PATH
表示不要添加 CMAKE_SYSTEM_
前缀的路径,CMAKE_FIND_ROOT_PATH_BOTH|ONLY|NEVER
表示是否查找根路径,CMAKE_FIND_ROOT_PATH_MODE_[BOTH|ONLY|NEVER]
表示根路径查找模式。该函数会将查找到的路径存储在 <VAR>
变量中,如果找到了多个路径,则只存储第一个。如果没找到,则 <VAR>
会被置为空。我们可以通过判断 <VAR>
变量是否为空来判断文件或目录是否存在。
find_path(TensorRT_INCLUDE_DIRS NvInfer.h
HINTS ${TensorRT_ROOT} ${CUDA_TOOLKIT_ROOT_DIR}
PATH_SUFFIXES include)
在这段代码中,HINTS
和 PATH_SUFFIXES
都是 find_path
命令的参数。HINTS
是为了指定查找路径的提示,PATH_SUFFIXES
是为了指定文件夹名称的后缀,让 find_path
在提示路径下的特定文件夹中查找目标文件。
find_library()
find_library
是 CMake 内置的命令之一,用于查找和设置链接到目标文件需要的外部库。它的语法为
find_library(<VAR> name1 path1 path2 ...)
其中,<VAR>
是用户定义的一个变量名,用于保存查找到的库的路径;name1
是要查找的库的名称,可以指定多个,每个库名之间用空格分隔;path1
、path2
等是指定查找路径,也可以指定多个,每个路径之间用空格分隔。在执行 find_library
命令后,它会尝试在指定的路径中查找库文件,并将找到的库的完整路径保存到 <VAR>
变量中。如果找不到,则 <VAR>
变量将为空。
find_library(TensorRT_LIBRARY_INFER nvinfer
HINTS ${TensorRT_ROOT} ${CUDA_TOOLKIT_ROOT_DIR}
PATH_SUFFIXES lib lib64 lib/x64)
这段代码中的find_library()
函数是用来在给定的目录和路径后缀中查找库文件的。其中,第一个参数TensorRT_LIBRARY_INFER
是一个变量名,表示我们要查找的库文件名;第二个参数nvinfer
表示我们要查找的库文件的基本名称,也就是libnvinfer.so
或nvinfer.lib
的nvinfer
部分;第三个参数HINTS
是指示查找过程的提示信息,表示在哪些目录中进行查找;第四个参数PATH_SUFFIXES
是指示查找过程的路径后缀,表示在哪些子目录中进行查找。