项目构建优化:CMake

news/2025/10/28 19:22:08/文章来源:https://www.cnblogs.com/YouEmbedded/p/19167273

CMake 介绍

在 Linux 工程管理中,make 是常用的工程管理器,但它依赖的 Makefile 语法晦涩、编写复杂,尤其在多文件、跨平台项目中维护成本极高。为解决这一问题,主流方案有两种:

  • 使用 automake 生成 configure 脚本,再由脚本自动生成 Makefile(适用于传统 Linux 项目);
  • 使用 CMake 直接生成 Makefile(跨平台、简单高效,是当前主流选择)。

CMake 是一款 跨平台免费开源的构建工具,核心作用是:通过开发者编写的简单配置文件 CMakeLists.txt,自动生成适配不同平台(Linux、Windows、macOS)、不同编译器(GCC、Clang、MSVC)的 Makefile 或工程文件(如 Visual Studio 项目),彻底摆脱手动编写 Makefile 的麻烦。

image

CMake、Makefile、编译器的关系如下:

image

CMake 安装

Ubuntu 系统安装

Ubuntu 下通过包管理器安装,命令简单且自动配置环境:

# 安装 CMake
sudo apt update  # 更新软件源
sudo apt install cmake -y# 验证安装(查看版本,确认安装成功)
cmake --version  # 输出示例:cmake version 3.22.1# 升级 CMake(如需更新到最新版本)
sudo apt upgrade cmake -y

CMake 基础实战

入门操作(单文件编译)

以一个简单的 C 语言程序 main.c 为例,演示 CMake 最基础的使用流程。

步骤 1:准备源码

创建 main.c,内容如下:

#include <stdio.h>
int main(int argc, char const *argv[]) {printf("Hello CMake!\n");return 0;
}

步骤 2:编写 CMakeLists.txt

在 main.c 同一目录下,创建 严格命名为 CMakeLists.txt 的文件(注意:文件名首字母大写、Lists 为复数,CMake 仅识别此名称,不可修改),内容如下:

# 设定 CMake 最低版本要求(避免版本兼容问题,推荐 3.10+)
cmake_minimum_required(VERSION 3.10)# 设定项目名称(可自定义,后续可用 ${PROJECT_NAME} 引用)
project(HelloCMake LANGUAGES C)  # LANGUAGES C 表示仅用 C 语言# 生成可执行程序
# 语法:add_executable(可执行程序名 依赖的源文件)
# 作用:指定最终生成的可执行文件名为 "hello",依赖源文件 "main.c"
add_executable(hello main.c)

步骤 3:生成 Makefile 并编译

在源码目录执行以下命令:

# 读取 CMakeLists.txt,生成 Makefile(. 表示当前目录)
cmake .# 执行 make 编译(自动读取生成的 Makefile)
make# 执行生成的可执行程序
./hello  # 输出:Hello CMake!

执行后目录结构如下(新增的 MakefileCMakeFiles 等为 CMake 生成的文件):

.
├── CMakeFiles/       # CMake 构建过程的临时文件
├── CMakeCache.txt    # CMake 缓存文件(加速后续构建)
├── cmake_install.cmake  # 安装配置文件
├── Makefile          # 自动生成的 Makefile
├── main.c            # 源码文件
└── hello             # 编译生成的可执行程序

源码隔离(推荐实战方式)

入门操作中,CMake 生成的文件与源码混在一起,不利于项目整洁。源码隔离 是工业界常用方式:创建单独的 build 目录存放所有构建文件,避免污染源码。

步骤 1:创建 build 目录并进入

# 在源码目录创建 build 目录(存放构建文件)
mkdir build# 进入 build 目录(后续所有构建操作在此目录执行)
cd build

步骤 2:生成 Makefile 并编译

# 读取上层目录(.. 表示 build 的父目录,即源码目录)的 CMakeLists.txt,生成 Makefile
cmake ..# 编译(生成的可执行程序在 build 目录下)
make# 执行程序(在 build 目录下)
./hello  # 输出:Hello CMake!

执行后目录结构如下(所有构建文件均在 build 内,源码目录仅保留 main.c 和 CMakeLists.txt):

.
├── build/            # 构建目录(所有临时文件、可执行程序在此)
│   ├── CMakeFiles/
│   ├── CMakeCache.txt
│   ├── cmake_install.cmake
│   ├── Makefile
│   └── hello         # 可执行程序
├── main.c            # 源码文件
└── CMakeLists.txt    # CMake 配置文件

优势:如需清理构建文件,直接删除 build 目录即可,不影响源码。

CMake 核心语法与进阶用法

多文件编译

当项目包含多个源文件(如 main.ca.cb.c)时,需在 add_executable 中指定所有源文件。

示例:多文件项目结构

.
├── build/
├── main.c  # 主函数文件
├── a.c     # 模块 1:实现加法
├── b.c     # 模块 2:实现减法
└── CMakeLists.txt

源文件内容

// a.c
int add(int a, int b) {return a + b;
}// b.c
int sub(int a, int b) {return a - b;
}// main.c
#include <stdio.h>
// 声明 a.c、b.c 中的函数
int add(int a, int b);
int sub(int a, int b);int main() {printf("3 + 2 = %d\n", add(3, 2));printf("3 - 2 = %d\n", sub(3, 2));return 0;
}

CMakeLists.txt 配置

cmake_minimum_required(VERSION 3.10)
project(MultiFile LANGUAGES C)# 多文件编译:指定可执行程序 "calc" 依赖的所有源文件
add_executable(calc main.c a.c b.c)

编译与执行

cd build
cmake ..
make
./calc  # 输出:3 + 2 = 5;3 - 2 = 1

优化:自动收集源文件(多文件场景推荐)

若源文件数量多,手动写所有文件名繁琐,可使用 aux_source_directory 自动收集指定目录下的所有源文件:

cmake_minimum_required(VERSION 3.10)
project(MultiFile LANGUAGES C)# 语法:aux_source_directory(目录 变量名)
# 作用:将当前目录(.)下所有 .c 文件路径存入变量 SRC_FILES
aux_source_directory(. SRC_FILES) # aux 是 auxiliary(中文意为 “辅助的”)# 用变量指定源文件(避免手动写多个文件名)
add_executable(calc ${SRC_FILES})

指定头文件路径

当项目包含单独的头文件目录(如 inc/)时,需用 include_directories 告诉编译器头文件位置,否则会报 “头文件未找到” 错误。

示例:带头文件的项目结构

.
├── build/
├── inc/              # 头文件目录
│   └── math.h        # 头文件:声明 add、sub 函数
├── src/              # 源文件目录
│   ├── main.c
│   ├── a.c
│   └── b.c
└── CMakeLists.txt    # 顶层 CMakeLists.txt

头文件与源文件内容

// inc/math.h
#ifndef MATH_H
#define MATH_H
// 声明函数
int add(int a, int b);
int sub(int a, int b);
#endif
// src/a.c
// 引用头文件(后续会用 CMake 简化路径)
#include "../inc/math.h"  
int add(int a, int b) {return a + b;
}// src/main.c
#include <stdio.h>
// 简化引用(需 CMake 指定头文件路径)
#include "math.h"  
int main() {printf("3 + 2 = %d\n", add(3, 2));return 0;
}

CMakeLists.txt 配置

cmake_minimum_required(VERSION 3.10)
project(WithHeader LANGUAGES C)# 语法:include_directories(头文件目录1 目录2 ...)
# 作用:告诉编译器,头文件在 "../inc" 目录(相对路径,基于当前 CMakeLists.txt 所在目录)
# 推荐用内置变量 ${CMAKE_CURRENT_SOURCE_DIR} 表示当前 CMakeLists.txt 所在目录,避免硬编码
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)# 收集 src 目录下的所有源文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)# 生成可执行程序
add_executable(calc ${SRC_FILES})

关键说明

  • CMAKE_CURRENT_SOURCE_DIR 是 CMake 内置变量,指向当前 CMakeLists.txt 所在的目录,跨平台兼容;
  • 若用绝对路径(如 /home/user/project/inc),会导致项目在其他电脑上无法运行,优先用相对路径 + 内置变量。

设定变量与调用 Shell 命令

设定变量

用 set 命令定义变量,变量引用用 ${变量名},常用于统一管理路径、源文件列表等,提升配置文件的可维护性。

cmake_minimum_required(VERSION 3.10)
project(UseVariable LANGUAGES C)# 设定头文件目录变量
set(HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/inc)# 设定源文件目录变量
set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)# 收集源文件(用变量指定目录)
aux_source_directory(${SRC_DIR} SRC_FILES)# 使用变量指定头文件路径
include_directories(${HEADER_DIR})# 使用变量生成可执行程序
add_executable(calc ${SRC_FILES})

调用 Shell 命令

CMake 中用 execute_process 调用 Shell 命令(如 lspwd),需指定命令和输出变量(可选)。

cmake_minimum_required(VERSION 3.10)
project(CallShell LANGUAGES C)# 语法:execute_process(COMMAND 命令1 [命令2 ...] OUTPUT_VARIABLE 输出变量)
# 作用:执行 "pwd" 命令,将输出(当前路径)存入变量 CURRENT_PATH
execute_process(COMMAND pwd OUTPUT_VARIABLE CURRENT_PATH)# 打印变量值(用于调试)
message(STATUS "当前目录路径:${CURRENT_PATH}")# 后续配置...
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)
add_executable(calc ${SRC_FILES})

执行 cmake .. 时会输出:

- 当前目录路径:/home/user/project/build
-- Configuring done
-- Generating done

添加工程子目录与编译库文件

当项目包含子模块(如 lib/ 目录,需编译成库文件)时,用 add_subdirectory 引入子目录,用 add_library 编译库文件(动态库或静态库)。

示例:带子目录库的项目结构

.
├── build/
├── inc/
│   └── math.h        # 头文件:声明 add、sub 函数
├── lib/              # 子目录:存放库的源文件
│   ├── a.c           # 库源文件1:实现 add
│   ├── b.c           # 库源文件2:实现 sub
│   └── CMakeLists.txt# 子目录的 CMake 配置文件
├── src/
│   └── main.c        # 主程序:调用库中的函数
└── CMakeLists.txt    # 顶层 CMake 配置文件

子目录 lib/ 的 CMakeLists.txt

# lib/CMakeLists.txt
# 编译库文件:将 a.c、b.c 编译成动态库或静态库# 语法:add_library(库名 库类型 源文件1 源文件2 ...)
# 库类型:SHARED(动态库,Linux 下生成 libmath.so)、STATIC(静态库,Linux 下生成 libmath.a)
# 作用1:编译动态库 libmath.so
add_library(math SHARED a.c b.c)# 作用2:(可选)编译静态库 libmath.a(若需同时生成两种库,需改库名,如 math_static)
# add_library(math_static STATIC a.c b.c)

顶层 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(WithLibrary LANGUAGES C)# 指定头文件路径(inc/ 目录)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)# 引入子目录 lib/(CMake 会自动执行 lib/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib)# 收集主程序源文件(src/ 目录)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)# 生成主程序可执行文件
add_executable(calc ${SRC_FILES})# 链接库文件:主程序 calc 依赖 libmath.so
# 语法:target_link_libraries(可执行程序名 库名1 库名2 ...)
target_link_libraries(calc math)

编译与验证

cd build
cmake ..
make

编译后,build/lib/ 目录下会生成动态库 libmath.sobuild/ 目录下生成主程序 calc,执行 ./calc 即可调用库中的函数。

指明库路径与链接外部库

若主程序依赖的库文件不在 CMake 自动搜索路径(如 /usr/lib、子目录库)中(如外部库 /tmp/libxxx.so),需用 link_directories 指定库的搜索路径,再用 target_link_libraries 链接。

示例:链接外部库

假设主程序依赖 /tmp/liblog.so(外部动态库),CMakeLists.txt 配置如下:

cmake_minimum_required(VERSION 3.10)
project(LinkExternalLib LANGUAGES C)# 指定头文件路径(若外部库有头文件,需添加)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)# 指定外部库的搜索路径(/tmp 目录下存放 liblog.so)
# 语法:link_directories(库路径1 路径2 ...)
link_directories(/tmp)# 收集主程序源文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)# 生成主程序
add_executable(calc ${SRC_FILES})# 链接外部库:calc 依赖 liblog.so(库名写 "log",CMake 自动补全 "lib" 和 ".so")
target_link_libraries(calc log)

注意link_directories 需在 add_executable 之前,确保 CMake 生成 Makefile 时能找到库路径。

指定工具链(交叉编译)

在嵌入式开发中,需为目标平台(如 ARM 架构的开发板)指定 交叉编译器(如 aarch64-linux-gnu-gcc),CMake 通过设置 CMAKE_C_COMPILER 和 CMAKE_CXX_COMPILER 实现。

示例:为 ARM 架构指定交叉工具链

cmake_minimum_required(VERSION 3.10)
project(CrossCompile LANGUAGES C)# 指定交叉编译器(根据实际工具链路径修改)
set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc")   # C 交叉编译器
set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++") # C++ 交叉编译器# 后续配置(头文件、源文件、链接库等,与之前一致)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)
add_executable(calc ${SRC_FILES})
target_link_libraries(calc math)

进阶:工具链文件(多平台切换)

若项目需部署到多个平台(如 x86、ARM、Rockchip),可将工具链配置单独放在 .cmake 文件中,编译时通过 -DCMAKE_TOOLCHAIN_FILE 指定,无需修改顶层 CMakeLists.txt。

步骤 1:ARM 平台工具链文件 arm.toolchain.cmake

# arm.toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)          # 目标系统:Linux
set(CMAKE_SYSTEM_PROCESSOR arm)       # 目标架构:ARM# 指定交叉编译器路径
set(TOOLCHAIN_DIR "/usr/local/arm-toolchain")
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-g++)# 指定目标平台的头文件和库路径(交叉编译时需用到)
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR})

步骤 2:编译时指定工具链文件

cd build
# 语法:cmake .. -DCMAKE_TOOLCHAIN_FILE=工具链文件路径
cmake .. -DCMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/arm.toolchain.cmake
make

生成的 calc 可执行程序将适配 ARM 架构,可放到开发板上运行。

指定编译选项

通过 CMAKE_C_FLAGS(C 语言)或 CMAKE_CXX_FLAGS(C++)设置编译选项,如优化等级、警告开关、运行时库路径等。

常用编译选项说明

选项 作用
-O2 优化等级 2(平衡性能与编译速度,推荐)
-Wall 显示所有警告信息
-Werror 将警告视为错误(强制修正所有警告)
-Wl,-rpath=./lib 指定程序运行时的库搜索路径(./lib)

示例:设置编译选项

cmake_minimum_required(VERSION 3.10)
project(CompileOptions LANGUAGES C)# 设置 C 语言编译选项:优化等级 O2 + 显示所有警告 + 运行时库路径
set(CMAKE_C_FLAGS "-O2 -Wall -Wl,-rpath=./lib")# 后续配置
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)
add_executable(calc ${SRC_FILES})
target_link_libraries(calc math)

设定 CMake 最低版本

用 cmake_minimum_required(VERSION x.x) 设定 CMake 最低版本,避免因版本差异导致的语法不兼容问题(如新版本的 target_include_directories 在旧版本中不可用)。

# 设定最低版本为 3.10(低于此版本的 CMake 会报错)
cmake_minimum_required(VERSION 3.10)# 若需兼容旧版本,可指定版本范围(如 3.10 到 3.30)
# cmake_minimum_required(VERSION 3.10...3.30)

执行 cmake .. 时,若当前 CMake 版本低于设定值,会报错:

CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
CMake 3.10 or higher is required.  You are running version 3.5.1

设定项目名称与版本

用 project 命令设定项目名称、版本号和支持的语言,便于版本管理和后续引用。

# 语法:project(项目名 VERSION 主版本.次版本.修订版 LANGUAGES 语言列表)
project(MyProject VERSION 1.2.3        # 版本号:1.2.3(主版本1,次版本2,修订版3)LANGUAGES C CXX      # 支持 C 和 C++ 语言
)# 引用项目相关的内置变量(后续可用于生成版本信息)
message(STATUS "项目名称:${PROJECT_NAME}")       # 输出:MyProject
message(STATUS "项目版本:${PROJECT_VERSION}")    # 输出:1.2.3
message(STATUS "主版本号:${PROJECT_VERSION_MAJOR}") # 输出:1

CMake 常用内置变量

CMake 提供大量内置变量,用于获取项目路径、配置输出目录等,提升配置文件的灵活性和跨平台兼容性。

内置变量 含义说明
PROJECT_SOURCE_DIR 项目根目录(顶层 CMakeLists.txt 所在的目录)
PROJECT_BINARY_DIR 构建目录(执行 cmake 命令的目录,通常是 build 目录)
PROJECT_NAME 项目名称(由 project 命令设定)
PROJECT_VERSION 项目版本号(由 project(VERSION ...) 设定)
CMAKE_CURRENT_SOURCE_DIR 当前处理的 CMakeLists.txt 所在的目录
CMAKE_CURRENT_BINARY_DIR 当前目标(可执行程序 / 库)的编译目录(如 build/lib
EXECUTABLE_OUTPUT_PATH 自定义可执行程序的输出路径(如 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
LIBRARY_OUTPUT_PATH 自定义库文件的输出路径(如 set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
CMAKE_C_COMPILER 当前使用的 C 编译器路径(如 /usr/bin/gcc
CMAKE_SYSTEM_NAME 目标系统名称(如 Linux、Windows、Darwin(macOS))

实用技巧

精准指定目标的头文件路径(推荐)

include_directories 会为所有目标(可执行程序、库)添加头文件路径,若需为特定目标添加,用 target_include_directories(更精准,避免冲突)。

cmake_minimum_required(VERSION 3.10)
project(TargetHeader LANGUAGES C)# 生成库文件 math
add_library(math SHARED lib/a.c lib/b.c)# 只为库 math 添加头文件路径(其他目标不生效)
target_include_directories(math PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/inc  # PRIVATE:仅库内部使用
)# 生成主程序 calc
add_executable(calc src/main.c)# 只为主程序 calc 添加头文件路径,并链接 math 库
target_include_directories(calc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc   # PUBLIC:calc 和依赖 calc 的目标都可用
)
target_link_libraries(calc math)

清理构建文件

源码隔离场景下,直接删除 build 目录即可清理所有构建文件:

# 在源码目录执行
rm -rf build/

非隔离场景下,用 make clean 清理编译生成的可执行程序和目标文件:

make clean

生成 Visual Studio 项目(Windows 平台)

CMake 支持生成 Windows 下的 Visual Studio 项目文件,只需在执行 cmake 时指定生成器:

# 生成 Visual Studio 2022 项目(64 位)
cmake .. -G "Visual Studio 17 2022" -A x64

执行后会生成 .sln 解决方案文件,用 Visual Studio 打开即可编译。

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

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

相关文章

项目构建优化:Make 与 Makefile

项目构建优化背景与 Make 工具基础 项目构建的核心痛点 在模块化开发中,会将可复用的函数接口、数据结构封装为源文件(.c) 和头文件(.h) 。当项目规模扩大(如大型 C/C++ 项目、Linux 内核),源文件与头文件数量…

科幻——面包

“卖面包咯,卖面包咯”一个面包小贩的声音从街边传来,但毕竟卖不出去啊,哪个现代人还买路边摊上的面包呢?饥寒交迫而又无奈,真有点“现代卖炭翁”的感觉了。 有什么办法呢?自从专业坍塌的那一瞬间,它便看清了它…

2025年中国钢结构码垛机制造商Top 5排名解析

摘要 钢结构码垛机行业随着工业自动化浪潮的推进,正迎来快速增长期,预计2025年全球市场规模将突破百亿元,中国作为制造大国,占据重要份额。行业发展聚焦于智能化、高效化和定制化,企业竞相提升技术实力和服务水平…

2025年钢结构码垛机品牌前十强权威盘点:江苏众利达引领智能制造新浪潮

文章摘要 随着工业4.0时代的深入发展,钢结构码垛机行业正迎来智能化升级的关键时期。2025年全球智能码垛设备市场规模预计突破百亿美元,中国作为制造业大国占据近40%市场份额。本文基于技术参数、市场口碑、服务能力…

处理django.db.utils.OperationalError: attempt to write a readonly database错误

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

10.28代码大全2

10.28代码大全2今天翻了《代码大全2》的“前期准备”章,原来写代码前花半小时理需求、画个简单架构图,比上来就敲键盘省时间多了,之前总踩“写一半发现逻辑错”的坑,现在算找到原因了。

[GESP202509 二级] 菱形

[GESP202509 二级] 菱形GESP202509 二级 菱形 题目描述 小 A 想绘制一个菱形。具体来说,需要绘制的菱形是一个 n 行 n 列的字符画,n 是一个大于 1 的奇数。菱形的四个顶点依次位于第 1 行、第1列、第 n 行、第 n 列的…

别再空谈企业架构!TOGAF的4A模型让你的技术投入至少省50%!

4A架构是技术管理者解决"系统混乱、业务脱节、数据不通"的实用工具文 / 勇哥 原创文章,转载请联系授权在上一篇文章企业架构标准深度解析:TOGAF、Zachman、ArchiMate 实战指南中,我们讲述了常见的企业架构…

linux 配置vnc

rpm -qa|grep vnc[root@dmc1 ~]# rpm -qa|grep vnc tigervnc-server-minimal-1.10.1-8.p01.ky10.x86_64 tigervnc-1.10.1-8.p02.ky10.x86_64 tigervnc-server-1.10.1-8.p02.ky10.x86_64么没有通过下面命令安装 yum ins…

2025 ICPC 成都 游记

简单写一篇成都站的流水张 25日 day 0 早上 10 点多从学校打车去赛场体育馆签到,坐一个多小时的车也是要坐吐了。在签到处玩游戏拿了只奶龙。不得不说 UESTC 出手还是阔绰的,直接给每队发了 200 美团卡。签完到回酒店…

基于PSO粒子群优化算法的64QAM星座图的最优概率整形matlab仿真,对比PSO优化前后整形星座图和误码率

1.算法仿真效果仿真操作步骤可参考程序配套的操作视频。 2.算法涉及理论知识概要 64QAM是一种高阶调制方式,星座图中有64个星座点,每个星座点对应6比特信息。传统的74QAM采用均匀分布。通过改变改变星座图不同位置符…

第七周第二天7.2

所用时间:270分钟 代码量(行):352 了解到的知识点:

apisix流量高峰期服务卡住问题

apisix流量高峰期服务卡住问题apisix,网络抓包现象描述 在流量高峰期,apisix偶现服务卡住,部分请求无法经过apisix转发。 分析步骤 1.起初线上服务出现异常,开发优先关注解决线上问题,发现降低业务流量之后,apisi…

第七周第一天7.1

所用时间:315分钟 代码量(行):198 了解到的知识点:

第六周第五天6.5

所用时间:180分钟 代码量(行):113 了解到的知识点:

在vue-markdown-render中解析LaTeX公式

<VueMarkdown:options="{html: true}":plugins="markdownPlugins"class="markdown":source="message.content" />import texmath from markdown-it-texmath import * a…

完整教程:IP 地址管理:IPv4 和 IPv6 地址规划、子网划分与 CIDR

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

102302107_林诗樾_数据采集与融合技术实践作业1

作业① 1)、上海软科2020大学排名爬取实验(requests+BeautifulSoup) import requests from bs4 import BeautifulSoup import warnings warnings.filterwarnings("ignore") # 忽略SSL等无关警告def craw…