代码改变世界

Makefile学习笔记

2019-03-18 15:03  剑动情缥缈  阅读(282)  评论(0编辑  收藏  举报

一、C程序编译过程

  1.源码结构

  

// test.c
#include <stdio.h>
#include "mymath.h"// 自定义头文件
int main(){
    int a = 2;
    int b = 3;
    int sum = add(a, b); 
    printf("a=%d, b=%d, a+b=%d\n", a, b, sum);
}
// mymath.h
#ifndef MYMATH_H
#define MYMATH_H
int add(int a, int b);
int sub(int a, int b);
#endif
// mymath.c
#include<mymath.h>
int add(int a, int b){
    return a+b;
}
int sub(int a, int b){
    return a-b;
}

  2.编译流程

   

  a.预处理:进行宏替换、include文件展开等工作

  命令:gcc -E -I./inc test.c -o test.i

  观察:对include内容进行展开,从几行程序扩展成为800+行程序,如将#include<mymath.h>这行代码展开为mymath.h文件中的具体内容,仍然为C语言程序

  

  b.编译:将预处理后的程序编译为汇编代码

  命令:gcc -S -I./inc test.c -o test.s

  结果:

  

  c.汇编:将汇编代码翻译为机器码,每一个源文件均会生成一个.o文件

  命令:gcc -c test.s -o test.o

  d.链接:多个目标文.o以及所需的库文件(.so等)链接成最终的可执行文件

  命令:ld -o test.out test.o inc/mymath.o  ...libraries...

  可替换命令:gcc -o test.out test.o inc/mymath.o

  静态链接与动态链接:

  • 静态链接:函数代码将从其所在的静态链接库中被拷贝到最终的可执行程序中。
  • 动态链接:链接程序此时所做的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的信息,在可执行程序被执行时,动态链接库(.so)的全部内容将被影射到运行时相应进程的虚拟地址空间。动态链接程序将根据可执行程序中记录的信息找到对应的函数代码。

  

  3.名词解析

  

二、Makefie

  1.规则:prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。

  • target:目标文件、.o文件或者标签
  • prerequisites:生成目标所依赖的文件,可以为.o、.c或者.h
  • command:该target需要执行的命令,可以为任意shell命令
target ... : prerequisites ...
    command
    ...
    ...

 

  2.工作过程

  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 了。

  3.显示(隐式)规则、使用变量、自动推导、引用其他makefile(#include<filename>)等

  4.clean

  1).PHONY表示伪目标文件

  2)-rm中的-:若出现问题,则忽略

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

参考:

  https://www.cnblogs.com/CarpenterLee/p/5994681.html

  https://www.jianshu.com/p/4dfa5dea63b5