编译链接专题第3篇-初识makefile中的伪目标

admin 2024年1月31日11:08:15评论8 views字数 2992阅读9分58秒阅读模式

前言

很多非科班出身的工程师对项目的编译链接其实是很不熟悉的(包括作者自己),但是如果我们想自己做项目或者从01实现一个项目,或者想要优化程序,或者要修改memory layout,或者要实现AUTOSAR架构下内存保护,编译链接是必不可少的知识。本着打破沙锅学到底的目的,我们决定从01实现一个Windows操作系统下基于AUTOSAR架构的编译环境,同时为了锻炼我们的代码能力,从01实现一个常用的数据结构库,如果有比较优秀的开源AUTOSAR代码也计划加入进去。计划手写整个工程的makefile使用make工具能直接编译工程,同时编写CMakeLists文件,支持CMake生成makefile文件来编译整个工程。

对编译链工具不熟悉的,可以参考这篇文章:https://blog.51cto.com/xiacaojun/5648507

编译链接专题第3篇-初识makefile中的伪目标

我们将使用的工具:

项目构建生成工具:CMake

编译链接专题第3篇-初识makefile中的伪目标

编译链接专题第3篇-初识makefile中的伪目标

项目构建工具:make

编译链接专题第3篇-初识makefile中的伪目标

编译链接专题第3篇-初识makefile中的伪目标

编译器:

Windosw: gcc/g++

编译链接专题第3篇-初识makefile中的伪目标

编译链接专题第3篇-初识makefile中的伪目标

编译链接专题第3篇-初识makefile中的伪目标

TC3xx: Green Hills (GHS)

关于WindowCMake入门安装请参考这篇文章:Windows下CMake的小白级入门使用教程(hello world)

专题文章:

编译链接专题第1篇-make和makefile介绍

编译链接专题第2篇-初识makefile结构

本文目录

编译链接专题第3篇-初识makefile中的伪目标

注:本文章引用了一些第三方工具和文档,若有侵权,请联系作者删除!

正文

1.思考一个问题

问题makefile中的目标究竟是什么?

make程序的设计初衷谈起,make程序是被设计用来编译C语言源代码的,一个项目或者工程里面C语言文件太多了,我们需要一个程序来自动的管理自动的编译,于是make就被设计出来了

在默认情况下:

-- make认为目标对应着一个文件

-- make比较目标文件和依赖文件的新旧关系,决定是否执行命令。

-- make文件处理作为第一优先级们,也就说在默认的情况下make认为一个目标对应一个文件。

2.看一个makfile代码

下面的代码又什么意义?

clean:  del *.o hello.out

在这个上下文当中,我们不希望clean是一个文件,我们希望clean是一个标签,clean这个目标当作一个标签来使用,我们执行make clean的时候,就是希望执行这个标签之下的这些命令。

#makefilehello.exe all : func.o main.o  gcc -o hello.exe func.o main.ofunc.o : func.c  gcc -o func.o -c func.cmain.o : main.c  gcc -o main.o -c main.cclean :  del *o hello.exe

注意main.cfunc.c参加专题第2篇文章《编译链接专题第2篇-初识makefile结构

build目录下只有源文件(没有.o中间文件和.exe可执行文件)的时候,执行make,然后再执行make clean.

make: 生成.o.exe文件

make clean: 删除.o.exe文件

编译链接专题第3篇-初识makefile中的伪目标

如果我们这样操作:build目录下只有源文件(没有.o中间文件和.exe可执行文件)的时候,执行make,然后创建一个clean的文件,然后再执行make clean

make: 生成.o.exe文件

new-item clean: 创建一个名为clean的文件

make clean: 想要删除.o.exe文件,make提示clean是最新的,所以clean之下的命令就不需要执行了

编译链接专题第3篇-初识makefile中的伪目标

这不是我们期望的结果,我们希望无论何时make clean都要删除.o和最终的.exe文件;make为啥有这种行为了?--因为在默认的情况下make认为自己是处理文件的,makefile里的每一个目标都应该对应着一个具体的文件,这个时候clean这个目标确实的对应了一个文件,所以说当make clean的时候,make程序发现clean文件时最新的,那就没有必要去执行del *.o hello.exe命令了

那么该如何解决这个问题了?

3.伪目标的引入

makefile中的伪目标

-- 通过.PHONY关键字声明一个伪目标

-- 伪目标不对应任何实际的文件

-- 不管伪目标的依赖是否更新,命令总是执行

伪目标的语法:先声明,后使用

本质:伪目标是make中特殊目标.PHONY的依赖

.PHONY : cleanclean:  Del *.o hello.out

修改makefile如下:

hello.exe all : func.o main.o  gcc -o hello.exe func.o main.ofunc.o : func.c  gcc -o func.o -c func.cmain.o : main.c  gcc -o main.o -c main.c.PHONY : clean  clean :  del *o hello.exe

clean文件存在的情况下,执行make命令后,能按我们想要的删除所有中间文件。

编译链接专题第3篇-初识makefile中的伪目标

4.伪目标的秒用

编译链接专题第3篇-初识makefile中的伪目标

Make rebuild的时候执行的就是cleanall目标下的命令,也就是先删除上一次生成的中间文件,在重新编译。

编译链接专题第3篇-初识makefile中的伪目标

5.技巧

技巧:绕开.PHONY关键字定义伪目标

原理:如果规则没有命令或者依赖,并且它的目标不是一个存在的文件名,在执行此规则时,目标总是会被认为是最新的。

clean : FORCES  del *.o hello.exeFORCE:

FORCE总是被认为是最新的,则clean就会一定被执行,就算makefile目录下有clean文件存在,也不会影响clean目标下的命令执行.

.PHONY关键字是标准make里面才有的关键字,换句话说,.PHONY关键字在GNU make里面是存在的,如果使用GNU的make,要定义伪目标则可以使用.PHONY关键字。但是如果使用的make不是标准的make,不是GNU的make,它没有.PHONY关键字,就可以使用这个技巧

hello.exe : func.o main.o  gcc -o hello.exe func.o main.ofunc.o : func.c  gcc -o func.o -c func.cmain.o : main.c  gcc -o main.o -c main.cclean : FORCE  del *.o hello.exeFORCE :

编译链接专题第3篇-初识makefile中的伪目标

6.小结

-- 默认情况下,make认为目标对应着一个文件。

-- .PHONY用于声明一个伪目标,伪目标不对应时机的文件。

-- 伪目标的本质是make中特殊目标.PHONY的依赖。

-- 使用伪目标可以模拟函数调用

7.使用CMake如何删除中间文件

我们通过编写Build.bat脚本来删除过程文件和目录。

@echo offREM save current directoryPUSHD .@if "%1" == "--clean" (echo Delete all object files and directories.rd build /s/q) else (@echo start buildmkdir buildcd buildcmake -G "MinGW Makefiles" ..makeecho end buildpauseREM restore original current directoryPOPD)

编译链接专题第3篇-初识makefile中的伪目标

参考资料:

1.狄泰软件唐老师课程

2.专业嵌入式软件开发书籍

End

原文始发于微信公众号(汽车电子嵌入式):编译链接专题第3篇-初识makefile中的伪目标

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月31日11:08:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   编译链接专题第3篇-初识makefile中的伪目标https://cn-sec.com/archives/2448687.html

发表评论

匿名网友 填写信息