zoukankan      html  css  js  c++  java
  • Makefile

    总结下边的内容 :

    1. 文件中的第一个target是最终目标
    2. 命令列表中的每条命令必须以 Tab 开头
    3. 如果 prerequistes 中如果有一个以上的文件比 target 文件更新的话,command 所定义的命令就会执行,这就是 Makefile 规则
    4. 如果这个工程的头文件改变了,那么我们需要编译引用了这个头文件的C文件,并链接目标程序。
    5. make clean 执行删除文件和所有中间文件。这里要说明,clean, 类似C语言中的 label一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令,要执行其后的命令,就要在make命令后明显得指出这个label的名字,这样的方法非常有用,我们可以在一个makefile中定义不用的编译或和编译无关的命令,比如程序的打包,程序的备份.
    6. make 会比较 targets 文件和 prerequisits 文件的修改日期,如果 prerequistes 文件的日期要比 targets文件的日期新,或者 target不存在的话,那么,make就会执行后续定义的命令.
    7. make 会一层一层的找文件的依赖关系。知道编译出第一个目标文件。如果在找的过程中,出现问题,那么make 就会自动退出,并报错。但是make只管文件依赖性,比如,编译错误等等问题,make根本不理。即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那我就不工作了。
    8. 自动推到 只要 make 看到一个.o 文件,它就会自动的把 .c 文件加载依赖关系中。所以不需要我们自己指定. 如果一个目标在 Makefile 中的所有规则都没有零零列表,make会尝试在内建的隐含规则 ( Implicit Rule) 数据库中查找适用的规则,所以才会有如下例子中,哪些没有被指定的命令,只是指定了规则的,会执行隐含规则 gcc -c main.c 例如
    9.  all : ( 表示缺省的目标,就是最后目标啦,跟clean,是大家约定俗成的 )
    10. @echo 正在编译 XXX 模块, 当我们用 “@”字符在命令行前,那么,这个命令将不被make显示出来。这个例子,当make执行时,会输出”正在编译 XXX 模块”,但不会输出命令

    例子:

    # This is a temple makefile ( comment )

    all : main

    main : main.o stack.o maze.o  

      gcc main.o stack.o maze.o -o main

    main.o : main.h stack.h maze.h

    stack.o : stack.h main.h

    maze.o : maze.h main.h

    .PHONY : clean

    clean :  

      @echo "cleanning project"  

      -rm main *.o  

      @echo "clean completed"


    Makefile 不需要任何文件扩展名,只需要用 vi Makefile,编辑就可以了。

    除了Hello World 这种极为简单的程序之外,一般的程序都是由多个源文件编译链接而成的,这些源文件的处理通常用 Makefile 来管理。

    多个文件编译时,如果一个文件需要修改,例如有3个源文件, gcc main.c stack.c maze.c –o main 如果编译之后又对 maze.c做了修改,又要把所有的源文件编译一遍,即使 main.c stack.c 和那些头文件都没有修改也要跟着重新编译。(还记的以前不,只要你的文件中加入了新修改的文件的头文件,即有 #include “maze.h”, 那么就要跟着重新编译),一个大型的软件项目往往由上千个源文件组成,全部编译一遍要几个小时,而且,只改一个源文件就要求全部重新编译肯定是不合理的。

    写一个makefile文件和源代码放在同一个目录下: ( 使用 Makefile 做文件名 )

    makefile文件

    然后,在这个目录下运行 make 编译

    make

    gcc –c main.c

    gcc –c stack.c

    gcc –c maze.c

    gcc main.o stack.o maze.o –o main

    make命令会自动读取当前目录下的Makefile文件,完成相应编译步骤,Makefile由一组规则组成,每条格式为:

    target : prerequistes

         command1

         command2

    例如:

    main: main.o stack.o maze.o

              gcc main.o stack.o maze.o –o main

    目标和条件之间的关系是,欲更新目标,必须首先更新它的所有条件,所有条件中只要有一个条件被更新了,目标也必须随之被更新,所谓“更新”就是执行一遍规则中的命令列表,命令列表中的每条命令必须以一个 Tab开头,注意不能是空格,Makefile的格式不像C语言的缩进那么随意,对于Makefile中的每个以Tab开头的命令,make会创建一个Shell进程去执行它。

    如果 prerequistes 中如果有一个以上的文件比 target 文件更新的话,command 所定义的命令就会执行,这就是Makefile的规则,也是Makefile最核心的内容。

    总体规则

    1)如果这个过程没有编译过,那么我们的所有C文件都要编译并被链接。

    2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并列接目标程序。

    3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。

    只要我们Makefile学的好,所有这一切,只用一个make命令就可以完成。

    以上的 Makefile 格式可以稍微调整,比如 ( 可以修改的更格式清楚一点 )

    main: main.o stack.o maze.o

              gcc main.o maze.o stack.o –o main

    main.o: main.h stack.h maze.h

    stack.o: stack.h main.h

    maze.o: maze.h main.h

    .PHONY : clean

    clean:

                  -rm main *.o

    .PHONY: clean         ( 表示 clean 是个伪目标文件 )

    其中的,clean是删除多余文件。

    #号在 Makefile中时注释。


    make 执行编译

    make clean 执行删除执行文件和所有的中间目标文件。

    make 会比较 targets 文件和 prerequisits 文件的修改日期,如果 prerequistes 文件的日期要比 targets文件的日期新,或者 target不存在的话,那么,make就会执行后续定义的命令.

    这里要说明,clean, 类似C语言中的 label一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令,要执行其后的命令,就要在make命令后明显得指出这个label的名字,这样的方法非常有用,我们可以在一个makefile中定义不用的编译或和编译无关的命令,比如程序的打包,程序的备份。

    注意, Makefile中的第一个 target 一定是最终目标,比如最后的可执行程序。

    make 会一层一层的找文件的依赖关系。知道编译出第一个目标文件。如果在找的过程中,出现问题,那么make 就会自动退出,并报错。但是make只管文件依赖性,比如,编译错误等等问题,make根本不理。即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那我就不工作了。

    变量

    变量类似间接引用,比如我们有很多 .o 文件,当我们修改时,可能需要在Makefile中的很多地方都要修改,如果Makefile很大时,维护困难,但是如果我们将所有的.o文件保存在一个变量中,例如obj这个变量中,那么只要在Makefile中的一个地方修改,就可以实现全部修改。

    obj = main.o kdb.o command.o display.o \   ( 这个反斜杠是换行 )

              insert.o search.o files.o utils.o

    这样的话,比如,你想增加一个.o文件,那么只需要在这个地方增加就可以了。

    在Makefile后边,格式为

    edit : $(obj)   在Makefile中 其实就是使用 shell 脚本,shell脚本中 $(obj) 是变量

    edit : $(obj)

              cc –o edit $(obj )

    这样就简单多了。

    自动推到

    只要 make 看到一个.o 文件,它就会自动的把 .c 文件加载依赖关系中。所以不需要我们自己指定。类似上边的

    main.o: main.h stack.h maze.h

    stack.o: stack.h main.h

    maze.o: maze.h main.h

    简单风格 Makefile

    objects = main.o kdb.o command.o display.o \

                     insert.o search.o files.o utils.o

    edit : $(objects)

                     cc –o edit $(objects)

    $(objects): defs.h        ( 全部需要引用这个头文件 )

    kdb.o command.o files.o : command.h

    display.o insert.o search.o files.o : buffer.h

    .PHONY : clean

    clean :

                    rm edit $( objects)                //删除全部编译文件,目的是,如果有问题,重新编译

                                                                  // 当然需要删除以前编译过的文件

    这种简单的风格,Makefile便的简单了。但是依赖关系变的有点凌乱了。没办法,鱼和熊掌不能兼得。

    还是好的依赖关系比较好吧。毕竟程序都不打。顶多几个~10几个文件而已。

    clean 都是放在文件的最后,好的风格。

    .PHONY : clean

    clean :

                   -rm edit $(objects)

    Makefile总述

    Makefile中 主要包括 5 个东西: 显示规则,隐晦规则,变量定义,文件指示,注释

    1)显示规则说明了,文件的依赖和生成的命令

    2)隐晦规则,由于make有自动推到功能,可以方便我们比较粗略的写Makefile

    3)变量定义,间接,有点类似C语言中的宏

    4)文件指示,包括 3 点

    • 在一个Makefile中引用另一个Makefile,有点像C中的 #include
    • 根据情况制定Makefile的有效部分,有点类似C中的 #if
    • 定义多行命令

    5)注释,#号表示注释,如果要用这个符号,可以使用”\#”转义

    文件名: Makefile 也可以使用 Make.linux 等等,不过在使用make命令时,要加上 make –f Make.linux

    @echo 正在编译 XXX 模块, 当我们用 “@”字符在命令行前,那么,这个命令将不被make显示出来。这个例子,当make执行时,会输出”正在编译 XXX 模块”,但不会输出命令。

    all : ( 表示缺省的目标,就是最后目标啦,跟clean,是大家约定俗成的 )

    标准
  • 相关阅读:
    idea maven install java: 程序包不存在
    Window10取消文件默认打开方式
    @ModelAttribute与@RequestBody的区别
    python小知识
    CentOS下yum方式安装FFmpeg
    推荐一款可以直接下载浏览器sources资源的Chrome插件
    如何在python中使用Elasticsearch
    python logging模块“另一个程序正在使用此文件,进程无法访问。”问题解决办法
    Python的伪造数据生成器:Faker
    docker修改系统时间总结
  • 原文地址:https://www.cnblogs.com/moveofgod/p/2727709.html
Copyright © 2011-2022 走看看