侧边栏

Makefile实例讲解

库函数(Library Functions):

  • 库函数是一组相关的函数,它们被封装在一个或多个源文件中,并被组织成一个单独的库文件。
  • 库函数的目的是提供一种可重用的方式来实现特定的功能。这些功能可以是通用的,如字符串处理、数学运算等,也可以是特定领域的,如图像处理、网络通信等。
  • 在一个项目中,如果多个文件需要使用相同的功能,可以将这些功能封装成库函数,然后在需要的地方调用它们,从而避免重复编写相同的代码。

例如:

左图:其中 max.c和Swap.c都是可以打开文件查看的。gcc main.c -o bin/main 生成main可执行文件  

右图: 把max.c和Swap.c制作成库函数libmy_lib.a,里面包含了max.c和Swap.c的内容。gcc src/*.c -I./inc -L./lib -lmy_lib -o bin/main 生成main可执行文件

注意:max.h和swap.h按理说可以删除,但是最好不要,因为可以提供开发人员库函数的声明,以及库函数使用的说明帮助。

      

makefile:

1.在当前文件夹中只有Makefile,代码如下图,运行make后会输出

ChuiHua:
Jacy:ChuiHua
Even:Jacy

再运行make还是一样,最后文件夹只会有Makefile这一个文件,并不会创建ChuiHua等文件。

2.如果touch  ChuiHua后(当前文件夹中只有ChuiHua和Makefile),再make,输出

Jacy:ChuiHua
Even:Jacy

3.如果touch  Jacy后(当前文件夹中只有Jacy和Makefile),再make,输出

ChuiHua:
Jacy:ChuiHua
Even:Jacy

 总结:只要是目标和依赖都串联的,那么就会从最后一个依赖/目标开始检查!另外在3中,如果touch  Jacy后(当前文件夹中只有Jacy和Makefile),再make

Makefile是这样工作的:先到最后一个目标ChuiHua,发现没有ChuiHua文件那么执行echo "ChuiHua:",然后会更新ChuiHua目标的时间戳(并不是文件的时间戳),因此ChuiHua比Jacy新,所以执行

echo "Jacy:ChuiHua",更新Jacy目标的时间戳(不是文件的时间戳),因此Jacy比Even新,所以执行echo "Even:Jacy"。

book@100ask:/mnt/hgfs/vscode/my_code/09 JPEG/azq$ touch ChuiHua
book@100ask:/mnt/hgfs/vscode/my_code/09 JPEG/azq$ touch Jacy
book@100ask:/mnt/hgfs/vscode/my_code/09 JPEG/azq$ touch Even
book@100ask:/mnt/hgfs/vscode/my_code/09 JPEG/azq$ make

结果一定是------make: 'Even' is up to date.因为Even>Jacy>ChuiHua(时间新的程度)

用xxx.c ------xxx.o-----main(可执行文件)代入就可以更加清楚。因为主要是在这个方面使用Makefile。

------------------------------------------------------------------------------开始Makefile实例讲解

 

makefile的作用:

对于大型项目来说,通常只有少量的源文件会被频繁修改,而大多数源文件保持不变。因此,在每次构建过程中,只有那些被修改过的源文件需要重新编译成 .o 文件,而其他未被修改的源文件对应的 .o 文件仍然有效。

因此,相比之下,被修改过的 .c 文件的数量通常要少于整个项目的 .c 文件的数量,因为只有这些被修改过的文件需要重新编译。这就是为什么在大型项目中,make 工具通常会根据 .o 文件的时间戳来判断哪些文件需要重新编译,以提高构建的效率。

 

这是示例代码:

https://files.cnblogs.com/files/luckyleon/%E7%A4%BA%E4%BE%8B%E4%BB%A3%E7%A0%81.zip?t=1710574135&download=true

项目结构:

  1. include 目录:

    • jconfig.h, jerror.h, jmorecfg.h, jpeglib.h: 这些是 JPEG 图像处理库的头文件,用于声明函数和数据结构。
  2. lib 目录:

    • libjpeg.a, libjpeg.la, libjpeg.so.9.3.0: 这些是 JPEG 图像处理库的实现文件,包含了函数的定义和实现代码。
  3. lcd.c 和 lcd.h 文件:

    • lcd.c 提供了 LCD 相关功能的实现代码。
      • lcd.c 中的函数使用到其他的库函数,这些库函数的声明位于 include/ 目录下的头文件中。这些头文件用于告诉编译器库函数的接口(函数原型、宏定义等),以便在编译时进行类型检查和函数调用检查。
    • lcd.h 包含了 LCD 相关功能的声明,供其他文件引用。
  4. main.c 文件:

    • main.c 中使用了 lcd.c 中定义的函数。这表明 lcd.c 提供了一些功能,而 main.c 利用了这些功能来完成特定任务。
  5. Makefile 文件:

    • Makefile 中包含了自动化构建项目的规则,其中定义了编译器、编译选项、源文件、目标文件以及编译和链接的规则。

 

Makefile代码:

这里有错误,应该是所有的T改为TARGET!!!!!

 

main.c 文件发生改变时,根据 Makefile 的运行步骤,可以如下说明:

  1. Makefile 中的变量定义:

    • CC=arm-linux-gcc:定义了编译器为 arm-linux-gcc
    • T=WangDaNiang:定义了最终的目标文件名为 WangDaNiang
    • CONFIG=-I./include -L./lib -ljpeg:定义了编译选项,包括头文件路径 -I./include、库文件路径 -L./lib 和链接的库文件 -ljpeg
    • SRCS=$(wildcard *.c):使用 wildcard 函数获取当前目录下的所有 .c 文件。
    • OBJS=$(patsubst %.c, %.o, $(SRCS)):将所有的 .c 文件名替换成对应的 .o 文件名。
  2. 生成目标文件:

    • 当执行 make 命令时,Make 工具会按照 Makefile 中定义的规则进行操作。
    • 首先,它会检查所有的依赖关系,如果有任何一个依赖文件比目标文件更新,或者目标文件不存在,那么就需要重新生成目标文件。
    • 因为 main.c 发生了改变,因此它的修改时间会比 main.o 更新,这会导致 Make 工具认为需要重新生成 main.o 文件。
  3. 编译目标文件:

    • Make 工具会执行 main.o 文件的编译规则:%.o:%.c
    • 即使 main.o 已经存在,但由于 main.c 文件发生了改变,根据规则,Make 工具会重新编译 main.o 文件。
  4. 链接目标文件:

    • 当所有的 .o 文件都重新生成之后,Make 工具会执行链接操作,生成最终的可执行文件 WangDaNiang
    • 在链接过程中,Make 工具会检查所有的依赖关系,如果发现有任何一个依赖文件比目标文件更新,或者目标文件不存在,那么就需要重新生成目标文件。
    • 因为 WangDaNiang 依赖于所有的 .o 文件,而 main.o 已经重新生成,所以 WangDaNiang 也会被重新生成。

综上所述,即使 WangDaNiang 比其他 .o 文件新,但由于 main.c 文件发生了改变,导致 main.o 文件重新生成,进而影响到 WangDaNiang 的重新生成。

posted @ 2024-03-16 14:55  LeonVK  阅读(25)  评论(0)    收藏  举报