初识 makefile 的结构(二)

我们在上节中说到 makefile 的本质就是一个脚本程序,用来解释执行的。那么它的意义是用于定义源文件间的依赖关系,说明如何编译各个源文件并生成可执行文件。我们来看看依赖的定义,如下

下来我们来分析下 makefile 中元素的意义:a> targets:通常是需要生成的目标文件名,make 所需执行的命令名称;b> perequisities:当前目标所依赖的其他目标或文件;c> command:完成目标所需要执行的命令。我们来说说规则中的注意事项:a> targets 可以包含多个目标,使用空格对多个目标名进行分隔;b> perequisities 可以包含多个依赖,使用空格对多个依赖进行分隔;c> [ Tab ] 键 '\t',每一个命令行必须以 [ Tab ] 字符开始,[ Tab ] 字符告诉 make 此行是一个命令行;d> 续行符 \,可以将内容分开写到下一行,提高代码可读性。

下来我们看看一个 makefile 的依赖示例,如下

依赖规则是:a> 当目标对应的文件不存在,执行对应命令;b> 当依赖在时间上比目标更新,执行对应命令;c> 当依赖关系连续发生时,对比依赖链上的每一个目标。在这讲个小技巧:makefile 中可以在命令前加上 @ 符,作用为命令无回显。

我们还是以代码为例来进行分析说明

all : test
    @echo "make all"

test : 
    @echo "make test"

我们定义的目标 all 的依赖是 test,而 test 目标则没有依赖,只是执行打印语句。当 test 目标正确执行后,all 目标的执行语句便会进行正常输出。也就是说,先打印 make test,在输出 make all。我们来看看编译结果

那为什么只打印出这两句,没有打印出上一节我们看到的 echo "make all" 呢?原因就是我们在它们前面加的 @  无回显符号,下来我们去掉 @ 符号看看编译效果

以后如果我们不想看到 echo 那条命令本身的话,可以加上 @ 无回显符号。下来我们来看个 make 的编译案例,结构如下

我们来根据上面的结构编写相应的 makefile 程序,看看执行效果

func.c 源码

#include <stdio.h>

int foo()
{
    printf("void foo()\n");
}

main.c 源码

extern void foo();

int main()
{
    foo();

    return 0;
}

makefile 源码

hello.out : func.o main.o
    gcc -o hello.out func.o main.o

func.o : func.c 
    gcc -o func.o -c func.c

main.o : main.c
    gcc -o main.o -c main.c

我们来看看编译结果

我们看到已经实现了。我们再来在 func.c 中打印的语句前加上 hello,再来看看编译结果

我们看到再次进行编译时,它只编译了 func.c 文件,没有编译 main.c 文件,这也极大的提升了嵌入式编译的效率。那么在这块有个小技巧,在工程开发中可以将最终可执行文件名和 all 同时作为 makefile 中第一条规则的目标,如下

我们再次来编译,看看编译结果

我们看到它说 hello.out 是最新的,执行的结果和我们之前是一样的。因此这个小技巧可以极大的提高我们因重复编译带来的效率低下的问题。我们也可以直接 make all 进行再次编译,如下

这次因为源文件都没有改动,所以只执行了 hello.out 目标后面的语句。提高对 makefile 结构的学习,总结如下:1、makefile 用于定义源文件间的依赖关系;2、makefile 说明如何编译各个源文件并生成可执行文件;3、makefile 中的目标之间存在连续依赖关系;4、依赖存在并且命令执行成功是目标完成的充要条件。

欢迎大家一起来学习 makefile 语言,可以加我QQ:243343083。

原文地址:http://blog.51cto.com/12810168/2126854

时间: 2024-10-13 22:12:32

初识 makefile 的结构(二)的相关文章

初识java-循环结构(二):6

一,格式 for(赋值语句//为循环变量赋初值;条件语句//循环结构的循环条件;赋值语句//迭代,修改循环变量的值){ //循环体; } for(int i=m;i<=n;i++){ System.out.print("第"+i+"遍循环"); } 二,for循环条件可以少吗? 当然可以,他可以放在for循环内或者外面 三,举个例子 示例: 示例:

初识java-选择结构(二):4

一switch(int/char): 1 switch(条件){ case 1: break; case 2: break; default: break; } 示例 2switch(条件){ case 1: case 2: case 3: break; case 4: case 5: case 6: break; default: break; } 示例 -判断用户从键盘上输入的字符是否合法: if(input.hasNextInt()==true){ }

Makefile持续学习二

Makefile概述 一.Makefile里有什么? Makefile里主要包含5个东西:显式规则.隐晦规则.变量定义.文件指示和注释 1.显式规则:显式规则说明如恶化生成一个或多的目标文件,包含要生成的文件,文件的依赖文件,生成的命令 2.隐晦规则:由make自动推动功能完成 3.变量定义:变量一般都是字符串,类似C语言中的宏定义,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上 4.文件指示: 在一个Makefile中引用另一个Makefile 根据某些情指定Makefil

【Linux学习】Makefile学习(二)

FatMouse' Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 40975    Accepted Submission(s): 13563 Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats g

二叉树的链式存储结构----二叉链表

头文件:head.h #include<string.h> #include<ctype.h> #include<malloc.h> /* malloc()等 */ #include<limits.h> /* INT_MAX等 */ #include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<stdlib.h> /* atoi() */ #include<io.h> /* eof()

Contiki 2.7 Makefile 文件(二)

二.Makefile.include 1.第一部分 (1) ifndef CONTIKI ${error CONTIKI not defined! You must specify where Contiki resides} endif 含义: 如果没有定义CONTIKI变量,make停止运行. 并产生一个致命的错误信息,CONTIKI not  defined! You must specify where Contiki resides. hello-world这个例子在主控Makefil

初识C#程序结构

一.编写第一个C#程序.注释: 1.编写程序 static void Main(string[] args)//在Mian方法下编写代码输出数据 { Console.WriteLine("Hello World!");//输出“Hello World!” Console.ReadLine();//打印 } 2.注释 C#程序结构分为注释.命名空间.类.Main方法.标示符及关键字.语句. 注释:行注释都是以“//”开头 段注释引用“/*”开头,以“*/”结尾 二.命名空间: C#程序利

Makefile文件(二)_总述

Makefile总述 一.Makefile里面有什么 Makefile主要包含了五个东西:显示规则.隐晦规则.变量定义.文件指示和注释. 显示规则:明显指出要生成的文件,文件的依赖文件,生成的命令 隐晦规则:make具有自动推导功能,隐晦规则可以比较粗糙地简略书写Makefile 变量定义:如一中的objects 文件指示:一个Makefile中引用另一个Makefile:根据某些情况指定Makefile中的有效部分:定义一个多行的命定 注释:'#',文件中使用该符号可以利用转义符号'/#' 注

Makefile学习(二)----生成静态库文件

Lunix下编译静态库文件: .o后缀文件:编译生成的中间代码文件: .a后缀文件:静态库文件,编译的时候会合到可执行程序中,文件比较大: .so后缀文件:动态库文件,只是一个指向,不会合到可执行程序中,当要调用函数库的时候才使用: 用一个简单的例子阐述下在lunix环境下生成静态库文件的过程: 一.   源码文件: so_test.h: void test_a(); void test_b(); void test_c(); test_a.c: #include "so_test.h"