makefile使用实例(一)

先引用一段经典的makefile名言————》什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。

因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。

makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

本实例使用的又以下几个文件(foo.h foo1.c foo2.c 和mian.c)

foo.h内容如下:

void foo1(void);
void foo2(void);

foo1.c内容如下:

#include <stdio.h>

void foo1(void)
{
    printf("%s:+start\n",__FUNCTION__);
    printf(" foo1 called\n");
    printf("%s:+end\n",__FUNCTION__);
}

主要作用打印函数名

foo2.cde 内容:

#include <stdio.h>

void foo2(void)
{
    printf("%s:+start\n",__FUNCTION__);
    printf(" foo2 called\n");
    printf("%s:+end\n",__FUNCTION__);
}

main.c内容:

#include <stdio.h>
#include "foo.h"
#include "foo1.h"

int main()
{
    printf("%s:+start\n",__FUNCTION__);
    foo1();
    foo2();
    printf("%s:-end\n",__FUNCTION__);
}

写一个最简单的makefile:

main  : main.o foo1.o foo2.o
    gcc -o main main.o foo1.o foo2.o

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

foo1.o : foo1.c
    gcc -c foo1.c

foo2.o : foo2.c
    gcc -c foo2.c

clean:
    rm -f *.o

按照makefile手册所说makefile终极目标是:默认的情况下,make执行的是Makefile中的第一个规则,此规则的第一个目标称之为“最终目的”或者“终极目标”(就是一个Makefile最终需要更新或者创建的目标。

而一个规则标准定义如下:

TARGET… : PREREQUISITES…

COMMAND

target:规则的目标。通常是最后需要生成的文件名或者为了实现这个目的而必需

的中间过程文件名。可以是.o文件、也可以是最后的可执行程序的文件名等。另外,目

标也可以是一个make执行的动作的名称,如目标“clean”,我们称这样的目标是“伪

目标”。

prerequisites:规则的依赖。生成规则目标所需要的文件名列表。通常一个目标依

赖于一个或者多个文件。

command:规则的命令行。是规则所要执行的动作(任意的shell命令或者是可在

shell下执行的程序)。它限定了make执行这条规则时所需要的动作。

一个规则可以有多个命令行,每一条命令占一行。注意:每一个命令行必须以[Tab]

字符开始,[Tab]字符告诉make此行是一个命令行。make按照命令完成相应的动作。

这也是书写Makefile中容易产生,而且比较隐蔽的错误。

命令就是在任何一个目标的依赖文件发生变化后重建目标的动作描述。一个目标可

以没有依赖而只有动作(指定的命令)。比如Makefile中的目标“clean”,此目标没有

依赖,只有命令。它所定义的命令用来删除make过程产生的中间文件(进行清理工作)。

在Makefile中“规则”就是描述在什么情况下、如何重建规则的目标文件,通常

规则中包括了目标的依赖关系(目标的依赖文件)和重建目标的命令。make执行重建

目标的命令,来创建或者重建规则的目标(此目标文件也可以是触发这个规则的上一个

规则中的依赖文件)。规则包含了文件之间的依赖关系和更新此规则目标所需要的命令。

一个Makefile文件中通常还包含了除规则以外的很多东西(后续我们会一步一步

的展开)。一个最简单的Makefile可能只包含规则。规则在有些Makefile中可能看起来

非常复杂,但是无论规则的书写是多么的复杂,它都符合规则的基本格式。

make程序根据规则的依赖关系,决定是否执行规则所定义的命令的过程我们称之

为执行规则。

在上个makefile中main main.o foo1.o 和foo2.o都是目标。但是main是终极目标因为main是makefile中最先出现的目标。

在中断下执行make命令结果如下:

 make
gcc -c main.c
gcc -c foo1.c
gcc -c foo2.c
gcc -o main main.o foo1.o foo2.o

执行文件

 ./main
main:+start
foo1:+start
 foo1 called
foo1:+end
foo2:+start
 foo2 called
foo2:+end
main:-end

有没有发现main这个目标没有依赖clean,所以编译的时候也不会执行clean这个规则,但是我想执行这个规则咋办,很简单直接执行

make clean
rm -f *.o

make 加上 规则目标就可以执行特定的目标。(也可以make foo1.o等等)

一个规则可以有多个命令执行比如我下面修改多加一个

main  : main.o foo1.o foo2.o
    gcc -o main main.o foo1.o foo2.o
    mv main main1

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

foo1.o : foo1.c
    gcc -c foo1.c

foo2.o : foo2.c
    gcc -c foo2.c

clean:
    rm -f *.o main1 main

多加一个cp main main1

当然也可以写成一行

main  : main.o foo1.o foo2.o
    gcc -o main main.o foo1.o foo2.o ;mv main main1

结果:

gcc -c main.c
gcc -c foo1.c
gcc -c foo2.c
gcc -o main main.o foo1.o foo2.o
mv main main1

是不是感觉上个makefile写的很挫!!我们可以修改一下顺便说说makefile其他用法.

main  : main.o foo1.o foo2.o
    gcc -o main main.o foo1.o foo2.o 

main.o :

foo1.o : 

foo2.o : 

clean:
    rm -f *.o main1 main

makefile规则含有隐式推倒,遇到 var.o 目标就会找var.c文件,遇到 main.o就会找main.c文件

上面还是有点不简单,下面好看多了

main  : main.o foo1.o foo2.o
    gcc -o main main.o foo1.o foo2.o
clean:
    rm -f *.o main1 main

每次都写 main.o foo1.o foo2.o还是很多,假如在加一个foo3 岂不是每个都加。在编译大型程序,那么多文件很容易出错,修改后如下:

obj= main.o foo1.o foo2.o
main  : $(obj)
    gcc -o main $(obj)

clean:
    rm -f *.o main1 main

这个加一个文件直接在 obj后面添加就可以了。

在当前目录新建文件夹src 把 foo2.c移动到src下,

main  : main.o foo1.o foo2.o
    gcc -o main main.o foo1.o foo2.o 

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

foo1.o : foo1.c
    gcc -c foo1.c

foo2.o : foo2.c
    gcc -c foo2.c
clean:
    rm -f *.o main1 main

发现编译有错误,修改后

foo2.o : ./src/foo2.c
    gcc -c ./src/foo2.c

就可以了。

这样还是有点不雅观!!在修改一下:

vpath %.c src
main  : main.o foo1.o foo2.o
    gcc -o main main.o foo1.o foo2.o 

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

foo1.o : foo1.c
    gcc -c foo1.c

foo2.o : foo2.c
    gcc -c $<
clean:
    rm -f *.o main1 main

vpath %.c src 表示 如果在当前目录下找不到.c文件就去子目录src下去找,

foo2.o : foo2.c

gcc -c $<

不可写成

foo2.o : foo2.c

gcc -c foo2.c

因为 foo2.c 是一个定量,指定死了文件,所以要用自动化变量,让makefile自动搜索

时间: 2024-10-05 10:05:54

makefile使用实例(一)的相关文章

makefile 使用实例(二)

在智能一点,全部使用自动化变量 obj= main.o foo1.o foo2.o main : $(obj) gcc -o [email protected] $^ clean: rm -f *.o main1 main @代表规则目标本例就是main,^代表规则所依赖文件本例是 main.o foo1.o 和foo2.o makefile也可以编译多目标文件,我们本例拷贝一份 main.c 命名为 main1.c, obj= main.o foo1.o foo2.o obj1= main1.

Makefile 编写实例

make命令常用的三个选项: 1.-k:它的作用是让make命令在发现错误的时候仍然继续执行.我们可以利用这个选项在一次操作中发现未编译成功的源文件. 2.-n:它的作用是让make命令输出将要执行的操作步骤,而不是真正执行这些操作. 3.-f  <filename>:它的作用是告诉make命令将哪个文件作为makefile文件.如果未使用这个选项,make命令将依次查找当前目录下的makefile文件,Makefile文件. Makefile文件中,将第一个目标定义为all,然后列出其他从属

makefile 使用实例(三)

这一篇主要讲一下makefile 内置函数的使用,明天就回家了.能写多少就写多少!! 变量的替换引用 对于一个已经定义的变量,可以使用"替换引用"将其值中的后缀字符(串)使用 指定的字符(字符串)替换.格式为"(VAR:A=B)"(或者"{VAR:A=B}"),意思是, 替换变量"VAR"中所有"A"字符结尾的字为"B"结尾的字."结尾"的含义是空格 之前(变量值多个

[转]MAKEFILE

http://www.ruanyifeng.com/blog/2015/02/make.html 代码变成可执行文件,叫做编译(compile):先编译这个,还是先编译那个(即编译的安排),叫做构建(build). Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目.但是实际上 ,任何只要某个文件有变化,就要重新构建的项目,都可以用Make构建. 本文介绍Make命令的用法,从简单的讲起,不需要任何基础,只要会使用命令行,就能看懂.我的参考资料主要是Isaac Schlueter

Makefile 简易教程

作者: 阮一峰 日期: 2015年2月20日 代码变成可执行文件,叫做编译(compile):先编译这个,还是先编译那个(即编译的安排),叫做构建(build). Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目.但是实际上 ,任何只要某个文件有变化,就要重新构建的项目,都可以用Make构建. 本文介绍Make命令的用法,从简单的讲起,不需要任何基础,只要会使用命令行,就能看懂.我的参考资料主要是Isaac Schlueter的<Makefile文件教程>和<GNU M

【转】Makefile步步为营

Makefile步步为营 本目录主要包含Makefile一步步递进学习的示例代码 makefile代码实例:https://www.lanzous.com/i9m9npi step0:Makefile小实验 进行Makefile小实验,体验Makefile的功能. 目录中的Makefile是不严谨的编写方式. 目录中的Makefile_PHONY是严谨的编写方式. make实验 切换至step0目录下,即Makefile所在的同级目录,使用如下命令实验: #在主机上Makefile所在的目录执行

Make命令

Make 命令教程 代码变成可执行文件,叫做编译(compile):先编译这个,还是先编译那个(即编译的安排),叫做构建(build). Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目.但是实际上 ,任何只要某个文件有变化,就要重新构建的项目,都可以用Make构建. 本文介绍Make命令的用法,从简单的讲起,不需要任何基础,只要会使用命令行,就能看懂.我的参考资料主要是Isaac Schlueter的<Makefile文件教程>和<GNU Make手册>. (题

make命令用法--转

转自:http://www.techug.com/make 代码变成可执行文件,叫做编译(compile):先编译这个,还是先编译那个(即编译的安排),叫做构建(build). Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目.但是实际上 ,任何只要某个文件有变化,就要重新构建的项目,都可以用Make构建. 本文介绍Make命令的用法,从简单的讲起,不需要任何基础,只要会使用命令行,就能看懂.我的参考资料主要是Isaac Schlueter的<Makefile文件教程>和&l

实例学习gcc+gdb+make

1 小侃GCC 在正式使用gcc之前,我们先来侃侃gcc是啥玩意儿? 历史 现在的GCC是GNU Compiler Collection的简称,既然是Collection,就是指一些工具链的集合. 最初的GCC(当时还只有C编译器,GCC还是GNU C Comiler的简写)是由Richard Stallman开发的,Stallman也是GNU工程的首创者,那时还是在1984年. 随着程序设计语言的发展,GCC逐渐开始支持C语言之外的语言,如C++.Objective-C.Java.Fortra