GCC编译器的使用以及使用Makefile语法进行操控

Makefile

这里使用的Makefile操控编译器

gcc

常见的组成部分

  • c++: gcc 的一个版本,默认语言设置为 C++,而且在链接的时候自动包含标准 C++ 库。这和 g++ 一样
  • configure: GCC 源代码树根目录中的一个脚本。用于设置配置值和创建 GCC 编译程序必需的 make 程序文件
  • g++: gcc 的一个版本,默认语言设置为 C++,而且在链接的时候自动包含标准 C++库。这和 c++ 一样
  • gcc: 该驱动程序等同于执行编译程序和连接程序以产生需要的输出
  • libgcc: 该库包含的例程被作为编译程序的一部分,是因为它们可被链接到实际的可执行程序中。它们是特殊的例程,链接到可执行程序,来执行基本的任务,例如浮点运算。这些库中的例程通常都是平台相关的
  • libstdc++: 运行时库,包括定义为标准语言一部分的所有的 C++类和函数

包含的常见的软件

  • ar: 这是一个程序,可通过从文档中增加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理连接程序使用的目标库文档。该程序是 binutils 包的一部分
  • as: GNU 汇编器。实际上它是一族汇编器,因为它可以被编译或能够在各种不同平台上工作。该程序是 binutjls 包的一部分 autoconf:产生的 shell 脚本自动配置源代码包去编译某个特定版本的 UNIX
  • gdb: GNU 调试器,可用于检查程序运行时的值和行为 GNATS:GNU 的调试跟踪系统(GNU Bug Tracking System)。一个跟踪 GCC和其他 GNU 软件问题的在线系统
  • gprof: 该程序会监督编译程序的执行过程,并报告程序中各个函数的运行时间,可以根据所提供的配置文件来优化程序。该程序是 binutils 包的一部分
  • ld: GNU 连接程序。该程序将目标文件的集合组合成可执行程序。该程序是 binutils 包的一部分
  • libtool: 一个基本库,支持 make 程序的描述文件使用的简化共享库用法的脚本
  • make: 一个工具程序,它会读 makefile 脚本来确定程序中的哪个部分需要编译和连接,然后发布必要的命令。它读出的脚本(叫做 makefile 或 Makefile)定义了文件关系和依赖关系

默认的搜索路径

查看命令

echo | gcc -v -x c -E -
  • /usr/lib/gcc/x86_64-linux-gnu/7/include
  • /usr/local/include
  • /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
  • /usr/include/x86_64-linux-gnu
  • /usr/include

简单的编译原理

image-20230909101423089

预处理阶段, 把.c结尾的文件的#开头的命令进行预处理, 直接把对应的文本内容放到对应的位置

编译器, 把预处理之后的文件修改为汇编文件

汇编器, 汇编文件转换为二进制文件

连接器, 把所有的.o文件连接在一起形成一个可执行文件

各种文件的后缀

.a 静态库文件

.c C语言文件

.h 头文件

.i 预处理之后的文件

.o 目标文件

.s 汇编文件

.so 共享的库

实际使用gcc进行编译

  • 预处理
gcc -E mian.c

这一个会进行预处理但是没有生成一个文件

gcc -E main.c -o main.i

使用-o指明输出文件的名字

  • 生成汇编文件
gcc -S main.c
gcc -S main.c -o main.s
  • 生成目标文件
gcc -c main.c
gcc -c main.c -o main.o
  • 之间编译成可执行文件
gcc main.c

静态库编译以及链接

  1. 把c文件编译成o文件
  2. 编译静态库
ar -r [lib库名.a] [.o] [.o]
  1. 连接成可执行文件
gcc [.c] [.a] -o [输出的文件名]
gcc [.c] -o [输出的文件名] -l [库的名字] -L [库所在的位置]

注: windows下面为.lib文件, 但是测试的时候.a文件才可以使用

编译动态库

gcc -c -fpic [.c/.cpp] ...

编译成-o文件, 这样编译出来的文件使用都是相对地址

gcc -shared [.o] [.o] ... -o [lib.so]

创建动态库

gcc [.c/.cpp] -o [自定义可执行文件] -l[库名] -L[库路径] -wl,-rpath=[库路径]

链接动态库到可执行文件

注: windows下面为dll文件

静态库和动态库的区别

静态库在编译时会被完整地复制到可执行文件中,因此它们会增加可执行文件的大小。在链接时刻,编译器会将静态库的代码与可执行文件的代码合并,生成一个完整的可执行文件。由于静态库已经被完整地复制到可执行文件中,因此程序在运行时不需要再加载静态库,这样可以提高程序的运行速度。但是,如果多个可执行文件都使用同一个静态库,那么静态库的代码会被复制多次,浪费空间。

动态库则是在程序运行时才被加载到内存中,因此它们不会增加可执行文件的大小。在链接时刻,编译器只会将动态库的引用信息添加到可执行文件中,而不会将动态库的代码复制到可执行文件中。程序在运行时会动态地加载动态库,并将其映射到内存中。由于多个可执行文件可以共享同一个动态库,因此动态库可以节省内存空间。但是,由于动态库需要在程序运行时才能加载,因此程序的启动速度可能会受到影响。

总的来说,静态库适用于需要高效运行的小型程序,而动态库适用于需要共享代码和节省内存空间的大型程序。

C++编译文件的过程

  • .a 静态库文件
  • .c .c++ .cc .cp .cpp .cxx 源代码的文件
  • .h 头文件
  • .ii 预处理文件
  • .o 目标文件
  • .s 汇编文件
g++ -E main.c
g++ -E main.c -o maim.i

预处理文件

g++ -S main.c -o mian.s

生成汇编文件

g++ -c main.c -o main.o

生成预处理文件

g++ main.c -o main.exe

生成可执行文件

ar -cr [lib库的名字.a] [.o] [.o]
g++ [.c] [.a] -o [输出的文件名]
g++ [.c] -o [输出的文件名] -l[库的名字] -L[库所在的位置]

静态库文件

g++ -c -fpic [.c/.cpp] ...

编译成-o文件

g++ -shared [.o] [.o] ... -o [lib库的名字.lib]

创建动态库

g++ [.c/.cpp] -o [自定义可执行文件] -l[库名] -L[库路径] -wl,-rpath=[库路径]

链接动态库到可执行文件

Makefile语法

基本的格式

targets : prerequisties
[tab键]command
  • target:目标文件,可以是 OjectFile,也可以是执行文件,还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
  • prerequisite:要生成那个 target 所需要的文件或是目标。
  • command:是 make 需要执行的命令

image-20230909194637856

image-20230909194651591

这样的话会输出使用的命令, 可以在前面添加@使得输出隐藏

debug :
	@echo hello
PS E:\桌面\c_test> make
hello
PS E:\桌面\c_test> 

Makefile规则

  • 会在文件夹里面找到Makefile文件或者makefile文件
  • 会找到文件中的第一个目标文件(target), 把这个文件作为目标文件
  • target文件不存在或者依赖的.o文件修改时间比这个文件新的话会执行定义的commang命令生成这个文件
  • 如果.o文件也存在, 会找到.o文件的依赖, 依据规则生成.o文件

伪目标

为了避免 target 和 Makefile 同级目录下 文件/文件夹 重名的这种情况,我们可以使用一个特殊的标记 .PHONY 来显式地指明一个目标是 “伪目标”,向 make 说明,不管是否有这个文件/文件夹,这个目标就是 “伪目标”

.PHONY : clean

如果有一个名字叫clean的文件在这个文件夹下面, 就不会执行这一个命令

image-20230909195857917

这个时候就会输出

debug : world
	@echo hello

world :
	@echo world

clean :
	@rm *.o
PS E:\桌面\c_test> make clean
make: 'clean' is up to date.
PS E:\桌面\c_test>

只要有这个声明,不管是否有 “clean” 文件/文件夹,要运行 “clean” 这个目标,只有"make clean" 这个命令

注意

  • 对于有 prerequisties 的 target
debug : world
	@echo hello

world :
	@echo world

clean :
	@rm *.o

.PHONY : clean

这个时候就会执行这一个命令了

变量

变量的定义
cpp := src/main.cpp 
obj := objs/main.o
变量的引用
  • 可以使用()或者{}
cpp := src/main.cpp 
obj := objs/main.o

$(obj) : ${cpp}
	@g++ -c $(cpp) -o $(obj)

compile : $(obj)
compiler := cpp

debug : 
	@echo $(compiler)
PS E:\桌面\c_test> make      
cpp

变量会被转化为在上面输入的变量

预定义的变量

  • $@: 目标(target)的完整名称
  • $<: 第一个依赖文件(prerequisties)的名称
  • $^: 所有的依赖文件(prerequisties),以空格分开,不包含重复的依赖文件
cpp := src/main.cpp 
obj := objs/main.o

$(obj) : ${cpp}
	@g++ -c $< -o $@
	@echo $^

compile : $(obj)
.PHONY : compile

常用的符号

  1. =
  • 简单的赋值
  • 在后面的语句里面重新定义该变量, 会使用新的值
HOST_ARCH = arrch64
TARGET_ARCH = $(HOST_ARCH)

HOST_ARCH = amd64
debug :
	@echo $(TARGET_ARCH)
PS E:\桌面\c_test> make debug
amd64
PS E:\桌面\c_test> 

会随时更新使用=的变量

  1. :=

赋值了之后就不会进行更改

HOST_ARCH := arrch64
TARGET_ARCH := $(HOST_ARCH)

HOST_ARCH := amd64
debug :
	@echo $(TARGET_ARCH)
	@echo $(HOST_ARCH)
PS E:\桌面\c_test> make debug
arrch64
amd64
PS E:\桌面\c_test> 
  1. ?=
  • 默认赋值运算符
  • 如果变量已经定义就不进行任何操作
  • 如果没有定义就求值并进行分配
HOST_ARCH := arrch64
TARGET_ARCH := $(HOST_ARCH)

HOST_ARCH ?= amd64
debug :
	@echo $(TARGET_ARCH)
	@echo $(HOST_ARCH)
PS E:\桌面\c_test> make debug
arrch64
arrch64
  1. +=
  • 累加符号
HOST_ARCH := arrch64
TARGET_ARCH := $(HOST_ARCH)

HOST_ARCH += amd64
debug :
	@echo $(TARGET_ARCH)
	@echo $(HOST_ARCH)
PS E:\桌面\c_test> make debug
arrch64
arrch64 amd64
PS E:\桌面\c_test> 
  1. \
  • 续行符
HOST_ARCH := arrch64 \
			 arm63 x86
TARGET_ARCH := $(HOST_ARCH)

HOST_ARCH += amd64
debug :
	@echo $(TARGET_ARCH)
	@echo $(HOST_ARCH)
PS E:\桌面\c_test> make debug
arrch64 arm63 x86
arrch64 arm63 x86 amd64
PS E:\桌面\c_test> 

常用的函数

函数的调用

$(fn , argument) or ${fn, argument}

  • fn: 函数名
  • argument: 函数的参数
  1. shell
$(shell <commend> <argument>)

名称: shell

功能: 调用shell 使用commend

返回: shell执行commend的结果

pwd := $(shell pwd)

debug :
	@echo $(pwd)
PS E:\桌面\c_test> make debug
/e/妗岄潰/c_test
PS E:\桌面\c_test> 
  1. subst
$(subst <from>,<to>,<text>)
  • 名称: 字符串替换函数
  • 功能: 把字符串 中的 替换为
  • 返回的是替换之后的字符串
cpp_src := $(shell ls *.c)
cpp_objs := $(subst .c,.exe, $(cpp_src))

debug : 
	@echo $(cpp_src)
	@echo $(cpp_objs) 
PS E:\桌面\c_test> make
add.c main.c
add.exe main.exe
PS E:\桌面\c_test> 
  1. patsubst
$(patsubst <pattern>,<replacement>,<text>)

通配符替换字符串

通配符%把要替换的文字分割开来, 可以一次性替换多个不同的字符串

cpp_src := $(shell pwd)
cpp_objs := $(patsubst /e%/c_test,/c%/jiao, $(cpp_src))

debug : 
	@echo $(cpp_src)
	@echo $(cpp_objs) 

.PHONY : debug
PS E:\桌面\c_test> make debug
/e/妗岄潰/c_test
/c/妗岄潰/jiao
PS E:\桌面\c_test> 
  1. foreach
$(foreach <var>,<list>,<text>)
  • 名称:循环函数——foreach。
  • 功能:把字串中的元素逐一取出来,执行 包含的表达式
  • 返回: 所返回的每个字符串所组成的整个字符串(以空格分隔)
library_paths := /datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib \
                 /usr/local/cuda-10.1/lib64

library_paths := $(foreach item,$(library_paths),-L$(item))

debug : 
	@echo $(library_paths)
PS E:\桌面\c_test> make debug
-L/datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib -L/usr/local/cuda-10.1/lib64
PS E:\桌面\c_test> 
  • 可以使用下面的方式进行代替
I_flag := $(include_paths:%=-I%)
library_paths := /datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib \
                 /usr/local/cuda-10.1/lib64

# library_paths := $(foreach item,$(library_paths),-L$(item))
library_paths := $(library_paths:%=-L%)
debug : 
	@echo $(library_paths)
PS E:\桌面\c_test> make debug
-L/datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib -L/usr/local/cuda-10.1/lib64
PS E:\桌面\c_test> 
  1. dir
$(dir <names...>)

名称:取目录函数——dir。
功能:从文件名序列中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前 的部分。如果没有反斜杠,那么返回“./”。
返回:返回文件名序列的目录部分。

.PHONY : debug
cpp_srcs := $(shell ls *.c)
# 在文件名前面加上路径
cpp_objs := $(foreach item,$(cpp_srcs),./output/$(item))
# 获取输出的文件的文件名
cpp_objs := $(subst .c,.o,$(cpp_objs))
debug :
	@echo $(cpp_srcs) 
	@echo $(cpp_objs)
# 生成所有的.o文件
./output/%.o : %.c
	@mkdir -p $(dir $@)
	gcc -c $^ -o $@

compile : $(cpp_objs)
PS E:\桌面\c_test> make compile
gcc -c add.c -o output/add.o
gcc -c main.c -o output/main.o
PS E:\桌面\c_test> 

使用makedir -p可以在没有文件夹的时候创建文件夹

In a Makefile, the % symbol is used as a wildcard character to match any string. It is often used in conjunction with pattern rules to specify a set of targets and dependencies that follow a certain pattern.

  1. notdir
$(notdir <names...>)

如果输入的文件里面有文件夹的路径名, 就会去掉

libs   := $(notdir $(shell find /usr/lib -name lib*))

会寻找这里面的所有的库文件, 之后会把所有的文件的文件路径去除

  1. filter
$(filter <names...>)

根据自己的需求过滤掉一些文件

libs    := $(notdir $(shell find /usr/lib -name lib*))
a_libs  := $(filter %.a,$(libs))
so_libs := $(filter %.so,$(libs))

在这里面可以会找到两种不同格式的库文件

  1. basename

会把文件的后缀去掉

$(basename <names...>)
libs    := $(notdir $(shell find /usr/lib -name lib*))
a_libs  := $(subst lib,,$(basename $(filter %.a,$(libs))))
so_libs := $(subst lib,,$(basename $(filter %.so,$(libs))))

会去除.o和.so的文件后缀名,在之后就是去掉文件的前缀

  1. filter-out
  • 剔除不想要的字符串
objs := objs/add.o objs/minus.o objs/main.o
cpp_objs := $(filter-out objs/main.o, $(objs))
  1. wildcard
  • The wildcard function expands to a space-separated list of filenames that match the given patterns
cpp_srcs := $(wildcard src/*.cc src/*.cpp src/*.c)

实战教程

.PHONY : debug compile
c_srcs := $(shell ls *.c)
# 添加输出的文件的文件夹名字
c_objs := $(foreach item,$(c_srcs),./output/$(item))
# 获取要输出的各种文件的名字
c_objs := $(subst .c,.o,$(c_objs))
c_i := $(subst .o,.i,$(c_objs))
c_s := $(subst .o,.s,$(c_objs))

run : output/result.exe
	@.\$<

debug :
	@echo $(c_objs) 
	@echo $(c_i)

output/%.o : %.c
	@mkdir -p $(dir $@)
	gcc -c $^ -o $@

output/%.i : %.c
	@mkdir -p $(dir $@)
	gcc -E $^ -o $@

output/%.s : %.c
	@mkdir -p $(dir $@)
	gcc -S $^ -o $@

output/result.exe : $(c_objs)
	@mkdir -p $(dir $@)
	gcc $^ -o $@ 

clean :
	rm -rf output

compile : $(c_objs) $(c_i) $(c_s) output/result.exe

编译的选项

编译选项

  • -m64: 指定编译为 64 位应用程序
  • -std=: 指定编译标准,例如:-std=c++11、-std=c++14
  • -g: 包含调试信息
  • -w: 不显示警告
  • -O: 优化等级,通常使用:-O3
  • -I: 加在头文件路径前
  • fPIC: (Position-Independent Code), 产生的没有绝对地址,全部使用相对地址,代码可以被加载到内存的任意位置,且可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的

链接选项

  • -l: 加在库名前面
  • -L: 加在库路径前面
  • -Wl,<选项>: 将逗号分隔的 <选项> 传递给链接器
  • -rpath=: “运行” 的时候,去找的目录。运行的时候,要找 .so 文件,会从这个选项里指定的地方去找

通常使用的变量名

  • CC: Program for compiling C programs; default cc
  • CXX: Program for compiling C++ programs; default g++
  • CFLAGS: Extra flags to give to the C compiler
  • CXXFLAGS: Extra flags to give to the C++ compiler
  • CPPFLAGS: Extra flags to give to the C preprocessor
  • LDFLAGS: Extra flags to give to compilers when they are supposed to invoke the linker

编译带头文件的程序

c_srcs := $(shell ls ./src//*.c)
c_objs := $(patsubst ./src%.c,./output%.o, $(c_srcs))

in_path := ./inc
I_flags := $(foreach item,$(in_path),-I$(item))

compile_options := -g -O1 -w $(I_flags)

output/%.o : src/%.c
	@mkdir -p $(dir $@)
	@gcc -c $^ -o $@ $(compile_options)

output/result : $(c_objs)
	@mkdir -p $(dir $@)
	@gcc $^ -o $@ $(compile_options)

run : output/result
	@./output/result

clean : 
	@rm -rf ./output

gdb : output/result
	gdb

debug :
	@echo $(I_flags)

.PHOHY : debug run gdb clean

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FPS游戏穿模最强解决方案!开发一款FPS游戏射击游戏真的太简单!

FPS游戏穿模最强解决方案&#xff01;开发一款FPS游戏射击游戏真的太简单&#xff01; 2001年&#xff0c;FPS游戏老大哥《CS》横空出世&#xff0c;迅速在国内外掀起了一波FPS游戏的热潮&#xff0c;随后《CF穿越火线》在国内上线&#xff0c;一举拿下“玩家最喜爱的十大网络…

Java设计模式大全:23种常见的设计模式详解(二)

本系列文章简介&#xff1a; 设计模式是在软件开发过程中&#xff0c;经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合&#xff0c;可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…

Ubuntu使用Docker部署Nginx并结合内网穿透实现公网远程访问

文章目录 1. 安装Docker2. 使用Docker拉取Nginx镜像3. 创建并启动Nginx容器4. 本地连接测试5. 公网远程访问本地Nginx5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 在开发人员的工作中&#xff0c;公网远程访问内网是其必备的技术需求之一。对于…

鸿蒙内核框架

1 内核概述 内核简介 用户最常见到并与之交互的操作系统界面&#xff0c;其实只是操作系统最外面的一层。操作系统最重要的任务&#xff0c;包括管理硬件设备&#xff0c;分配系统资源等&#xff0c;我们称之为操作系统内在最重要的核心功能。而实现这些核心功能的操作系统模…

【LeetCode力扣】单调栈解决Next Greater Number(下一个更大值)问题

目录 1、题目介绍 2、解题思路 2.1、暴力破解法 2.2、经典Next Greater Number问题解法 1、题目介绍 原题链接&#xff1a;496. 下一个更大元素 I - 力扣&#xff08;LeetCode&#xff09; 示例1&#xff1a; 输入&#xff1a;nums1 [4,1,2], nums2 [1,3,4,2].输出&…

【计算机网络】Socket的SO_TIMEOUT与连接超时时间

SO_TIMEOUT选项是Socket的一个选项&#xff0c;用于设置读取数据的超时时间。它指定了在读取数据时等待的最长时间&#xff0c;如果在指定的时间内没有数据可读取&#xff0c;将抛出SocketTimeoutException异常。 SO_TIMEOUT的设置 默认情况下&#xff0c;SO_TIMEOUT选项的值…

引入echarts环形图及显示后端数据

实现效果&#xff1a; 1.下载echarts 并引用 npm install echarts --save 或 pnpm install -S echarts 项目中引用&#xff1a; 在项目main.ts中 import * as echarts from "echarts"; //引入echarts 3.页面中使用 <div id"main" class&quo…

近屿智能发布AIGC大模型工程师和产品经理学习路径图

近日&#xff0c;上海近屿智能科技有限公司&#xff08;下称“近屿智能”&#xff09;&#xff0c;基于其在大模型研发和产品设计领域深厚的专业积累&#xff0c;终于总结出AIGC大模型工程师与产品经理的学习路线图。该学习路线图不仅为追求专业发展的学习者提供了一条清晰明确…

从[redis:LinkedList]中学习链表

文章目录 adlistlistNodelistmacros[宏定义]listCreatelistInitNodelistEmptylistReleaselistAddNodeHeadlistLinkNodeHeadlistAddNodeTaillistLinkNodeTaillistInsertNodelistDelNodelistUlinkNodelistIndexredis3.2.100quicklistredis7.2.2quicklist redis的基本数据类型之一…

TTime翻译软件下载使用教程~~

简介 TTime是一款翻译软件&#xff0c;主要功能为输入翻译、截图翻译、划词翻译 平时工作或学习中难免会有存在需要翻译的场景&#xff0c;但是又没有一款好用而又简单的翻译工具 为此TTime出现了&#xff0c;它可以帮助我们更好的提高工作和学习效率 下载安装及使用教程 跳转…

【C语言 - 哈希表 - 力扣 - 相交链表】

相交链表题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0…

希望你用不上这篇文章!

每年的调剂信息非常重要。可以说是成绩不太理想的同学&#xff0c;最后一根救命稻草&#xff01;这篇文章很重要&#xff0c;但希望你用不上&#xff01; 调剂是一场信息战。注意&#xff01;千万不要轻信哪个学校容易调剂的建议。今天就给大家详细讲讲关于调剂的全流程。请耐…

验证码倒计时:用户界面的小细节,大智慧

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 验证码倒计时&#xff1a;用户界面的小细节&#xff0c;大智慧 前言为什么需要验证码倒计时防止滥用&#xff1a;用户心理&#xff1a; 设计考量可见性&#xff1a;友好性&#xff1a;适应性&#xff…

2023年全球软件架构师峰会(ArchSummit上海站):核心内容与学习收获(附大会核心PPT下载)

微服务架构是当今软件架构的主流趋势之一。随着云计算和分布式系统的普及&#xff0c;越来越多的企业开始采用微服务架构来构建他们的应用。微服务架构可以将一个大型的应用拆分成多个小型的服务&#xff0c;每个服务都独立部署、独立运行&#xff0c;并通过轻量级的通信协议进…

【Boost】:阶段性测试和阶段性代码合集(五)

阶段性测试和阶段性代码合集 一.编写测试程序-server.cc二.一些问题三.完整源代码 在这里添加了一些打印信息&#xff0c;方便我们观察&#xff0c;由于比较分散就不一一列举&#xff0c;可以看下面的完整源代码。 一.编写测试程序-server.cc 1.原版 只是简单的测试&#xff0…

如何有效的开展接口自动化测试(超详细整理)

一、简介 接口自动化测试是指使用自动化测试工具和脚本对软件系统中的接口进行测试的过程。其目的是在软件开发过程中&#xff0c;通过对接口的自动化测试来提高测试效率和测试质量&#xff0c;减少人工测试的工作量和测试成本&#xff0c;并且能够快速发现和修复接口错误&…

视频业务像素、带宽、存储空间计算

一、像素和分辨率 分辨率的单位通常是像素&#xff08;或点&#xff09;&#xff0c;用水平像素数乘以垂直像素数来表示。例如&#xff0c;一个分辨率为1920 x 1080的屏幕有1920个水平像素和1080个垂直像素。 总像素分辨率公式运算 例如 1920 x 10802073600总约200万 500W≈…

【05_发送测试报告到邮箱】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 05_发送测试报告到邮箱 1、获取邮箱授权码2、构造附件3、发送邮件4、完整示例 测试报告生成后&#xff0c;可以将报告发送至开发、测试邮箱&#xff0c;以便查看测试报告详情…

爬虫实战--爬取简单文字图片并保存到mongodb数据库

文章目录 前言发现宝藏 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便日后回顾。当然&#xff0c;如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚&#xff0c;文章中如果有记录错误&#xff0c;欢迎读者朋友们…

基于ESP8266 开发板(MCU)遥控小车

遥控小车 ​ 遥控界面 ​ 【项目源码】 第一版ESP8266 https://github.com/liyinchigithub/esp8266_car_webServerhttps://github.com/liyinchigithub/esp8266_car_webServer 第二版ESP32 GitHub - liyinchigithub/esp32-wroom-car: 嵌入式单片机 ESP32 Arduino 遥控小车&a…