CMake学习:CMake在二进制工程场景上应用

前面我们已经基本学习了CMake的使用,我们知道CMake是一套特别强大的编译构建工具链。那么它可以用于哪些工程场景呢?本期就来介绍一下CMake在编译可执行二进制程序、链接动静态库、打包分发等各种场景下的应用。

相关代码已经上传至作者的个人gitee:CMake 学习: CMake工具开发介绍仓库,虽然标记的是C++喜欢请点个赞谢谢

目录

代码示例

重点命令

cmake_minimum_required

表达式:

参数:

project

表达式:

参数:

include

表达式:

参数:

install

表达式:

参数:

安装目标类型(TYPE)

通用参数

特殊参数

add_executable


代码示例

源码

cpp 复制代码
#include<iostream>
int main()
{
    std::cout<<"hello world"<<std::endl;
    return 0;
}

CMakeLists.txt

bash 复制代码
#设置CMake最低版本
cmake_minimum_required(VERSION 3.18)
#项目名称
project(hello VERSION 1.0.0)
#添加构建目标
add_executable(main main.cpp)
#安装路径设置
include(GNUInstallDirs)
#安装本地
install(TARGETS main DESTINATION ${CMAKE_INSTALL_BINDIR})

# printf
message(STATUS "PROJECT_NAME: ${PROJECT_NAME}")
# print version
message(STATUS "PROJECT_VERSION:" ${PROJECT_VERSION})
message(STATUS "PROJECT_VERSION_MAJOR:" ${PROJECT_VERSION_MAJOR})
message(STATUS "PROJECT_VERSION_MINOR:" ${PROJECT_VERSION_MINOR})
message(STATUS "PROJECT_VERSION_PATCH:" ${PROJECT_VERSION_PATCH})

编译链接运行,结果为:

成功下载。

下面我们针对以上的示例,对重点命令进行解释

重点命令

cmake_minimum_required

作用版本兼容性保证 :确保构建系统使用指定版本以上的 CMake,避免使用过时的命令和特性。策略设置 :根据指定版本自动设置 CMake 策略(policies)的行为,平衡新功能与向后兼容性。错误预防 :在项目配置阶段早期检测版本不匹配,防止后续构建失败。通常应该在CMake文件的第一行

表达式

bash 复制代码
cmake_minimum_required(VERSION <min>[.<patch>] [...<max>[.<patch>]] [FATAL_ERROR])

参数

1. VERSION(必需)

  • 类型:关键字,标识版本参数的开始

  • 作用:告诉 CMake 后面的参数是版本号

2. <min>(必需)

  • 格式major.minor[.patch[.tweak]]

  • 示例

    • 3.18 → 3.18.0

    • 3.18.2 → 3.18.2

  • 作用:最低要求的 CMake 版本

  • 规则:必须是数值,至少包含 major.minor 两部分

3. ...<max>(可选,CMake 3.12+)

  • 格式...major.minor[.patch]

  • 示例3.18...3.25

  • 作用:指定可接受的 CMake 版本范围

  • 适用场景

    • 项目使用了特定版本引入的功能

    • 避免使用更高版本中可能不兼容的更改

4. FATAL_ERROR(可选,已弃用)

  • 历史:早期版本中用于强调版本不匹配是致命错误

  • 现状:现在版本不匹配总是致命错误,已不再需要此参数

现代新项目推荐CMake3.18版本及以上,因为文档丰富、社区支持力度高。可以用以下指令查询CMake版本

bash 复制代码
cmake -version

project

作用

  1. 项目标识:定义项目的基本信息(名称、版本、描述等)

  2. 初始化构建环境:设置编译器、语言标准、系统检测等

  3. 变量定义:创建一系列项目相关的CMake变量

  4. 语言启用:指定项目使用的编程语言,并启用相应的编译器和特性

表达式

bash 复制代码
#完整版本
project(<PROJECT-NAME>
    [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
    [DESCRIPTION <project-description-string>]
    [HOMEPAGE_URL <url-string>]
    [LANGUAGES <language-name>...])
#现代写法
project(<PROJECT-NAME>
    VERSION <version>
    DESCRIPTION <description>
    LANGUAGES <languages>)

参数

1. <PROJECT-NAME>(必需)

  • 类型:字符串

  • 规则:只能包含字母、数字、下划线、连字符

  • 作用

    • 定义项目标识符

    • 设置 PROJECT_NAME 变量

    • 设置 CMAKE_PROJECT_NAME 变量

2. VERSION(可选,推荐使用)

  • 格式:数字序列,用点分隔

  • 示例

    bash 复制代码
    VERSION 1.0.0
    VERSION 2.3.1
    VERSION 2024.12.31.1
  • 生成的变量

    bash 复制代码
    PROJECT_VERSION           # 完整版本 "1.2.3"
    PROJECT_VERSION_MAJOR     # 主版本 "1"
    PROJECT_VERSION_MINOR     # 次版本 "2"
    PROJECT_VERSION_PATCH     # 修订号 "3"
    PROJECT_VERSION_TWEAK     # 构建号 "4"(如果有)

3. DESCRIPTION(可选,CMake 3.9+)

  • 类型:字符串

  • 作用:项目简短描述

  • 生成变量PROJECT_DESCRIPTION

4. HOMEPAGE_URL(可选,CMake 3.12+)

  • 类型:URL字符串

  • 作用:项目主页链接

  • 生成变量PROJECT_HOMEPAGE_URL

5. LANGUAGES(可选,默认"C"和"CXX")

  • 取值CCXXCUDAOBJCOBJCXXFortranASMNONE

  • 作用

    • 启用指定语言的编译器检测

    • 设置语言相关的默认变量

    • 影响构建系统配置

project指令执行后,会生成以下新变量:

变量名 作用 生成条件 应用场景
PROJECT_NAME 当前项目的名称 总是生成 1. 在CMake脚本中引用当前项目 2. 作为子目录项目标识 3. 生成文件名前缀
PROJECT_VERSION 完整的项目版本号 使用 VERSION 参数 1. 在代码中嵌入版本信息 2. 生成版本配置文件 3. 打包和发布时使用
PROJECT_VERSION_MAJOR 主版本号 使用 VERSION 参数 1. API 兼容性检查 2. 主要特性变更标识
PROJECT_VERSION_MINOR 次版本号 使用 VERSION 参数 1. 新功能添加标识 2. 向后兼容的更新
PROJECT_VERSION_PATCH 修订号/补丁号 使用 VERSION 参数且版本至少有3部分 1. Bug修复标识 2. 微小的改进
PROJECT_VERSION_TWEAK 构建号/微调号 使用 VERSION 参数且版本有4部分 1. 构建序号 2. 内部测试版本
PROJECT_DESCRIPTION 项目描述文本 使用 DESCRIPTION 参数 1. 生成文档说明 2. 安装包描述信息
PROJECT_HOMEPAGE_URL 项目主页URL 使用 HOMEPAGE_URL 参数 1. 生成项目链接 2. 安装包元数据
PROJECT_SOURCE_DIR 当前项目源码目录 总是生成 1. 引用项目源码文件 2. 配置文件的相对路径 3. 资源文件定位
PROJECT_BINARY_DIR 当前项目构建目录 总是生成 1. 输出构建产物路径 2. 临时文件存放位置 3. 生成的文件存放
CMAKE_PROJECT_NAME 顶级项目名称(第一个project) 总是生成 1. 在多项目构建中识别根项目 2. 全局配置引用
CMAKE_PROJECT_VERSION 顶级项目版本 第一个project使用 VERSION 参数 1. 整体版本管理 2. 依赖关系检查
<PROJECT-NAME>_SOURCE_DIR 项目源码目录(大写名称) 总是生成 1. 兼容旧代码 2. 明确指定特定项目目录
<PROJECT-NAME>_BINARY_DIR 项目构建目录(大写名称) 总是生成 1. 兼容旧代码 2. 跨项目引用构建产物
<PROJECT-NAME>_VERSION 项目版本(大写名称) 使用 VERSION 参数 1. 兼容旧代码 2. 脚本中明确指定项目版本

变量使用示例表

变量 示例代码 解释
PROJECT_NAME message("Building ${PROJECT_NAME}") 输出项目名称
PROJECT_VERSION configure_file(version.h.in version.h) 生成版本头文件
PROJECT_SOURCE_DIR include_directories(${PROJECT_SOURCE_DIR}/include) 添加项目包含目录
PROJECT_BINARY_DIR set(OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin) 设置输出目录
组合使用 set(TARGET_NAME "${PROJECT_NAME}-v${PROJECT_VERSION}") 生成带版本的目标名

特殊场景变量表

场景 关键变量 用途
多项目构建 CMAKE_PROJECT_NAME 识别根项目
子目录项目 PROJECT_SOURCE_DIR 每个子项目有自己的源码目录
版本化安装 PROJECT_VERSION 生成版本化的安装路径
条件编译 PROJECT_VERSION_MAJOR 根据主版本启用/禁用特性
资源管理 PROJECT_SOURCE_DIR 定位项目资源文件
测试输出 PROJECT_BINARY_DIR 测试结果输出路径
文档生成 PROJECT_DESCRIPTION 嵌入到文档中
打包部署 所有版本变量 生成包元数据

项目变量继承关系表

变量类型 作用域 示例 说明
项目局部变量 当前项目 PROJECT_SOURCE_DIR 每个项目独立
全局顶级变量 整个构建 CMAKE_PROJECT_NAME 第一个project设置
大写别名变量 兼容性 MYPROJECT_SOURCE_DIR 大写项目名前缀
语言相关变量 全局/项目 CMAKE_CXX_STANDARD 影响编译设置

我们来试试

bash 复制代码
# CMake最低版本要求
cmake_minimum_required(VERSION 3.10)

# 设置项目名称
project(hello VERSION 1.2.3 LANGUAGES CXX)

# 设置C++标准
set(CMAKE_CXX_STANDARD 11)

# 添加可执行文件
add_executable(hello main.cpp)
# add_executable(app src/app.cpp)

# 安装可执行文件
include(GNUInstallDirs)
install(TARGETS hello)
# install(TARGETS hello RUNTIME DESTINATION bin)

# 输出一些调试信息

# 项目名称相关
message(STATUS "PROJECT_NAME: ${PROJECT_NAME}")
message(STATUS "CMAKE_PROJECT_NAME: ${CMAKE_PROJECT_NAME}")
message(STATUS "PROJECT_LANGUAGES: ${PROJECT_LANGUAGES}")

# 版本信息
message(STATUS "PROJECT_VERSION: ${PROJECT_VERSION}")
message(STATUS "PROJECT_VERSION_MAJOR: ${PROJECT_VERSION_MAJOR}")
message(STATUS "PROJECT_VERSION_MINOR: ${PROJECT_VERSION_MINOR}")
message(STATUS "PROJECT_VERSION_PATCH: ${PROJECT_VERSION_PATCH}")

# 目录信息
message(STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
message(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
message(STATUS "PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}")
message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}")

# 文件信息
message(STATUS "CMAKE_CURRENT_LIST_FILE: ${CMAKE_CURRENT_LIST_FILE}")
message(STATUS "CMAKE_CURRENT_LIST_DIR: ${CMAKE_CURRENT_LIST_DIR}")

# 安装路径信息
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "CMAKE_INSTALL_BINDIR: ${CMAKE_INSTALL_BINDIR}")

结果为:

include

作用

  1. 模块化引入:将其他CMake文件的内容导入到当前位置执行

  2. 代码复用:复用预定义的CMake模块、函数和宏

  3. 配置扩展:引入项目特定的配置或第三方CMake脚本

  4. 功能集成:使用标准CMake模块提供的功能和变量

表达式

bash 复制代码
#完整形式
include(<file|module> 
    [RESULT_VARIABLE <var>] 
    [OPTIONAL] 
    [NO_POLICY_SCOPE]
)
#路径名形式
include(相对/绝对路径)
include(${变量}/文件名)
include(模块名)  # 从CMAKE_MODULE_PATH搜索

参数

1. <file|module>(必需)

  • 类型:字符串,指定要包含的文件或模块名

  • 形式

    • 相对路径:相对于当前文件所在目录

    • 绝对路径:完整的文件路径

    • 模块名 :CMake模块名称,会从CMAKE_MODULE_PATH搜索

2. RESULT_VARIABLE <var>(可选)

  • 作用:将包含操作的结果存储到指定变量中

  • 变量值

    • 成功:包含文件的完整路径

    • 失败:NOTFOUND(未使用OPTIONAL时)或空值(使用OPTIONAL时)

3. OPTIONAL(可选)

  • 作用:如果文件不存在,不报错,继续执行

  • 使用场景:包含可选配置文件,不影响主要构建流程

4. NO_POLICY_SCOPE(可选)

  • 作用:不创建新的策略作用域

  • 使用场景:高级用法,控制策略(policies)的传播范围

核心目录变量的变化

变量名 include() 执行前(调用文件) include() 执行中(被包含文件) include() 执行后(返回调用文件) 说明
CMAKE_CURRENT_LIST_FILE 调用文件的路径 被包含文件的路径 调用文件的路径 总是指向当前正在处理的CMake文件
CMAKE_CURRENT_LIST_DIR 调用文件所在目录 被包含文件所在目录 调用文件所在目录 总是等于 CMAKE_CURRENT_LIST_FILE 的目录部分
CMAKE_CURRENT_LIST_LINE 调用文件中的行号 被包含文件中的行号 调用文件中下一行行号 逐行递增,跨文件时继续计数
CMAKE_CURRENT_SOURCE_DIR 调用文件所在目录 保持不变 保持不变 相对于 add_subdirectory()include() 不改变此变量
CMAKE_CURRENT_BINARY_DIR 调用文件对应构建目录 保持不变 保持不变 相对于 add_subdirectory()include() 不改变此变量

项目级变量的变化

变量名 include() 执行前 include() 执行中 include() 执行后 说明
PROJECT_SOURCE_DIR 当前项目源码目录 保持不变 保持不变 由最近的 project() 调用设置
PROJECT_BINARY_DIR 当前项目构建目录 保持不变 保持不变 由最近的 project() 调用设置
CMAKE_SOURCE_DIR 顶级源码目录 保持不变 保持不变 整个CMake项目的根目录
CMAKE_BINARY_DIR 顶级构建目录 保持不变 保持不变 整个CMake项目的构建根目录
CMAKE_MODULE_PATH 当前模块搜索路径 可能改变 保持改变 如果在被包含文件中修改,变化会持续

作用域和变量传递

类别 行为 示例
变量作用域 同一作用域 被包含文件可以直接访问和修改调用文件的变量
函数定义 全局可用 在被包含文件中定义的函数在包含后仍然可用
宏定义 全局可用 在被包含文件中定义的宏在包含后仍然可用
缓存变量 全局可用 set(var value CACHE) 定义的变量全局可见
环境变量 可能改变 set(ENV{var} value) 可能影响后续执行

install

作用

  1. 安装规则定义:指定项目构建产物如何安装到目标目录

  2. 打包准备:为生成安装包(deb、rpm、msi等)提供元数据

  3. 部署配置:定义文件在目标系统中的布局结构

  4. 组件管理:支持组件化安装,允许用户选择安装部分功能

表达式

bash 复制代码
install(
    <TYPE> <args>... |                      # 安装目标、文件、目录等
    [EXPORT <export-name>] |                # 导出安装目标
    [SCRIPT <file>] |                       # 安装脚本
    [CODE <code>] |                         # 安装代码片段
    [EXPORT_ANDROID_MK <file>]              # Android.mk导出
    [DESTINATION <dir>]                     # 目标目录
    [PERMISSIONS <permissions>...]          # 权限设置
    [CONFIGURATIONS <configs>...]           # 配置限定
    [COMPONENT <component>]                 # 组件标识
    [OPTIONAL]                              # 可选安装
    [EXCLUDE_FROM_ALL]                      # 排除默认安装
    [NAMELINK_COMPONENT <component>]        # 符号链接组件
    [NAMELINK_ONLY|NAMELINK_SKIP]           # 符号链接控制
    [...]
)

参数

安装目标类型(TYPE)

1. TARGETS <targets> - 安装构建目标

bash 复制代码
install(TARGETS <target>...
    [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
      PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
        [DESTINATION <dir>]
        [PERMISSIONS <permissions>...]
        [CONFIGURATIONS [Debug|Release|...]]
        [COMPONENT <component>]
        [NAMELINK_COMPONENT <component>]
        [OPTIONAL] [EXCLUDE_FROM_ALL]
        [NAMELINK_ONLY|NAMELINK_SKIP]
    ] [...]
    [INCLUDES DESTINATION [<dir> ...]]
)

目标分类:

  • ARCHIVE:静态库(.a/.lib)

  • LIBRARY:动态库(.so/.dylib/.dll)

  • RUNTIME:可执行文件(.exe/.out)

  • FRAMEWORK:macOS框架

  • BUNDLE:macOS应用包

  • PUBLIC_HEADER:公共头文件

  • PRIVATE_HEADER:私有头文件

  • RESOURCE:资源文件

2. FILES <files> - 安装普通文件

bash 复制代码
install(FILES <files>...
    [TYPE <type> | DESTINATION <dir>]
    [PERMISSIONS <permissions>...]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT <component>]
    [RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL]
)

3. DIRECTORY <dirs> - 安装目录

bash 复制代码
install(DIRECTORY <dirs>...
    [TYPE <type> | DESTINATION <dir>]
    [FILE_PERMISSIONS <permissions>...]
    [DIRECTORY_PERMISSIONS <permissions>...]
    [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT <component>]
    [FILES_MATCHING]
    [[PATTERN <pattern> | REGEX <regex>]
     [EXCLUDE] [PERMISSIONS <permissions>...]] [...]
)
通用参数

1. DESTINATION <dir> - 目标目录

bash 复制代码
# 相对路径:相对于CMAKE_INSTALL_PREFIX
install(TARGETS myapp DESTINATION bin)  # -> /usr/local/bin

# 绝对路径
install(FILES header.h DESTINATION /opt/myapp/include)

# 使用GNU标准目录变量
include(GNUInstallDirs)
install(TARGETS mylib 
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

2. PERMISSIONS - 文件权限

bash 复制代码
# 权限选项:
# OWNER_READ, OWNER_WRITE, OWNER_EXECUTE
# GROUP_READ, GROUP_WRITE, GROUP_EXECUTE
# WORLD_READ, WORLD_WRITE, WORLD_EXECUTE
# SETUID, SETGID

install(FILES script.sh
    DESTINATION bin
    PERMISSIONS 
        OWNER_READ OWNER_WRITE OWNER_EXECUTE
        GROUP_READ GROUP_EXECUTE
        WORLD_READ WORLD_EXECUTE
)

3. CONFIGURATIONS - 配置限定

bash 复制代码
# 仅Debug配置安装调试符号
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/debug.pdb
    DESTINATION bin
    CONFIGURATIONS Debug
)

# 仅Release配置安装文档
install(FILES README.md
    DESTINATION share/doc
    CONFIGURATIONS Release
)

4. COMPONENT <component> - 组件标识

bash 复制代码
# 将安装内容分组到不同组件
install(TARGETS myapp
    RUNTIME DESTINATION bin
    COMPONENT runtime
)

install(FILES documentation.pdf
    DESTINATION share/doc
    COMPONENT docs
)

# 用户可以按组件安装
# cmake --install . --component runtime

5. EXPORT <export-name> - 导出安装目标

bash 复制代码
# 创建导出的CMake包,供其他项目使用
install(TARGETS mylib
    EXPORT MyLibTargets
    ARCHIVE DESTINATION lib
    LIBRARY DESTINATION lib
    RUNTIME DESTINATION bin
    INCLUDES DESTINATION include
)

install(EXPORT MyLibTargets
    FILE MyLibConfig.cmake
    NAMESPACE MyLib::
    DESTINATION lib/cmake/MyLib
)

6. SCRIPTCODE - 自定义安装脚本

bash 复制代码
# 执行安装脚本
install(SCRIPT postinstall.cmake)

# 执行代码片段
install(CODE "
    execute_process(
        COMMAND ${CMAKE_COMMAND} -E create_symlink
            myapp-${PROJECT_VERSION} myapp
        WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin
    )
")
特殊参数

OPTIONAL - 可选安装

bash 复制代码
# 如果文件不存在,不报错
install(FILES optional.txt
    DESTINATION etc
    OPTIONAL
)

EXCLUDE_FROM_ALL - 排除默认安装

bash 复制代码
# 不包含在默认安装中,需显式指定
install(TARGETS tests
    RUNTIME DESTINATION bin
    EXCLUDE_FROM_ALL
)
# 安装:cmake --install . --component tests

RENAME <name> - 重命名文件

bash 复制代码
install(FILES config.txt
    DESTINATION etc
    RENAME myapp.conf
)

NAMELINK 相关参数 - 符号链接控制

bash 复制代码
# 控制库版本符号链接
install(TARGETS mylib
    LIBRARY
        DESTINATION lib
        NAMELINK_COMPONENT devel
    PUBLIC_HEADER
        DESTINATION include
        COMPONENT devel
)

cmake --install默认下载路径为usr/local

add_executable

作用add_executable 告诉 CMake 需要从指定的源文件构建一个可执行文件。它创建一个目标(target),后续可以通过其他命令为该目标添加依赖、编译选项等。最终在生成构建系统时,CMake 会根据这个目标生成相应的构建规则。

表达式

bash 复制代码
add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]
               source1 [source2 ...])

参数

  • <name> :目标的逻辑名称,也是生成的可执行文件的基本名称 (平台会自动添加后缀,如 Windows 加 .exe)。该名称可用于其他命令中引用此目标。

  • WIN32 :仅影响 Windows 平台。设置后,生成的程序入口点为 WinMain(而不是 main),且链接时指定 /SUBSYSTEM:WINDOWS

  • MACOSX_BUNDLE :仅影响 macOS。设置后,构建输出将是一个 .app 包,而非普通的可执行文件。

  • EXCLUDE_FROM_ALL :若指定,该目标不会包含在默认构建目标(如 ALL)中,需要手动构建(例如 make target_name)。

  • 源文件列表 :可以是多个文件,支持使用变量、生成器表达式(如 $<TARGET_PROPERTY:...>)或通配符(但通常不建议用通配符,因为 CMake 无法自动检测新增文件)。若省略源文件,可以后续通过 target_sources() 添加。

本期关于CMake在普通的可执行文件角度上的工程应用就讲完了,下面我们还会深入学习其他方面的内容。喜欢请点个赞

封面图自取:

相关推荐
知识分享小能手1 小时前
SQL Server 2019入门学习教程,从入门到精通,SQL Server 2019 新增功能 — 语法知识点及使用方法详解(20)
数据库·学习·sqlserver
『往事』&白驹过隙;1 小时前
瑞芯微(RK平台)调试指令常用整理
linux·arm开发·驱动开发
俩娃妈教编程2 小时前
2025 年 06 月 三级真题(1)--分糖果
c++·算法·gesp真题
tankeven2 小时前
HJ97 记负均正
c++·算法
俩娃妈教编程2 小时前
2025 年 06 月 三级真题(2)--奇偶校验
c++·算法·gesp真题
papaofdoudou2 小时前
Linux内核任务调度时机总结
linux·运维·网络
草莓熊Lotso2 小时前
Ext 系列文件系统核心:块、分区、inode 与块组结构详解
android·linux·c语言·开发语言·c++·人工智能·文件
2501_944934732 小时前
高职金融大数据应用专业,怎么学习金融数据建模基础?
大数据·学习·金融
nix.gnehc2 小时前
Go进阶攻坚+专家深耕级学习清单|聚焦高并发、高性能中间件/底层框架开发(Java开发者专属)
学习·中间件·golang