当前位置: 首页 > news >正文

Makefile学习1

文章目录

  • Makefile学习1
    • Makefile简介
    • Makefile重要性
    • Makefile内容
        • 1) 显式规则
        • 2) 隐晦规则
        • 3) 变量的定义
        • 4) 文件指示
        • 5) 注释
    • Makefile规则
      • 规则
      • 默认目标
      • 多目标
      • 多规则目标
      • 伪目标
    • Makefile目标依赖
      • 头文件依赖
      • 自动生成头文件依赖关系
    • Makefile命令
    • Makefile变量
      • 变量定义和使用
      • 赋值
      • 立即变量/延迟变量
      • 自动变量
      • 变量替换
        • 字符串替换
        • 模式匹配替换
      • 环境变量
      • Override指示符
    • Makefile递归执行

Makefile学习1

Makefile简介

Makefile是在Linux环境下 C/C++ 程序开发必须要掌握的一个工程管理文件。当你使用make命令去编译一个工程项目时,make工具会首先到这个项目的根目录下去寻找Makefile文件,然后才能根据这个文件去编译程序。

linux下编写程序,因为早期没有成熟的IDE,一般都是使用不同的命令进行编译:将源文件分别使用编译器、汇编器、链接器编译成可执行文件,然后手动运行。

要将 .c源文件编译成可执行文件,一般需要预处理、编译、汇编、链接四个步骤,每个步骤会分别调用预处理器、编译器、汇编器、链接器来完成。

在Linux环境下,安装了GCC编译器,在程序的安装目录下面会有各种二进制可执行文件:

  • cpp:预处理器
  • ccl:编译器
  • as:汇编器
  • ld:链接器
  • ar:静态库制作工具

程序在编译过程中会分别使用这些工具,完成程序编译的每个流程。

为了简化程序编译流程,GCC编译器一般会提供一个gcc命令:

gcc -o a.out helloworld.c

gcc会分别调用预处理器、编译器、汇编器和链接器来自动完成程序编译的整个过程,不需要用户一个命令一个命令分别输入了。

gcc还提供了一些列参数,用来控制编译流程:

-E #进行预处理,不作编译
-S #只做汇编处理
-c #进行编译,不链接
-o #指定生成可执行程序名

对于大型项目使用gcc编译的话,每编译一次,都要敲进去几万个源文件,太折腾了,此时自动化编译工具make就派上用场了:使用make编译程序,不需要每次都输入源文件,直接在命令行下敲击make命令,就可一键自动化完成编译。

使用make命令编译程序之前,需要编写一个Makefile文件:

a.out: helloworld.ogcc -o a.out helloworld.o
helloworld.o: helloworld.cgcc -c -o helloworld.o helloworld.c
clean:rm -f a.out helloworld.o

makefile的文件名通常有三种格式:Makefile、makefile、GNUmakefile,make会在当前目录下自动寻找找三个文件名

如果同时存在执行makefile;如果没有找到的话,make就无法继续编译程序,产生一个错误并退出;如果名称自定的话,可以使用 -f 选项指定执行的文件

Makefile重要性

会不会写Makefile,是侧面可以看出一个人是否具有完成大型项目工程的能力。如果你是在Linux下进行C/C++开发,掌握Makefile可能让你更深地去理解项目,去掌控整个项目的构建和维护。

Makefile也是一个研究开源项目的利器。很多开源项目可能文档不完整,而Makefile就是开源项目的地图,从Makefile入手,可以让你快速窥探整个开源项目的框架和概貌,让你深入代码而不至于迷路。

掌握Makefile是一门必备技能,它和git、vim一样,掌握了这个“Linux三剑客”会让你的工作事半功倍、更加高效。

Makefile内容

简单的概括一下Makefile 中的内容,它主要包含有五个部分,分别是:

1) 显式规则

显式规则说明了,如何生成一个或多的的目标文件。这是由 Makefile 的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。

2) 隐晦规则

由于我们的 make 命名有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写 Makefile,这是由 make 命令所支持的。

3) 变量的定义

在 Makefile 中我们要定义一系列的变量,变量一般都是字符串,这个有点像C语言中的宏,当 Makefile 被执行时,其中的变量都会被扩展到相应的引用位置上。

4) 文件指示

其包括了三个部分,一个是在一个 Makefile 中引用另一个 Makefile,就像C语言中的 include 一样;另一个是指根据某些情况指定 Makefile 中的有效部分,就像C语言中的预编译 #if 一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。

5) 注释

Makefile 中只有行注释,和 UNIX 的 Shell 脚本一样,其注释是用“#”字符,这个就像 C/C++ 中的“//”一样。如果你要在你的 Makefile 中使用“#”字符,可以用反斜框进行转义,如:“#”。

Makefile规则

规则

Makefile通过规则进行构建可执行文件编译所依赖的关系树

规则是Makefile的基本组成单元。一个规则通常由目标、目标依赖和命令三部分构成:

目标:目标依赖命令
a.out: hello.cgcc -o a.out hello.c

说明:

a.out就是我们要生成的目标,目标一般是一个可执行文件。

目标依赖是指生成这个可执行文件所依赖的源文件,如 hello.c。

而命令则是如何将这些目标依赖生成对应的目标,一般是gcc命令、链接命令、objcopy命令,一些shell命令等。

命令必须使用tab键进行缩进,否则Makefile就会报错。

有的规则可能无目标依赖,仅仅是为了实现某种操作,如下面的clean命令:

clean:rm -f a.out hello.o

使用make clean命令清理编译的文件时,会调用这个规则中的命令,不需要什么依赖,仅仅是执行删除操作,所以这个规则中并没有目标依赖。

规则中也可以没有命令,仅仅包含目标和目标依赖,仅仅用来描述一种依赖关系,但一个规则中一定要有一个目标。

默认目标

一个Makefile文件里通常会有多个目标,一般会选择第一个作为默认目标。

正常情况下,当你想编译生成a.out时,要使用make a.out命令。

Makefile文件中a.out是文件中的第一个目标,当我们在make编译时没有给make指定要生成的目标,make就会选择Makefile文件中的第一个目标作为默认目标。

多目标

一个规则中也可以有多个目标,多个目标具有相同的生成命令和依赖文件。

如一个目标文件%.o都是由其对应的源文件%.c编译生成的,生成命令也是相同的:

%.o: %.cgcc -o %.o %.c

多规则目标

多个规则可能是同一个目标,make在解析Makefile文件时,会将具有相同目标的规则的依赖文件合并。

伪目标

伪目标并不是一个真正的文件,可以看做是一个标签。

伪目标一般没有依赖关系,也不会生成对应的目标文件,可以无条件执行,纯粹是为了执行某一个命令。

伪目标可以在执行默认目标之前先执行。

.PHONY: clean
a.out: hello.ogcc -o a.out hello.o
hello.o: hello.cgcc -c -o hello.o hello.c
clean:rm -f a.out hello.o

Makefile目标依赖

make第一次编译某个项目时,会依次编译所有的源文件。

但是当我们修改程序后,再次使用make编译,make只编译你新添加或修改了的源文件。

make是根据时间戳来判断一个规则中的目标依赖文件是否有更新。

make在编译程序时,会依次检查依赖关系树中的所有源文件的时间戳,如果发现某个文件的时间戳有更新,会认为这个文件有改动过,会重新编译这个源文件。

但是还有一种情况:在Makefile的规则中,一般不会把头文件添加到目标依赖中。当一个.c文件中包含多个头文件时,如果对应的头文件发生了变化,因为头文件没有包含在依赖关系树中,所以这个.c文件就不会重新编译:

//hello.c
#include <stdio.h>
#include "module.h"
int main(void)
{printf("PI = %f\n", PI);func();printf("hello zhaixue.cc!\n");return 0;
}
//module.c
#include <stdio.h>
void func(void)
{printf("hello func!\n");
}
//module.h
#ifndef __MODULE_H__
#define __MODULE_H__
#define PI 3.14
#endif
//Makefile
.PHONY: clean
a.out: hello.o module.ogcc -o a.out hello.o module.o
hello.o: hello.cgcc -c -o hello.o hello.c
module.o: module.cgcc -c -o module.o module.c
clean:rm -f a.out hello.o

修改module.h中的宏定义PI值为3.1415,再次使用make编译程序,make并没有重新编译,因为module.h并没有添加到Makefile的规则依赖目标中,所以无论你怎么修改module.h,都不会重新编译helloworld.c源文件。

头文件依赖

其中一个解决方法是将头文件module.h添加到规则的目标依赖列表中:

//Makefile
.PHONY: clean
a.out: hello.o module.o module.hgcc -o a.out hello.o module.o

缺点:包含几十个头文件时,把包含的这些头文件都手工添加进去,工作量还是蛮大的。

自动生成头文件依赖关系

更高效的解决方法是:使用gcc -M 命令自动生成头文件依赖关系

通过gcc -M命令,我们就可以自动生成一个hello.o目标文件的依赖关系,就不需要我们手动将头文件添加到规则中了。

Makefile命令

命令一般由shell命令(echo、ls)和编译器的一些工具(gcc、ld、ar、objcopy等)组成,使用tab键缩进。

命令是make在编译程序时真正要执行的部分。对于规则中的每一个命令,make会开一个进程执行,每条命令执行完,make会监测每个命令的返回码。

若命令返回成功,make继续执行下一个命令;若命令执行出错,make会终止执行当前的规则,退出编译流程。

make每执行一条命令,会把当前的命令打印出来。

如果你不想在make编译的时候打印正在执行的执行,可以在每条命令的前面加一个@:

.PHONY: clean
a.out: hello.c@echo "start compiling..."@gcc -o a.out hello.c@echo "compile done"
clean:rm -f a.out hello.o

Makefile变量

变量定义和使用

可以在Makefile中定义一个变量val,使用使用 $(val) 或 ${val} 的形式去引用它。

可以定义一些变量,分别表示编译器名称、目标、目标依赖文件:

PHONY: clean
CC  = gcc
BIN = a.out
OBJS = hello.o module.o
$(BIN): $(OBJS)@echo "start compiling..."@echo $(CC)$(CC) -o $(BIN) $(OBJS)@echo "compile done"
hello.o: hello.c$(CC) -c -o hello.o hello.c
module.o: module.c$(CC) -c -o module.o module.c
clean:rm -f $(BIN) $(OBJS)

好处:便于维护makefile文件,例如当项目中需要添加更多的源文件时,你只需要更改OBJS的值就可以了。如果不使用变量的话,你得修改Makefile多处地方。

赋值

Makefile中的变量赋值有多种形式,比如:

  • 条件赋值:?=
  • 追加赋值:+=

条件赋值是指一个变量如果没有被定义过,就直接给它赋值;如果之前被定义过,那么这条赋值语句就什么都不做。

CC = gcc
CC ?= arm-linux-gnueabi-gcc #不执行
$(BIN): $(OBJS)@echo $(CC)$(CC) -o $(BIN) $(OBJS)

追加赋值是指一个变量,以前已经被赋值,现在想给它增加新的值,此时可以使用+=追加赋值。

OBJS = hello.o
OBJS += module.o

立即变量/延迟变量

立即变量和延迟变量是按展开时间来划分的。

立即变量使用 := 操作符进行赋值,在解析阶段就直接展开了,顾名思义,立即展开变量。

延迟变量则是使用 = 操作符进行赋值,在make解析Makefile阶段不会立即展开,而是等到实际使用这个变量时才展开,获得其真正的值。

a = 1
b = 2
val_a := $(a)
val_b  = $(b)
a = 10
b = 20
test:echo $(val_a)echo $(val_b)

解释:

val_a是立即变量,当make解析到:=赋值符号时,会把$(a)变量的值立即赋值给val_a,虽然后面a的值发生了变化,但val_a因为已经展开,所以值就不再发生变化。

而val_b则不同,因为是延迟展开变量,所以,当make解析到 = 符号时,并没有立即把$(b)的值赋值给val_b,而是在运行echo命令时才对其展开,因为此时b的值已经是20,所以$(val_b)的值是20。

应用:

立即展开变量一般用在规则中的目标、目标依赖中。make在解析Makefile阶段,需要这些变量有确切的值来构建依赖关系树。一个项目中的文件依赖关系在程序编译期间是固定不变的,因此需要立即变量在解析阶段就要有明确的值,立即展开。

延迟展开变量一般用在规则的命令行中,这些变量在make编译过程中被引用到才会展开,获得其实际的值。

自动变量

在Makefile中,大家经常会见到类似 @ 、 @、 @^、$<这种类型的变量。

这种变量一般称为自动变量,自动变量是局部变量,作用域范围在当前的规则内,它们分别代表不同的含义:

  • $@:目标
  • $^:所有目标依赖
  • $<:目标依赖列表中的第一个依赖
  • $?:所有目标依赖中被修改过的文件
.PHONY: clean
CC  = gcc
BIN = a.out
OBJS = hello.o module.o
$(BIN): $(OBJS)@echo "start compiling..."@echo $(OBJS)$(CC) -o $@ $^@echo "compile done"
hello.o: hello.c$(CC) -c -o $@ $^
module.o: module.c$(CC) -c -o $@ $^
clean:rm -f $(BIN) $(OBJS)

还有一些自动变量不太常用,但是大家在以后阅读Makefile时可能会遇到,比如:

$%:当规则的目标是一个静态库文件时,$%代表静态库的一个成员名
$+:类似$^,但是保留了依赖文件中重复出现的文件
$*:在模式匹配和静态模式规则中,代表目标模式中%的部分。比如hello.c,当匹配模式为%.c时,$*表示hello
$(@D):表示目标文件的目录部分
$(@F):表示目标文件的文件名部分
$(*D):在模式匹配中,表示目标模式中%的目录部分
$(*F):在模式匹配中,表示目标模式中%的文件名部分
-: :告诉make在编译时忽略所有的错误
@: :告诉make在执行命令前不要显示命令

变量替换

字符串替换

.PHONY: all
SRC := main.c sub.c
OBJ := $(SRC:.c=.o)
all:@echo "SRC = $(SRC)"@echo "OBJ = $(OBJ)"
# make
SRC = main.c sub.c
OBJ = main.o sub.o

模式匹配替换

使用匹配符%匹配变量,使用 % 保留变量值中的指定字符串,然后其他部分使用指定字符串代替。

.PHONY: all
SRC := main.c sub.c
OBJ := $(SRC:%.c=%.o)
all:@echo "SRC = $(SRC)"@echo "OBJ = $(OBJ)"

环境变量

除了用户自定义的一些变量,make在解析Makefile中还会引入一些系统环境变量,如编译参数CFLAGS、SHELL、MAKE等。这

些变量在make开始运行时被载入到Makefile文件中,因为是全局性的系统环境变量,所以这些变量对所有的Makefile都有效。

若Makefile中有用户自定义的同名变量,系统环境变量将会被用户自定义的变量覆盖。若用户在命令行中传递跟系统环境变量同名的变量,系统环境变量也会被传递的同名变量覆盖。

PHONY:all
CFLAGS = -g
all:@echo "CFLAGS = $(CFLAGS)"@echo "SHELL = $(SHELL)"@echo "MAKE = $(MAKE)"@echo "HOSTNAME = $(HOSTNAME)"
wit@pc:/home/makefile/demo# make HOSTNAME=zz.cc #命令行传入
CFLAGS = -g
SHELL = /bin/sh
MAKE = make
HOSTNAME = zz.cc

除此之外,我们还可以通过export命令给Makefile传递变量,在shell环境下使用export命令,就相当于将对应变量声明为系统环境变量

Override指示符

override的作用及使用:

在一个Makefile中使用define、:=、= 定义的变量,我们可以在执行make命令时重新指定这个变量的值。

如果不希望在命令行指定的变量值替代在Makefile中的原来定义,那么我们可以在Makefile中使用指示符 override 对这个变量进行声明:

.PHONY: all
override web = www.baidu.com
all:@echo "web = $(web)"

Makefile中的变量分为多种:追加变量、立即变量、展开变量、使用define定义的变量,它们都可以使用override修饰。

当一个追加变量在定义时使用了override,后续对它的值进行追加时,也需要使用带有override指示符的追加方式。否则对此变量值的追加不会有效。

.PHONY: all
override fruits = apple
override fruits += banana
all:@echo "fruits = $(fruits)"

override的存在目的:

为了使用户可以改变或者追加哪些使用make命令行指定的变量的定义。从另一个角度上看,就是实现了在Makefile中增加或者修改命令行参数的一种机制。

比如在编译程序时,无论在命令行指定什么参数,编译器在编译时必需打开 -Wall选项,那么在Makefile中的CFLAGS应该这样定义:

.PHONY: all
override CFLAGS += -Wall
all:@echo "CFLAGS = $(CFLAGS)"
# make
CFLAGS = -Wall
# make CFLAGS=-g
CFLAGS = -g -Wall

不使用override修饰:

# make
CFLAGS = -Wall
# make CFLAGS=-g
CFLAGS = -g

Makefile递归执行

在实际工程项目中,各个源文件通常存放在各个不同的目录中,make在编译工程项目时,会依次遍历各个不同的子目录,编译每个子目录下的源文件。

make -C subdir1 subdir2 subdir3 ...

上面的make 命令就等价于:

cd subdir1 && $(MAKE)
cd subdir2 && $(MAKE)
cd subdir3 && $(MAKE)

顶层Makefile:

.PHONY:all
all:@echo "make start"make -C subdir1make -C subdir2make -C subdir3@echo "make done"

make通过 -C subdir参数,会分别到各个子目录下去执行,解析各个子目录下的Makefile并运行,遍历完所有的子目录

make依次遍历到各个子目录下解析新的Makefile时,项目顶层目录的主Makefile定义的一些变量,如何传递到子目录的Makefile文件中:将对应变量使用export声明为环境变量

相关文章:

Makefile学习1

文章目录 Makefile学习1Makefile简介Makefile重要性Makefile内容1) 显式规则2) 隐晦规则3) 变量的定义4) 文件指示5) 注释 Makefile规则规则默认目标多目标多规则目标伪目标 Makefile目标依赖头文件依赖自动生成头文件依赖关系 Makefile命令Makefile变量变量定义和使用赋值立即…...

城市内涝监测预警系统,科学“智治”应对灾害

近日&#xff0c;台风“杜苏芮”以摧枯拉朽之势给我国东南沿海地区带来狂风骤雨&#xff0c;福建的三个国家气象观测站日降水量突破历史极值。之后&#xff0c;“杜苏芮”一路北上。中央气象台预报称&#xff0c;7月29日至8月1日&#xff0c;北京、天津、河北、山东西部、河南北…...

切片[::-1]解析列表list表示的“非负整数加1”

列表数位表示非负整数&#xff0c;熟练操作“满十进位”。 (本笔记适合熟练操作Python列表list的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅…...

Mac下certificate verify failed: unable to get local issuer certificate

出现这个问题&#xff0c;可以安装证书 在finder中查找 Install Certificates.command找到后双击&#xff0c;或者使用其他终端打开 安装完即可...

Django项目启动错误

uwsgi项目启动错误信息如下Did you install mysqlclient?Command pkg-config --exists mysqlclient returned non-zero exit status 1Command pkg-config --exists mariadb returned non-zero exit status 1.Traceback (most recent call last):File "/home/dream21th/co…...

Vue2 第十二节 Vue组件化编程 (二)

1. VueComponent 2. 单文件组件 一. VueComponent 组件本质上是一个名为VueComponent的构造函数&#xff0c;不是程序员定义的&#xff0c;是Vue.extend生成的只需要写<school/>或者<school><school/>&#xff0c;Vue解析时&#xff0c;会帮我们创建schoo…...

pycharm 远程连接服务器并且debug, 支持torch.distributed.launch debug

未经允许&#xff0c;本文不得转载&#xff0c;vx&#xff1a;837007389 文章目录 step1&#xff1a;下载专业版本的pycharmstep2 配置自动同步文件夹&#xff0c;即远程的工程文件和本地同步2.1 Tools -> Deployment -> configuration2.2 设置同步文件夹2.3 同步服务器…...

SAP ABAP 基础语法超详细

1&#xff0e;表声明 Tables: 表名[,表名]. 声明多个表时可用逗号分隔当你声明了一个数据表的同时&#xff0c;系统也同时自动生成了一个和数据表同名的结构&#xff0c;结构的变量集等于数据表里面的字段。 2&#xff0e;定义变量 Data: v1[(l)] [type t] [decimals d] [v…...

html学习3(表格table、列表list)

1、html表格由<table>标签来定义。 <thead>用来定义表格的标题部分&#xff0c;其内部用 <th > 元素定义列的标题&#xff0c;可以使其在表格中以粗体显示&#xff0c;与普通单元格区分开来。<tbody>用来定义表格的主体部分&#xff0c;其内部用<t…...

【SpringBoot】85、SpringBoot中Boolean类型数据转0/1返回序列化配置

在 SpringBoot 中,前端传参数 0,1,后端可自动解析为 boolean 类型,但后端返回前端 boolean 类型时,却无法自动转换为 0,1,所以我们需要自定义序列化配置,将 boolean 类型转化为 0,1 1、类型对应 boolean 类型有false,true对应的 int 类型0,12、序列化配置 import com.f…...

hbase优化:客户端、服务端、hdfs

hbase优化 一.读优化 1.客户端&#xff1a; scan。cache 设置是否合理&#xff1a;大scan场景下将scan缓存从100增大到500或者1000&#xff0c;用以减少RPC次数使用批量get进行读取请求离线批量读取请求设置禁用缓存&#xff0c;scan.setBlockCache(false)以指定列族或者列进行…...

docker安装memcached

查找容器是否有该镜像存在 docker search memcached拉取镜像 docker pull memcached创建容器 docker create --name memcache1 memcached或者映射一下端口 docker create -p 11211:11211 --name memcache1 memcached启动 docker start memcache1指定容器的 IP docker net…...

Redis 客户端有哪些?

文章目录 JedisLettuceRedisson最佳实践 - 到底用哪个&#xff1f; Redis 最常见的 Java 客户端有两个&#xff0c;Jedis 和 Lettuce&#xff0c;高级客户端有 Redisson&#xff0c;见下图&#xff08;图源 Clients | Redis&#xff09; Jedis Github地址&#xff1a;redis/j…...

smbms 超市订单管理系统设计与实现计划表

smbms 超市订单管理系统 项目描述 smbms-JDBC&#xff1a;不使用 SSM 框架进行开发bookStore&#xff1a;学完ssm框架后的整合项目smbms-SSM&#xff1a;使用 SSM 框架开发 项目记录 smbms-JDBC 2023-10-28&#xff1a;第一天&#xff0c;搭建环境&#xff0c;写好基本的工…...

如何解决制造业数字化改造的障碍?

制造业的数字化转型可能是一个复杂且具有挑战性的过程&#xff0c;但解决以下障碍有助于为成功实施铺平道路&#xff1a; 抵制变革&#xff1a;数字化转型中最常见的挑战之一是员工的抵制&#xff0c;尤其是那些习惯传统方法的员工。为了克服这一问题&#xff0c;组织需要培养一…...

代码随想录算法训练营day49

文章目录 Day49买卖股票的最佳时机题目思路代码贪心算法动态规划法(推荐) 买卖股票的最佳时机II题目思路代码 Day49 买卖股票的最佳时机 121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09; 题目 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i]…...

云计算与大数据——部署Kubernetes集群+完成nginx部署(超级详细!)

云计算与大数据——部署Kubernetes集群完成nginx部署(超级详细&#xff01;) 部署 Kubernetes 集群的基本思路如下&#xff1a; 准备环境&#xff1a; 选择适合的操作系统&#xff1a;根据需求选择适合的 Linux 发行版作为操作系统&#xff0c;并确保在所有节点上进行相同的选…...

Maven 打包项目后,接口识别中文乱码

背景 项目在Idea里面运行&#xff0c;调用接口发送中文消息正常&#xff0c;用Maven打包项目后&#xff0c;运行jar包&#xff0c;调用接口发送中文出现乱码。 解决方法 1.Idea编译配置 2.如果更改了上述配置之后还是没有效果&#xff0c;则在运行jar包的前面加上 -Dfile.en…...

计算机视觉项目中的文件批量操作与文件批量预处理

计算机视觉项目中的文件批量操作与文件批量预处理 目录 数据集制作文件批量重命名文件批量移动将文件批量按照一定格式进行重命名修改xml文件内容的方法 引言 在计算机视觉项目中&#xff0c;文件批量操作和文件批量预处理是必不可少的步骤。它们涉及处理大量的图像文件&am…...

PHP数组转对象和对象转数组

PHP数组转对象和对象转数组 <?php function array_to_object($arr){$obj new stdClass();foreach ($arr as $key > $val) {if (is_array($val) || is_object($val)) {$obj->$key array_to_object($val);} else {$obj->$key $val;}}return $obj; } function o…...

前后端分离开发中的传参

1.post请求&#xff0c;后台代码使用RequestBody注解接收前端传过来的参数 PostMapping("/saveHosp") public Result SaveHosp(RequestBody HospitalSet hospitalSet){//此处省略中间代码......} 此时前端传过来的参数须为JSON格式&#xff0c;前端VUE传参数为&…...

mount: wrong fs type, bad option, bad superblock报错 ubuntu

问题描述 mount: wrong fs type, bad option, bad superblock Ubuntu无法挂载磁盘。 原因 很大概率是你的硬盘是NTFS。 解决 sudo apt install ntfs-3g即可。...

【图像分类】CNN+Transformer结合系列.3

介绍两篇图像分类的论文&#xff1a;ResMLP&#xff08;arXiv2305&#xff09;&#xff0c;MetaFormer&#xff08;CVPR2022&#xff09;&#xff0c;两者都与Transformer有关系&#xff0c;前者基于transformer结构的特点设计ResMLP&#xff0c;后者认为宏观架构才是Transform…...

IDA分析实例android_crackme/EasyJNI/Transformers/pingan2

文章目录 第一个实例android_crackme将32位的android_server放到手机目录下给android_server赋予root更改root用户组运行android_serverpc端端口转发安装apk&#xff0c;并运行app打开32位IDA并attach到进程先使用jadx看java层逻辑定位要分析的方法IDA 给两个方法打断点 第二个…...

拿捏--->求一元二次方程的根

文章目录 题目描述算法思路代码示例 题目描述 从键盘输入a, b, c的值&#xff0c;编程计算并输出一元二次方程ax2 bx c 0的根&#xff0c;当a 0时&#xff0c;输出“Not quadratic equation”&#xff0c;当a ≠ 0时&#xff0c;根据△ b2 - 4ac的三种情况计算并输出方程…...

深入浅出之Docker Compose详解

目录 1.Docker Compose概述 1.1 Docker Compose 定义 1.2 Docker Compose产生背景 1.3 Docker Compose 核心概念 1.4 Docker Compose 使用步骤 1.5 Docker Compose 常用命令 2. Docker Compose 实战 2.1 Docker Compose下载和卸载 2.2 Docker Compose 项目概述 2.3 Do…...

spring5源码篇(12)——spring-mvc请求流程

spring-framework 版本&#xff1a;v5.3.19 文章目录 一、请求流程1、处理器映射器1.1、 RequestMappingHandlerMapping1.2、获取对应的映射方法1.3、添加拦截器 2、获取合适的处理器适配器3、通过处理器适配器执行处理器方法3.1、拦截器的前置后置3.2、处理器的执行3.2.1 参数…...

风辞远的科技茶屋:来自未来的信号枪

很久之前&#xff0c;有位朋友问我&#xff0c;现在科技资讯这么发达了&#xff0c;你们还写啊写做什么呢&#xff1f; 我是这么看的。最终能够凝结为资讯的那个新闻点&#xff0c;其实是一系列事情最终得出的结果&#xff0c;而这个结果又会带来更多新的结果。其中这些“得出”…...

MongoDB教程-8

ObjectId 在之前的所有章节中&#xff0c;我们一直在使用MongoDB的Object Id。在本章中&#xff0c;我们将了解ObjectId的结构。 ObjectId是一个12字节的BSON类型&#xff0c;具有以下结构-- 1. 前4个字节代表自unix epoch以来的秒数 接下来的3个字节是机器标识符 接下来的2…...

Redis 理论部分

前面写了很多redis项目&#xff0c;今天在通过redis的理论加深redis的了解&#xff0c;顺便做个总结 Redis 理论部分 1.redis 速度快的原因 纯内存操作单线程操作&#xff0c;避免频繁的上下文切换以及资源争用的问题&#xff0c;多线程需要占用更多的cpu资源采用非阻塞I/O多…...