`

MakeFile 2nd

阅读更多
this article is from:http://www.chinaunix.net/jh/23/408225.html


make是如何工作的

在默认的方式下,也就是我们只输入make命令。那么,

    1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
    2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。
    3、如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。
    4、如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
    5、当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件edit了。

这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

通过上述分析,我们知道,像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。

于是在我们编程中,如果这个工程已被编译过了,当我们修改了其中一个源文件,比如file.c,那么根据我们的依赖性,我们的目标file.o会被重编译(也就是在这个依性关系后面所定义的命令),于是file.o的文件也是最新的啦,于是file.o的文件修改时间要比edit要新,所以edit也会被重新链接了(详见edit目标文件后定义的命令)。

而如果我们改变了“command.h”,那么,kdb.o、command.o和files.o都会被重编译,并且,edit会被重链接。


四、makefile中使用变量

在上面的例子中,先让我们看看edit的规则:

      edit : main.o kbd.o command.o display.o \
                  insert.o search.o files.o utils.o
            cc -o edit main.o kbd.o command.o display.o \
                       insert.o search.o files.o utils.o

我们可以看到[.o]文件的字符串被重复了两次,如果我们的工程需要加入一个新的[.o]文件,那么我们需要在两个地方加(应该是三个地方,还有一个地方在clean中)。当然,我们的makefile并不复杂,所以在两个地方加也不累,但如果makefile变得复杂,那么我们就有可能会忘掉一个需要加入的地方,而导致编译失败。所以,为了makefile的易维护,在makefile中我们可以使用变量。makefile的变量也就是一个字符串,理解成C语言中的宏可能会更好。

比如,我们声明一个变量,叫objects, OBJECTS, objs, OBJS, obj, 或是 OBJ,反正不管什么啦,只要能够表示obj文件就行了。我们在makefile一开始就这样定义:

     objects = main.o kbd.o command.o display.o \
              insert.o search.o files.o utils.o

于是,我们就可以很方便地在我们的makefile中以“$(objects)”的方式来使用这个变量了,于是我们的改良版makefile就变成下面这个样子:

    objects = main.o kbd.o command.o display.o \
              insert.o search.o files.o utils.o

    edit : $(objects)
            cc -o edit $(objects)
    main.o : main.c defs.h
            cc -c main.c
    kbd.o : kbd.c defs.h command.h
            cc -c kbd.c
    command.o : command.c defs.h command.h
            cc -c command.c
    display.o : display.c defs.h buffer.h
            cc -c display.c
    insert.o : insert.c defs.h buffer.h
            cc -c insert.c
    search.o : search.c defs.h buffer.h
            cc -c search.c
    files.o : files.c defs.h buffer.h command.h
            cc -c files.c
    utils.o : utils.c defs.h
            cc -c utils.c
    clean :
            rm edit $(objects)


于是如果有新的 .o 文件加入,我们只需简单地修改一下 objects 变量就可以了。

关于变量更多的话题,我会在后续给你一一道来。


五、让make自动推导

GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。

只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。我们的是新的makefile又出炉了。


    objects = main.o kbd.o command.o display.o \
              insert.o search.o files.o utils.o

    edit : $(objects)
            cc -o edit $(objects)

    main.o : defs.h
    kbd.o : defs.h command.h
    command.o : defs.h command.h
    display.o : defs.h buffer.h
    insert.o : defs.h buffer.h
    search.o : defs.h buffer.h
    files.o : defs.h buffer.h command.h
    utils.o : defs.h

    .PHONY : clean
    clean :
            rm edit $(objects)

这种方法,也就是make的“隐晦规则”。上面文件内容中,“.PHONY”表示,clean是个伪目标文件。

关于更为详细的“隐晦规则”和“伪目标文件”,我会在后续给你一一道来。


六、另类风格的makefile

即然我们的make可以自动推导命令,那么我看到那堆[.o]和[.h]的依赖就有点不爽,那么多的重复的[.h],能不能把其收拢起来,好吧,没有问题,这个对于make来说很容易,谁叫它提供了自动推导命令和文件的功能呢?来看看最新风格的makefile吧。

    objects = main.o kbd.o command.o display.o \
              insert.o search.o files.o utils.o

    edit : $(objects)
            cc -o edit $(objects)

    $(objects) : defs.h
    kbd.o command.o files.o : command.h
    display.o insert.o search.o files.o : buffer.h

    .PHONY : clean
    clean :
            rm edit $(objects)

这种风格,让我们的makefile变得很简单,但我们的文件依赖关系就显得有点凌乱了。鱼和熊掌不可兼得。还看你的喜好了。我是不喜欢这种风格的,一是文件的依赖关系看不清楚,二是如果文件一多,要加入几个新的.o文件,那就理不清楚了。


七、清空目标文件的规则

每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。这是一个“修养”(呵呵,还记得我的《编程修养》吗)。一般的风格都是:

        clean:
            rm edit $(objects)

更为稳健的做法是:

        .PHONY : clean
        clean :
                -rm edit $(objects)

前面说过,.PHONY意思表示clean是一个“伪目标”,。而在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。当然,clean的规则不要放在文件的开头,不然,这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean从来都是放在文件的最后”。


上面就是一个makefile的概貌,也是makefile的基础,下面还有很多makefile的相关细节,准备好了吗?准备好了就来。

<-上
分享到:
评论

相关推荐

    Thinking in C++, 2nd edition, Volume 2

    《Thinking in C++, 2nd Edition, Volume 2》是一本深入探讨C++编程语言的经典著作,由Bruce Eckel撰写。这本书以HTML格式呈现,便于读者在线阅读和学习,同时包含源代码树和makefiles,使得实践编程变得更加方便。...

    TICPP-2nd-ed-Vol-one-code

    《TICPP-2nd-ed-Vol-one-code》是一个与C++编程相关的压缩包,其中包含了一系列的源代码文件和文档。这个项目可能是《Thinking in C++》第二版第一卷的代码示例集,这本书由Bruce Eckel撰写,是C++初学者和进阶者的...

    aqt2nd-源码.rar

    【标题】"aqt2nd-源码.rar" 指的是一个压缩文件,其中包含了与"AQT2nd"相关的源代码。AQT可能代表一个项目、工具或库的名称,"2nd"可能表示这是该项目的第二个版本。由于没有提供更具体的标签,我们无法确定这属于...

    GNU+Autoconf+Automake+and+Libtool.pdf

    接下来的章节深入讨论了Makefile的基本概念,如规则、依赖关系和Makefile的语法特性,以及如何定义和使用变量(宏)来简化和自动化构建过程。通过这些章节,开发者将能够更好地理解如何用Makefile来组织和控制软件的...

    Addison Wesley - Linux Kernel Internals 2nd Ed

    - **编译步骤**:详细介绍了如何编译内核,包括使用makefile进行编译的具体步骤。 - **配置选项**:除了基本的编译流程外,还探讨了如何根据自己的需求定制内核配置,包括开启或关闭某些特性。 ##### 内核配置选项详解 ...

    HW1_2nd_Part

    a Makefile has been defined. User has to input the dimension of the matrix Sequential version of mmm Parallel version of mmm We verify that parallel version is correct by comparing the result matrix ...

    c++ gui with QT 2nd source code,gui源码,供参考

    本资源“c++ gui with QT 2nd source code”提供了使用C++和QT库构建GUI应用的示例代码,对于学习和理解QT编程非常有帮助。以下是基于这个主题的详细知识点讲解: 1. **QT库介绍**: - QT库是一个跨平台的开发框架...

    21世纪C语言教程(21st Century C, 2nd Edition)-2015年英文原版,0积分

    ### 21世纪C语言教程(21st Century C, 2nd Edition) #### 核心知识点概述 《21世纪C语言教程》是针对现代编程环境中的C语言使用进行深入探讨的一本教程,该书由Ben Klemens编写,并在2015年发布了第二版。本书...

    GNU.Linux.Application.Programming.2nd.2008

    此外,书中还讨论了动态链接和静态链接,以及如何使用Makefile进行项目构建和管理。读者将学习到如何有效地组织和编译源代码,以及如何使用版本控制系统如Git来管理代码。 最后,书中对调试工具进行了介绍,如GDB...

    OpenBLAS-0.2.20.tar.gz

    在下载并解压"OpenBLAS-0.2.20.tar.gz"后,你会得到OpenBLAS的源代码目录,其中包括Makefile、配置脚本、源代码文件以及相关的文档。安装OpenBLAS通常涉及编译源代码、配置参数以及链接到系统路径。用户需要根据自己...

    symbian坦克游戏源码

    3. 构建脚本:如Makefile或项目文件,用于编译和链接源代码。 4. 配置文件:用于设置游戏的参数和设置。 5. 文档:可能包括设计文档、API参考或开发者笔记,帮助理解和修改源码。 通过研究这个坦克游戏源码,开发者...

    Programming Embedded Systems with C and GNU Development.Tools 英文 pdf

    在这个压缩包中包含的文件是“Programming.Embedded.Systems.with.C.and.GNU.Development.Tools.(OReilly-2nd.Ed-2006).pdf”,这表明它是该书的第二版,由O'Reilly出版社出版。 在嵌入式系统编程中,C语言是广泛...

    算法入门经典

    压缩包文件"aoapc-bac2nd-master"的名称暗示了这可能是一个开源项目或者课程的代码库,"aoapc"可能代表《算法导论》或者《算法竞赛入门经典》的缩写,"bac2nd"可能指的是第二版或者某种特定的版本号。"master"通常是...

    sol-hoffman-kunze:霍夫曼和昆兹线性代数第二版的精选解决方案

    要生成PDF,可以使用随附的Makefile(需要此),也可以使用pdflatex src/hksol.tex手动pdflatex src/hksol.tex 。 版权 版权所有:copyright:2020 Greg Kikola。许可CC BY-SA 4.0: 。 本指南是根据知识共享署名-相同...

    wattcp.wat2002b

    3. `makefile` 是构建程序的脚本,它指示如何编译源代码并生成可执行文件,这对于在DOS环境下编译wattcp库至关重要。 4. `manual.txt` 应该是wattcp库的用户手册,详述了如何使用提供的函数和API。 5. `ertos.txt` ...

    wile_file.rar_对话框与窗口

    1. awk脚本(mk-1st.awk、mk-2nd.awk、mk-0th.awk、mk-hdr.awk):AWK是一种用于处理文本文件的语言,常用于数据处理和生成报告。这些脚本可能是用来自动化ncurses项目中的某些任务,如代码生成、预处理或构建过程。...

    ParaCL

    ParaCL 是一个与C语言编程相关的项目,特别针对iLab 2nd课程设计。这个项目强调了编程类的实践操作,要求参与者使用MAKEFILE来组织和编译代码。MAKEFILE是Unix/Linux环境中的一种自动化构建工具,它允许程序员定义...

    intc-525x.rar_Linux/Unix编程_Unix_Linux_

    在实际应用中,开发人员可能还需要使用调试工具(如gdb)进行内核模块调试,以及使用makefile来构建和加载模块。 总的来说,这个压缩包提供的是针对Intel 525x芯片2nd INTC控制器的Linux/Unix驱动程序代码,对于...

    WATTCP

    1. **readme.2nd**:通常这是一个包含额外信息的读我文件,可能包括更新、注意事项或其他不包含在主`readme`文件中的内容。 2. **changes**:这个文件可能记录了WATTCP自上次发布以来的改动和更新历史,对理解版本...

    内核驱动归纳总结(二):内核模块

    使用`make`命令和配置文件(如`Makefile`)来编译模块。 2. 模块的加载:编译完成后,使用`insmod`命令将模块插入内核。例如,`insmod my_module.ko`。 3. 模块的卸载:使用`rmmod`命令移除已加载的模块。例如,`...

Global site tag (gtag.js) - Google Analytics