Makefile基础教程(自动生成依赖关系)

简介: Makefile基础教程(自动生成依赖关系)

前言

在前面的文章中我们都只使用到了.c文件作为依赖但是在实际的工程中肯定是不可能只有.c文件的还存在.h文件,那么在包含了.h文件后又该如何来包含依赖关系呢?


一、makefile不包含.h依赖的后果

首先先在目录下新建四个文件夹,其中就包含了fun.h这个文件。

makefile:

OBJS := fun.o main.o 
hello : $(OBJS)
  gcc -o $@ $^
$(OBJS): %.o : %.c
  gcc -o $@ -c $^

运行结果:

通过运行结果可以发现不包含.h文件的依赖,将没有办法找到头文件。

那么这样就需要将头文件包含进来:

将头文件的依赖包含进来后就能够成功编译。

OBJS := fun.o main.o 
hello : $(OBJS)
  gcc -o $@ $^
$(OBJS) : %.o : %.c fun.h
  gcc -o $@ -c $<

那么这也带来了一个问题,这里是只有一个.h头文件,在实际项目中肯定会有成千上万的头文件,当有很多头文件时也是需要一个个来进行添加吗?这样添加肯定会导致makefile的移植性降低,而且不容易维护。

那么如何自动的生成依赖关系呢?下面先做一些预备知识,我们这篇文章将会完成自动生成依赖关系。


二、gcc -M 和 gcc -MM命令

gcc -M命令会根据输入的源代码文件,输出这个源文件及所包含的头文件清单。例如,下面的命令会输出main.c文件及其相关的头文件清单:

gcc -MM命令与gcc -M命令类似,但会自动忽略掉标准库的头文件。例如,下面的命令会输出main.c文件及其相关的头文件清单(忽略标准库的头文件):

三、sed命令

sed是一种流文本编辑器,常用于在Linux系统中进行文本处理。sed可以对文本文件进行修改、替换、删除、添加等操作。使用sed命令可以方便地批量处理大量的文本文件。

sed命令的基本用法如下:

sed options ‘commands’ file

其中,options是sed的选项,'commands’是需要执行的命令(可以是多个命令),file是需要处理的文件名。如果没有指定文件名,sed命令会从stdin中读取文本。

常用的sed命令如下:

替换文本

sed ‘s/原文本/新文本/’ file

这个命令将会把file文件中的所有"原文本"替换成"新文本",并输出修改后的文本。如果需要替换所有的原文本,可以在s命令后加上"g"选项,如下所示:

sed ‘s/原文本/新文本/g’ file

删除行

sed ‘行号d’ file

这个命令将会删除file文件中指定行号的内容,并将剩余内容输出。

插入文本

sed ‘行号i\插入文本’ file

这个命令将会在file文件的指定行号前插入一行文本,并输出修改后的文本。

列出行号

sed ‘=’ file

这个命令将会在file文件的每一行前输出行号。

执行脚本

sed -f script.sed file

这个命令将会执行脚本文件script.sed中的命令,对file文件进行处理。

上述仅是sed命令的一部分,sed具有其他更多的选项和用法。在实际应用中,我们可以根据需要灵活运用sed命令,对文本数据进行快速、方便的处理。

下面来使用一下sed命令的修改功能:


四、makefile中命令的执行机制

在makefile中规则中的每个命令默认是在一个新的进程中执行(shell)

可以通过接续符(;)将多个命令组合成一个命令

组合的命令依次在同一个进程中被执行

下面编写一个makefile验证:

all : 
  mkdir test
  cd test
  mkdir test1

执行结果:

通过执行结果可以发现test1并不是在test里面创建的,但是我们这样写makefile的本意就是让他在test里面创建一个test1子文件夹,这样的运行结果是为什么呢?这是因为在makefile中规则中的每个命令默认是在一个新的进程中执行(shell)。

要想让这些命令在同一个进程下执行的话可以使用set -e命令。

修改后的makefile:

all : 
  set -e;\
  mkdir test;\
  cd test;\
  mkdir test1

运行结果:

四、生成依赖文件并单独放入文件夹中

编写下面的makefile为每一个文件都生成对应的依赖,并存放在deps文件夹中。

.PHYON : all clean
CC := gcc
MKDIR := mkdir
RM := rm -rf
DIR_DEPS := deps
SRCS := $(wildcard *.c)
DEPS := $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
include $(DEPS)
all : 
  @echo all
$(DIR_DEPS) :
  $(MKDIR) $@
$(DIR_DEPS)/%.dep : $(DIR_DEPS) %.c
  @echo "Creating $@ ..."
  @set -e;\
  $(CC) -MM -E $(filter %.c, $^) | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g' > $@
clean :
  $(RM) $(DIR_DEPS)

运行结果:


总结

本篇文章讲述了如何自动生成依赖关系这对我们后面项目的构建是非常重要的。

相关文章
|
7月前
|
程序员 Linux C语言
【cmake 项目依赖冲突】CMake进阶:优雅解决目标依赖和安装问题
【cmake 项目依赖冲突】CMake进阶:优雅解决目标依赖和安装问题
448 0
|
7月前
|
C语言 C++
win32编程 -- 编写静态库空项目
win32编程 -- 编写静态库空项目
35 0
|
Shell
如何使用makefile
如何使用makefile
|
Java 数据库连接 API
Gradle依赖管理:编译时和运行时依赖的区别
Gradle依赖管理:编译时和运行时依赖的区别
115 0
|
C++
2022-9-28-CMAKE工程中Cmakelist文档编写的一些注意点
2022-9-28-CMAKE工程中Cmakelist文档编写的一些注意点
110 0
|
安全 编译器 测试技术
C/C++项目构建指南:如何使用Makefile提高开发效率
Makefile是一个常用的自动化构建工具,它可以为开发人员提供方便的项目构建方式。在C/C++项目中,Makefile可以用来编译、链接和生成可执行文件。使用Makefile的好处是可以自动执行一系列命令,从而减少手动操作的复杂性和出错的可能性。此外,Makefile还可以根据源代码的修改情况,自动更新目标文件,从而提高了构建的效率和准确性
152 0
|
Linux 编译器 C语言
Linux驱动开发笔记(一):helloworld驱动源码编写、makefile编写以及驱动编译基本流程
基于linux的驱动开发学习笔记,本篇是描述了一个字符驱动的基础开发流程,以便做嵌入式开发多年的应用或者系统学习驱动开发。
|
XML 编译器 数据格式
xml开发笔记(一):tinyXml2库介绍、编译和工程模板
xml开发笔记(一):tinyXml2库介绍、编译和工程模板
xml开发笔记(一):tinyXml2库介绍、编译和工程模板
|
IDE 开发工具 C语言
xmake入门,构建项目原来可以如此简单
前言 在开发xmake之前,我一直在使用gnumake/makefile来维护个人C/C++项目,一开始还好,然而等项目越来越庞大后,维护起来就非常吃力了,后续也用过一阵子automake系列工具,并不是很好用。
1531 0