make和makefile

概念

make 是一个应用程序

  • 解析源程序之间的依赖关系
  • 根据依赖关系自动维护编译工作
  • 直行宿主操作系统中的各种命令

makefile 是一个描述文件

  • 定义一系列的规则来制定源文件编译后的先后顺序
  • 拥有特定的语法规则,支持函数定义和函数调用
  • 能够直接集成操作系统中的各种命令

make makefile之间的关系

  • make makefile 中描述用于指导make 程序如何完成工作

  • make根据makefile中的规则执行命令,最后完成编译输出

makefile入门

2.1.1 简单示例

make的示例

  

注意:

  目标后的命令需要用Tab键(不是四个空格)隔开

hello : 
    echo "hello makefile"

make的使用示例

make  -f mf.txt hello

功能说明:

  以hello为关键字作为目标查找mf.txt文件并指令hello处的命令

结果:

echo "hello makefile"
hello makefile

第一行是make 要直行的命令 第二行是结果。

2.1 helloworld

  在linux中直行sudo vim makefile 回车

  在文件中输入

hello : 
    echo "hello makefile"

  然后打开底行模式,输入wq!退出直行

1 make hello
2 make 

第一行的功能说明:

  以hello为关键字作为目标查找makefile或makefile文件,并且直行hello处的命令

第一行的功能说明: 

  查找makefile 或者makefile文件中最顶层目标,并执行最顶层目标的命令

结果:

  两种方法此makefile的结果自然是一样的

1 hello : 
2     echo "hello makefile"
3     
4 test : 
5     echo "test"
6     pwd
7     ls

执行

1 make
2 make hello
3 make test

观察结果

2.2 初识makefile的结构

makefile的意义

  makefile 用于定义源文件间的依赖关系

  makefile  说明如何编译各个源文件并生成可执行文件

依赖的定义

 makefile中的元素含义

  • targets 通常是需要生成的目标文件名 make 所需执行的命令名称
  • prerequisities 当前目标所依赖的其他目标或者文件
  • command 完成目标所需要执行的命令

     规则中的注意事项

  • targets 可以包含多个目标 使用空格对多个目标名进行分隔
  • prerequisities 可以包含多个依赖,使用空格对多个依赖进行分隔
  • [tab]键 :‘ ’ 每个命令行必须以[tab]字符开始,[tab]字符告诉make此行是一个命令行
  • 续行符: 可以姜内容分开写到下一行,提高可读性

示例1

1 hello :test
2     echo "hello"
3 test :
4     echo "test"

结果实现打印 test hello的依赖是test,所以先执行test,test 没有依赖 所以执行对应的命令

依赖规则:

  • 当目标对应的文件不存在,执行对应命令
  • 当依赖在时间上比目标新,执行对应命令
  • 当依赖关系发生时,对比依赖上的每一个目标 

技巧:makefile中可以在命令前加上@符号,作用位命令无回显

示例2

 1 //func.c
 2 
 3 #include<stdio.h>
 4 
 5 void func()
 6 {
 7      printf("func 
"); 
 8      return ;      
 9 }
10 
11 //main.c
12 
13 #include<stdio.h>
14 
15 int main()
16 {
17     func();
18      printf("main
"); 
19      return 0;      
20 }  

如上,我们目前有了两个.c文件

1 hello.out : main.o func.o
2     gcc -o hello.out main.o func.o
3 main.o : main.c
4     gcc -o main.o main.c
5 func.o : func.c
6     gcc -o func.o func.c

执行make ,func.c main.c的打印都打出来了

当依赖在时间上比目标新,执行对应命令,反之,得不执行命令;在次执行make我们可以根据命令的回显,func.o main.o 两条命令没有执行。

因为我们没有修改这个.c文件,func.o main.o的时间比对应的.c文件新,所以没有必要执行命令,这个也比较好理解。但是我们再次执行make

 hello.out 对应的指令又执行了。

技巧:工程中开发可以将最终可执行文件名和all同时作为makefile的第一条规则的目标

1 hello.out all : main.o func.o
2     gcc - o hello.out main.o func.o

如果代码没有修改,多次make,也不会执行命令了。

3.1伪目标

 默认情况下

  make认为目标对应这一个文件

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

  make以文件处理作为第一优先级

1 clean :
2     rm *.o hello.out
3     
4 #执行make
5  make clean
6     

此目录中如果有一个clean文件,如果执行make clean 则会一直提示clean 是最新的没有更新,如果没有clean文件,此目录

下面的*.o将会被删除。

 伪目标

  通过.PHONY 关键字生命一个伪目标

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

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

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

  本质: 

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

  

1 .PHONY : clean
2  clean :
3     sudo rm *.o hello.out

执行make clean的时候 会把.o hello.out删掉,ls ll 下确实没有.o .out 文件

伪目标的妙用:规则调用(函数调用)

1 .PHONY : clean rebuild all
2  rebulid : clean all

执行make rebuild的时候会先执行clean  然后执行all 对应的命令

原理:当一个目标的依赖包含伪目标时,伪目标所定义的命令总会被执行

技巧:绕开.PHONY关键字作为伪目标

clean : FORCE
    sudo rm *.o hello.out
FORCE :

原理:

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

4 变量与赋值方式

4.1makefile变量

  • makefile中支持程序设计语言的变量的概念
  • makefile中的变量只代表文本数据(字符串)
  • makefile中变量名规则
    • 变量名可以包含字符,数字,下划线
    • 不能包含 “:” ,“#” ,“=” 或 “ ”
    • 变量名大小写敏感

  变量的定义和使用

      

 代码示例

 1 CC := gcc
 2 TARGET := hello-world.out
 3 
 4 $(TARGET) : func.o main.o
 5     $(CC) -o $(TARGET) func.o main.o
 6 
 7 func.o : func.c
 8     $(CC) -o func.o -c func.c
 9 
10 main.o : main.c
11     $(CC) -o main.o -c main.c
12 
13 .PHONY : rebuild clean all
14 
15 rebuild : clean all
16 
17 
18 all : $(TARGET)
19 
20 clean :
21     rm *.o $(TARGET)
22 
23     

CC 此处是gcc 我们可以修改成g++ 或交叉编译(arm-linux-gccXXXX)这样就很方便了,不用挨着修改

目标名也是,如果想换一个目标名,那我们可以修改变量的值就行了。

4.2makefile中变量的赋值方式

  • 简单赋值(:=)  (可以理解为c语言中=)
  • 递归赋值(=)     (可以理解为c语言指针赋值)  
  • 条件赋值 (?=) (可以理解为C++的引用赋值)
  • 追加赋值 (+=)  (可以理解为c语言+=)

  

  

 

 

 

 

 

  

  

  

  

  

 

时间不会留下一切,只有记忆记录了过去!
原文地址:https://www.cnblogs.com/itxiaoye/p/14944677.html