• 嵌入式Linux应用开发基础知识(三)——Makefile入门


    使用keil、mdk、avr等工具开发时,点点鼠标就可以编译了,但是你是否理解它的内部机制呢?它是怎么组织管理程序的?怎么决定编译哪一个文件的?这些其实都是和Makefile息息相关

    一、Makefile作用

    说起作用的话,得看看我们平时怎么使用GCC进行编译,比如我们需要编译main.c和sub.c生成可执行程序test, 那么我们有两种方式进行编译:

    • 方式一: 直接使用gcc -o test main.c sub.c进行编译
    • 方式二:使用gcc -c -o main.o main.c 和gcc -c -o sub.o sub.c生成main.o和sub.o OBJ文件,然后使用gcc -o test main.o sub.o生成可执行文件test

    方式一用于源文件比较少的程序,方式二用于源文件比较多的程序。但是如果源文件很多时,我们一条一条输入命令就变得很不高效。这时我们的Makefile就起作用了。
    Makefile可以根据文件的更新时间选择性的进行执行相应的命令。

    二、Makefile规则

    Makefile的书写框架如下:

    目标1:依赖1 依赖2 ...
    【TAB】命令1
    目标2:依赖3 依赖4 ...
    【TAB】命令2
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Makefile的执行情况如下:

    • 当"目标文件"不存在或者依赖文件比目标文件更新时间更新时,则执行"命令", 注意如果依赖1和依赖2文件不存在,Makefile会先跳过相关的命令,在下方查找相关依赖文件,如果还是查找不到相关的依赖文件,那么编译报错。

    三、Makefile实验

    源程序如下:
    main.c

    #include <stdio.h>
    #include "sub.h"
    
    int main(int argc, char *argv[])
    {
           int i;
           printf("Main fun!\n");
           sub_fun();
           return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    sub.c

    void sub_fun(void)
    {
           printf("Sub fun!\n");
    }
    
    • 1
    • 2
    • 3
    • 4

    3.1 Makefile文件书写

    Makefile文件我们一般是按照命令的执行顺序进行编写,首先第一行是最后执行的命令,如:
    gcc -o test main.o sub.o 可见目标文件为test 依赖为 main.o sub.o
    则第一部分如下:

    test : main.o sub.o
    	gcc -o test main.o sub.o
    
    • 1
    • 2

    随后部分就是依次生成目标文件
    生成main.o如下:

    main.o : main.c
    	gcc -c -o main.o main.c
    
    • 1
    • 2

    生成sub.o如下:

    sub.o : sub.c
    	gcc -c -o sub.o sub.c
    
    • 1
    • 2

    合并之后的Makefile:

    test : main.o sub.o
    	gcc -o test main.o sub.o
    main.o : main.c
    	gcc -c -o main.o main.c
    sub.o : sub.c
    	gcc -c -o sub.o sub.c
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Makefile执行过程为,先判断test是否存在,不存在则想执行命令, 发现main.o和sub.o也不存在,,那么会往下查找这两个文件,发现main.o 依赖main.c 那么执行gcc -c -o main.o main.c, 发现sub.o 依赖sub.c 执行gcc -c -o sub.o sub.c, 再返回执行gcc -o test main.o sub.o
    如下图为执行的顺序图
    在这里插入图片描述

    接着我们试图修改main.c,再次编译:
    在这里插入图片描述
    编译过程为判断main.o和sub.o有没有更新,发现main.o依赖main.c, main,c有更新,那么需要执行gcc -c -o main.o main.c, 发现sub.o依赖sub.c, 而sub.c没有更新,那么不执行,再发现main.o有更新了, 那么需要执行gcc -o test main.o sub.o 。

    为了再次验证makefile是不是根据时间来更新的,我们这里使用ls -l查看文件的时间,和使用touch来更新文件时间,重新编译:
    在这里插入图片描述

    和我们想的一样

  • 相关阅读:
    JuiceFS 在多云存储架构中的应用 | 深势科技分享
    Linux提权
    FluentValidation在C# WPF中的应用
    [ 目标检测 ] 经典网络模型——性能评价指标 AP、mAP
    基于深度优先搜索的图遍历
    使用docker快速安装开发环境
    netty基本用法, 拆包、粘包等常见解决方案,看本文即可,不做原理说明,只进行实战操作
    09.Json语法
    Node.js躬行记(21)——花10分钟入门Node.js
    BadUsb程序大全-值得收藏
  • 原文地址:https://blog.csdn.net/FourLeafCloverLLLS/article/details/126185858