C++及cmake语法介绍

news2024/11/26 13:52:16

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+5
    int 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 dlib
        RUNTIME 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 dlib
        RUNTIME 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.coloradmin.cn/o/1833662.html

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

相关文章

【PB案例学习笔记】-22制作一个语音朗读金额小应用

写在前面 这是PB案例学习笔记系列文章的第22篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

计算机网络:3数据链路层

数据链路层 概述封装成帧和透明传输帧透明传输&#xff08;填充字节或比特&#xff09;差错检测奇偶校验循环冗余校验CRC Cyclic Redundancy Check 可靠传输停止-等待协议回退n帧协议&#xff08;滑动窗口协议&#xff09;选择重传协议 点对点协议PPP共享式以太网网络适配器&am…

Spring系统学习 -Spring IOC 的XML管理Bean之P命名空间、实现引入MySQL外部链接属性文件

P命名空间 在Spring框架中&#xff0c;P命名空间是一种用于简化XML配置文件中属性注入的方式。通过引入P命名空间&#xff0c;可以使用更简洁的语法来设置bean的属性值&#xff0c;而无需显式地使用<property>子元素。这使得XML配置文件更加简洁和易于阅读。 要在Sprin…

【vue3|第9期】Vue3中watch监视的深度解读

日期&#xff1a;2024年6月10日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…

期末复习GGG-----查找子串

郭的 char *search( char *s, char *t ){int i0;while(s[i]){int j0;if(s[i]t[0]){while(s[ij]t[j]&&t[j]){j;}if(t[j]\0)return si;}i;}return NULL; } AI的 #include <stdio.h> #include <string.h> #define MAXS 30char *search(char *s, char *t);in…

Matlab使用Simulink仿真实现AM和BPSK信号的解调

前言 本篇实现了基于AM和BPSK调制的通信系统&#xff0c;采用Bernoulli Binary Generator生成随机二元序列&#xff0c;码元速率为0.5秒/个。AM调制使用Sine Wave模块生成载波&#xff0c;频率40Hz&#xff0c;相位π/2。BPSK调制通过Switch模块切换相位0和π的载波。信号传输…

红利之外的A股底仓选择:A50

内容提要 华泰证券指出&#xff0c;当前指数层面下行风险不大&#xff0c;市场再入震荡期下&#xff0c;可关注三条配置线索&#xff1a;1&#xff09;A50为代表的产业巨头&#xff1b;2&#xff09;以家电/食饮/物流/出版为代表的稳健消费龙头&#xff0c;3&#xff09;消费电…

使用 Iceberg、Tabular 和 MinIO 构建现代数据架构

现代数据环境需要一种新型的基础架构&#xff0c;即无缝集成结构化和非结构化数据、轻松扩展并支持高效的 AI/ML 工作负载的基础架构。这就是现代数据湖的用武之地&#xff0c;它为您的所有数据需求提供了一个中心枢纽。然而&#xff0c;构建和管理有效的数据湖可能很复杂。 这…

【离散化 二维差分】850. 矩形面积 II

本文涉及知识点 离散化 二维差分 LeetCode850. 矩形面积 II 给你一个轴对齐的二维数组 rectangles 。 对于 rectangle[i] [x1, y1, x2, y2]&#xff0c;其中&#xff08;x1&#xff0c;y1&#xff09;是矩形 i 左下角的坐标&#xff0c; (xi1, yi1) 是该矩形 左下角 的坐标…

物联网协议基础知识

协议允许节点以结构化的方式在它们之间进行交互。由于物联网设备的需求和用例在过去几年中迅速发展&#xff0c;协议也随之发展。总而言之&#xff0c;主要有两类协议&#xff1a;网络协议和数据协议。此分类来自广泛应用于 IT 通信网络的 OSI&#xff08;开放系统互连&#xf…

深入探讨JavaScript的执行机制

预编译 首先下面这段代码的执行是一个怎样的结果呢&#xff1f; showName(); console.log(MyName);var MyName 小陈同学function showName() {console.log(函数showName被执行); }在这段代码中我们声明了一个变量MyName和一个函数showName&#xff0c;调用函数&#xff0c;打…

TWM论文阅读笔记

这是ICLR2023的一篇world model论文&#xff0c;用transformer来做世界模型的sequence prediction。文章贡献是transformer-based world model&#xff08;不同于以往的如transdreamer的world model&#xff0c;本文的transformer-based world model在inference 的时候可以丢掉…

手机usb共享网络电脑没反应的方法

适用于win10电脑&#xff0c;安卓手机上可以 开启usb网络共享选择&#xff0c;如果选择后一直跳&#xff0c;让重复选择usb选项的话&#xff0c;就开启 开发者模式&#xff0c;进到 开发者模式 里设置 默认usb 共享网络 选项 &#xff0c;就不会一直跳让你选。 1.先用数据线 连…

一款.NET开源、功能强大、跨平台的绘图库 - OxyPlot

前言 今天大姚给大家分享一款.NET开源&#xff08;MIT License&#xff09;、免费、跨平台、功能强大的绘图库&#xff0c;支持多平台使用&#xff08;包括&#xff1a;WPF、UWP、WinForm、Silverlight、Xamarin.iOS、Xamarin.Android、Xamarin.Forms 和 Xamarin.Mac等&#x…

Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors

Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors 块设备名称为&#xff1a; /dev/sda 设备的大小为&#xff1a;107.4 GB 107374182400 bytes &#xff1a; 107374182400/1024/1024/1024100G &#xff08;1&#xff09;块设备名称为&#xff1a;/dev/sd…

DS18B20温度传感器完整使用介绍(配合51单片机)

DS18B20是一款由Maxim Integrated&#xff08;原Dallas Semiconductor&#xff09;生产的数字温度传感器&#xff0c;以其高精度、低功耗、灵活的接口方式和易于使用的特性&#xff0c;在各种温度监测应用中被广泛采用。 以下是DS18B20的详细介绍&#xff1a; 基本特性 数字输…

【CSS in Depth2精译】1.1 层叠

CSS 本质上就是声明规则&#xff0c;并让这些特定的规则在各种情况下生效。一个类添加到某个元素上&#xff0c;则应用这个类包含的这一些样式&#xff1b;元素 X 是元素 Y 的一个子节点&#xff0c;则应用另一些样式。浏览器于是根据这些规则&#xff0c;判定所有样式生效的具…

数据结构-十大排序算法集合(四万字精讲集合)

前言 1&#xff0c;数据结构排序篇章是一个大的工程&#xff0c;这里是一个总结篇章&#xff0c;配备动图和过程详解&#xff0c;从难到易逐步解析。 2&#xff0c;这里我们详细分析几个具备教学意义和实际使用意义的排序&#xff1a; 冒泡排序&#xff0c;选择排序&#xff0c…

解决安全规模问题:MinIO 企业对象存储密钥管理服务器

在强大可靠的存储解决方案领域&#xff0c;MinIO 作为持久层脱颖而出&#xff0c;为组织提供安全、持久和可扩展的存储选项。MinIO 通常负责处理关键任务数据&#xff0c;在确保高可用性方面发挥着至关重要的作用&#xff0c;有时甚至在全球范围内。存储数据的性质&#xff0c;…

vue音乐播放条

先看效果 再看代码 <template><div class"footer-player z-30 flex items-center p-2"><div v-if"isShow" class"h-12 w-60 overflow-hidden"><div :style"activeStyle" class"open-detail-control-wrap&…