动漫设计工作室网站制作公司,中文网站建设设计,个人网站可以做淘客,阜阳市城乡建设网站4.5自动构建make/Makefile4.5.1基本使用1示例2进一步解释3实践4最佳实践4.6练习#xff1a;进度条4.6.1倒计时4.6.2进度条version14.6.2进度条version24.7版本控制器Git4.7.1git操作1操作一次#xff0c;以后不愁2经典三件套3常用4版本回退4.7.2小结4.5自动构建m…4.5自动构建make/Makefile4.5.1基本使用1示例2进一步解释3实践4最佳实践4.6练习进度条4.6.1倒计时4.6.2进度条version14.6.2进度条version24.7版本控制器Git4.7.1git操作1操作一次以后不愁2经典三件套3常用4版本回退4.7.2小结4.5自动构建make/Makefile
make是⼀条命令Makefile是⼀个文件两个搭配使用完成项目自动化构建。
makefile带来的好处就是⸺“自动化编译”⼀旦写好只需要⼀个make命令整个⼯程完全自动编译极⼤的提高了软件开发的效率。
make是⼀个命令⼯具是⼀个解释makefile中指令的命令⼯具⼀般来说⼤多数的IDE都有这个命令⽐如Delphi的makeVisual C的nmakeLinux下GNU的make。
make命令和makefile文件——依赖关系和依赖方法
4.5.1基本使用
1示例
简述创建Makefile/makefile文件写入依赖关系和依赖方法通过make命令执行。
touch test.c
touch Makefile//test.c
#includestdio.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.c2进一步解释
//Makefile
test.exe:test.cgcc -o test.exe test.ctest.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.exemake会解析Makefile文件形成推导依赖关系的推导栈(依赖方法的集合)
依赖方法不存在就入栈推导成功就执行对应命令出栈
其实实现过程类似于函数递归的过程
3实践
//构建
test.exe:test.cgcc -o test.exe test.c//加上会禁止命令回显//清理
.PHONY:clean
clean:rm -f test.exe test.i test.s test.oPHONY假的伪造的
.PHONY用来修饰目标文件是一个伪目标.PHONY:修饰的伪目标总是被执行的。
总是被执行的原理是什么为什么gcc无法二次编译旧代码
首先我们知道可执行文件是文件拥有修改时间的属性而源文件是否需要被重新编译需要判断源文件修改时间和可执行文件的修改时间谁更新更接近当前时间而**.PHONY:可以让gcc或者对应的命令忽略MOD时间对比新旧。**
关于文件时间
stat 文件名
简记ACM时间
access文件访问时间
modify文件内容更改时间
change文件属性更改时间
了解
更改文件内容不仅会更新文件内容的时间还会更新文件属性的时间因为Mod时间也属于文件属性。
在对文件进行访问时并不是每次都会更新access时间。原因是查看文件会更新时间接着更新文件属性然后过程会刷新到磁盘磁盘属于外设效率比较低如果每当文件被访问时都会更新时间进行以上过程会导致OS整体的效率低下。所以为了提高效率会设置为当访问次数达到一定次数时1020次等才会更新时间。
结论
1依赖关系必须存在依赖文件列表可以为空
2依赖方法可以是任何shell命令
3clean目标只是利用make的自动推导能力执行了rm命令在构建工程的视角拦起来就是清理项目即删除不需要的临时建立的文件。
4make命令后面可以跟目标名之后解析推导对应的依赖关系和依赖方法
默认情况下make只会推导一条完整的推导链路默认只会推导第一个依赖关系对应的推导链。
5源文件发生更改才会重新编译
4最佳实践
//其实类似于宏替换
BINtest.exe
SRCtest.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删除
BINtest.exe
//SRC$(shell ls *.c)
SRC$(wildcard *c) //wildcard函数获取当前目录下的源文件
OBJ$(SRC:.c.o) //.c文件全部替换为.o文件
CCgcc //编译器
Echoecho
Rmrm -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。
到此我们就可以实现一个简单的倒计时
#includestdio.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
#includestdio.h
void progress_v1();cat progress.c
#includeprogress.h
#includestring.h
#includeunistd.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
#includeprogress.hint main()
{progress_v1();return 0;
}4.6.2进度条version2
cat progress.h
#includestdio.h
#includestring.h
#includeunistd.hvoid progress(double total, double current);cat progress.c
#includeprogress.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
#includeprogress.hdouble 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 --prettyoneline
查看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手动撤销麻烦易出错2git checkout – file_namexxx codexxx codexxx codexxx codexxx code
4.7.2小结
1git进行版本控制时通过同步记录变化信息来进行版本控制可以减少空间的消耗。
2git是一个去中心化的、分布式的版本控制器但是使用时还是以中心化的模式为主。