‍️代码的华尔兹:在 Makefile 的指尖上舞动自动化的诗篇

在这里插入图片描述

文章目录

  • 😶‍🌫️😶‍🌫️😶‍🌫️背景——一个优秀工程师必备技能😶‍🌫️😶‍🌫️😶‍🌫️
  • 一、🤩🤩快速了解make与Makefile核心思想🤩🤩
    • 1. 快速见一面
    • 2. 具体语法——Makefile
    • 3. 具体语法——make
  • 二、🥳🥳.PHONY原理解释🥳🥳
    • 1. ACM时间
    • 2. make对比时间
    • 3. 回到.PHONY
    • 4. Make 的智能编译机制的好处
  • 三、😴😴makefile会自行推导😴😴
    • 1. 现象分析——自行推导
    • 2. 原理解释
    • 3. Make 的默认工作流程
  • 四、❤️❤️必看!!!❤️❤️逐层深入构建万能通用Makefile模板❤️❤️
    • 1. 初代改进——.c到.o
    • 2. 二代进阶版本——类似宏定义
    • 3. ❤️❤️❤️! ! ! 最终版本——多文件通配 ! ! !❤️❤️❤️
    • 4. 适度扩展的语法
  • 👍👍👍总结: Makefile 的好处👍👍👍


😶‍🌫️😶‍🌫️😶‍🌫️背景——一个优秀工程师必备技能😶‍🌫️😶‍🌫️😶‍🌫️


关于 Makefile 的重要性

  1. Makefile 的掌握与工程能力
    是否会编写 Makefile,从某种程度上反映了一个人是否具备完成大型工程项目的能力。它不仅是一个编译文件,更是一种有效的项目管理工具。

  2. 工程中的文件管理与编译规则
    在工程项目中,源文件通常按类型、功能或模块组织在不同的目录中。Makefile 定义了一系列规则,指定文件的编译顺序与依赖关系,包括:

    • 哪些文件需要优先编译
    • 哪些文件需要重新编译
    • 更复杂的功能操作
  3. 自动化编译的优势
    Makefile 的最大优势在于实现“自动化编译”。一旦编写完成,仅需一个 make 命令,即可完成整个项目的自动编译,大大提高了开发效率。

  4. 工具支持
    Make 是一种解释 Makefile 指令的命令工具,广泛应用于各种 IDE,例如:

    • Delphi 的 make
    • Visual C++ 的 nmake
    • Linux 下的 GNU make

    因此,Makefile 已成为工程项目中的主流编译方法。

  5. Make 与 Makefile 的配合
    Make 是一条命令,而 Makefile 是一个配置文件。两者相互配合,可实现项目的自动化构建与高效管理。

在这里插入图片描述


一、🤩🤩快速了解make与Makefile核心思想🤩🤩

1. 快速见一面

问:make与Makefile是什么呢?
答:make是一个命令,Makefile是一个指令。
在这里插入图片描述


2. 具体语法——Makefile

Makefile 语法基础

  1. 依赖关系与依赖方法
    Makefile 的核心语法就是“依赖关系 + 依赖方法”。这两者决定了文件编译的顺序和方式。

    • 依赖关系:某个文件(称为“目标”)需要其他文件(称为“依赖”)准备好才能编译。例如,main.o: main.c utils.h 表示 main.o 依赖于 main.cutils.h。换句话说,在生成 main.o 之前,main.cutils.h 必须是最新的。
    • 依赖方法:告诉 Makefile 如何生成目标文件的具体指令。例如,gcc -c main.c -o main.o 指明如何生成 main.o 文件。Makefile 会执行这些方法来自动编译项目。
  2. .PHONY 的作用
    .PHONY 是 Makefile 中的一个特殊指令,用来定义“伪目标”,即它不会检查文件的时间戳,只会直接执行定义的命令。

    • 用法:比如 .PHONY: clean 表示 clean 是个伪目标。这样在执行 make clean 时,无论有没有名为 clean 的文件,Makefile 都会直接运行 clean 目标的命令,而不去判断文件是否最新。
    • 作用:让依赖方法始终被执行,而不受文件的更新情况影响。这在清理文件、初始化环境等操作中尤其有用。

以上,大家其实都不用看,J桑带大家把这些换成人话😉😉😉

我们生活中有这样的场景:
对于mytest来说:
在这里插入图片描述

对于这里clean来说:
在这里插入图片描述

这里.PHONY的作用是,它所修饰的clean是一个伪目标,所以clean被依赖的方法总是被执行。


3. 具体语法——make

make默认执行Makefile中第一个,也可以make后家对应的目标名(targetname),那么就执行对应的目标。
在这里插入图片描述

.PHONY的目标可以重复执行,不带.PHONY的目标只能执行一次:
在这里插入图片描述


二、🥳🥳.PHONY原理解释🥳🥳

1. ACM时间

我们使用stat命令可以看到一个文件的ACM时间:
在这里插入图片描述
stat 命令的输出中,我们可以看到文件的三个主要时间属性:

  1. Access Time(atime) - 访问时改变时间
    表示文件最后一次被读取的时间。任何对文件内容的读取(如打开文件查看)都会更新这个时间,但文件的属性和内容不会因此改变。A时间不是每一次访问都被修改,这样有效降低了IO,一般可能访问10次会做一次修改。

  2. Modify Time(mtime) - 修改内容改变时间
    表示文件内容最后一次被修改的时间。如果文件的内容发生变化(例如文件被编辑或写入新数据),mtime 就会更新。一般来说M时间变化了,代表文件被修改,而一般文件被修改,它的大小等等可能会变,因此C时间会跟着变化。

  3. Change Time(ctime) - 修改属性改变时间
    表示文件元数据最后一次被更改的时间。例如,修改文件的权限、所有者或文件名都会更新 ctime。注意,ctime 反映的是文件状态的变化,而不是文件内容的直接修改。


2. make对比时间

当你运行 make 时,Make 会检查源文件和生成的可执行文件的时间戳。工作流程如下:

  1. 初次执行
    在源文件和可执行文件都存在的情况下,Make 会对比它们的时间戳。如果源文件比可执行文件更新,说明源代码被修改过,Make 将重新编译生成可执行文件。

  2. 重复执行
    此时源文件如果没有被修改过,bin的时间比较新,他就不会去执行make(即没有更新),再次执行 make 时不会重新编译,节省了重复编译的时间。如果源文件被修改过了,源文件的时间就会更新,比bin的时间更新,因此就可以执行。

  3. 执行 make clean
    使用 make clean 时,定义的清理规则会删除生成的文件(如可执行文件、目标文件等),清理掉这些文件的时间戳记录。

  4. 重新生成可执行文件
    由于 make clean 删除了之前生成的可执行文件,再次执行 make 时,系统找不到这些文件,于是会重新编译并生成可执行文件。


通过这种时间戳的比对机制,make 实现了智能编译,即只在必要时重新编译文件,从而加快开发流程。

在这里插入图片描述


3. 回到.PHONY

make比较的是原文件与可执行程序的M时间,
因此,PHONY修饰的目标原理是忽略了时间的比较,它的方法总是被执行。

以下是优化后的内容,进一步阐明了 make 的时间戳比对机制和 .PHONY 的作用及好处:


4. Make 的智能编译机制的好处

  1. 避免不必要的编译,提升效率
    make 通过源文件和可执行文件的时间戳对比,判断哪些文件需要重新编译。这种机制确保只有在源文件发生更改时才会触发编译,从而节省时间、降低 CPU 和 I/O 资源消耗。

  2. 减少错误和不一致
    这种机制也降低了手动编译可能产生的版本不一致或遗漏文件更新的风险。编译流程变得更可靠,确保了最新的源代码得到正确的编译。


三、😴😴makefile会自行推导😴😴

1. 现象分析——自行推导

Makefile 能够自行推导多个依赖目标的生成步骤,使得我们可以从一份源文件自动构建出最终的可执行文件。例如,以下代码展示了从 test.c 文件逐步生成可执行文件 mytest 的过程:

我们有这样的依赖关系:
在这里插入图片描述

依赖关系会自动推导如下:
在这里插入图片描述

最终可以执行:
在这里插入图片描述


2. 原理解释

这种逐步生成的编译流程可以理解为依赖栈的原理make 会依次推导每个目标文件的依赖关系,将最底层的依赖按顺序编译生成最终的目标文件 mytest。过程如下:

  1. 查找依赖:当执行 make mytest 时,make 会检查 mytest 的依赖项(即 test.o)是否存在且最新。
  2. 向下递归:如果 test.o 不存在或不是最新,make 会检查 test.o 的依赖 test.s 是否存在且最新。
  3. 逐层构建:依次向下直到最底层的 test.c,按顺序执行编译命令:
    • test.c 生成 test.i(预处理)
    • test.i 生成 test.s(汇编代码生成)
    • test.s 生成 test.o(汇编)
    • test.o 最终生成 mytest(链接)
      在这里插入图片描述
      通过 make 的自动推导机制,我们可以通过依赖栈的形式按需生成目标文件,而无需手动编写每一步的命令。

以下是对内容的优化:


3. Make 的默认工作流程

当只输入 make 命令时,make 将按照默认方式执行以下步骤:

  1. 查找 Makefile 文件
    make 会在当前目录中寻找名为 Makefilemakefile 的文件。

  2. 定位第一个目标文件
    找到 Makefile 文件后,make 会将其中定义的第一个目标(target)文件作为最终的构建目标。例如,上例中,make 会将 myproc 作为最终生成的文件。

  3. 检查目标文件及依赖项时间
    如果 myproc 文件不存在,或者它依赖的文件(例如 myproc.o)有较新的修改时间,make 将执行 Makefile 中定义的命令来生成 myproc

  4. 递归生成依赖项
    如果 myproc 的依赖文件 myproc.o 不存在,make 会继续查找 myproc.o 的生成规则。这会递归地查找依赖,直到找到一个存在的文件或底层源文件,例如 .c 文件。

  5. 编译生成目标
    make 找到底层源文件(如 .c 文件)时,便会执行对应的命令来生成依赖文件,如 myproc.o,再继续编译生成最终目标 myproc

  6. 逐层查找依赖关系
    make 逐层检查和生成每一层的依赖,直到最终生成第一个目标文件。这种递归查找和编译依赖的过程类似于一个栈结构。

  7. 错误处理
    在查找或生成的过程中,如果某个关键文件缺失,make 会退出并报错。如果是执行命令时出现错误,例如编译失败,make 将跳过该命令继续查找其他依赖关系。

  8. 依赖关系管理
    make 只管理文件的依赖关系。如果在解析依赖关系时无法找到某个依赖文件,make 将终止工作,不会执行进一步的命令。

这种依赖机制让 make 仅在必要时重新编译文件,从而简化了构建流程,避免了重复编译,提高了效率。


四、❤️❤️必看!!!❤️❤️逐层深入构建万能通用Makefile模板❤️❤️

1. 初代改进——.c到.o

我们说使用上述iso逐步推导的方式太麻烦了,直接从test.cmytest也不方便,我们期望的是将所有的文件转换为.o,文件,在进行连接的时候,就是这些.o文件与库中的直接连接在一起,比较方便,因此,我们希望先将所有的.c文件变为.o文件。

在这里插入图片描述

在这里插入图片描述


2. 二代进阶版本——类似宏定义

# 二代代码
BIN = mytest
SRC = test.c
OBJ = test.o
CC = gcc
RM = rm -f$(BIN): $(OBJ)$(CC) $(OBJ) -o $(BIN)$(OBJ): $(SRC)$(CC) -c $(SRC) -o $(OBJ).PHONY: clean
clean:$(RM) $(BIN) $(OBJ)
  1. 变量定义

    BIN = mytest
    SRC = test.c
    OBJ = test.o
    CC = gcc
    RM = rm -f
    
    • BIN: 目标可执行文件的名称。
    • SRC: 源文件名称。
    • OBJ: 目标文件(编译后的中间文件)的名称。
    • CC: 编译器(gcc)。
    • RM: 用于删除文件的命令(rm -f)。
  2. 生成目标 $(BIN)

    $(BIN): $(OBJ)$(CC) $(OBJ) -o $(BIN)
    
    • 表示 $(BIN) 依赖于 $(OBJ)
    • 如果 $(BIN) 不存在或者 $(OBJ) 的修改时间比 $(BIN) 更新,则执行编译命令 gcc test.o -o mytest
  3. 生成目标 $(OBJ)

    $(OBJ): $(SRC)$(CC) -c $(SRC) -o $(OBJ)
    
    • 表示 $(OBJ) 依赖于 $(SRC)
    • 如果 $(OBJ) 不存在或 test.c 有更新,则执行 gcc -c test.c -o test.o 来生成目标文件 test.o
  4. 清理目标 clean

    .PHONY: clean
    clean:$(RM) $(BIN) $(OBJ)
    
    • .PHONY: clean 指定 clean 为伪目标,不与文件同名。
    • clean 目标用于删除生成的二进制文件和目标文件。

3. ❤️❤️❤️! ! ! 最终版本——多文件通配 ! ! !❤️❤️❤️

首先我们需要创建100个.c文件来模拟:
使用 {} 来一次性创建 100 个 .c 文件,可通过 touch{} 来批量创建文件:

touch file{1..100}.c

在这里插入图片描述

# 最终代码BIN = mytest  # 定义目标可执行文件的名称为 mytest
# SRC = $(shell ls *.c)  # 使用 shell 命令列出当前目录下的所有 .c 文件(已注释掉,改用 wildcard)
SRC = $(wildcard *.c)  # 使用 wildcard 函数获取当前目录下所有的 .c 文件,赋值给 SRC 变量
OBJ = $(SRC:.c=.o)  # 使用模式替换,将 SRC 中的每个 .c 文件名替换为对应的 .o 文件名,赋值给 OBJ 变量CC = gcc  # 定义使用的编译器为 gcc
RM = rm -f  # 定义删除文件的命令为 rm -f(强制删除)# 目标文件 $(BIN) 依赖于所有的目标文件 $(OBJ)
$(BIN): $(OBJ)@$(CC) $^ -o $@  # 编译命令,$^ 表示所有依赖文件(即 OBJ),$@ 表示目标文件(即 BIN)@echo "链接 $^ 成 $@"  # 输出编译链接的命令信息,$^ 表示依赖文件,$@ 表示目标文件# %.o: %.c 是一个模式规则,表示对于每个 .c 文件生成对应的 .o 文件
%.o: %.c@$(CC) -c $<  # 编译命令,$< 表示第一个依赖文件(即 .c 文件),$@ 表示目标文件(即 .o 文件)@echo "编译... $< 成 $@"  # 输出编译过程的命令信息,$< 表示 .c 文件,$@ 表示 .o 文件.PHONY: clean  # 声明 clean 为伪目标,避免与文件名冲突
clean:  # clean 目标用于清理编译生成的文件$(RM) $(BIN) $(OBJ)  # 使用 rm -f 命令删除可执行文件和目标文件
  • $(BIN): 表示目标文件(在这里是 mytest)。$@ 在命令中代表当前目标文件名。
  • $(OBJ): 表示目标文件的依赖(即 .o 文件)。$^ 在命令中表示所有的依赖文件。
  • $^: 在命令中表示所有的依赖文件(即所有 .o 文件)。
  • $@: 在命令中表示当前目标文件(例如 mytest)。
  • $<: 在命令中表示第一个依赖文件(例如 .c 文件)。
  • .PHONY: clean: 声明 clean 为伪目标,意味着 clean 不是文件名,而是一个命令目标,防止与实际的 clean 文件冲突。
  • @: 在命令前加 @,表示不输出执行命令本身,仅输出命令的结果。
  • $(wildcard *.c): 使用 wildcard 函数获取当前目录下所有 .c 文件名,并将其赋值给 SRC 变量。
  • $(SRC:.c=.o): 使用模式替换,将 SRC 中所有 .c 文件名替换为对应的 .o 文件名,赋值给 OBJ 变量。
  • $(shell ls *.c): 使用 shell 函数执行 ls *.c 命令来获取 .c 文件(虽然该行被注释掉,已用 wildcard 替代)。

4. 适度扩展的语法

BIN=proc.exe # 定义变量
CC=gcc
#SRC=$(shell ls *.c) # 采⽤shell命令⾏⽅式,获取当前所有.c⽂件名
SRC=$(wildcard *.c) # 或者使⽤ wildcard 函数,获取当前所有.c⽂件名
OBJ=$(SRC:.c=.o) # 将SRC的所有同名.c 替换 成为.o 形成⽬标⽂件列表
LFLAGS=-o # 链接选项
FLAGS=-c # 编译选项
RM=rm -f # 引⼊命令
$(BIN):$(OBJ)
@$(CC) $(LFLAGS) $@ $^ # $@:代表⽬标⽂件名。 $^: 代表依赖⽂件列表
@echo "linking ... $^ to $@"
%.o:%.c # %.c 展开当前⽬录下所有的.c。 %.o: 同时展开同
名.o
@$(CC) $(FLAGS) $< # %<: 对展开的依赖.c⽂件,⼀个⼀个的交给gcc。
@echo "compling ... $< to $@" # @:不回显命令
.PHONY:clean
clean:
$(RM) $(OBJ) $(BIN) # $(RM): 替换,⽤变量内容替换它
.PHONY:test
test:
@echo $(SRC)
@echo $(OBJ)

👍👍👍总结: Makefile 的好处👍👍👍

Makefile 的好处包括:

  1. 自动化构建:通过定义规则,Makefile 可以自动化编译、链接等过程,节省手动操作时间。

  2. 增量编译:Makefile 会根据文件的修改时间自动判断哪些文件需要重新编译,避免重复编译未修改的文件,提高效率。

  3. 简化管理复杂项目:对于有多个源文件的项目,Makefile 可以统一管理文件的依赖关系,避免手动处理每个文件,减少错误。

  4. 跨平台支持:Makefile 是跨平台的构建工具,支持在多种操作系统和环境中使用,如 Linux、macOS 和 Windows。

  5. 灵活性和可扩展性:可以根据项目的需要灵活地定义不同的构建规则,处理各种需求,如清理临时文件、执行测试等。

  6. 易于维护:集中管理构建命令和依赖关系,使得构建过程清晰明了,便于团队协作和后期维护。

  7. 支持并行构建:在支持的环境下,Makefile 可以并行执行多个任务,加速大规模项目的构建过程。

  8. 简化团队协作:通过共享 Makefile,团队成员可以确保一致的构建流程和规范,减少人为差错。

总的来说,Makefile 提供了一种高效、灵活、易于维护的自动化构建方式,尤其适用于大型和复杂的项目。


那么到这里,make与Make的内容就结束啦,欢迎大家交流讨论~~~😘😘😘

创作不易,J桑求各位大大一个一键三连,谢谢各位大佬 ! ! !

在这里插入图片描述

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

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

相关文章

SpringBoot中使用Thymeleaf模板引擎

和使用freemarker差不多的方式 1、导入thymeleaf的启动器 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> 2、编写Controller类 3、编写模板页面 注…

vue之子组件向父组件传值

参考博客先挂上 vue3中子传父&#xff08;emit&#xff09;、父传子&#xff08;props&#xff09;一篇文章拿下第一次写文章&#xff0c;告诉你vue3中如何实现父子相传&#xff0c;一篇文章帮 - 掘金 父组件通过 props 向子组件传值 1.子组件使用 $emit 触发事件 2.在父组件…

第26天 安全开发-PHP应用模板引用Smarty渲染MVC模型数据联动RCE安全

时间轴&#xff1a; 演示案例 新闻列表&模板引用-代码RCE安全 知识点 1、PHP 新闻显示-数据库操作读取显示 2、PHP 模版引用-自写模版&Smarty 渲染 3、PHP 模版安全-RCE 代码执行&三方漏洞 新闻列表 1.数据库创建新闻存储 2.代码连接数据库读取 3.页面进行自定…

【微服务】Docker 容器化

一、初识Docker 1. 为什么需要 Docker 大型项目组件较多&#xff0c;运行环境也较为复杂&#xff0c;部署时会遇到一些问题&#xff1a; 依赖关系复杂&#xff0c;容易出现兼容性的问题开发、测试、生产环境有差异 Docker 如何解决依赖的兼容问题 将应用的Libs&#xff08;…

(十四)JavaWeb后端开发——MyBatis

目录 1.MyBatis概述 2.MyBatis简单入门 3.JDBC&#xff08;了解即可&#xff09; 4.数据库连接池​ 5.lombok 6.MyBatis基本操作 7.XML映射文件 8.动态SQL 8.1 if标签 8.2 foreach标签 8.3 sql/include标签​ 1.MyBatis概述 MyBatis是一款优秀的持久层&#xff08…

pytorch实现深度神经网络DNN与卷积神经网络CNN

DNN概述 深度神经网络DNN来自人脑神经元工作的原理&#xff0c;通过在计算机中逻辑抽象出多个节点&#xff0c;接收处理并向后传递信息&#xff0c;实现计算机的自我学习&#xff0c;类比结构见下图&#xff1a; 该方法通过预测输出与实际值的差异不断调整节点参数&#xff0…

私域流量圈层在新消费时代的机遇与挑战:兼论开源 AI 智能名片、2 + 1 链动模式、S2B2C 商城小程序的应用

摘要&#xff1a;本文剖析了私域流量圈层在新消费时代呈现出的独特温度与信任优势&#xff0c;阐述了从传统销售到新消费转型中用户心理的变化。同时&#xff0c;强调了内容对于私域流量的关键作用&#xff0c;并分析开源 AI 智能名片、2 1 链动模式、S2B2C 商城小程序在私域流…

1.4 配置 Android 构建系统

Android 构建系统会编译应用资源和源代码&#xff0c;然后将它们打包成 APK 或 Android App Bundle 文件&#xff0c;供您测试、部署、签名和分发。 创建自定义 build 配置需要您对一个或多个 build 配置文件做出更改。这些纯文本文件使用领域特定语言 (DSL) 通过 Kotlin 脚本&…

containerd配置私有仓库registry

机器ip端口regtisry192.168.0.725000k8s-*-------k8s集群 1、镜像上传 rootadmin:~# docker push 192.168.0.72:5000/nginx:1.26.1-alpine The push refers to repository [192.168.0.72:5000/nginx] 6961f0b8531c: Pushed 3112cd521249: Pushed d3f50ce9b5b5: Pushed 9efaf2eb…

ABAP:SET CURSOR FIELD设置鼠标焦点

SET CURSOR FIELD <字段名>&#xff1a;设置鼠标焦点到该字段 SET CURSOR 设置到鼠标焦点列还是行 SET CURSOR LINE 设置鼠标焦点到行 GET CURSOR field <字段名> &#xff1a;这个相对应的获取鼠标焦点得到的字段

PHP和Python脚本的性能监测方案

目录 1. 说明 2. PHP脚本性能监测方案 2.1 安装xdebug 2.2 配置xdebug.ini 2.3 命令行与VS Code中使用 - 命令行 - VS Code 2.4 QCacheGrind 浏览 3. Python脚本性能监测方案 3.1 命令行 4. 工具 5.参考 1. 说明 获取我们的脚本程序运行时的指标&#xff0c;对分析…

VS code 远程连接到docker容器

1.需要在vscode中下载remote 、docker、dev container插件。 如下图&#xff1a; 有小鲸鱼标志&#xff0c;说明已经成功。 右键可以运行或者停止容器运行

阿里1688 阿里滑块 231滑块 x5sec分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我删…

Spring Validation数据校检

文章目录 Spring Validation1 关于Spring Validation2 使用流程3 快速入门4 运行异常处理4.1 说明4.2 处理异常4.3 明确提示消息 5 常用注解5.1 NotNull注解5.2 NotEmpty 注解5.3 NotBlank 注解5.4 Size 注解5.5 Range 注解 6 非POJO参数校验6.1 使用流程6.2 使用示例 Spring V…

‌STAR法则

一&#xff1a;STAR法则 STAR法则是一种简单而实用的表现技巧&#xff0c;常被用于求职过程中的个人经历描述&#xff0c;富有条理性&#xff0c;可以帮助你在职场中脱颖而出。“STAR”分别对应的是situation-task-action-result&#xff0c;通过情境、目标、行动和结果四个方面…

uniapp—android原生插件开发(1环境准备)

本篇文章从实战角度出发&#xff0c;将UniApp集成新大陆PDA设备RFID的全过程分为四部曲&#xff0c;涵盖环境搭建、插件开发、AAR打包、项目引入和功能调试。通过这份教程&#xff0c;轻松应对安卓原生插件开发与打包需求&#xff01; 项目背景&#xff1a; UniApp集成新大陆P…

国标GB28181设备管理软件EasyGBS国标GB28181视频平台:GB/T28181中的流类型

在当今的视频监控领域&#xff0c;GB/T28181协议作为中国国家标准委员会发布的重要技术规范&#xff0c;发挥着举足轻重的作用。这一标准不仅为视频监控系统的设备接入、视频流传输、设备控制等功能提供了明确的技术指导&#xff0c;还极大地促进了不同厂家设备之间的兼容性和互…

使用pip安装项目时,遇到以下错误的解决方案:error: [Errno 13] Permission denied

我是在虚拟环境下出现了这个错误 出现这种情况大概率是conda环境没有下载用户路径下的python解释器&#xff0c;你可以使用下面命令来检查 which python3这里如果出现的路径不是你用户目录下的&#xff0c;就是这个原因&#xff0c;你的conda环境在用户目录下&#xff0c;但是…

无人车之定位技术篇

无人车的定位技术是指确定无人车在世界坐标系&#xff08;一般指二维环境&#xff09;中的位置及其本身的姿态的技术。随着技术的不断发展&#xff0c;无人车的定位技术已经实现了多种方法的融合与创新。 一、主要定位技术 GPS定位 原理&#xff1a;基于全球定位系统&#x…

微观经济学速成笔记

需求的收入弹性 需求的收入弹性表示在一定的时期内消费者对某种商品的需求量的变动对于消费者收入量变动的反应程度,供给的收入弹性公式为: 永非证可eM或w-此公-可 根据商品的需求和收入弹性公式&#xff0c;可以将商品分类: em < 0的商品为劣等品(也称低档品)&#xff0c;因…