掌握CMAKE常用命令,这一篇文章就够了


引入头文件

  • 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_executableadd_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只需要链接foobar库文件,其他的库文件不需要链接。如果使用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函数及其用法:

  1. file(GLOB var globbing_expression):用于获取指定模式的文件列表,将结果保存到变量var中。例如:

    file(GLOB SOURCES src/*.cpp)
    

    上面的命令会将src目录下所有以.cpp结尾的文件名保存到变量SOURCES中。

  2. file(COPY source_dir DESTINATION dest_dir):用于复制文件或目录,将源目录或文件夹复制到目标位置。例如:

    file(COPY data DESTINATION ${PROJECT_BINARY_DIR})
    

    上面的命令会将项目中的data文件夹复制到构建目录中。

  3. file(MAKE_DIRECTORY dir):用于创建目录。例如:

    file(MAKE_DIRECTORY output)
    

    上面的命令会在当前目录下创建一个名为output的目录。

  4. file(REMOVE_RECURSE dir):用于删除目录或文件。例如:

    file(REMOVE_RECURSE output)
    

    上面的命令会删除当前目录下的output目录及其所有子目录和文件。

  5. file(STRINGS filename variable):用于读取文件中的字符串并保存到变量中。例如:

    file(STRINGS config.ini CONFIG_CONTENT)
    

    上面的命令会将文件config.ini中的所有行保存到变量CONFIG_CONTENT中。

  6. file(WRITE filename content):用于将字符串写入文件。例如:

    file(WRITE output.txt "Hello, world!")
    

    上面的命令会在当前目录下创建一个名为output.txt的文件,并写入字符串Hello, world!

  7. 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)

在这段代码中,HINTSPATH_SUFFIXES 都是 find_path 命令的参数。HINTS 是为了指定查找路径的提示,PATH_SUFFIXES 是为了指定文件夹名称的后缀,让 find_path 在提示路径下的特定文件夹中查找目标文件。

find_library()

find_library 是 CMake 内置的命令之一,用于查找和设置链接到目标文件需要的外部库。它的语法为

find_library(<VAR> name1 path1 path2 ...)

其中,<VAR> 是用户定义的一个变量名,用于保存查找到的库的路径;name1 是要查找的库的名称,可以指定多个,每个库名之间用空格分隔;path1path2 等是指定查找路径,也可以指定多个,每个路径之间用空格分隔。在执行 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.sonvinfer.libnvinfer部分;第三个参数HINTS是指示查找过程的提示信息,表示在哪些目录中进行查找;第四个参数PATH_SUFFIXES是指示查找过程的路径后缀,表示在哪些子目录中进行查找。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_62491765

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值