Makefile 和 Bash 脚本之间区别和联系

        我们在使用unix/linux的过程中,经常会碰到Makefile Bash 脚本,它们长得都比较像,很多命令还是相同的,那么,它们的命令是不是可以通用?有什么区别呢?

一、Makefile 和 Bash 脚本的定义

(一)Bash 脚本

        Bash 脚本是一种使用 BashBourne Again SHellshell 编写的脚本文件。Bash 是一种流行的 Unix shell,它提供了丰富的命令行界面和强大的编程功能。Bash 脚本通常包含一系列命令,这些命令按照特定的顺序执行,以实现特定的任务或自动化过程。

(二)Makefile

        Makefile是为 Make 工具设计的,Make 工具用于控制编译和构建过程,特别是在大型项目中。Makefile 包含了一组规则和命令,这些规则和命令告诉 Make 如何从源代码生成目标文件(通常是可执行文件或库文件)。

二、Makefile 和 Bash 脚本的相同之处

1、自动化任务

        两者都可以用来自动化重复性或定期性的任务,从而减少手动操作的错误并提高效率。

2、脚本语言

        它们都是基于文本的脚本语言,可以通过编辑文本文件来创建和修改。

3、条件判断和循环

        Makefile和Bash脚本都支持条件判断和循环结构,使得脚本能够根据不同的条件执行不同的操作。

4、依赖管理

        两者都可以在某种程度上管理依赖关系。在Bash脚本中,可以通过命令的顺序来隐式地管理依赖。而在Makefile中,有一个更明确的依赖管理系统。

        另外,在 Makefile 中可以调用 Bash 脚本,或者在 Makefile 中直接写入 Bash 命令。这使得在构建过程中执行更复杂的任务成为可能。

三、Makefile 和 Bash 脚本的不同点

以下是 Makefile Bash 脚本之间的区别可以归纳为如下几个方面:

(一)目的

  1. Makefile:主要用于自动化编译和构建过程,尤其是当项目包含多个源文件,并且需要按特定顺序编译它们时。
  2. Bash 脚本:用于执行一系列命令以自动化任何类型的任务,不仅限于编译和构建。

(二)语法

  1. Makefile:具有其自己的语法,包括规则、目标、依赖项和命令。它通常比 Bash 脚本更简洁,因为它为常见的编译任务提供了很多内置规则。
  2. Bash 脚本:使用 Bash shell 的语法,包括变量、条件、循环等。

(三)执行方式

  1. Makefile使用 make 命令执行,可以指定一个目标(如果不指定,则通常执行第一个目标或默认目标)。可以很容易地并行执行多个命令,只需使用 -j 选项指定要同时运行的作业数。
  2. Bash 脚本:直接运行脚本,或者使用 bash 命令后跟脚本名。虽然也可以实现并行执行,但通常需要更多的脚本编写工作。

(四)环境

  1. Makefile:通常在开发环境中使用,特别是当需要编译源代码时。
  2. Bash 脚本:可以在任何支持 Bash 的环境中使用,不仅限于开发环境。

(五)错误处理

  1. Makefile:如果任何命令失败,Make 会停止执行,除非使用特定的错误处理规则。
  2. Bash 脚本:提供了更丰富的错误处理机制,包括条件、捕获和自定义错误消息。

(六)跨平台性

  1. Makefile虽然也主要用于Unix-like环境,但有一些变体(如NMake)可以在Windows上使用。
  2. Bash脚本:在大多数Unix-like系统上运行良好,但在Windows上可能需要额外的工具(如Cygwin或WSL)。

(七)应用场景不同

这个不同在后面章节详细阐述。

四、Makefile 和 Bash 脚本的语法

MakefileBash脚本在语法上既有相似之处,又有明显不同。下面我将分别描述比较:

(一)相同点

  1. 变量赋值:Makefile和Bash脚本都支持变量赋值,并且可以使用这些变量来定制脚本的行为。在Bash中,变量赋值时等号两边不能有空格,例如VAR="value",而在Makefile中,等号两边可以有空格,例如VAR = value。不过,在Makefile中也可以使用:=来进行立即赋值,此时等号两边不能有空格。
  2. 条件判断:两者都支持条件判断,根据条件执行不同的代码块。在Bash中,这通常通过if、elif、else和fi关键字实现。在Makefile中,条件判断可以通过ifeq、ifneq、ifdef、ifndef等指令实现。
  3. 循环结构:Bash脚本和Makefile都支持循环结构,用于重复执行一段代码。在Bash中,常见的循环有for、while和until。在Makefile中,可以通过foreach来实现类似的循环功能。
  4. 函数/定义:Bash脚本支持函数定义,可以在脚本中调用这些函数。Makefile中没有函数的概念,但可以通过定义规则来达到类似的效果,规则中的命令可以被多次调用。
  5. 注释:两者都支持注释,可以在脚本中添加说明性文字。在Bash中,使用#开头表示注释。在Makefile中,同样使用#开头表示注释。

(二)不同点

  1. 基本结构:Bash脚本是基于命令行的,由一系列命令组成,按照顺序执行。而Makefile是基于规则的,由目标(target)、依赖(dependencies)和命令(commands)组成,通过指定目标来触发相应的规则执行。
  2. 命令执行:在Bash脚本中,命令直接执行,并且每条命令默认在当前shell中执行(除非使用子shell)。而在Makefile中,规则的命令通常在一个新的shell实例中执行,每条命令默认单独执行(可以通过.ONESHELL特殊目标改变这一行为)。
  3. 通配符:在Bash中,*用作通配符,匹配任意字符串。而在Makefile中,%用作通配符,用于模式匹配和自动变量。
  4. 命令连接:在Bash中,命令可以通过;、&&或||连接,分别表示顺序执行、条件执行(仅当前一个命令成功时)和条件执行(仅当前一个命令失败时)。而在Makefile中,命令通常通过换行符分隔,并且每条命令在一个独立的shell中执行(除非特别指定)。
  5. 错误处理:Bash脚本中,需要显式检查命令的退出状态来处理错误。而在Makefile中,如果任何命令执行失败(返回非零退出状态),则整个规则的执行将立即终止,并且Make会报告错误。
  6. 特殊字符处理:在Bash脚本中,特殊字符(如变量、引号、反斜杠等)的处理需要特别小心,以避免语法错误或意外的行为。而在Makefile中,由于它的语法和解析规则与Bash不同,特殊字符的处理也有所不同,例如$用于引用变量,@用于禁止命令回显等。
  7. 包含文件:在Makefile中,可以使用include指令来包含其他Makefile文件,从而实现模块化和复用。而在Bash脚本中,通常通过source或.命令来包含其他脚本文件。

        Makefile和Bash脚本由于它们的设计目标和用途不同,它们在基本结构、命令执行、通配符使用、错误处理等方面存在显著的差异。了解这些差异对于正确编写和理解MakefileBash脚本至关重要。

五、Makefile 和 Bash 脚本的应用

        Makefile和Bash脚本各自在不同的情境下被广泛应用。以下是它们主要的应用场景:

(一)Makefile应用场景

  1. 软件构建:Makefile是软件构建中最常见的工具之一,尤其在C、C++等需要编译的项目中。它定义了如何从源代码编译出可执行文件或库,并处理了文件间的依赖关系。
  2. 自动化构建:Makefile通过定义一系列的规则,可以自动化完成诸如编译、链接、测试、打包、安装等任务,提高开发效率。
  3. 版本控制:Makefile通常与版本控制系统(如Git)结合使用,以自动化处理构建相关的任务,如生成构建日志、清理构建产生的临时文件等。
  4. 项目文档生成:Makefile也可以用来自动化生成项目文档,如API文档、用户手册等。
  5. 清理和安装:Makefile通常包含清理(clean)和安装(install)目标,用于清理构建产生的临时文件和将最终产品安装到系统中。

(二)Bash脚本应用场景

  1. 系统管理和维护:Bash脚本经常用于系统管理员的日常任务,如监控磁盘空间、管理用户账户、备份数据、配置网络服务等。
  2. 自动化任务:Bash脚本可以自动化执行一系列命令行任务,如批量处理文件、下载和安装软件、定时执行某项任务等。
  3. 数据处理:Bash脚本经常用于处理文本和文件数据,如日志分析、文本搜索和替换、数据提取和转换等。
  4. 部署和配置:Bash脚本可以用于自动化部署应用程序或配置系统环境,如配置Web服务器、数据库服务器等。
  5. 与其他工具集成:Bash脚本可以与其他命令行工具和脚本语言(如Python、Perl等)集成,以创建更复杂的自动化解决方案。

        总之,Makefile主要用于编译和构建软件项目,而Bash脚本则更广泛地应用于系统管理和自动化任务。在实际工作中,两者可以结合使用,以创建一个完整、自动化的构建和部署流程。


相关文章

  • 如何在 Nginx 中进行速率限制?

    http {server {# 其他配置...在这个例子中,当请求超过速率限制时,通过error_page指令将 503 错误映射到页面。这使得可以为用户提供更友好的自定义页面,以解释为什么请求被拒绝。在本文中,我们详细介绍了在 Nginx 中进行速率限制的方法。我们从基础开始,讨论了模块的使用以及指令的配置。随后,我们深入探讨了不同的速率限制策略,包括按 IP 进行限制、限制特定 URI 或请求类型,以及设定速率限制的阈值。在高级策略方面,我们讨论了如何使用。

  • C# 实现网页内容保存为图片并生成压缩包

    通过动态页面技术,可以实现简历配置后的网页内容输出,但制作对应的各种模板会遇到开发效率和服务跟进的问题。为了保障原样输出,折中而简单的方案就是将动态输出的页面转化为图片格式。

  • 五种多目标优化算法(MSSA、MOJS、NSWOA、MOPSO、MOAHA)性能对比(提供MATLAB代码)

    多目标优化算法是用于解决具有多个目标函数的优化问题的一类算法。其求解过程可以分为以下几个步骤:1. 定义问题:首先需要明确问题的目标函数和约束条件。多目标优化问题通常涉及多个目标函数,这些目标函数可能是相互矛盾的,因此需要进行权衡和平衡。2. 生成初始解集:通过某种方式生成初始解集,可以是随机生成、根据经验生成或者使用已有的解集。3. 评估解集:对初始解集中的每个解进行评估,计算其在各个目标函数上的值。评估方法可以根据具体问题选择,例如计算目标函数值、计算约束违反程度等。

  • 【C#小知识】c#中的delegate(委托)和event(事件)

    今天来介绍一下delegate和event。delegate在c#中可以定义一个函数类型,可以将函数作为一个对象来使用。event在c#中则可以看做一个函数的集合,event中包含了一个或多个函数。

  • 如何在 Linux 中安装 Fish Shell(带 Starship)?

    Fish Shell是一款现代的、用户友好的命令行 Shell,设计初衷是提供更好的用户体验和强大的功能。它采用友好的语法和强大的自动补全功能,使得命令行操作更加轻松愉快。Starship是一款轻量级的、快速的命令行提示符,它为Shell提供了一个漂亮、高度可定制的提示符。Starship的设计理念是简洁、高效,同时允许用户自由定制外观和显示的信息。Fish Shell允许你创建自定义提示符,包括颜色、图标、以及显示的信息。修改# 自定义提示符end。

  • 如何在 Ubuntu 22.04 上安装 Consul 服务器?

    通过这篇文章,你已经学会了在 Ubuntu 22.04 上安装 Consul 服务器的详细步骤,包括配置集群、服务发现、健康检查、安全性特性等方面。同时,你还了解了如何维护 Consul 和进行故障排除,以及一些进阶主题。Consul 是一个功能强大的工具,适用于构建可靠的微服务架构,希望这篇文章对你有帮助。

  • 【Linux】信号保存与信号捕捉处理

    介绍信号的保存,理解信号在操作系统中的保存方式,理解系统中信号捕捉的处理过程以及介绍信号的其它知识!

  • C#使用重载方法实现不同类型数据的计算

    为了避免异常,可以先使用Decimal.Parse(string)方法将字符串转换为小数,然后再使用Convert.ToInt32(decimal)方法将小数转换为整数。如果一个类中存在两个以上的同名方法,并且方法的参数类型、个数或者顺序不同,当调用这样的方法时,编译器会根据传入的参数自动进行判断,决定调用哪个方法。例如,字符串是"123.456",包含非数字字符"."。重载方法就是方法名称相同,但是每个方法中参数的数据类型、个数或顺序不同的方法。如果字符串包含非数字字符,例如小数点,该方法将引发异常。

  • C#:Sleep() 和 Wait() 有什么区别

    Sleep() 和 Wait() 是两个不同的方法,用于控制线程的执行。

  • DockerUI如何部署结合内网穿透实现公网环境管理本地docker容器

    DockerUI是一个docker容器镜像的可视化图形化管理工具。DockerUI可以用来轻松构建、管理和维护docker环境。它是完全开源且免费的。基于容器安装方式,部署方便高效,浏览和维护docker单节点或集群节点worker和manager。DockerUI具有易于使用的界面。它不需要记住 docker 指令。只需下载镜像即可立即加入并完成部署。使用DockerUI并结合cpolar内网穿透可以更加轻松的管理docker和swarm,实现后台公网访问并管理,视觉性更加直观,后台开发更加便利。

  • C++ STL库详解:容器适配器stack和queue的结构及功能

    详细介绍了c++中的stack和queue两大容器适配器的功能、接口与使用方法,通过与vector、string等容器的配合使用来实现特定的功能。介绍了stack与queue的底层默认容器deque的原理及结构以及它的优缺陷。

  • 【Linux】linux自动化构建工具make/makefile

    是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。当对文件的内容做修改时,该文件的Modify和Change的时间都会被修改,所以当改变文件的属性时,修改时间发生了变化,再次make时,会比源文件的最近修改时间新。这里的mytest-d表示的是目标文件,test.c表示的是要编译的源文件,第二行则是编译指令。是一个命令,用来执行makefile里面编写的编译命令。

  • C语言——深入理解指针(1)

    我们已经知道,32内存位计算器有32条地址总线,每条线有1和0两个状态,那么一个内存的编号就有32条地址线表示,一条地址线占一个比特位,那么32条地址线就是32个比特位,因此就是4个字节。,可以这么理解,32位的计算器有32条这样的线,每个线有两种状态,分别是0和1,那么32根线一共能表示2^32种状态,这样的每个状态就是我们的一个地址,他们分别储存在不同的硬件上,地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据在通过数据总线传入CPU内寄存器。当然,需要我们了解一下计算机的进制转换,

  • C,C++,C# 的区别

    C#是一种面向对象的编程语言,由微软开发。总的来说,C适合系统级编程和嵌入式开发,C++适合大型项目和需要高性能的应用程序开发,而C#适合Windows应用程序开发和.NET平台。C++是一种面向对象的编程语言,是C的扩展。C++也具有更强大的标准库,以支持更多的功能和任务。它具有简单的语法和较小的标准库,适合于高效的低级编程和处理底层细节。C++具有更高的性能和更好的底层控制能力,但开发过程中更复杂。C#的开发速度更快,代码更易于维护,但性能可能稍逊于C++。C,C++,C# 是三种不同的编程语言。

  • 如何在 Linux 命令行中检查 CPU 使用率

    使用top来实时查看系统资源的使用情况,特别是 CPU 和内存的使用率。使用sar定期收集系统性能数据,以便后续分析历史性能趋势。使用mpstat来监控多核 CPU 的使用率,了解每个核心的性能状况。使用perf进行更深入的性能分析,包括函数调用图、指令和缓存的分析等。使用strace跟踪系统调用,解决程序执行中的异常情况。使用topvmstat和sar进行实时和历史性能监控,以便了解系统整体的健康状况。使用mpstatperf和strace进行更深入的 CPU 使用率分析,找出潜在的性能瓶颈。

  • 一些著名的软件都用什么语言编写?

    比如你的两个朋友与你分别玩用VB、Java、与C++编写的“跑跑卡丁车”,你玩C++编写的游戏已经跑玩结束了,发现你的两个朋友还没开始跑呢,那是相当的卡啊。备注:曾经在智能手机的操作系统(Windows Mobile)考虑掺点C#写的程序,比如软键盘,结果因为写出来的程序太慢,实在无法和别的模块合并,最终又回到C++重写。:2008 年推出:C语言(有传言说是用Java开发的操作系统,但最近刚推出原生的C语言SDK): 部分JAVA(对外接口),主要为C++ (开源,可下载其源代码)

  • 计算机缺失duilib.dll的5种解决方法,轻松解决dll报错问题

    首先,可能是由于操作系统在更新或修复过程中出现了文件丢失的情况;最后,也有可能是由于软件自身的bug或设计缺陷,使得在运行过程中未能正确加载或使用这个dll文件,从而表现出“丢失”的现象。通常情况下,duilib.dll是一个与用户界面设计和渲染相关的库文件,它的缺失可能导致依赖于它的软件无法正常启动、运行时出现错误提示、窗口界面显示不全或者功能受限等问题。7.针对开发环境:如果你是开发者,确保在构建和部署项目时包含所有必需的DLL文件,并且配置正确的运行环境,防止因项目发布遗漏文件而造成的问题。

  • 【Docker】linux、nginx、容器镜像三者基本概念

    由于在工作中接触到的都是windows操作系统,服务器也是,所以对于linux系统就比较陌生。对于windows操作系统,web服务器一般都是使用IIS。那对于linux系统,web服务器一般使用的是nginx。不同操作系统,web服务器自然不一样,但是目的都是一样的,都是为了渲染和呈现网站内容。因此,基本概念还是要了解一下。

  • git提交代码到远端仓库的方法详解

    自己学习到的git关联远端仓库的方法,希望可以帮到大家。

  • 文件传输协议:FTP、TFTP、SFTP和SCP

    你好,这里是网络技术联盟站。文件传输协议在计算机网络中扮演着关键的角色,为用户提供了在网络上共享和传输文件的标准化方式。本文将深入介绍四种常见的文件传输协议:FTP、TFTP、SFTP和SCP,探讨它们的工作原理、特点以及在不同场景下的应用。

  • 2024年了,Fedora和Ubuntu,哪个更适合工程师使用?

    在Fedora与Ubuntu的比较中,我们深入探讨了它们在安装和配置、桌面环境、软件包管理、系统更新与稳定性、社区支持、性能、安全性、容器化支持、桌面用户体验、开发者工具、虚拟化支持、硬件兼容性、多版本支持、跨平台支持等方面的差异。最终,选择Fedora还是Ubuntu取决于您的个人需求和偏好。如果您是一个追求最新技术和功能的开发者,喜欢滚动更新的模式,那么Fedora可能更适合您。如果您更注重系统的稳定性,希望在长期内获得支持,并且对桌面和服务器环境都有需求,那么Ubuntu可能更符合您的期望。

  • 如何强制Linux用户在下次登录时更改密码?

    在Linux系统中,用户账户的密码信息存储在和文件中。其中,文件包含用户的基本信息,而文件包含用户的加密密码以及与密码相关的设置。PAM模块允许管理员定义在用户登录、更改密码等操作时执行的任务。在密码管理方面,我们关注的是模块。本文介绍了如何强制Linux用户在下次登录时更改密码,并详细讨论了密码管理的各个方面。通过配置密码过期策略、使用PAM模块增加密码复杂性要求、设置强制密码更改通知、批量更改用户密码以及自动化密码更改过程,管理员可以提高系统的安全性,降低密码被滥用的风险。

  • Java编程模型:VO,BO,PO,DO,DTO

    Java编程模型中的VO,BO,PO,DO,DTO提供了一种结构化和组织代码的方法。通过合理运用这些概念,可以使代码更具可读性、可维护性和可扩展性。在实际项目中,根据需求和架构设计,合理选择和运用这些概念将有助于构建清晰、高效的Java应用程序。

  • 一文带你全方位了解 Shell 脚本,给力!

    使用等号(=)给变量赋值,并通过美元符号($)引用变量的值。# 变量的定义和使用通过本文的学习,您已经了解了如何为 Linux 命令创建脚本的基础知识和高级技巧。Shell 脚本是一种强大的工具,通过结合 Linux 命令和脚本编程,您可以实现自动化任务、系统管理以及日志分析等各种功能。深入学习和实践将使您成为一个熟练的脚本程序员,能够更高效地处理各种任务。