129 Linux 系统编程7 ,make 的编写和解析

前文中,我们有多少个.c文件,就需要build 出来多少个.o文件

假设我们的项目很大,怎么管理这些 .c文件呢?

这里就要学习一个make文件的编写了。

makefile 本质上是一个脚本语言

脚本语言实际上就是将一系列命令放在一起执行

makefile 的用途:

项目代码编译管理

节省编译项目时间

一次编译终身受益

Makefile 工作内容:

makefile 会把遇见的第一条指令作为他的终极指令

但是如果开发者在前面加了关键字 ALL

就会把ALL:后面的 做为 makefile 的终极目标

因此一般,我们都会写ALL

ALL:a.out

make file的写法:

命名只有两种,一种叫做makefile 一种叫做Makefile

一个规则,

目标:依赖条件

                (一个tab缩进)命令

hello:hello.cgcc hello.c -o hello

解释:

目标是生成hello 这个可执行文件

依赖条件的意思是:要生成hello这个目标文件,需要依赖于 hello.c这个文件

然后缩进,这个是语法格式要求

命令的意思是:怎么使用 hello.c生成hello这个目标文件

基本原则的原文:

        若想生成目标, 检查规则中的额依赖条件是否存在,如不存在,则寻找是否有规则用来生成该依赖文件。

好,我们把这段话从自己刚才写的例子理解一下:

上述我们写的时候 是目标是 hello ,依赖条件是hello.c

我们改写一下 先从hello.c生成 hello.o

然后从hello.o生成目标文件hello

hello:hello.ogcc hello.o -o hellohello.o:hello.cgcc -c hello.c -o hello.o

hunandede@hunandede-virtual-machine:~/day03/makefilestudy$ ls
hello.c  makefile
hunandede@hunandede-virtual-machine:~/day03/makefilestudy$ make
gcc -c hello.c -o hello.o
gcc hello.o -o hello
hunandede@hunandede-virtual-machine:~/day03/makefilestudy$ 

1.学习这个之前,我们将昨天的部分整理过来并 按照g++的方法手动build 一下

文件内容如下,head 中存放.h文件

src 文件夹下放着所有的.cpp文件

g++ src/test.cpp src/addfunc.cpp src/devfunc.cpp src/mulfunc.cpp src/subfunc.cpp -o a.out -I ./head

如上,我们build 出来了一个 a.out文件,如下是执行 a.out文件

hunandede@hunandede-virtual-machine:~/day03/makefilestudy2$ ./a.out 
a+b = 15
a-b = 5
a*b = 50
a/b = 2

2. 改造成makefile 的写法

a.out:addfunc.o subfunc.o mulfunc.o devfunc.o test.og++ addfunc.o subfunc.o mulfunc.o devfunc.o test.o -o a.out
addfunc.o:addfunc.cppg++ -c addfunc.cpp -o addfunc.o -I../headsubfunc.o:subfunc.cppg++ -c subfunc.cpp -o subfunc.o -I../headmulfunc.o:mulfunc.cppg++ -c mulfunc.cpp -o mulfunc.o -I../headdevfunc.o:devfunc.cppg++ -c devfunc.cpp -o devfunc.o -I../headtest.o:test.cppg++ -c test.cpp -o test.o -I../head

执行make 就会生成a.out文件,然后我们运行 a.out文件

hunandede@hunandede-virtual-machine:~/day03/makefilestudy2/src$ ./a.out 
a+b = 15
a-b = 5
a*b = 50
a/b = 2

 这里有一个问题:我们上面为什么要将所有的.c分开写,转成.o,然后再使用使用所有的.o生成 a.out呢? 直接 g++ addfunc.cpp subfunc.cpp mulfunc.cpp divfunc.cpp -o a.out 写起来不是更方便吗?

原因是 当addfunc.cpp的代码有改动后,重新build的时候,这么一行的写法会让所有的.cpp文件编译成.o,然后将所有的.o文件再链接成 a.out文件。

实际上只有 addfunc.cpp改动了,其他的都没有变化,让其他的跟着重新build出来自己的.o文件是很没有必要的。因此要分开写。

回顾 g++编译的四个阶段预处理:头文件展开,宏替换,注释去掉编译:检查语法错误,将c语言变成汇编语言,消耗时间和系统资源最多汇编:将汇编语言变成 二进制指令链接:数据段合并以及地址回填,将函数库中相应的代码组合到目标文件中

引申出的另一个问题:g++是如何知道addfunc.cpp有变化了,那就要看file 属性中的ctime了,changed time,当一旦发现ctime有变化,就会重新编译了。实际上应该是说 当addfunc.cpp的ctime比addfunc.o的时间晚,则会重新编译 addfunc.cpp

1.目标的时间必须晚于依赖条件的时间,否则,更新目录。

2.依赖条件如果不存在找寻新的规则去产生依赖。

新的问题:


看起来是可以完全fix此类问题,好,又有一个新问题,我们的需求变化了,增加了一个 模余.cpp文件,用来求余数的。

那么我们就要改动 makefile文件以支持,类似如下的写法,

虽然也可以实现功能,但是很笨拙

a.out:addfunc.o subfunc.o mulfunc.o devfunc.o moyufunc.o test.og++ addfunc.o subfunc.o mulfunc.o devfunc.o test.o -o a.out
addfunc.o:addfunc.cppg++ -c addfunc.cpp -o addfunc.o -I../headsubfunc.o:subfunc.cppg++ -c subfunc.cpp -o subfunc.o -I../headmulfunc.o:mulfunc.cppg++ -c mulfunc.cpp -o mulfunc.o -I../headdevfunc.o:devfunc.cppg++ -c devfunc.cpp -o devfunc.o -I../headmoyufunc.o:moyufunc.cppg++ -c moyufunc.cpp -o moyufunc.o -I../headtest.o:test.cppg++ -c test.cpp -o test.o -I../head

解决这样笨拙写法的方案是 使用两个函数,类似通配符

二个函数

wildcard  和 patsubst

wildcard :通配符,白搭牌的意思

patsubst: 是用来匹配和替换的。

src = $(wildcard *.cpp) 

src = $(wildcard *.cpp)    匹配当前工作目录下的所有.cpp文件, 将文件名组成列表,赋值给变量src
也就是说,在这一句执行完毕之后,src = addfunc.cpp subfunc.cpp mulfunc.cpp divfunc.cpp
解释:
$(wildcard *.c) 整个是函数调用, wildcard 是函数名,*.c 表示参数
整个函数调用完成后,会交给 src 这个变量, 脚本变量只有一种类型,字符类型
注意的是  wildcard 和 *.cpp 是有空格的。

obj = $(patsubst %.cpp,%.o, $(src))

obj = $(patsubst %.cpp,%.o, $(src))
将参数3中 ,包含参数1的部分,替换为参数2
$(src)表示将 src 中变量依次 取出来,src 中是 addfunc.cpp subfunc.cpp mulfunc.cpp divfunc.cpp
然后把src变量里所有后缀为.cpp的文件替换成.o
将addfunc.cpp替换成addfunc.o
将subfunc.cpp替换成subfunc.o
将mulfunc.cpp替换成mulfunc.o
将divfunc.cpp替换成divfunc.o
因此当 $(patsubst %.cpp,%.o, $(src))执行完毕后,
obj中的值是:addfunc.o subfunc.o mulfunc.o divfunc.o
有了这两个函数,makefile就能简化
但是这个简化程度 只能将 集体的.cpp  或者.c 或者.o 替换,还不能完全达到我们想要的结果,因此还要往后面学习三个自动变量的使用
src = $(wildcard *.cpp)     #src = addfunc.cpp, subfunc.cpp mulfunc.cpp devfunc.cpp test.cpp
obj = $(patsubst %.cpp, %.o, $(src))      #obj = addfunc.o subfunc.o mulfunc.o devfunc.o test.oALL:a.outa.out:$(obj)g++ $(obj) -o a.out
addfunc.o:addfunc.cppg++ -c addfunc.cpp -o addfunc.o -I../headsubfunc.o:subfunc.cppg++ -c subfunc.cpp -o subfunc.o -I../headmulfunc.o:mulfunc.cppg++ -c mulfunc.cpp -o mulfunc.o -I../headdevfunc.o:devfunc.cppg++ -c devfunc.cpp -o devfunc.o -I../headtest.o:test.cppg++ -c test.cpp -o test.o -I../headclean:-rm -rf $(obj) a.out#a.out:addfunc.o subfunc.o mulfunc.o devfunc.o test.o
#	g++ addfunc.o subfunc.o mulfunc.o devfunc.o test.o -o a.out
#addfunc.o:addfunc.cpp
#	g++ -c addfunc.cpp -o addfunc.o -I../head#subfunc.o:subfunc.cpp
#	g++ -c subfunc.cpp -o subfunc.o -I../head#mulfunc.o:mulfunc.cpp
#	g++ -c mulfunc.cpp -o mulfunc.o -I../head#devfunc.o:devfunc.cpp
#	g++ -c devfunc.cpp -o devfunc.o -I../head#test.o:test.cpp
#	g++ -c test.cpp -o test.o -I../head

clean 清除不想要的文件

还有一个问题,我们每次build 出来的都有.o文件,实际上这个.o文件是中间文件,没啥用,

可以使用 clean指令删除这些不想要的.o文件,也可以将 a.out

clean:-rm -rf $(obj) a.out

使用时,先用 make clean -n,看一下要删除哪些东西,确认没有问题后,

再使用 make clean 真正的删除。

-rm 这个 -的意思是 即使这个文件不存在,也不会报错

三个自动变量

$@      在规则的命令中,表示规则中的目标,也就是说,只能出现在如下的“命令”中

目标:依赖条件(一个tab缩进)命令

$^         在规则的命令中,表示所有的依赖条件

$<        在规则的命令中,表示第一个依赖条件

如果将该变量应用在模式规则中,它可将依赖条件列表中的依赖条件,依次取出,套用模式规则。

那就在改一版

src = $(wildcard *.cpp)     #src = addfunc.cpp, subfunc.cpp mulfunc.cpp devfunc.cpp test.cpp
obj = $(patsubst %.cpp, %.o, $(src))      #obj = addfunc.o subfunc.o mulfunc.o devfunc.o test.oALL:a.outa.out:$(obj)g++ $^ -o $@    #changed the 规则的命令中,只能是在命令行改动
addfunc.o:addfunc.cppg++ -c $< -o $@ -I../headsubfunc.o:subfunc.cppg++ -c $< -o $@ -I../headmulfunc.o:mulfunc.cppg++ -c $< -o $@ -I../headdevfunc.o:devfunc.cppg++ -c $< -o $@ -I../headtest.o:test.cppg++ -c $< -o $@ -I../headclean:-rm -rf $(obj) a.out#a.out:$(obj)
#	g++ $(obj) -o a.out
#addfunc.o:addfunc.cpp
#	g++ -c addfunc.cpp -o addfunc.o -I../head#subfunc.o:subfunc.cpp
#	g++ -c subfunc.cpp -o subfunc.o -I../head#mulfunc.o:mulfunc.cpp
#	g++ -c mulfunc.cpp -o mulfunc.o -I../head#devfunc.o:devfunc.cpp
#	g++ -c devfunc.cpp -o devfunc.o -I../head#test.o:test.cpp
#	g++ -c test.cpp -o test.o -I../head#clean:
#	-rm -rf $(obj) a.out#a.out:addfunc.o subfunc.o mulfunc.o devfunc.o test.o
#	g++ addfunc.o subfunc.o mulfunc.o devfunc.o test.o -o a.out
#addfunc.o:addfunc.cpp
#	g++ -c addfunc.cpp -o addfunc.o -I../head#subfunc.o:subfunc.cpp
#	g++ -c subfunc.cpp -o subfunc.o -I../head#mulfunc.o:mulfunc.cpp
#	g++ -c mulfunc.cpp -o mulfunc.o -I../head#devfunc.o:devfunc.cpp
#	g++ -c devfunc.cpp -o devfunc.o -I../head#test.o:test.cpp
#	g++ -c test.cpp -o test.o -I../head

4.模式规则

我们发现上面的代码是有些是很相似的

#都是
%o:%.cpp

        g++ -c $< -o $@ -I../head

addfunc.o:addfunc.cppg++ -c $< -o $@ -I../headsubfunc.o:subfunc.cppg++ -c $< -o $@ -I../headmulfunc.o:mulfunc.cppg++ -c $< -o $@ -I../headdevfunc.o:devfunc.cppg++ -c $< -o $@ -I../headtest.o:test.cppg++ -c $< -o $@ -I../head#都是
%o:%.cppg++ -c $< -o $@ -I../head#因此可以直接替换,这个就是规则模式

5.还有问题:模式规则的疑问fix-使用静态模式规则

我们前面通过模式规则将.cpp变成.o

那么如果我们有些.cpp不想变成.o文件呢?

或者说我们还有一些c文件也要变成.o文件呢?

静态模式规则就是用来fix上述问题的。

obj2 = main.c func1.c func2.c
obj1 = aa.cpp bb.cpp cc.cpp

$(obj1):%o:%.cpp

        g++ -c $< -o $@ -I../head

$(obj2):%o:%.c

        g++ -c $< -o $@ -I../head

因此可以再改动一版

src = $(wildcard *.cpp)     #src = addfunc.cpp, subfunc.cpp mulfunc.cpp devfunc.cpp test.cpp
obj = $(patsubst %.cpp, %.o, $(src))      #obj = addfunc.o subfunc.o mulfunc.o devfunc.o test.oALL:a.outa.out:$(obj)g++ $^ -o $@    #changed the 规则的命令中,只能命令行%.o:%.cppg++ -c $< -o $@ -I../head#addfunc.o:addfunc.cpp
#	g++ -c $< -o $@ -I../head#subfunc.o:subfunc.cpp
#	g++ -c $< -o $@ -I../head#mulfunc.o:mulfunc.cpp
#	g++ -c $< -o $@ -I../head#devfunc.o:devfunc.cpp
#	g++ -c $< -o $@ -I../head#test.o:test.cpp
#	g++ -c $< -o $@ -I../headclean:-rm -rf $(obj) a.out#a.out:$(obj)
#	g++ $(obj) -o a.out
#addfunc.o:addfunc.cpp
#	g++ -c addfunc.cpp -o addfunc.o -I../head#subfunc.o:subfunc.cpp
#	g++ -c subfunc.cpp -o subfunc.o -I../head#mulfunc.o:mulfunc.cpp
#	g++ -c mulfunc.cpp -o mulfunc.o -I../head#devfunc.o:devfunc.cpp
#	g++ -c devfunc.cpp -o devfunc.o -I../head#test.o:test.cpp
#	g++ -c test.cpp -o test.o -I../head#clean:
#	-rm -rf $(obj) a.out#a.out:addfunc.o subfunc.o mulfunc.o devfunc.o test.o
#	g++ addfunc.o subfunc.o mulfunc.o devfunc.o test.o -o a.out
#addfunc.o:addfunc.cpp
#	g++ -c addfunc.cpp -o addfunc.o -I../head#subfunc.o:subfunc.cpp
#	g++ -c subfunc.cpp -o subfunc.o -I../head#mulfunc.o:mulfunc.cpp
#	g++ -c mulfunc.cpp -o mulfunc.o -I../head#devfunc.o:devfunc.cpp
#	g++ -c devfunc.cpp -o devfunc.o -I../head#test.o:test.cpp
#	g++ -c test.cpp -o test.o -I../head

删除各个版本演化注释的,就变成下面的样子了

src = $(wildcard *.cpp)     #src = addfunc.cpp, subfunc.cpp mulfunc.cpp devfunc.cpp test.cpp
obj = $(patsubst %.cpp, %.o, $(src))      #obj = addfunc.o subfunc.o mulfunc.o devfunc.o test.oALL:a.outa.out:$(obj)g++ $^ -o $@    #changed the 规则的命令中,只能命令行%.o:%.cppg++ -c $< -o $@ -I../headclean:-rm -rf $(obj) a.out

6. makefile脚本的运行

1.直接make 就会执行makefile 中的所有指令

2.使用make -n 不会真的执行指令,会将指令显示出来

2.使用make clean -n 查看要清除的文件

3.使用make clean 真正清除文件

7.make执行时候的问题

从上述的学习知道,我们会在makefile 中写一个

ALL:a.outclean:-rm -rf $(obj) a.out

如果这时候我们当前文件下,还有一个 clean的文件,

再使用make clean的时候就会有问题。

因此我们还有改动 makefile文件,写一个伪目标

.PHONY: clean ALL 这句话的意思是:即使当前文件夹下有 clean的文件,或者有ALL的文件,会认为clean文件和ALL文件是伪目标。不会执行真正的文件,而是执行make 命令参数。例如:make clean

src = $(wildcard *.cpp)     #src = addfunc.cpp, subfunc.cpp mulfunc.cpp devfunc.cpp test.cpp
obj = $(patsubst %.cpp, %.o, $(src))      #obj = addfunc.o subfunc.o mulfunc.o devfunc.o test.oALL:a.outa.out:$(obj)g++ $^ -o $@    #changed the 规则的命令中,只能命令行%.o:%.cppg++ -c $< -o $@ -I../headclean:-rm -rf $(obj) a.out.PHONY: clean ALL

8.优化,可以将-g -Wall -I 作为参数加进去

src = $(wildcard *.cpp)
obj = $(patsubst %.cpp, %.o, $(src))ALL:a.outmyargs = -g -Wall -I../heada.out:$(obj)g++ $^ -o $@ ${myargs} %.o:%.cppg++ -c $< -o $@ ${myargs}clean:-rm -rf $(obj) a.out.PHONY: clean ALL


 

9.练习 1

要求 inc 目录下放置.h文件

obj目录下放置生成的.obj文件

src目录下放置.cpp 文件

最终生成的 a.out可执行文件和makefile文件在同一级目录

写出makefile文件

src1 = $(wildcard ./src/*.cpp)   #这时候 src1 = ./src/addfunc.cpp ./src/subfunc.cpp ......
obj = $(patsubst ./src/%.cpp, ./obj/%.o, $(src1))  #这里要注意 将参数3中 ,包含参数1的部分,替换为参数2 ,这时候参数3取出来的值是 ./src/addfunc.cpp
#因此需要将 patsubst %.cpp 换成 .src/%.cpp, 将第二个参数%.o改成 ./obj/%o, 
#这样 % 才能代表同样的部分,也就是文件名的部分, obj的值就是 ./obj/addfunc.o ./obj/subfunc.o  ......ALL:a.outmyargs = -g -Wall -I./inca.out:$(obj)g++ $^ -o $@ ${myargs}./obj/%.o : ./src/%.cppg++ -c $< -o $@ ${myargs}clean:-rm -rf $(obj) a.out.PHONY: clean ALL

10.练习 2 ,本地有多个 main程序,一键生成

假设有a.cpp, b.cpp, c.cpp 每个.cpp文件中都有main函数,

我们的目标是实现

g++ a.cpp -o a

g++ b.cpp -o b

g++ c.cpp -o c

src = $(wildcard *.cpp)target = $(patsubst %.cpp, %, $(src))ALL: $(target)%:%cppgcc &< -o $@clean:-rm -rf $(target).PHONY: clean ALL

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

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

相关文章

Jetson Xavier NX 与笔记本网线连接 ,网络共享,ssh连接到vscode

Jetson Xavier NX 与笔记本网线连接 &#xff0c;网络共享&#xff0c;ssh连接到vscode Jetson Xavier NX桌面版需要连接显示屏、鼠标和键盘&#xff0c;操作起来并不方便&#xff0c;因此常常需要ssh远程连接到本地笔记本电脑&#xff0c;这里介绍一种连接方式&#xff0c;通过…

如何不患心肌梗塞

目录 一&#xff0c;个人面板 二&#xff0c;公共版图 三&#xff0c;卡牌 1&#xff0c;食物牌 2&#xff0c;药物牌 3&#xff0c;事件牌 四&#xff0c;回合操作 1&#xff0c;起始玩家 2&#xff0c;一轮操作 3&#xff0c;个人回合 4&#xff0c;轮末结算 5&a…

Vision Transfomer系列第二节---Tricks测试

目录 学习式和固定式位置编码测试dropout的作用测试block深度的作用测试embeding维度大小的作用测试多头的作用测试Overlap Patch的作用 学习式和固定式位置编码测试 主要测试无位置编码\可学习位置编码和固定式位置编码的训练效果: 其中固定式位置编码采用之前博客的正余弦位…

第十一天-Excel的操作

目录 1.xlrd-Excel的读模块 安装 使用 获取工作簿 读取工作簿的内容 xlsxwriter-Excel的写模块 安装 使用 生成图表 add_series参数 图表的样式 demo&#xff1a;生成图表 Excel的操作在python中有多个模块&#xff0c;为了能够快速使用&#xff0c;选择了相对简单…

【Docker】初学者 Docker 基础操作指南:从拉取镜像到运行、停止、删除容器

在现代软件开发和部署中&#xff0c;容器化技术已经成为一种常见的方式&#xff0c;它能够提供一种轻量级、可移植和可扩展的应用程序打包和部署解决方案。Docker 是目前最流行的容器化平台之一&#xff0c;它提供了一整套工具和技术&#xff0c;使得容器的创建、运行和管理变得…

想设计智能手环,我需要设计哪种电路?

随着电子技术的高速发展&#xff0c;可穿戴设备逐渐火爆&#xff0c;其中之一是智能手环&#xff0c;作为现代可穿戴技术的热门产品之一&#xff0c;它集成了多种功能&#xff0c;如健康检测、运动跟踪、通知提醒等&#xff0c;为了实现这些功能&#xff0c;需要用上哪些电路模…

模板注入 [WesternCTF2018]shrine1

打开题目 直接查看源代码 发现注册了一个名为FLAG的config&#xff0c;这里可能有flag&#xff0c; 存在flask-jinja2模板注入&#xff0c; 并且存在黑名单过滤 输入shrine/{{7*7}}验证成功 通过url_for()与globals()函数&#xff0c;绕过黑名单 /shrine/{{url_for.__globa…

Android 输入法框架简介

每种平台都有自己的输入法框架. GNU/Linux 桌面环境有多种输入法框架, 比如 ibus, fcitx 等. 但是 Android 操作系统只有一种, 是统一提供的输入法框架. 相关链接: 《ibus 源代码阅读 (1)》 https://blog.csdn.net/secext2022/article/details/136099328https://developer.and…

2024年 最新python调用ChatGPT实战教程

2024年 最新python调用ChatGPT实战教程 文章目录 2024年 最新python调用ChatGPT实战教程一、前言二、具体分析1、简版程序2、多轮对话3、流式输出4、返回消耗的token 一、前言 这个之前经常用到&#xff0c;简单记录一下,注意目前chatgpt 更新了&#xff0c;这个是最新版的&am…

MIT-BEVFusion系列九--CUDA-BEVFusion部署4 c++解析pytorch导出的tensor数据

目录 创建流打印 engine 信息打印结果内部流程 启动计时功能加载变换矩阵并更新数据&#xff08;重要&#xff09;内部实现 该系列文章与qwe一同创作&#xff0c;喜欢的话不妨点个赞。 在create_core方法结束后&#xff0c;我们的视角回到了main.cpp中。继续来看接下来的流程。…

挑战杯 基于大数据的时间序列股价预测分析与可视化 - lstm

文章目录 1 前言2 时间序列的由来2.1 四种模型的名称&#xff1a; 3 数据预览4 理论公式4.1 协方差4.2 相关系数4.3 scikit-learn计算相关性 5 金融数据的时序分析5.1 数据概况5.2 序列变化情况计算 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &…

【操作系统】14.I/O设备怎么分配和回收?

5.2 I/O设备怎么分配和回收&#xff1f; 5.2.1 I/O核心子系统 I/O调度 设备保护 假脱机技术&#xff08;SPOOLing技术&#xff09; ​ 输入井和输出井 ​ 输入进程和输出进程 ​ 输入缓冲区和输出缓冲区 设备分配与回收 ​ 设备分配应考虑的因素 ​ 静态分配与动态分配 ​ 设备…

Runaway Queries 管理:提升 TiDB 稳定性的智能引擎

在数字化系统扮演重要角色的今天&#xff0c;数据库稳定性成为企业关注的核心问题。对于重要计算机系统而言&#xff0c;突发的性能下降可能对业务造成不可估量的损失。为了稳定数据库性能&#xff0c;用户可以从管理流程入手规范变更的测试&#xff0c;或者利用产品手段减少预…

3DIoUMatch: Leveraging IoU Prediction for Semi-Supervised 3D Object Detection

3DIoUMatch: Leveraging IoU Prediction for Semi-Supervised 3D Object Detection 论文链接&#xff1a;https://arxiv.org/pdf/2012.04355.pdf 代码链接&#xff1a;https://github.com/yezhen17/3DIoUMatch 作者单位&#xff1a;Stanford University等 发表平台&#xff1a;…

【JavaEE】_Servlet程序的编写方法

目录 1. 创建项目 2. 引入依赖 3. 创建目录结构 3.1 在main目录下创建一个webapp目录 3.2 在webapp目录下创建一个WEB-INF目录 3.3 在WEB-INF目录下创建一个web.xml文件 3.4 在web.xml中进行代码编写 4. 编写代码 4.1 在java目录下创建类 4.2 打印"hello world&…

无人机精准定位技术,GPS差分技术基础,RTK原理技术详解

差分GPS的基本原理 差分GPS&#xff08;Differential GPS&#xff0c;简称DGPS&#xff09;的基本原理是利用一个或多个已知精确坐标的基准站&#xff0c;与用户&#xff08;移动站&#xff09;同时接收相同的GPS卫星信号。由于GPS定位时会受到诸如卫星星历误差、卫星钟差、大…

uniapp离线打包(使用Android studio打包)

一、准备工作 安装HbuilderX&#xff0c;记住版本号下载对应HbuilderX版本的Android离线SDK&#xff0c;如我使用3.6.18版本打包&#xff0c;则对应应下载3.6.18版本的SDK&#xff08;官网不提供旧版本的SDK&#xff0c;有些需要自己找&#xff09;官网下载地址&#xff1a;ht…

2、Web攻防-SQL注入-联合查询注入

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 声明&#xff1a;只用于学习交流&#xff0c;点到为止&#xff0c;请勿非法测试。 概念&#xff1a; 联合查询注入&#xff1a;联合注入是回显注入的一种&#xff0c;也就是说联合注入的前…

【Python如何求出水仙花数】

1、求水仙花数Python代码如下&#xff1a; # 求水仙花数&#xff1a;只需要个十百位的3次幂之和与原数相等 for i in range(100, 1000): # 循环100-999整数i1 i % 10 # 取个位 “%”表示除以后取余数i2 i // 10 % 10 # 取十位i3 i // 100 # 取百位 “//”表示除以后取整…

二十六、直方图均衡化

项目功能实现&#xff1a;对灰度图片进行直方图均衡化操作 按照之前的博文结构来&#xff0c;这里就不在赘述了 一、头文件 histogram_equal.h #pragma once#include<opencv2/opencv.hpp>using namespace cv;class HISTOGRAM_EQUAL { public:void histogram_equal(Mat…