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.rhkb.cn/news/353545.html

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

相关文章

Java开发笔记Ⅲ (一些零碎记录)

一些报错处理 找不到注入的对象 可以在 dao 层 的接口上添加 Repository 注解 common 模块报错 Unable to find main class 由于common中只有一些常量与工具类&#xff0c;不需要主类&#xff0c;故出现该错误时只需删除pom文件中的build标签即可解决 网关模块报错 Failed…

MYSQL 四、mysql进阶 1(mysql逻辑架构以及查询流程)

一、mysql的逻辑架构 1. 逻辑架构剖析 1.1 服务器处理客户端请求 mysql是典型的c/s架构&#xff0c;即 client/server 架构&#xff0c;不论是客户端进程和服务器进程是采用哪种方式进行通信&#xff0c;最后实现的效果都是&#xff1a;客户端进程向服务器进程发送一段文本&am…

高效、智能、安全:小型机房EasyCVR+AI视频综合监控解决方案

一、背景需求分析 随着信息技术的迅猛发展&#xff0c;小型机房在企事业单位中扮演着越来越重要的角色。为了确保机房的安全稳定运行&#xff0c;远程监控成为了必不可少的手段。 二、视频监控 视频监控是机房远程监控的重要组成部分。通过安装IP摄像机及部署视频监控系统Ea…

【Docker安装】Ubuntu系统下部署Docker环境

【Docker安装】Ubuntu系统下部署Docker环境 前言一、本次实践介绍1.1 本次实践规划1.2 本次实践简介二、检查本地环境2.1 检查操作系统版本2.2 检查内核版本2.3 更新软件源三、卸载Docker四、部署Docker环境4.1 安装Docker4.2 检查Docker版本4.3 配置Docker镜像加速4.4 启动Doc…

Redis 内存策略

一、Redis 内存回收 Redis 之所以性能强&#xff0c;最主要的原因就是基于内存存储。然而单节点的 Redis 其内存大小不宜过大&#xff0c;会影响持久化或主从同步性能。 我们可以通过修改配置文件来设置 Redis 的最大内存&#xff1a; # 格式&#xff1a; # maxmemory <byt…

【神经网络】基于CNN(卷积神经网络)构建猫狗分类模型

文章目录 解决问题数据集探索性数据分析数据预处理数据集分割数据预处理 构建模型并训练构建模型训练模型 结果分析与评估模型保存结果预测经验总结 解决问题 针对经典猫狗数据集&#xff0c;基于卷积神经网络&#xff0c;构建猫狗二元分类模型&#xff0c;使用数据集进行参数…

驱动开发(四):Linux内核中断

驱动开发系列文章&#xff1a; 驱动开发&#xff08;一&#xff09;&#xff1a;驱动代码的基本框架 驱动开发&#xff08;二&#xff09;&#xff1a;创建字符设备驱动 驱动开发&#xff08;三&#xff09;&#xff1a;内核层控制硬件层 驱动开发&#xff08;四&#xf…

【数据结构C++】表达式求值(多位数)课程设计

&#x1f4da;博客主页&#xff1a;Zhui_Yi_ &#x1f50d;&#xff1a;上期回顾&#xff1a;图 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f387;追当今朝天骄&#xff0c;忆顾往昔豪杰。 …

房地产房型展示信息小程序的内容是什么

地产业规模之大且品牌众多&#xff0c;还有房屋租赁、中介等&#xff0c;无论开发商公司还是衍生行业商家都需要多渠道宣传品牌和客户触达沟通转化&#xff0c;除了线下各种传单&#xff0c;线上也是主要场景&#xff0c;通过各种连接来达到相应目标。 也因此需符合平台生态开…

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

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

iCopy for Mac 剪切板 粘贴工具 历史记录 安装(保姆级教程,新手小白轻松上手)

Mac分享吧 文章目录 效果可留存文本、图片、文件等复制历史记录也可根据关键字进行历史记录检索点击一下&#xff0c;可复制双击两下&#xff0c;复制内容&#xff0c;并将信息粘贴至鼠标指针处 一、准备工作二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹…

【包管理】Node.JS与Ptyhon安装

文章目录 Node.JSPtyhon Node.JS Node.js的安装通常包括以下几个步骤&#xff1a; 访问Node.js官网&#xff1a; 打开Node.js的官方网站&#xff08;如&#xff1a;https://nodejs.org/zh-cn/download/&#xff09;。 下载安装包&#xff1a; 根据你的操作系统选择对应的Node…

Kotlin编程实践-【Java如何调用Kotlin中带默认值参数的函数】

问题 如果你有一个带有默认参数值的 Kotlin 函数&#xff0c;如何从 Java 调用它而无须为每个参数显式指定值&#xff1f; 方案 为函数添加注解JvmOverloads。 也就是为Java添加重载方法&#xff0c;这样Java调用Kotlin的方法时就不用传递全部的参数了。 示例 在 Kotlin …

python中scrapy

安装环境 pip install scrapy 发现Twisted版本不匹配 卸载pip uninstall Twisted 安装 pip install Twisted22.10.0 新建scrapy项目 scrapy startproject 项目名 注意&#xff1a;项目名称不允许使用数字开头&#xff0c;也不能包含中文 eg: scrapy startproject scrapy_baidu_…

【vue baidu-map】解决更新数据,bm-marker显示不完全问题

实现效果&#xff1a; 问题&#xff1a;切换上面基地tab键&#xff0c;导致地图图标展示不完全&#xff1b;刷新页面就可以正常展示。判断是<bm-marker>标记元素没有动态刷新dom元素引起的问题。 方案&#xff1a;this.$nextTick({}) this.$nextTick(()>{this.equipm…

Python复数的加、减、乘、除运算

一、复数 复数由实部和虚部组成&#xff0c;形如(a,b均为实数)的数为复数&#xff0c;其中&#xff0c;a被称为实部&#xff0c;b被称为虚部&#xff0c;i为虚数单位&#xff0c;。复数通常用z表示&#xff0c;即zabi&#xff0c;当z的虚部b&#xff1d;0时&#xff0c;则z为实…

云电脑有多好用?适合哪些人使用?

云电脑作为一种新型的计算模式&#xff0c;其应用场景广泛且多样&#xff0c;适合各类人群使用。云电脑适合什么人群使用&#xff1f;云电脑有哪些应用场景&#xff1f;有什么好的云电脑推荐&#xff1f;以下本文将详细探讨云电脑的主要应用场景及其适用人群的相关内容&#xf…

怎样搭建serveru ftp个人服务器

首先说说什么是ftp&#xff1f; FTP协议是专门针对在两个系统之间传输大的文件这种应用开发出来的&#xff0c;它是TCP/IP协议的一部分。FTP的意思就是文件传输协议&#xff0c;用来管理TCP/IP网络上大型文件的快速传输。FTP早也是在Unix上开发出来的&#xff0c;并且很长一段…

【Android】基于webView打造富文本编辑器(H5)

目录 前言一、实现效果二、具体实现1. 导入网页资源2. 页面设计3. 功能调用4. 完整代码 总结 前言 HTML5是构建Web内容的一种语言描述方式。HTML5是Web中核心语言HTML的规范&#xff0c;用户使用任何手段进行网页浏览时看到的内容原本都是HTML格式的&#xff0c;在浏览器中通过…

Boosting原理代码实现

1&#xff0e;提升方法是将弱学习算法提升为强学习算法的统计学习方法。在分类学习中&#xff0c;提升方法通过反复修改训练数据的权值分布&#xff0c;构建一系列基本分类器&#xff08;弱分类器&#xff09;&#xff0c;并将这些基本分类器线性组合&#xff0c;构成一个强分类…