首页 > 其他分享 >Makefile基础教程(自动生成依赖关系)

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

时间:2023-06-08 11:02:33浏览次数:24  
标签:依赖 头文件 基础教程 makefile Makefile 命令 sed file DEPS

@TOC


前言

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

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

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

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

makefile:

OBJS := fun.o main.o 

hello : $(OBJS)
	gcc -o $@ $^

$(OBJS): %.o : %.c
	gcc -o $@ -c $^

运行结果:

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

Makefile基础教程(自动生成依赖关系)_头文件_02

那么这样就需要将头文件包含进来: 将头文件的依赖包含进来后就能够成功编译。

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文件及其相关的头文件清单:

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

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

Makefile基础教程(自动生成依赖关系)_sed命令_04

三、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基础教程(自动生成依赖关系)_sed_05

四、makefile中命令的执行机制

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

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

组合的命令依次在同一个进程中被执行 下面编写一个makefile验证:

all : 
	mkdir test
	cd test
	mkdir test1

执行结果:

Makefile基础教程(自动生成依赖关系)_sed命令_06

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

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

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

运行结果:

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

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

编写下面的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)

运行结果:

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

Makefile基础教程(自动生成依赖关系)_头文件_09

总结

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

标签:依赖,头文件,基础教程,makefile,Makefile,命令,sed,file,DEPS
From: https://blog.51cto.com/u_16153875/6438360

相关文章

  • 【解决问题】libevent 编译时报错 Makefile:1708: test/.deps/test_regress-tinytest.
    1开发环境linux版本:统信UOS1030(可以认为是特殊的ubuntu)开发语言:C++2报错现象截图:报错语句:make:进入目录“/home/depend/libevent-2.1.11-stable”Makefile:1708:test/.deps/test_regress-tinytest.Po:没有那个文件或目录make:***没有规则可制作目标“te......
  • 解决使用yarn安装依赖出现“The engine "node" is incompatible with this module. Ex
    1、问题描述某天在使用yarn安装依赖的时候,突然出现如下错误导致安装依赖终止:Theengine"node"isincompatiblewiththismodule.Expectedversion"^14.18.0||^16.14.0||>=18.0.0".Got"17.9.0"2、解决办法使用如下命令忽略错误:yarnconfigsetignore-enginestr......
  • WPF学习笔记一 依赖属性及其数据绑定
    本文想通过由浅入深的讲解让读者比较深的理解依赖属性. 首先,我们回顾一下依赖属性的发展历史. 最初,人们提出面向对象编程时,并没有属性这个说法,当时叫做成员变量.一个对象由成员变量和成员函数组成,如下:PublicClassA{PublicintIndex;//成员变量PublicvoidFu......
  • Spring 学习笔记(4)—— Bean 的基本配置、依赖注入(DI)、注入参数引用其他Bean
    一、Bean的基本配置1装配一个Bean在Spring容器的配置文件中定义一个简要Bean的配置片段2Bean的命名二、依赖注入1属性注入属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。2构造函数注入按索引匹配入参三、注入参数引用其他Bean......
  • Jmeter-依赖登录的接口测试
    JMETER接口测试问题解决二之后续接口请求依赖登录接口的操作-知识在于点滴的积累-博客园(cnblogs.com)问题现象:必须登录才能测试其他接口解决办法:    用到了http授权管理器和httpcookie管理器。注意:  要先判断当前的登录的token是在header中的Authorizat......
  • Jmeter-依赖上一个接口的响应数据
    问题:  下一个接口的入参需要依赖上一个接口的响应.如: 修改客户请求需要依赖添加客户请求响应中的id 1. 在上一个接口的请求中添加后置处理器:2. 将响应中的出参设置为变量 3. 在下一个接口的请求中使用变量  4. 请求成功  ......
  • RDS 、HDFS、 mapreduce 、spark 、hive、 hbase 、zookeeper 、kafka 、flume、mysql
    这些技术是大数据领域的常用组件,它们之间的配置文件依赖关系如下:RDS是一种关系型数据库,可以独立安装和使用,不需要依赖其他组件。HDFS是Hadoop分布式文件系统,通常与MapReduce一起使用。在Hadoop集群中,HDFS需要配置core-site.xml和hdfs-site.xml两个文件,其中core-site......
  • Maven project 中,运行时获取某依赖的版本号
    <dependency> <groupId>cn.xs</groupId> <artifactId>qishi-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>  // D:\mvnrepository\cn\xs\qishi-api\0.0.1-SNAPSHOT\qishi-api......
  • Bean的循环依赖问题
    1. 什么是Bean的循环依赖  54A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你,你也依赖我。比如:丈夫类Husband,妻子类Wife。Husband中有Wife的引用。Wife中有Husband的引用。packagecom.powernode.spring6.bean;/***什么是Bean的循环依赖54*丈夫类54**......
  • Flutter依赖注入
    依赖注入依赖注入(DependencyInjection,简称DI)是一种软件设计模式,它的主要目的是将对象之间的依赖关系解耦,使得代码更加可维护、可测试、可扩展,使得代码更易于维护和测试。在Flutter中,DI可以帮助我们管理应用程序中的各种依赖关系,包括服务、数据存储和UI组件等。在DI模式中,我们将......