C++及cmake语法介绍

c++/cmake学习

文章目录

  • c++/cmake学习
    • 1. c++
      • 1.1 基本模型
        • 1.1.1 for循环
        • 1.1.2 main函数
        • 1.1.2 带参数函数编译函数
    • 2. CMAKE
      • 2.1 相关命令
        • 2.1.1 编译基本命令
        • 2.1.2 动态库静态库编译
        • 2.1.3 消息输出
        • 2.1.4 cmake变量
          • 常见参数
          • 1. 设置构建类型
          • 2. 设置编译器标志
          • 3. 指定编译器
          • 4. 设置安装路径
          • 5. 指定查找库和包的路径
          • 6. 通过命令行传递自定义变量
          • 7. 通过环境变量设置
          • 8.运行时控制
        • [2.1.5 描述系统的变量](https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html#variables-that-describe-the-system)
      • 2.2 include
        • 注意事项
      • 2.3 if else语法
        • 2.3.1 基本语法
        • 2.3.2 常量判断
        • 2.3.3 未定义的变量判断
        • 2.3.4 已定义的变量判断
        • 2.3.5 字符串判断
        • 2.3.6 逻辑运算符
          • - 逻辑运算符示例
        • 2.3.7 其他条件判断
          • 判断文件是否存在
          • 判断目录是否存在
          • 判断变量是否定义
          • 综合示例
      • 2.4 生成表达式
        • 2.4. 1. 条件表达式
        • 2.4.2. 变量查询(Variable-Query)
        • 2.4.3. 目标查询(Target-Query)
        • 详细解释
      • 2.5 宏和函数
      • 2.6 安装项目
        • 1. 定义最低CMake版本和项目名称
        • 2. 包含头文件目录
        • 3. 添加库文件
        • 4. 设置RPATH
        • 5. 添加可执行文件
        • 6. 设置公共头文件属性
        • 7. 安装配置
        • 8. 安装命令
        • 总结
      • 2.7 查找项目
        • `find_package`的解释
          • 1. 定义最低CMake版本和项目名称
          • 2. 添加可执行文件
          • 3. 使用 `find_package` 查找库
          • 查找成功时设置的变量
          • 4. 检查库是否找到并设置相关配置
      • 总结

1. c++

1.1 基本模型

1.1.1 for循环
  • main.cpp
#include <iostream>
// using namespace std;int main(){// 计算 1+2+3+4+5int sum{0};for (int i{0}; i < 5; i++){sum += i;}// 输出结果std::cout << sum << std::endl;return 0;}
  • shell
g++ main.cpp -o main  -std=c++17
  • 结果

image-20240616134750783

1.1.2 main函数
  • code
#include <iostream>
using namespace std;int main()
{cout << "Hello World!" << endl;return 0;
}
  • 结果

image-20240616135215541

1.1.2 带参数函数编译函数
  • Code
#include <iostream>
using namespace std;// argc 代表argument count,参数数量
// argv 代表argumen vector,参数列表  int main(int argc, char** argv)
{cout << "参数数量:" << argc << endl;cout << "==========================" << endl;for (int i = 0;i < argc;i++){cout << argv[i] << endl;}return 0;
}// 调用方式
// ./program arg1 arg2
  • 结果

image-20240616201104325

2. CMAKE

2.1 相关命令

2.1.1 编译基本命令
# 最低版本要求
cmake_minimum_required(VERSION 3.10)# 项目名称
project(test_account)# 添加执行文件
add_executable(test_account test_account.cpp)# 指定目标包含的头文件目录
target_include_directories(test_account PUBLIC "../account_dir")
# 添加库文件目录,如果不添加,找不到库文件
target_link_directories(test_account PUBLIC "../account_dir/build")
# 指定目标链接的库
target_link_libraries(test_account PRIVATE Account)
2.1.2 动态库静态库编译
  • 静态库
# 添加静态库,Linux下会生成libAccount.a
# Account是库名,STATIC表示静态库,SHARED表示动态库,后面是源文件
add_library(Account STATIC Account.cpp Account.h)
  • 动态库
# 添加动态库,Linux下会生成libAccount.so
add_library(Account SHARED Account.cpp Account.h)
2.1.3 消息输出
# 输出消息
message("输出消息")
message("输出1" "输出2" "输出3") # 会做拼接
2.1.4 cmake变量
  • 基本变量
# 设置变量
set(VAR1 "变量1")
message("VAR1=" ${VAR1}) # 外部访问
message("输出变量VAR1:${VAR1}") # 内部拼接
message("\${VAR1}=${VAR1}") # 使用\转义
unset(VAR1) # 删除变量
message("\${VAR1}=${VAR1}") # 删除变量后,输出为空
  • 内置变量
# 设置变量缓存,可以在命令行中修改(-D参数)
set(CACHE_VARIABLE_TEST "原始值" CACHE STRING "变量缓存的描述")
message("变量缓存的值:${CACHE_VARIABLE_TEST}")
  • 提供信息变量
# 第一类:提供信息的变量
message("${PROJECT_NAME}") # 项目名称
message("${CMAKE_SOURCE_DIR}") # 源码目录
message("${CMAKE_BINARY_DIR}") # 编译目录
message("${CMAKE_CURRENT_LIST_FILE}") # 当前CMakeLists.txt文件路径
  • 控制运行变量
set(BUILD_SHARED_LIBS ON) # 设置是否构建动态库,默认为OFF,即构建静态库,设置为ON后,构建动态库

在 CMake 中,控制运行变量的参数有多种方式,包括通过 set() 命令直接设置变量,使用命令行参数,或者使用 cmake 命令的 -D 选项设置变量。

常见参数
  1. CMAKE_BUILD_TYPE: 指定构建类型,可以是 DebugReleaseRelWithDebInfoMinSizeRel
  2. CMAKE_CXX_FLAGS: 设置 C++ 编译器标志。
  3. CMAKE_C_COMPILER: 设置 C 编译器。
  4. CMAKE_CXX_COMPILER: 设置 C++ 编译器。
  5. CMAKE_INSTALL_PREFIX: 指定安装路径。
  6. CMAKE_PREFIX_PATH: 指定查找库和包的路径。
1. 设置构建类型

CMakeLists.txt 中:

set(CMAKE_BUILD_TYPE Debug)

或者在命令行中:

cmake -DCMAKE_BUILD_TYPE=Debug ..
2. 设置编译器标志

CMakeLists.txt 中:

set(CMAKE_CXX_FLAGS "-Wall -Wextra -O2")

或者在命令行中:

cmake -DCMAKE_CXX_FLAGS="-Wall -Wextra -O2" ..
3. 指定编译器

CMakeLists.txt 中:

set(CMAKE_C_COMPILER gcc)
set(CMAKE_CXX_COMPILER g++)

或者在命令行中:

cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ ..
4. 设置安装路径

CMakeLists.txt 中:

set(CMAKE_INSTALL_PREFIX /usr/local)

或者在命令行中:

cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
5. 指定查找库和包的路径

CMakeLists.txt 中:

set(CMAKE_PREFIX_PATH /path/to/dependencies)

或者在命令行中:

cmake -DCMAKE_PREFIX_PATH=/path/to/dependencies ..
6. 通过命令行传递自定义变量

CMakeLists.txt 中使用自定义变量:

set(MY_CUSTOM_VARIABLE OFF CACHE BOOL "A custom variable")

然后在命令行中设置这个变量:

cmake -DMY_CUSTOM_VARIABLE=ON ..
7. 通过环境变量设置

CMakeLists.txt 中:

if(DEFINED ENV{MY_ENV_VAR})set(MY_ENV_VAR $ENV{MY_ENV_VAR})
endif()

然后在命令行中:

export MY_ENV_VAR=value
cmake ..
8.运行时控制

CMakeLists.txt 中使用条件语句控制运行时行为:

if(CMAKE_BUILD_TYPE STREQUAL "Debug")message(STATUS "Debug build")set(SOME_FLAG ON)
else()message(STATUS "Release build")set(SOME_FLAG OFF)
endif()
2.1.5 描述系统的变量

message(“是否是Windows系统:${WIN32}”)

message(“是否是Linux系统:${UNIX}”)

message(“系统名称:${CMAKE_SYSTEM_NAME}”)

2.2 include

在 CMake 中,include 命令用于引入和执行指定的 CMake 脚本文件。每次调用 include 时,都会读取并执行被引入文件的内容。如果同一个文件被多次调用 include,它的内容将被多次执行。

具体来说,include 命令的作用如下:

  1. 包含外部 CMake 文件:可以将外部的 CMake 脚本文件引入当前的 CMake 配置中,使得这些脚本文件中的命令和变量定义可以被当前的 CMakeLists.txt 文件使用。
  2. 代码复用:可以将通用的 CMake 配置、宏和函数放在单独的文件中,通过 include 命令在多个项目或多个地方复用这些配置和代码。
  3. 模块化管理:通过 include 命令,可以将复杂的 CMake 配置分解成多个小文件,便于管理和维护。

举个例子,假设你有一个名为 module_1.cmake 的文件,其中包含一些通用的设置或函数:

# cmake/module_1.cmake
message("Hello from module_1.cmake")
set(MY_VARIABLE "Hello, World!")

然后在你的 CMakeLists.txt 中,你可以通过 include 命令引入这个文件:

# CMakeLists.txt
message("调用include前的信息")include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/module_1.cmake")
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/module_1.cmake")message("MY_VARIABLE is set to: ${MY_VARIABLE}")

当你执行 cmake 配置时,输出结果将是:

调用include前的信息
Hello from module_1.cmake
Hello from module_1.cmake
MY_VARIABLE is set to: Hello, World!

在这个示例中,module_1.cmake 文件被包含了两次,因此其中的消息被打印了两次。

注意事项
  1. 多次包含:如果你希望某个文件只被包含一次,可以使用 include_guard() 命令,避免重复包含。
  2. 路径include 命令的路径可以是相对路径或绝对路径,通常使用 ${CMAKE_CURRENT_SOURCE_DIR} 来构建相对路径,以确保路径的正确性。

通过 include 命令,你可以有效地组织和管理 CMake 项目的配置文件,提升代码的复用性和可维护性。

2.3 if else语法

2.3.1 基本语法
if(<condition>)<ifcommands>
elseif(<condition>)<commands>
else()` <commandsendif()
  • <condition>:条件表达式,可以是 常量、变量或复杂的逻辑表达式。
  • <commands语>:在条件为 true 时执行的命令句块。
cmake_minimum_required(VERSION 3,.10)
project(syntax_test)message("======常量 if ======")#常量
if(1)message("1字符串 是 true")
endif的()if(0)message("0 是 true值")
else()message("判断0 是 false")
endif# 规则()# 未定义的如下变量
if(UNDEFINED):message("-UNDEFINED 是 true")为else()message("UN真DEFINED 是 false")
endif()#( 定义了true的变量
set(DEFINED 1)
if(DEFINED)message(")的DEFINED 是 true")
else()message常("DEFINED 是 false")
endif()# 字符串
if("Y"):message("字符串是 true")
else()message("字符串是 false")
endif()message("====== if 配合逻辑运算符` ======")# AND
if(1 AND YES)messageON("1 AND YES 是 true")
else()message("1 AND YES 是 false`")
endif()# OR
if(1 OR NO)message("、1 OR NO 是 true")
else()message("1 OR NO 是 false")
endif()# NOT
if(NOT 0)message`("、NOT 0 是 true")
else()message("NOT 0 是 false")
endif()# 括号
if(1 AND (0 OR 1))message("1 AND (0 OR` 1) 是 true")
else()message("1 AND (0 OR TRUE1) 是 false")
endif()
2.3.2 常量判断
if(1)message("1 是 true")
endif()if(0)message("0 是")
else()message("0 是 false")
endif()
2.3.3 未定义的变量判断
if(UNDEFINED)message("UNDEFINED 是 true")
else()message("UNDEFINED 是 false")
endif()
2.3.4 已定义的变量判断
set(DEFINED 1)
if(DEFINED)message("DEFINED 是 true")
else()message("DEFINED 是 false")
endif()
2.3.5 字符串判断
if("Y") message("字符串是 true")
else()message("字符串是 false")
endif()
2.3.6 逻辑运算符

CMake 支持使用逻辑运算符(ANDORNOT 和括号)来组合多个条件。

- 逻辑运算符示例
# AND
if(1 AND YES)message("1 AND YES 是 true")
else()message("1 AND YES 是 false")
endif()# OR
if(1 OR NO)message("1 OR NO 是 true")
else()message("1 OR NO 是 false")
endif()# NOT
if(NOT 0)message("NOT 0 是 true")
else()message("NOT 0 是 false")
endif()# 括号
if(1 AND (0 OR 1))message("1 AND (0 OR 1) 是 true")
else()message("1 AND (0 OR 1) 是 false")
endif()
2.3.7 其他条件判断
判断文件是否存在
if(EXISTS "path/to/file")message("文件存在")
else()message("文件不存在")
endif()
判断目录是否存在
if(IS_DIRECTORY "path/to/directory")message("目录存在")
else()message("目录不存在")
endif()
判断变量是否定义
if(DEFINED VAR_NAME)message("变量已定义")
else()message("变量未定义")
endif()
综合示例
cmake_minimum_required(VERSION 3.10)project(syntax_test)message("====== if ======")# 常量判断
if(1)

2.4 生成表达式

在 CMake 中,生成表达式是一种用于在生成构建系统时进行条件判断和变量替换的机制。生成表达式通常以 $<...> 的形式表示,并在构建生成阶段被展开。以下是对生成表达式相关知识点的详细讲解:

2.4. 1. 条件表达式

条件表达式用于在条件为真时返回指定字符串,否则返回空字符串。

  • 基本语法$<condition:true_string>

  • 示例

    $<0:TEST>  # 条件为假,返回空字符串
    $<1:TEST>  # 条件为真,返回 "TEST"
    $<$<BOOL:TRUE>:TEST>  # BOOL:TRUE 为真,返回 "TEST"
    

由于生成表达式在生成构建系统时展开,不能直接通过 message 命令打印结果。可以通过生成文件的方式间接测试生成表达式。

  • 示例代码

    file(GENERATE OUTPUT "./generator_test.txt" CONTENT "$<$<BOOL:TRUE>:TEST>")
    
2.4.2. 变量查询(Variable-Query)

变量查询生成表达式用于检查特定条件或变量的状态。

  • 示例

    $<TARGET_EXISTS:target>  # 判断目标是否存在
    $<CONFIG:Debug>  # 判断当前构建类型是否为 Debug
    
  • 示例代码

    add_executable(generator_expression main.cpp)# 检查目标是否存在
    file(GENERATE OUTPUT "./generator_test.txt" CONTENT "$<TARGET_EXISTS:generator_expression>")
    file(GENERATE OUTPUT "./generator_test.txt" CONTENT "$<$<TARGET_EXISTS:generator_expression>:目标已存在>")  # 嵌套使用# 设置构建类型并检查
    set(CMAKE_BUILD_TYPE "Debug")
    file(GENERATE OUTPUT "./generator_test.txt" CONTENT "$<$<CONFIG:Debug>:--coverage>")  # 嵌套使用
    
2.4.3. 目标查询(Target-Query)

目标查询生成表达式用于获取编译目标的文件路径或文件名。

  • 示例

    $<TARGET_FILE:target>  # 获取编译目标的文件路径
    $<TARGET_FILE_NAME:target>  # 获取编译目标的文件名
    
  • 示例代码

    add_executable(generator_expression main.cpp)# 获取编译目标的文件路径
    file(GENERATE OUTPUT "./generator_test.txt" CONTENT "$<TARGET_FILE:generator_expression>")
    
详细解释
  1. 条件表达式

    • 条件表达式通过检查条件是否为真来返回对应的字符串。例如,$<1:TEST> 中,条件 1 为真,因此返回字符串 “TEST”。在嵌套表达式中,例如 $<$<BOOL:TRUE>:TEST>,内部表达式首先被解析为 TRUE,然后外部表达式返回 “TEST”。
  2. 变量查询

    • 变量查询生成表达式用于动态判断变量的状态。例如,$<TARGET_EXISTS:generator_expression> 用于判断目标 generator_expression 是否存在。如果目标存在,则返回真。
  3. 目标查询

    • 目标查询生成表达式用于获取编译目标的具体信息,如文件路径和文件名。这在需要生成配置文件或调试信息时非常有用。例如,$<TARGET_FILE:generator_expression> 返回目标文件的完整路径。

这些生成表达式在 CMake 中非常强大,允许在生成阶段进行复杂的条件判断和动态内容生成,使构建系统更加灵活和可配置。通过这些表达式,可以有效地管理不同构建配置和目标之间的差异。

2.5 宏和函数

  • 定义宏
# ====================================
# 定义一个宏,宏名为my_macro,没有参数
macro(my_macro)message("宏内部的信息")set(macro_var "宏内部变量test")
endmacro(my_macro)# 调用宏
my_macro()
my_macro()
# 输出宏内部的信息,也能访问到变量,理解为代码替换
message(${macro_var})
  • 定义函数
# ====================================
# 定义一个函数,函数名为my_func,没有参数
function(my_func)message("函数内部的信息")set(func_var "变量test")
endfunction(my_func)# 调用函数
my_func()
my_func()
# 访问不了函数内部的变量,因为函数是一个独立的作用域
# message(${func_var})
  • 传参函数
# ====================================
# 定义一个函数,函数名为second_func,有两个参数
function(second_func arg1 arg2)message("第一个参数:${arg1}, 第二个参数:${arg2}")
endfunction(second_func)
# 调用函数
second_func("hello" "world")

2.6 安装项目

cmake_minimum_required(VERSION 3.10)project(instal_demo)# 添加头文件
include_directories(include)# 添加静态库
add_library(slib STATIC src/slib.cpp include/slib.h)
# 添加动态库
add_library(dlib SHARED src/dlib.cpp include/dlib.h)# 设置RPATH,否则install后,运行时找不到动态库
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) 
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")# 添加可执行文件
add_executable(instal_demo main.cpp)
# 链接库
target_link_libraries(instal_demo slib dlib)# 设置公共头文件,以便install时,将头文件一起安装,或者使用install(DIRECTORY include/ DESTINATION include)
set_target_properties(slib PROPERTIES PUBLIC_HEADER include/slib.h)
set_target_properties(dlib PROPERTIES PUBLIC_HEADER include/dlib.h)# 安装头文件
install(DIRECTORY include/ DESTINATION include)# 设置安装
install(TARGETS instal_demo slib dlibRUNTIME DESTINATION bin # 可执行文件LIBRARY DESTINATION lib # 动态库ARCHIVE DESTINATION lib # 静态库PUBLIC_HEADER DESTINATION include # 公共头文件)#[[
如果不设置DCMAKE_INSTALL_PREFIX ,则会安装到 /usr/local 目录下
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=./installed
或者其他目录
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=~/Documents/install_demo
cmake --build build
cmake --install build
]]        

CMake脚本的目的是构建和安装一个包含静态库、动态库和可执行文件的项目。以下是对每一部分的详细解释:

1. 定义最低CMake版本和项目名称
cmake_minimum_required(VERSION 3.10)
project(instal_demo)

这两行代码定义了项目所需的最低CMake版本为3.10,并将项目命名为instal_demo

2. 包含头文件目录
include_directories(include)

指定了头文件的搜索路径为include目录。这意味着在编译过程中,会在这个目录中查找头文件。

3. 添加库文件
# 添加静态库
add_library(slib STATIC src/slib.cpp include/slib.h)
# 添加动态库
add_library(dlib SHARED src/dlib.cpp include/dlib.h)

这两行代码分别添加了一个静态库slib和一个动态库dlib,它们的源文件分别位于src/slib.cppsrc/dlib.cpp,头文件位于include/slib.hinclude/dlib.h

4. 设置RPATH
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) 
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

这两行代码用于设置RPATH(运行时库搜索路径),确保在安装后,运行时能够找到动态库。CMAKE_INSTALL_PREFIX是安装目录前缀,通常在cmake命令中通过-DCMAKE_INSTALL_PREFIX选项设置。

5. 添加可执行文件
add_executable(instal_demo main.cpp)
# 链接库
target_link_libraries(instal_demo slib dlib)

这两行代码添加了一个名为instal_demo的可执行文件,源文件为main.cpp,并链接了静态库slib和动态库dlib

6. 设置公共头文件属性
set_target_properties(slib PROPERTIES PUBLIC_HEADER include/slib.h)
set_target_properties(dlib PROPERTIES PUBLIC_HEADER include/dlib.h)

这两行代码设置了库的公共头文件属性,使这些头文件在安装时也会被包含进去。

7. 安装配置
# 安装头文件
# install(DIRECTORY include/ DESTINATION include)# 设置安装
install(TARGETS instal_demo slib dlibRUNTIME DESTINATION bin # 可执行文件LIBRARY DESTINATION lib # 动态库ARCHIVE DESTINATION lib # 静态库PUBLIC_HEADER DESTINATION include # 公共头文件)

这段代码定义了安装目标及其安装位置。它指定了可执行文件安装到bin目录,动态库和静态库安装到lib目录,公共头文件安装到include目录。

8. 安装命令
#[[
如果不设置DCMAKE_INSTALL_PREFIX ,则会安装到 /usr/local 目录下
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=./installed
或者其他目录
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=~/Documents/install_demo
cmake --build build
cmake --install build
]]

这部分注释解释了如何运行安装命令。如果不设置DCMAKE_INSTALL_PREFIX,安装路径会默认是/usr/local。示例命令展示了如何设置自定义安装路径并执行构建和安装过程。

总结

该CMake脚本安装总体流程如下:

  1. 定义项目名称和CMake最低版本要求。
  2. 指定头文件目录。
  3. 添加静态库和动态库。
  4. 设置RPATH以确保安装后的可执行文件能找到动态库。
  5. 添加可执行文件并链接静态库和动态库。
  6. 设置公共头文件属性。
  7. 定义安装目标和路径。
  8. 提供示例命令行,用于设置自定义安装路径并执行构建和安装。

2.7 查找项目

cmake_minimum_required(VERSION 3.10)project(find_demo)# 添加可执行文件
add_executable(find_demo main.cpp)#[[
使用find_package寻找<LibaryName>库,如果找到,有以下变量
<LibaryName>_FOUND:表示是否找到
<LibaryName>_INCLUDE_DIR:表示头文件目录
<LibaryName>_LIBRARIES:表示库文件目录
]]# 寻找gflags库,REQUIRED表示必须存在,否则报错
find_package(gflags REQUIRED)if(gflags_FOUND)message(STATUS "gflags found")message(STATUS "gflags include dir: ${gflags_INCLUDE_DIR}")message(STATUS "gflags lib dir: ${gflags_LIBRARIES}")# 为可执行文件添加头文件目录和库文件目录target_include_directories(find_demo PRIVATE ${gflags_INCLUDE_DIR})target_link_libraries(find_demo ${gflags_LIBRARIES})
else()message(FATAL_ERROR "gflags not found")
endif()
find_package的解释

find_package 是 CMake 提供的一个功能,用于在系统中查找并引入外部库。这个命令会搜索指定的库,并设置相应的变量来供后续使用。以下是对你提供的 CMake 脚本中 find_package 部分的详细解释:

1. 定义最低CMake版本和项目名称
cmake_minimum_required(VERSION 3.10)
project(find_demo)

这两行代码定义了项目所需的最低CMake版本为3.10,并将项目命名为find_demo

2. 添加可执行文件
add_executable(find_demo main.cpp)

这行代码添加了一个名为find_demo的可执行文件,源文件为main.cpp

3. 使用 find_package 查找库
# 寻找gflags库,REQUIRED表示必须存在,否则报错
find_package(gflags REQUIRED)

这一行代码使用find_package命令来查找gflags库。REQUIRED表示该库是必须找到的,如果找不到则会报错并停止配置过程。find_package命令会尝试在系统的标准库路径和CMake的模块路径中搜索指定的库。

查找成功时设置的变量

如果gflags库被成功找到,会设置以下几个变量:

  • gflags_FOUND:一个布尔变量,表示是否找到gflags库。
  • gflags_INCLUDE_DIRgflags库头文件的目录路径。
  • gflags_LIBRARIESgflags库文件的目录路径。
4. 检查库是否找到并设置相关配置
if(gflags_FOUND)message(STATUS "gflags found")message(STATUS "gflags include dir: ${gflags_INCLUDE_DIR}")message(STATUS "gflags lib dir: ${gflags_LIBRARIES}")# 为可执行文件添加头文件目录和库文件目录target_include_directories(find_demo PRIVATE ${gflags_INCLUDE_DIR})target_link_libraries(find_demo ${gflags_LIBRARIES})
else()message(FATAL_ERROR "gflags not found")
endif()

这部分代码会检查gflags_FOUND变量。如果gflags库被找到,它会输出一些状态消息来显示gflags库的头文件目录和库文件目录。然后,它会为可执行文件find_demo添加头文件目录和库文件目录,使得编译器能够找到并链接gflags库。

如果gflags库没有被找到,脚本会报错并停止配置过程,输出一条致命错误消息。

总结

  • find_package 用于查找并引入外部库。
  • REQUIRED 参数表示该库是必需的,如果找不到会报错。
  • find_package 成功时会设置相关变量供后续使用。
  • 使用这些变量可以为目标可执行文件添加头文件目录和库文件目录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/29801.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习_PCA

目录 一、概念 二、原理 三、步骤 四、实战 1、数据处理——转rgb为灰度图像 2、手动实现pca降维 3、查看信息保留数量 4、调用第三方库实现pca降维 五、小结 引入&#xff1a; 当说黄河五路和渤海三路交叉口的时候&#xff0c;这些路就类似于我们说的坐标系。而城市中的…

高等数学笔记(三):导数

一、导数概念 1.1 导数的定义 1.1.1 函数在一点处的导数与导函数 1.1.2 单侧导数 1.2 导数的几何意义 1.3 函数可导性与连续性的关系 二、函数的求导法则 2.1 函数的和、差、积、商的求导法则 2.2 反函数的求导法则 2.3 复合函数的求导法则 2.4 基本求导法则与导数公式 三…

必看!!! 2024 最新 PG 硬核干货大盘点(上)

PGConf.dev&#xff08;原名PGCon&#xff0c;从2007年至2023年&#xff09;首次在风景如画的加拿大温哥华市举办。此次重新定位的会议带来了全新的视角和多项新的内容&#xff0c;参会体验再次升级。尽管 PGCon 历来更侧重于开发者&#xff0c;吸引来自世界各地的资深开发者、…

深入理解并打败C语言难关之一————指针(5)(最终篇)

前言&#xff1a; 仔细一想&#xff0c;小编已经把指针的大部分内容都说了一遍了&#xff0c;小编目前有点灵感枯竭了&#xff0c;今天决定就结束指针这一大山&#xff0c;可能很多小编并没有提到过&#xff0c;如果有些没说的小编会在后续博客进行补充道&#xff0c;不多废话了…

服务器数据恢复—NTFS文件系统下双循环riad5数据恢复案例

服务器存储数据恢复环境&#xff1a; EMC CX4-480存储&#xff0c;该存储中有10块硬盘&#xff0c;其中有3块磁盘为掉线磁盘&#xff0c;另外7块磁盘组成一组RAID5磁盘阵列。运维人员在处理掉线磁盘时只添加新的硬盘做rebuild&#xff0c;并没有将掉线的硬盘拔掉&#xff0c;所…

ARCGIS 如何对河流等线条图形进行Smooth处理——具有多个断点高阶版

1.线转点折点&#xff08;注意&#xff01;很重要&#xff0c;不是线转点&#xff09; 2.点转线步骤 ## 3 线的融合 2.1 新建Filed 》短精度类型》利用选择工具的 线文件。全选同一条河流点&#xff0c;进入Tabel的选择界面。给同一条河赋值同一个值。 大功告成&#xff01;…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《计及多类型储能调频容量动态申报的电能量与调频市场联合出清方法研究》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

深入探究RTOS的任务调度

阅读引言&#xff1a; 此文将会从一个工程文件&#xff0c; 一步一步的分析RTOS的任务调度实现&#xff0c; 这里选用FreeRTOS分析&#xff0c; 别的也差不多的&#xff0c; 可能在细节上有少许不一样。 目录 1&#xff0c; 常见嵌入式实时操作系统 2&#xff0c; 任务调度的…

【机器学习】第11章 神经网络与深度学习(重中之重)

一、概念 1.神经元模型 &#xff08;1&#xff09;神经网络的基本组成单位 &#xff08;2&#xff09;生物上&#xff0c;每个神经元通过树突接受来自其他被激活神经元的信息&#xff0c;通过轴突释放出来的化学递质改变当前神经元内的电位。当神经元内的电位累计到一个水平时…

Kubernetes Dashboard

Dashboard Dashboard 的项目网站&#xff0c;可以查看说明文档和基本的使用情况。 下载yaml wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.0/aio/deploy/recommended.yaml注意需要修改镜像&#xff0c;不然可能会拉去不下来镜像 cat recommended.yaml…

人工智能--自然语言处理NLP概述

欢迎来到 Papicatch的博客 目录 &#x1f349;引言 &#x1f348;基本概念 &#x1f348;核心技术 &#x1f348;常用模型和方法 &#x1f348;应用领域 &#x1f348;挑战和未来发展 &#x1f349;案例分析 &#x1f348;机器翻译中的BERT模型 &#x1f348;情感分析在…

函数(下) C语言

函数下 嵌套调用和链式访问1. 嵌套调用2. 链式访问 函数的声明和定义1. 单个文件2. 多个文件3. static 和 extern3.1 static 嵌套调用和链式访问 1. 嵌套调用 嵌套调用就是函数之间的互相调用&#xff0c;每个函数就像⼀个乐高零件&#xff0c;正是因为多个乐高的零件互相无缝…

Nginx缓存之代理缓存配置

Nginx 的缓存功能是集成在代理模块中的&#xff0c;当启用缓存功能时&#xff0c;Nginx 将请求返回的响应数据持久化在服务器磁盘中&#xff0c;响应数据缓存的相关元数据、有效期及缓存内容等信息将被存储在定义的共享内存中。当收到客户端请求时&#xff0c;Nginx 会在共享内…

当同时绑定mousedown和mouseup时,不执行mouseup

问题描述&#xff1a; 当我同时给一个标签添加mousedown和mouseup两个鼠标事件&#xff0c;点击span的时候会触发mousedown事件&#xff0c;但是不会执行mouseup事件&#xff1b;但是注释图二中的setCloudControl方法又能触发mouseup。 后来查阅资料&#xff0c;发现是在封装a…

[算法刷题积累] 两数之和以及进阶引用

两数之和很经典&#xff0c;通常对于首先想到的就是暴力的求解&#xff0c;当然这没有问题&#xff0c;但是我们如果想要追求更优秀算法&#xff0c;就需要去实现更加简便的复杂度。 这里就要提到我们的哈希表法: 我们可以使用unordered_map去实现&#xff0c;也可以根据题目&a…

【Gradio】Chatbots 如何用 Gradio 创建聊天机器人

Creating A Chatbot Fast 简介 聊天机器人是大型语言模型的一个流行应用。使用 gradio &#xff0c;您可以轻松构建您的聊天机器人模型的演示&#xff0c;并与您的用户分享&#xff0c;或者使用直观的聊天机器人用户界面自己尝试。 本教程使用 gr.ChatInterface() &#xff0c;…

SpringMVC系列四: Rest-优雅的url请求风格

Rest请求 &#x1f49e;Rest基本介绍&#x1f49e;Rest风格的url-完成增删改查需求说明代码实现HiddenHttpMethodFilter机制注意事项和细节 &#x1f49e;课后作业 上一讲, 我们学习的是SpringMVC系列三: Postman(接口测试工具) 现在打开springmvc项目 &#x1f49e;Rest基本介…

基于Spark3.3.4版本,实现Standalone 模式高可用集群部署

目录 一、环境描述 二、部署Spark 节点 2.1 下载资源包 2.2 解压 2.3 配置 2.3.1 配置环境变量 2.3.2 修改workers配置文件 2.3.3 修改spark.env.sh文件 2.3.4 修改spark-defaults.conf 2.4 分发 2.5 启动服务 2.5.1 启动zookeeper 2.5.2 启动hdfs 2.5.3 启动spar…

归并排序 (递归实+非递归)

前言 归并排序是一种逻辑很简单&#xff0c;但是实现有点难度的排序&#xff0c;尤其是非递归&#xff0c;对于区间的把握更是需要一点逻辑的推导&#xff0c;但是没有关系&#xff0c;轻松拿捏 归并排序gif 归并排序单趟实现 1&#xff0c;创建tmp数组&#xff0c; 2&#xff…

javaWeb项目-在线考试系统详细功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、Java简介 Java语…