前言
在前面的文章中我们都只使用到了.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)
运行结果:
总结
本篇文章讲述了如何自动生成依赖关系这对我们后面项目的构建是非常重要的。