linux下make的使用,写一个自己的Makefile

学会编写Makefile很重要,因为在Linux的环境下要编译C语言程序要使用gcc命令,但是工程中的文件较多时,手动的执行gcc命令很麻烦也很容易出粗,所以学会Makefile的使用可以让我们在以后的linux学习中一劳永逸。

首先我们创建一个文件夹当做我们本次的工程。

进入learnMakefile,生成.c文件和.h文件。

main.c

linux下make的使用,写一个自己的Makefile_第1张图片

print.c

linux下make的使用,写一个自己的Makefile_第2张图片 

print.h

linux下make的使用,写一个自己的Makefile_第3张图片

现在有了三个文件,开始编写我们的Makefile。

 :前面是目标生成文件,:后面是生成目标文件的依赖文件。比如main是目标生成文件,main.o和print.o都是依赖文件。clean命令用于清空编译时生成的.o文件,前面加.PHONY是因为如果文件夹中如果有个文件名叫clean的话会出现错误,用了之后的clean相当于伪命令。

  1 main:main.o print.o
  2     gcc main.o print.o
  3 main.o:main.c print.h
  4     gcc -c main.c
  5 print.o:print.c print.h
  6     gcc -c print.c
  7 .PHONY:clean
  8 clean:
  9     rm -f main.o print.o

编写完成后输入make来执行Makefile文件。  

linux下make的使用,写一个自己的Makefile_第4张图片 

 可以看到执行了make命令后,执行了一系列编译,生成了许多.o文件和a.out执行文件,执行a.out输出hello,说明我们的makefile是正确的。执行make clean来删除刚刚生成的.o和可执行文件。

 这样写的makefile可以使用,但是如果再加几个.c文件我们需要对Makefile进行比较大的改动,现在使用自动化变量来对其进行简化。

  1 main:main.o print.o
  2     gcc $^
  3 main.o:main.c print.h
  4     gcc -c main.c
  5 print.o:print.c print.h
  6     gcc -c print.c
  7 .PHONY:clean
  8 clean:
  9     rm -f main.o print.o

 仅仅第二行改变了,但是效果是一样的,$^这里指的是所有的依赖文件就是main.o和print.o。

后面再引入我们定义的变量来进一步简化,引用自己的变量格式是$(变量名)

  1 ELF=main
  2 object=main.o print.o
  3 $(ELF):$(object)
  4     gcc $^ -o $@
  5 main.o:main.c print.h
  6     gcc -c main.c
  7 print.o:print.c print.h
  8     gcc -c print.c
  9 .PHONY:clean
 10 clean:
 11     rm -f $(object) main a.out

ELF是为了方便以后更改生成的可执行文件的名称,gcc -o就是可以指定生成可执行文件的名称,不指定的话就是默认生成a.out文件。 $@也是自动化变量,他指的是目标文件,这里我们已经指定了生成目标文件的名称是main。变量object存的是我们依赖文件,这样以后要加文件时只需要在object中加就可以了,很方便。下面是运行结果(可以看到生成了.o文件和main可执行文件):  

linux下make的使用,写一个自己的Makefile_第5张图片 

 第5-8行还是很多余,继续进行简化。

  1 ELF=main
  2 object=main.o print.o
  3 $(ELF):$(object)
  4     gcc $^ -o $@
  5 main.o:print.h
  6 print.o:print.h
  7 .PHONY:clean
  8 clean:
  9     rm -f $(object) main a.out

他还是可以运行成功的,为什么要删到只剩5.6行呢,因为make有自动推导的功能,可以根据目标文件推到出要依赖的文件。其实后面的.h还是可以简化:

  1 ELF=main
  2 object=main.o print.o
  3 $(ELF):$(object)
  4     gcc $^ -o $@
  5 $(object):
  6 .PHONY:clean
  7 clean:
  8     rm -f $(object) main a.out

前面的object已经包含了那两个目标文件所以直接第5行代替。

这样虽然很简单了,但是我们还要手动的输入object变量的结果,不能一劳永逸,所以还可以更简化。使用make中的函数wildcard自动推导出工程中的.c文件,在使用$(SRC:.c=.o)把SRC得到的.c文件都改名为.o文件,执行make还是成功的。除了wildcard函数当然也可以使用SHELL命令来找出所有的.c文件,比如ls *.c或者find *.c,写在Makefile的格式是$(shell ls *.c)或$(shell find *.c)。

  1 SRC=$(wildcard *.c)
  2 ELF=main
  3 object=$(SRC:.c=.o)
  4 $(ELF):$(object)
  5     gcc $^ -o $@
  6 $(object):
  7 .PHONY:clean
  8 clean:
  9     rm -f $(object) main a.out

这样以来已经可以说是最简化了,但是还有一个问题,无论是函数wildcard还是shell命令ls、find只能找到同一个目录下的.c文件,但是实际做工程的时候都是多目录,这样肯定会出错。

我们来试试:创建一个文件夹aaa把print.c(也要拷贝一份print.h放入aaa文件夹)文件放入。

linux下make的使用,写一个自己的Makefile_第6张图片

已经放入回到Makefile的目录,执行make会报错 :

linux下make的使用,写一个自己的Makefile_第7张图片

 现在如何解决呢,也很简单,继续用shell命令find,find可以在当前文件夹和子文件夹中查找,更改后的Makefile:

  1 SRC=$(shell find -name '*.c')
  2 ELF=main
  3 object=$(SRC:.c=.o)
  4 $(ELF):$(object)
  5     gcc $^ -o $@
  6 $(object):
  7 .PHONY:clean
  8 clean:
  9     rm -f $(object) main a.out

注意:*.c要使用''括起来,把print.h给aaa也拷贝一份上面忘记了。

linux下make的使用,写一个自己的Makefile_第8张图片

可以看到也是正确运行。我们试着再加一个.c文件,看看是否能一劳永逸。 

linux下make的使用,写一个自己的Makefile_第9张图片

又加了一个aaa.c文件还是打印hello,可以看到还是正确的,正阳这个makefile就实现了一次编写多次使用。这只是简单的使用make工具,可以看看uboot的Makefile,很复杂。 

你可能感兴趣的:(linux,linux)