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

四,基础开发工具(下)

    • 4.5自动构建make/Makefile
      • 4.5.1基本使用
        • 1示例
        • 2进一步解释
        • 3实践
        • 4最佳实践
    • 4.6练习:进度条
      • 4.6.1倒计时
      • 4.6.2进度条version1
      • 4.6.2进度条version2
    • 4.7版本控制器Git
      • 4.7.1git操作
        • 1操作一次,以后不愁
        • 2经典"三件套"
        • 3常用
        • 4版本回退
      • 4.7.2小结

4.5自动构建make/Makefile

make是⼀条命令,Makefile是⼀个文件,两个搭配使用,完成项目自动化构建。

makefile带来的好处就是⸺“自动化编译”,⼀旦写好,只需要⼀个make命令,整个⼯程完全自动编译,极⼤的提高了软件开发的效率。

make是⼀个命令⼯具,是⼀个解释makefile中指令的命令⼯具,⼀般来说,⼤多数的IDE都有这个命令,⽐如:Delphi的make,Visual C++的nmake,Linux下GNU的make。

make命令和makefile文件——依赖关系和依赖方法

4.5.1基本使用

1示例

简述:创建Makefile/makefile文件,写入依赖关系和依赖方法,通过make命令执行。

touch test.c
touch Makefile//test.c
#include<stdio.h>
int main()
{printf("hello world!\n");return 0;
}//Makefile
test.exe:test.c            //依赖关系,test.exe依赖test.cgcc -o test.exe test.c //依赖方法,test.c形成test.exemake
./test.c
2进一步解释
//Makefile
test.exe:test.cgcc -o test.exe test.c

test.exe是目标文件

test.c等是依赖文件列表

依赖关系,test.exe依赖test.c

依赖方法,test.c形成test.exe

二者共同构建可执行目标文件的语义。

形成可执行文件的过程:

//Makefile
test.exe:test.ogcc test.o -o test.exe
test.o:test.sgcc -c test.s -o test.o
test.s:test.igcc -S test.i -o test.s
test.i:test.cgcc -E test.c -o test.i//执行make后
gcc -E test.c -o test.i
gcc -S test.i -o test.s
gcc -c test.s -o test.o
gcc test.o -o test.exe

make会解析Makefile文件,形成推导依赖关系的推导栈(依赖方法的集合)

依赖方法不存在就入栈,推导成功就执行对应命令出栈

(其实实现过程类似于函数递归的过程)

3实践
//构建
test.exe:test.c@gcc -o test.exe test.c//加上@会禁止命令回显//清理
.PHONY:clean
clean:@rm -f test.exe test.i test.s test.o

PHONY:假的,伪造的

.PHONY:用来修饰目标文件是一个伪目标,.PHONY:修饰的伪目标总是被执行的。

总是被执行的原理是什么?为什么gcc无法二次编译旧代码?

首先我们知道可执行文件是文件,拥有修改时间的属性,而源文件是否需要被重新编译,需要判断源文件修改时间和可执行文件的修改时间谁更新,更接近当前时间;而**.PHONY:可以让gcc或者对应的命令,忽略MOD时间对比新旧。**

关于文件时间:

stat 文件名在这里插入图片描述

(简记ACM时间)

access:文件访问时间

modify:文件内容更改时间

change:文件属性更改时间

了解:

更改文件内容不仅会更新文件内容的时间,还会更新文件属性的时间,因为Mod时间也属于文件属性。

在对文件进行访问时,并不是每次都会更新access时间。原因是:查看文件会更新时间,接着更新文件属性,然后过程会刷新到磁盘(磁盘属于外设,效率比较低),如果每当文件被访问时都会更新时间进行以上过程,会导致OS整体的效率低下。所以为了提高效率会设置为当访问次数达到一定次数时(10,20次等)才会更新时间。

结论

1,依赖关系必须存在,依赖文件列表可以为空

2,依赖方法可以是任何shell命令

3,clean目标,只是利用make的自动推导能力,执行了rm命令,在构建工程的视角,拦起来就是清理项目,即删除不需要的临时建立的文件。

4,make命令,后面可以跟目标名,之后解析推导对应的依赖关系和依赖方法,

默认情况下make只会推导一条完整的推导链路,默认只会推导第一个依赖关系对应的推导链。

5,源文件发生更改才会重新编译!

4最佳实践
//其实类似于宏替换
BIN=test.exe
SRC=test.c$(BIN):$(SRC)@echo "编译开始"@gcc -o $@ $^      @echo "编译完成"
.PHONY:clean
clean:@echo "清理开始..."@rm -f $(BIN)@echo "清理完成..."

问题:如果有多个文件,怎么高效编译?

touch src{1..100}.c该命令意义是创建100个.c后缀文件命名为src1.c、src14.c等

rm src{1..100}.c删除

BIN=test.exe
//SRC=$(shell ls *.c)
SRC=$(wildcard *c)	//wildcard函数获取当前目录下的源文件
OBJ=$(SRC:.c=.o)	//.c文件全部替换为.o文件
CC=gcc				//编译器
Echo=echo
Rm=rm -f$(BIN):$(OBJ)	//.o文件链接形成可执行文件@$(CC) -o $@ $^
%.o:%.c@$(CC) -c $<.PHONY:clean
clean:@$(Rm) $(OBJ) $(BIN).PHONY:test
test:@$(Echo) "------"@$(Echo) $(SRC) @$(Echo) "------"@$(Echo) $(OBJ) @$(Echo) "------"

至此我们就完成了基本可以通用的Makefile文件。

4.6练习:进度条

4.6.1倒计时

回车和换行是两个不同的操作。

回车\r 换行\n

printf("hello world\r\n");
sleep(2);
//现象:先打印后休眠printf("hello world");
sleep(2);
//现象:先休眠后打印

在sleep期间,print函数已经执行完了,hello world此时被缓存到内存空间中了,没有打印到显示器,等到程序结束时,会自动刷新。刷新方式,以行为方式刷新,\r\n或者\n。

到此我们就可以实现一个简单的倒计时

#include<stdio.h>#define COUNT 15int main()
{int cnt = COUNT;while(cnt >= 0){printf("%-2d\r",cnt);fflush(stdout);  sleep(1);--cnt;}printf("\n");return 0;
}

4.6.2进度条version1

首先展示一下最后的效果图:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

实现的主要步骤与刚才练习的倒计时是相似的,主要是回车以及刷新缓冲区的操作。

cat progress.h

#pragma once
#include<stdio.h>
void progress_v1();

cat progress.c

#include"progress.h"
#include<string.h>
#include<unistd.h>#define NUM 101
#define STYLE '-'
const char *lable="|/-\\";void progress_v1()
{char buffer[NUM];memset(buffer,0,sizeof(buffer));int cnt = 0;while(cnt <= 100){int len = strlen(lable);printf("[%-100s][%d%%][%c]\r",buffer,cnt,lable[cnt%len]);fflush(stdout);buffer[cnt] = STYLE;++cnt;usleep(500000);}
}

cat main.c

#include"progress.h"int main()
{progress_v1();return 0;
}

4.6.2进度条version2

cat progress.h

#include<stdio.h>
#include<string.h>
#include<unistd.h>void progress(double total, double current);

cat progress.c

#include"progress.h"#define NUM 101
#define STYLE '-'void progress(double total, double current)
{if(current > total)current = total;char buffer[NUM];memset(buffer,0,sizeof(buffer));const char *lable = "|/-\\";int len = strlen(lable);static int index = 0;double rate = current / total * 100;int num = (int)(rate);int i = 0;for(; i < num; i++){buffer[i] = STYLE;}printf("[%-100s][%.1lf%%][%c]\r", buffer, rate, lable[index++]);index %= len;fflush(stdout);if(current >= total){//printf("\n");printf("[%-100s][%.1lf%%][%c]\r", buffer, 100.0, lable[index++]);}
}

cat main.c

#include"progress.h"double total = 800.0;
double speed = 3.4;void DownLoad()
{double current = 0;while(current <= total){progress(total, current);usleep(3000);current += speed;}// 循环结束后,确保显示100%progress(total, total);printf("\ndownload %.2lfMB Done\n", current);
}int main()
{DownLoad();//progress(total, current);return 0;
}

4.7版本控制器Git

Git可以控制电脑上所有格式的文件,例如doc、excel、dwg、dgn、rvt等等。对于我们开发人员来说,Git最重要的就是可以帮助我们管理软件开发项目中的源代码文件!

4.7.1git操作

1操作一次,以后不愁

安装:yum install -y git

查看版本:git --version

初始化本地仓库:git init

注意:千万不要在一个git仓库里面再执行 git init,这会创建嵌套的仓库,会导致各种问题。

配置本地仓库:name和email

git config user.name “用户名”

git config user.email “邮箱名”

免密码push:执行git config --global credential.helper store

之后进行一次push操作,输入用户名和密码即可

查看配置项:git config -l

删除配置项:git config --unset user.name

所有的git仓库设置git config --global user.name "用户名"

2经典"三件套"

添加指定文件:git add 文件名

添加所有文件到暂存区:git add .

提交本地:git commit -m "提交日志"

同步远端:git push

3常用

查看历史提交记录:git log

git log --pretty=oneline

查看git状态:git status

远端同步到本地:git pull

git pull的本质:提交自己的代码之前,必须把别人历史提交的代码同步到本地。

克隆现有的远程仓库到本地:git clone 远程仓库URL

查看远程仓库名:git remote

查看远程仓库详细信息:git remote -v

git diff 命令用于比较 Git 管理的代码在不同版本、不同区域之间的差异。它会以行-by-行的形式告诉你哪些内容被添加(+)、删减(-)或修改了。

4版本回退
工作区暂存区版本库指令
是否回退git reset --soft
是否回退git reset --mixed(默认选项)
是否回退git reset --hard(谨慎使用)

原因:hard选项会回退所有版本包括工作区未提交的代码,所以需要谨慎使用!!

将工作区回退到最近一次add的版本:git checkout -- 文件名

工作区暂存区版本库解决方式
xxx code1,手动撤销(麻烦易出错)2,git checkout – file_name
xxx codexxx code
xxx codexxx codexxx code

4.7.2小结

1,git进行版本控制时,通过同步记录"变化"信息来进行版本控制,可以减少空间的消耗。

2,git是一个去中心化的、分布式的版本控制器,但是使用时还是以中心化的模式为主。


文章转载自:

http://qOfRDF5X.bgnbr.cn
http://TYfBCuod.bgnbr.cn
http://ydxEl0GW.bgnbr.cn
http://61uoZXzU.bgnbr.cn
http://vcdkF769.bgnbr.cn
http://KO9UQYVB.bgnbr.cn
http://i5SeCwYj.bgnbr.cn
http://tsoEatjD.bgnbr.cn
http://uGzMwHHj.bgnbr.cn
http://GfkyiSj3.bgnbr.cn
http://479uyQU7.bgnbr.cn
http://6cifNmlw.bgnbr.cn
http://60EXhCCP.bgnbr.cn
http://eD6rAsgD.bgnbr.cn
http://nlwynimQ.bgnbr.cn
http://rI5sI5PM.bgnbr.cn
http://D5W7SgL5.bgnbr.cn
http://wdx6ruAs.bgnbr.cn
http://l4Q3kYmL.bgnbr.cn
http://rUTFVYdS.bgnbr.cn
http://7Rbs6WVY.bgnbr.cn
http://Bl96LlxM.bgnbr.cn
http://VWfNu0DV.bgnbr.cn
http://acqSfstV.bgnbr.cn
http://VfWFC9YK.bgnbr.cn
http://GmfTN78n.bgnbr.cn
http://USW4ZuTb.bgnbr.cn
http://bl2u3StY.bgnbr.cn
http://qX6Er2QW.bgnbr.cn
http://LSE7KNqB.bgnbr.cn
http://www.dtcms.com/a/378814.html

相关文章:

  • Docker+jenkinsPipeline 运行实现python自动化测试
  • Android图案解锁绘制
  • 分布式事务性能优化:从故障现场到方案落地的实战手记(一)
  • JVM第一部分
  • websocket和socket io的区别
  • codebuddy ai cli安装教程
  • MySQL5.7.44保姆级安装教程
  • 正则表达式基础
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘pandas-profiling’问题
  • GRPOConfig中参数num_generations
  • 电源线束选型
  • 系统稳定性保障:研发规约V1.0
  • Day13 | Java多态详解
  • hbuilderx配置微信小程序开发环境
  • opc ua c#订阅报错【记录】
  • Caffeine 本地缓存最佳实践与性能优化指南
  • MySQL 高级特性与性能优化:深入理解函数、视图、存储过程、触发器
  • Java常见排序算法实现
  • 生产环境禁用AI框架工具回调:安全风险与最佳实践
  • Git - Difftool
  • leetcode28( 汇总区间)
  • 直击3D内容创作痛点-火山引擎多媒体实验室首次主持SIGGRAPH Workshop,用前沿技术降低沉浸式内容生成门槛
  • 鸿蒙next kit 卡片引入在线|本地图片注意事项
  • 学习番外:Docker和K8S理解
  • Leetcode 刷题记录 21 —— 技巧
  • 卷积神经网络CNN-part5-NiN
  • 散斑深度相机原理
  • 中元的星问
  • 使用 NumPy 读取平面点集并分离列数据
  • uni-app + Vue3 开发展示 echarts 图表