当前位置: 首页 > news >正文

cmakelist文件中常见语句的含义

最近在进行c++代码的编译,发现cmakelist文件中有很多语句。一开始小白并不理解什么含义,学习后特此记录,以方便以后自己查阅。

情况一:单个模块,无主模块包含多个子模块的情况

文件目录如下:

MyProject/
├── CMakeLists.txt
├── include/
│   └── my_library.h
├── src/
│   ├── main.cpp
│   └── my_library.cpp
└── bin/

指定最低 CMake 版本

cmake_minimum_required(VERSION 3.10)

模块名称

project(MyProject)

设置头文件目录

 

target_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

将当前源代码目录下的 include 文件夹添加到头文件搜索路径中,编译时可以正确找到 my_library.h

添加目标(可执行文件或库)

add_executable(my_executable main.cpp)

(生成一个名为 my_executable 的可执行文件,源文件为 main.cpp)

add_library(my_library STATIC my_library.cpp)

(创建一个名为 my_library 的静态库,源文件为 my_library.cpp)

路径说明

(可选)

set(OpenCV_DIR "/usr/local/include/opencv4/")

OpenCV_DIR:这是一个变量名,通常用于指定 OpenCV 的安装路径。

"/usr/local/include/opencv4/":这是变量的值,表示 OpenCV 的头文件路径。

查找库

(可选)

find_package(OpenCV REQUIRED)

OpenCV:这是需要查找的库的名称。

REQUIRED:表示如果找不到 OpenCV,CMake 会报错并停止配置过程。

说明:

OpenCV 的库文件(如 .so 或 .a 文件)通常安装在 /usr/local/lib/ 目录下,而不是头文件路径 /usr/local/include/opencv4/

 

当使用 find_package(OpenCV REQUIRED) 命令时,CMake 会根据 OpenCV_DIR 提供的路径来查找 OpenCV 的头文件。同时,它会自动在标准路径(如 /usr/local/lib/)中查找 OpenCV 的库文件。

 

虽然 OpenCV_DIR 指向的是头文件路径,但 find_package() 会根据这个路径推断出库文件的可能位置(通常是 /usr/local/lib/)。如果在这个位置没有找到库文件,find_package() 会继续在其他标准路径中查找,以确保能够正确找到 OpenCV 的头文件和库文件)

 

找到后会自动配置变量:

OpenCV_INCLUDE_DIRS:包含OpenCV头文件的路径。

OpenCV_LIBRARIES:包含OpenCV库文件的路径

获取到的OpenCV_INCLUDE_DIRS、OpenCV_LIBRARIES路径可以在当前目录和子目录中使用。

然后就可以继续配置opencv的头文件和库文件了

target_include_directories(${OpenCV_INCLUDE_DIRS})

target_link_libraries(my_executable ${OpenCV_LIBRARIES})

 链接库

 

target_link_libraries(my_executable my_library)

my_library 链接到 my_executable。这样 my_executable 在运行时可以使用 my_library 中定义的函数。

设置输出目录

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)

将可执行文件的输出目录设置为 bin/,可在该目录下找到可执行文件

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)

将库文件的输出目录也设置为 bin/,可在该目录下找到动态/静态链接库

情况二:多个模块,主模块包含多个子模块的情况

文件目录如下:

MyMainProject/
├── CMakeLists.txt                # 主模块的 CMakeLists.txt
├── main.cpp                      # 主模块的源文件
├── subproject1/
│   ├── CMakeLists.txt            # 子模块1的 CMakeLists.txt
│   ├── src/
│   │   └── subproject1.cpp       # 子模块1的源文件
│   └── include/
│       └── subproject1.h         # 子模块1的头文件
├── subproject2/
│   ├── CMakeLists.txt            # 子模块2的 CMakeLists.txt
│   ├── src/
│   │   └── subproject2.cpp       # 子模块2的源文件
│   └── include/
│       └── subproject2.h         # 子模块2的头文件

现在的cmakelist文件分为两种,一种是主模块的cmakelist文件,一种是子模块的cmakelist文件。

先说主模块的cmakelist(主要把各个子模块链接起来)

指定最低 CMake 版本

cmake_minimum_required(VERSION 3.10)

主项目名称

project(MyMainProject)

添加子项目

add_subdirectory(subproject1)

add_subdirectory(subproject2)

将子项目 subproject1 和 subproject2 纳入主项目的构建体系中。CMake 会递归解析这些目录下的 CMakeLists.txt 文件。

 

 

注意:可能也会存在以下写法

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/ 3rdparty.out)

3rdparty 子目录纳入构建体系,输出目录为 3rdparty.out。

3rdparty.out 是相对于当前构建目录(build)的输出目录。

在构建过程中,3rdparty 子项目的输出将被放置在这些目录中。

 

定义主项目的可执行文件

add_executable(main_app src/main.cpp)

定义主项目的可执行文件 main_app,源文件为 src/main.cpp

链接子项目生成的库

 

target_link_libraries(main_app subproject1_lib subproject2_lib)

将子项目生成的库 subproject1_lib 和 subproject2_lib 链接到主项目的可执行文件 main_app

链接子项目的头文件

 

target_include_directories(main PUBLIC

${CMAKE_SOURCE_DIR}/subproject1/include

${CMAKE_SOURCE_DIR}/subproject2/include)

把这两个 include/ 目录挂到可执行文件上

设置输出目录

 

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)

将可执行文件的输出目录设置为 bin/

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)

库文件的输出目录设置为 bin/


如果不在主模块中target_include_directories(引入头文件搜索路径),那么必须在子模块中定义好此部分,以subproject2为例。

target_include_directories(subproject2 PUBLIC subproject2/include)

因为PUBLIC 关键字把 头文件搜索路径 登记到了这两个 库目标 的 INTERFACE_INCLUDE_DIRECTORIES 属性上。CMake 就会自动把这两条 INTERFACE 路径 追加 到 main 的编译 flags 里,无需再写一次 target_include_directories。

谨记:

如果只写 target_include_directories,编译能通过,链接会报 undefined reference;
如果只写 target_link_libraries,链接能找到库,但编译会报 找不到头文件;
因此 两个命令都必须出现,只是它们不一定都由“你”亲自写——现代 CMake 的传递性(PUBLIC)可以帮你省掉其中一段,但底层信息仍然缺一不可。

再说子模块的cmakelist(指定源文件,并管理自己“一亩三分地”的内部依赖)

子项目名称

project(Subproject1)

设置子项目头文件目录

target_include_directories(subproject1  PUBLIC  subproject1/include)

定义子项目的目标,生成一个静态链接库

add_library(subproject1_lib STATIC  subproject1/src/subproject1.cpp)

子项目的cmakelist向主项目cmakelist传递路径(可选)

set(JPEG_PATH ${CMAKE_CURRENT_SOURCE_DIR}/jpeg_turbo)

设置JPEG_PATH为子项目目录下的jpeg_turbo文件夹路径

 

set(LIBJPEG ${JPEG_PATH}/Linux/${TARGET_LIB_ARCH}/libturbojpeg.a PARENT_SCOPE)

使用PARENT_SCOPE将LIBJPEG(链接库)传递到上一级的CMakeLists.txt 文件中。

 

set(LIBJPEG_INCLUDES ${JPEG_PATH}/include PARENT_SCOPE)

使用PARENT_SCOPE将LIBJPEG_INCLUDES(头文件)传递到上一级的CMakeLists.txt 文件中。

 

如果在 3rd 文件夹下的 CMakeLists.txt 文件中设置了变量 LIBJPEG_INCLUDES 并使用了 PARENT_SCOPE,那么在与 3rd 同级的 cpp 文件夹下的 CMakeLists.txt 文件中也可以直接使用这个变量。

向生成的静态库添加头文件(比较绕)

set(SOURCES

    rknpu1/yolov8_seg.cc

    rknpu1/postprocess.cc

    ../utils/image_utils.c

    ../utils/file_utils.c

    ../utils/image_drawing.c

)

定义了一个变量 SOURCES,它包含了一系列源文件的路径。

 

 

add_library(yolov8_seg STATIC ${SOURCES})

作用是生成一个名为 yolov8_seg 的静态库,这个静态库包含了变量 SOURCES 中列出的所有源文件。

 

关于include_directories和target_include_directories的区别(link_libraries与target_link_libraries也同理)

捕获

关于target_include_directories、target_link_directories、target_link_libraries的区别,什么情况下使用

  •  #include 不到? -> 用 target_include_directories(告诉编译器去哪裡找头文件)
  • 函数找不到定义(链接错误)? -> 用 target_link_libraries(告诉链接器需要链接哪个库)
  • 尽量别用 target_link_directories(告诉链接器去哪裡找库文件)
 最后关于Cross.cmake的内容(交叉编译时可能会用到)

指定C编译器的路径。

指定C++编译器的路径。

set(CMAKE_C_COMPILER "arm-linux-gnueabihf-gcc")

set(CMAKE_CXX_COMPILER "arm-linux-gnueabihf-g++")

设置交叉编译的目标文件的根目录

(当前为/mnt)

set(CMAKE_SYSROOT $ENV{SYSROOT})

设置查找头文件、库文件和可执行文件的根路径(当前为/mnt)

set(CMAKE_FIND_ROOT_PATH $ENV{SYSROOT})

 

CMAKE_FIND_ROOT_PATH_MODE_PROGRAM:设置为NEVER,表示CMake不会在 CMAKE_FIND_ROOT_PATH 中查找可执行文件。

 

CMAKE_FIND_ROOT_PATH_MODE_PACKAGE:设置为 ONLY,表示 CMake 只在 CMAKE_FIND_ROOT_PATH 中查找包(如通过 find_package() 查找的库)。

 

CMAKE_FIND_ROOT_PATH_MODE_LIBRARY:设置为 ONLY,表示 CMake 只在 CMAKE_FIND_ROOT_PATH 中查找库文件。

 

CMAKE_FIND_ROOT_PATH_MODE_INCLUDE:设置为 ONLY,表示 CMake 只在 CMAKE_FIND_ROOT_PATH 中查找头文件。

 

 

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)

set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

 
http://www.wxhsa.cn/company.asp?id=2089

相关文章:

  • charles破解-在线生成激活码
  • 微信个人号开发
  • 内部排序-直接插入排序冒泡排序快速排序对比
  • STM32读写EEPROM
  • OpenStack Nova 创建虚拟机
  • AI革命2025:新一代人力资源管理系统十大标杆产品评测
  • 企业HR系统选型全指南:百人初创到万人集团的数字化方案与实施路径
  • C++ auto关键字
  • API 响应体加密场景下的调试实践:Postman 的局限与 Apipost 的优化
  • ARM主板:低功耗高性能的嵌入式计算核心
  • Gin 模板系统深度解析:客服系统实战开发
  • 系统盘爆了,.vscode,.android占内存太多,使用mklink命令符号链接
  • Acrobat Pro DC 2025下载及破解安装教程,附永久免费免激活中文破解版Acrobat Pro DC安装包(稳定版)
  • java锁升级过程
  • GAS_Aura-Setting Up Click to Move
  • 2025绩效管理必知
  • 【刷题笔记】cf808f
  • Laravel APP_DEBUG=true:存在账户信息泄露风险
  • 将当前目录下的所有文件 / 目录完整复制到/tmp目录,且会保留文件的权限、所有者、时间戳等属性
  • C# 操作 DXF 文件指南
  • 在Proxmox中部署Security Onion的安全配置实战
  • 报表到 BI:企业数据从展示到决策的进阶之路
  • 抢先体验智能测试时代,QA必备AI测试工具
  • Flink 与Flink可视化平台StreamPark教程(DataStreamApi基本使用)
  • 内部排序-直接插入排序
  • 玩转n8n测试自动化:核心节点详解与测试实战指南
  • Linux:龙晰系统(Anolis)更新yum(dnf)仓库源
  • (笔记)多项式基础 FFT
  • MAC tomcat启动报错
  • 研究生-必看-倒计时3天/武汉科技大学主办/稳定EI会议/高层次教授出席报告