Linux:自动化构建 - make

简介: Linux:自动化构建 - make

make基本概念

make是一个用于自动化编译和构建过程的工具。它主要用于管理大型软件项目的构建过程,帮助开发者更高效地编译和部署代码,并减少人为错误的发生,这使得软件的编译和部署变得更加自动化和可靠。

其中make是一个命令,执行该命令需要当前操作目录下有一个名为makefile或者Makefile的文件,在makefile内部编写指令,随后就可以通过make快速执行一系列的指令了。

当前目录下有一个test.c文件,需要把该文件编译为可执行文件mybin。该过程就可以用make来

自动执行。我先编写一个makefile,然后再讲解,代码如下:

mybin:test.c
    gcc -o mybin test.c
clean:
    rm -f mybin   

其中我们可以看到两条熟悉的指令:gcc -o mybin test.c,该指令完成把test.c文件编译为可执行文件mybinrm -f mybin,该指令完成对mybin的删除。

有了这个文件后,我们就可以直接输入make,完成对test.c的编译:

一开始目录下只有makefiletest.c两个文件,执行指令make后,Linux自动执行了指令gcc -o mybin test.c,最后目录中就出现了编译好的可执行文件mybin

我们也可以输入make clean,完成对mybin的删除:

执行make clean后,Linux自动执行了指令rm -f mybin,完成了mybin的删除。

看到其大致是如何执行后,我现在讲解以上代码中各个部分的作用是啥。

mybin:test.c
    gcc -o mybin test.c
  • mybin:test.c:这个由两个文件名通过一个:隔开的整体,叫做依赖关系。左侧的mybin叫做目标文件,右侧的test.c叫做依赖文件列表
  • gcc -o mybin test.c:这个语句叫做依赖方法

那么依赖关系目标文件依赖文件列表依赖方法之间有什么关系呢?

  1. 目标文件:
  • 目标文件是 make 命令要生成的文件,通常是可执行程序、库文件或中间目标文件。
  • 每个目标文件都有一条或多条命令来生成它。
  • 目标文件可以有多个依赖文件,这些依赖文件共同决定了目标文件的生成过程。
  1. 依赖文件列表:
  • 依赖文件列表描述了目标文件所依赖的输入文件,如源代码文件、头文件、库文件等。
  • 依赖文件列表告诉 make 哪些文件的变化会导致目标文件需要重新生成。
  • 依赖文件列表可以包含多个文件,用空格分隔。
  1. 依赖关系:
  • 目标文件与其依赖文件之间形成依赖关系。
  • 如果依赖文件中任何一个文件发生变化,目标文件就需要重新生成。
  • 依赖关系可以形成层次结构,实现文件之间的层次依赖。
  1. 依赖方法:
  • 依赖方法是生成目标文件所需执行的命令。
  • 依赖方法通常是 shell 命令,用于编译、链接等操作。
  • 依赖方法可以包含多条命令,每条命令用回车分隔。

这里要注意,依赖方法前面必须用一个Tab键隔开,不可以是四个空格。

再看到后半段:

clean:
    rm -f mybin

该代码中,目标文件是clean,没有依赖文件列表,依赖关系是删除mybin的指令。只要执行make clean就会执行后面的代码rm -f mybin ,从而实现文件的删除。


左侧的目标文件clean叫做伪目标,伪目标是 make 中的一种特殊目标,它不对应任何文件,只是用来执行一些命令。常见的伪目标有 all、clean、install 等。

那么现在有一个问题,为什么执行mybin:test.c直接使用make就可以,但是make clean才能执行clean呢?

make后面不接任何内容时,则在makefile中从上往下查找,找到第一个依赖关系执行

现有如下makefile

mybin:test.o
    gcc -o mybin test.o
test.o:test.s
    gcc -c -o test.o test.s
test.s:test.i
    gcc -S -o test.s test.i
test.i:test.c
    gcc -E -o test.i test.c

clean:
    rm -f test.i test.s test.o mybin

该文件完成了一个连续的C语言程序编译链接过程,但是其有一个问题在于,C语言编译过程应该依次生成.i,.s,.o文件,最后生成mybin。第一条依赖关系执行的时候,就缺少test.o文件,第二条依赖关系缺少test.s文件,以此类推,整个编译过程都是反的。那么该makefile可以执行成功吗?

我们试试:

可以看到,其执行成功了,这是为什么?我只输入了make指令,按理来说应该只执行第一条依赖关系,为什么除了clean的所有依赖关系都被执行了?

make会根据文件的依赖关系进行自动推导,以正确的顺序执行各个依赖关系

比如说一开始mybin缺少了test.o,于是make去makefile中查找,发现test.o:test.s的依赖关系可以生成test.o于是先执行该依赖关系。但是test.o:test.s的依赖关系缺少test.s,就再去找生成test.s的依赖关系,以此类推。

makefile语法

以上我们只简单讲解了一个基本的makefile例子,来帮助大家理解make,现在我们来讲解更多的makefile语法。

首先,在makefile中,指令内部的目标文件可以用$@代替,依赖文件列表可以用$^代替:

mybin:test.c
    gcc -o $@ $^  

在这里gcc -o $@ $^ gcc -o mybin test.c 是一样的。

变量

makefile中,是可以定义变量的,只需要用一个等号进行赋值即可:

bin=mybin
src=test.c

此时bin的值就是mybinsrc的值就是test.c,想要使用这个变量,就在对应的地方以$(变量名)的形式代替即可,这个变量可以放在任何地方,包括指令内部,依赖关系中等等。

比如下面这样:

bin=mybin
src=test.c

$(bin):$(src)
    gcc -o $(bin) $(src)

clean:
    rm -f $(bin)

任何需要test.cmybin的地方,都可以改为$(bin)$(src)


PHONY

讲解PHONY前,我们看到一个问题:

现在我们每次make都会生成一个mybin文件,如果直接gcc -o mybin test.c,那么新生成的mybin文件会覆盖原先的文件。但是make执行的指令,会进行一次检查,如果源文件test.c没有进行更新,那么make就会拒绝再次编译这个文件,因为编译出来的结果是一样的,导致mybin无法连续编译两次。

也就是上图中我们连续两次make,第二次拒绝了我们的原因。

PHONY在Makefile中是一个非常有用的特殊目标。当make执行到PHONY目标时,它会无条件执行该目标下定义的命令,而不会检查是否有同名的文件在。

因此我们就可以对mybin使用这个PHONY,让它强制执行命令,不论当前目录下有没有mybin。

修饰语法:

.PHONY:xxx

此时xxx对应的命令就会被强制执行。

makefile写法:

.PHONY:mybin
mybin:test.c
  gcc -o mybin test.c

此时mybin每次都会强制执行命令,不论之前是否存在mybin文件了。

但是这并不是PHONY的主要用途,其主要用于修饰伪目标。比如伪目标clean,如果当前目录下刚好有一个叫做clean的文件,那么clean作为一个目标文件,就有可能会被make禁止执行。可是我们的clean作为一个伪目标,其目的不是生成一个clean文件,而是执行命令,因此要用PHONY来强制执行clean对应的命令:

.PHONY: clean
clean:
    rm -rf *.o


相关文章
|
27天前
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
60 10
|
15天前
|
运维 监控 安全
构建高效运维体系:从监控到自动化的全方位实践
本文深入探讨了构建高效运维体系的关键要素,从监控、日志管理、自动化工具、容器化与微服务架构、持续集成与持续部署(CI/CD)、虚拟化与云计算以及安全与合规等方面进行了全面阐述。通过引入先进的技术和方法,结合实际案例和项目经验,为读者提供了一套完整的运维解决方案,旨在帮助企业提升运维效率,降低运营成本,确保业务稳定运行。
|
13天前
|
机器学习/深度学习 运维 Prometheus
构建高效运维体系:从自动化部署到智能监控的全方位实践
在当今数字化时代,企业对运维效率和稳定性的要求越来越高。本文将探讨如何构建一个高效的运维体系,从自动化部署、持续集成与持续交付(CI/CD)、智能监控、故障管理以及数据驱动决策等方面进行深入分析和实践指导。通过这些方法,企业可以实现更快速、更可靠的软件发布和问题解决,提升整体运营效率。
|
9天前
|
敏捷开发 运维 Prometheus
构建高效运维体系:从基础架构到自动化管理
本文探讨了如何通过优化基础架构、引入自动化工具和流程,以及加强团队协作,构建高效的运维体系。通过案例分析和实践建议,帮助运维人员实现系统的稳定性、可靠性和可维护性。
|
3天前
|
机器学习/深度学习 运维 Cloud Native
构建高效运维体系:从自动化到智能化的演进之路
在当今数字化时代,运维作为信息技术的重要支柱,其效率与创新能力直接关系到企业信息系统的稳定性和业务连续性。本文将探讨如何通过技术手段,实现运维从传统手工操作向自动化、智能化的转变,进而构建一个高效、可靠的运维体系。我们将从自动化工具的应用开始,逐步深入到智能运维的实践,最终展望云原生架构下的运维未来趋势。
|
7天前
|
机器学习/深度学习 人工智能 运维
构建高效运维体系:从自动化到智能化的演进之路
在当今数字化时代,运维作为保障企业IT系统稳定运行的关键环节,正经历着前所未有的变革。本文将探讨如何通过实施自动化和引入智能化技术,构建一个更加高效、可靠的运维体系,以应对日益复杂的业务需求和技术挑战。
18 1
|
17天前
|
存储 运维 监控
构建高效运维体系:从监控到自动化的全方位实践指南
在当今数字化时代,企业对运维(Operations)的需求日益增长。运维不仅仅是保持系统运行那么简单,它涉及到监控、日志管理、故障排除、性能优化和自动化等多个层面。本文将从实际操作的角度出发,详细探讨如何构建一个高效的运维体系。通过具体案例,我们将了解不同运维工具和方法的应用,以及它们是如何帮助企业提高生产效率和降低运营风险的。无论你是刚接触运维的新手,还是经验丰富的专家,这篇文章都将为你提供宝贵的参考和启示。
|
17天前
|
机器学习/深度学习 运维 安全
构建高效运维体系:从自动化到智能化的演进之路
在数字化转型的浪潮中,运维管理作为信息技术基础设施的重要支柱,正经历着从传统手工操作向自动化、智能化的深刻变革。本文将探讨如何通过引入自动化工具和平台,实现运维流程的标准化与效率提升;进而利用大数据分析和人工智能技术,迈向预测性维护和智能决策支持的高级阶段。通过案例分析,揭示成功转型的关键因素,为运维专业人士提供一套可借鉴的升级路径。
|
15天前
|
机器学习/深度学习 人工智能 运维
构建高效运维体系:从自动化到智能化的演进之旅
在当今数字化时代,运维作为信息技术领域的核心组成部分,其重要性日益凸显。随着企业业务的不断扩展和技术的日新月异,传统手工运维方式已难以满足现代IT架构的需求。因此,构建一个高效、智能的运维体系成为业界共识。本文将探讨如何通过自动化和智能化手段,实现运维效率的质的飞跃,并分享一些成功案例与实践经验。
|
20天前
|
机器学习/深度学习 运维 监控
构建高效运维体系:从自动化到智能化的演进
在当今信息技术飞速发展的时代,运维领域正经历着从传统手动操作向高度自动化和智能化转变。本文旨在探讨如何通过集成自动化工具、实施持续集成与持续部署(CI/CD)、采用容器化技术和探索AIOps实践,构建一个高效、可靠的运维体系。我们将分析这些技术如何相互配合,提升运维效率,降低系统故障率,并实现快速响应市场变化的能力。通过案例分析和最佳实践的分享,本文将为IT专业人员提供一套实用的指南,帮助他们在数字化转型的浪潮中,保持运维工作的前瞻性和竞争力。
下一篇
无影云桌面