• GNU make 总结 (一)


    make的执行依赖于一个makefile文件,该文件告诉make应该如何执行编译和链接操作。make通过比较对应文件的最后修改时间来决定哪些文件需要更新。make工具主要用来进行工程编译和程序链接操作。当使用make时,工程中的如下几种文件会被重新编译:

    • 所有从未被编译过的源文件
    • 执行make后,修改过的源文件
    • 执行make后,修改过头文件,则包含该头文件的源文件都需要重新编译

    2.1 makefile简介

    Target : Prerequisites

        command

        ...

        ...

    Target: 目标

    Prerequisites: 依赖

    Command: 命令

    一条规则可以有command,每个command占一行。command必须以Tab开头。command用于在prerequisites改变后重建target。make程序根据规则的依赖关系来决定是否执行所定义的command,这个过程我们称之为执行规则

    可以使用来断行,但是后边不能有空格。

    makefile文件中没有依赖项而只有command的目标称为“伪目标”。

    执行make时,将执行第一个定义的target

    注意:所有的command行都必须以Tab开始,但并不是所有以Tab开始的行都是command,make把出现在第一条规则之后的所有以Tab开始的行都作为command来处理

     

    头文件和源文件如下:

     1 // benxin.h
     2 void print_benxin();
     3 
     4 // benxin.c
     5 #include <stdio.h>
     6 
     7 void print_benxin()
     8 {
     9         printf("benxin ");
    10 }
    11 
    12 // tuzi.h
    13 void print_tuzi();
    14 
    15 // tuzi.c
    16 #include <stdio.h>
    17 
    18 void print_tuzi()
    19 {
    20         printf("tuzi !
    ");
    21 }
     1 // makefile
     2 main : main.o 
     3         benxin.o tuzi.o
     4   gcc -o main main.o benxin.o tuzi.o
     5 main.o : main.c benxin.h tuzi.h
     6   gcc -c main.c
     7 benxin.o : benxin.c benxin.h
     8   gcc -c benxin.c
     9 tuzi.o : tuzi.c tuzi.h
    10   gcc -c tuzi.c
    11 clean : 
    12   rm main main.o benxin.o tuzi.o

    执行:make

    执行:./main

    2.2 指定变量

    可以指定一个变量表示所有的文件列表,如下:

    OBJECTS = main.o benxin.o

    tuzi.o

    使用变量:

    main : $(OBJECTS)

        gcc –o main $(OBJECTS)

    clean :

        rm main $(OBJECTS)

     

    2.3 Makefile组成

    makefile文件中可能包含以下5个内容:显式规则、隐式规则、变量定义、提示符、注释。

    • 显式规则:规则中明确指定目标文件、依赖文件列表、更新目标所需的命令。
    • 隐式规则:make程序根据目标文件名自动产生目标依赖文件列表,并使用默认的命令更新目标。
    • 变量定义:定义一个变量表示一系列文件列表。
    • 指示符:包含文件、条件执行、多行定义。
      • 包含文件:include ----->  一个makefile文件中可以使用include包含另一个makefile文件中的内容,其告诉make程序,暂停执行当前makefile,而先去include指定的makefile,然后继续执行。书写include时独立占据一行,但是不能以Tab键开始,格式如下:include FILENAMES...其中,FILENAMES是shell所支持的文件名,可以使用通配符表示。如果被include的文件中存在变量或者函数,那么将会在包含它们的makefile中被展开。
      • include的应用:

          <1> 多个不同目录下的makefile文件都使用一组同样的变量或者模式规则,此时可以将这些共性的内容定义在一个文件中,然后在不同的makefile文件中include该文件。

          <2> 当根据源文件自动产生依赖时,可以将这些依赖关系保存到一个特定的文件中,然后在makefile文件中include这个特定的文件,这样可以减少错误。

    • 注释:用#表示注释,因此如果需要在makefile的非注释行中使用#时,需要加上转义字符,表示为”#”。

     

    2.4 makefile文件的指定规则

    make程序默认会执行名为makefile或者Makefile的文件。否则需要通过-f或者—file选项来指定makefile文件,具体格式为:-f FILENAME或者—file=FILENAME。当然,也可以直接指定make的目标,只要当前文件夹下存在该目标的依赖文件列表即可。

     

    2.5 MAKEFILES

    如果当前环境中定义了MAKEFILES变量,那么make程序执行时,首先将此变量的值作为需要读入的makefile文件。但是区别如下:

    MAKEFILES变量指定的makefile文件中的“目标”不会被当作make执行的“终极目标”。

    MAKEFILES变量指定的文件列表中的文件是否存在,make都不会提示错误。

    make程序执行时,首先读取MAKEFILES变量,然后才是当前工作目录下的makefile文件。

     

    2.6 MAKEFILE_LIST

    make程序在读取多个makefile文件时,比如,MAKEFILES变量、命令行、makefile、include等,在对这些文件进行解析之前,make读取到的文件名会被自动加到MAKEFILE_LIST中。如此,我们可以通过判断MAKEFILE_LIST变量的最后一块内容来获取当前make程序正在处理的makefile文件名。

     

    2.7 特殊变量.VARIABLE

    make包含一个特殊的变量,不能通过任何途径给它赋值,其被展开后是makefile文件中当前点之前的所有全局变量列表,包括:空变量和make的内嵌变量。

     

    2.8 makefile文件的重载

    如果两个makefile文件中拥有相同的目标,但是依赖与规则却不同,此时使用include命令显然行不通。此时需要使用“所有匹配模式 %”。%可以匹配任何一个目标,其依赖项假设为force,而force却使用空命令。这是为了防止make程序试图寻找一个规则去创建目标force时,又使用到% : force,这样就陷入死循环了。

     

    2.9 make解析makefile

    <1>依次读取变量MAKEFILES定义的makefile文件列表

    <2> 读取当前目录中的makefile文件

    <3> 读取当前目录makefile文件中使用的include包含的文件

    <4> 查找重建所有已读取的makefile文件的规则

    <5> 初始化变量值并展开那些需要立即展开的变量和函数,同时根据预设条件确定执行分支

    <6> 根据“终极目标”以及其他目标的依赖关系建立依赖关系链表

    <7> 执行除“终极目标”以外的所有的目标规则

    <8> 执行“终极目标”更新规则

    附注知识点:

    编译:

    将高级语言程序转换为机器码的过程,结果为中间目标文件,linux中以后缀名.o标识目标文件。

    链接:

     

    将多个.o文件以及库文件链接称为可执行文件。链接器并不检查函数所在的源文件,只检查.o文件中定义的符号,将.o文件中使用的函数和库文件中的函数进行合并,然后对合并后的符号重新排序,并链接上系统相关文件,最终生成可执行程序,Linux中的可执行程序为ELF格式。

    静态库:

     

    又名归档文件,其是多个.o文件的集合,库中不同的.o文件之间没有特殊的关系。Linux中静态库后缀名为.a,使用工具ar管理。

    共享库:

     

    也是多个.o文件的集合,但是这些.o文件是由编译器按照某种特殊方式生成的。Linux中,共享库格式通常为ELF,即该类型库具备可执行条件。

  • 相关阅读:
    crm 4 注释与上传附件权限
    动态图片轮播
    PHP 连接 MSSQL
    php mssql 中文各种乱码
    百度地图逆地址解析
    Microsoft Visual C++ 2015 Redistributable(x64)
    服务器 vps 空间
    Python之路【第二篇】:Python基础(二)
    Python之路【第一篇】:Python简介和入门
    2016年会成为Java EE微服务年吗?
  • 原文地址:https://www.cnblogs.com/benxintuzi/p/4619300.html
Copyright © 2020-2023  润新知