为什么我们描述构建Makefile文件,而不是shell脚本程序? [英] Why do we describe build procedures with Makefiles instead of shell scripts?

查看:260
本文介绍了为什么我们描述构建Makefile文件,而不是shell脚本程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

备注这是这个问题:变化的目的是什么
  在单独链接目标文件
  通过Makefile文件服用user4076675?

  一个稍微不同的角度。另请参见相应的<一个href=\"http://meta.stackoverflow.com/questions/272227/should-questions-receiving-a-general-answer-edit-with-a-more-general-title\">META
  讨论。

让我们考虑一个C项目的经典案例。在 GCC 编译
能够在一个步骤中编译和链接程序。我们可以很容易
描述了一个shell脚本编译程序:

Let us consider the classical case of a C project. The gcc compiler is able to compile and link programs in one step. We can then easily describe the build routine with a shell script:

case $1 in
    build)  gcc -o test *.c;;
    clean)  rm -f test;;
esac
# This script is intentionally very brittle, to keep
# the example simple.

不过,这似乎是惯用的描述构建过程
的Makefile ,涉及额外的步骤来编译每个编译
单元为一个目标文件,并最终连接这些文件。该
相应的GNU的Makefile将是:

However, it appears to be idiomatic to describe the build procedure with a Makefile, involving extra steps to compile each compilation unit to an object file and ultimately linking these files. The corresponding GNU Makefile would be:

.PHONY: all

SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)

%.o: %.cpp
    g++ -c -o $@ $<

all: default
default: $(OBJECTS)
    g++ -o test $^

clean:
    rm -rf *.o

这第二个解决方案是值得商榷比简单的外壳更复杂
脚本中,我们以前写的。它也作为一个缺点,因为它的杂波
源目录目标文件。那么,为什么我们描述的构建
与Makefile文件,而不是shell脚本程序?在手
在previous例如,它似乎是一个无用的并发症。

This second solution is arguable more involved than the simple shell script we wrote before. It as also a drawback, as it clutters the source directory with object files. So, why do we describe build procedures with Makefiles instead of shell scripts? At the hand of the previous example, it seems to be a useless complication.

推荐答案

在这里我们编译的简单情况以及将三个中等规模
文件,任何方法很可能是同样令人满意。我会
因此,考虑到一般情况,但使用的诸多好处
Makefile文件是大型项目唯一重要的。一旦我们学会了
这使我们掌握复杂的情况下最好的工具,我们要使用
它在简单的情况下也是如此。

In the simple case where we compile and link three moderately sized files, any approach is likely to be equally satisfying. I will therefore consider the general case but many benefits of using Makefiles are only important on larger projects. Once we learned the best tool which allows us to master complicated cases, we want to use it in simple cases as well.

让我强调使用制作的'好处'',而不是简单
shell脚本编译工作。但首先,我想作一个
无害观察。

Let me highlight the ''benefits'' of using make instead of a simple shell script for compilation jobs. But first, I would like to make an innocuous observation.

编写一个Makefile类似于编写shell脚本有轻微
视角的变化。在shell脚本中,我们描述了一个程序
解决一个问题:我们可以开始来描述整个过程
使用未定义功能非常抽象的术语,我们完善这一
说明,直到我们达到了说明最基本的水平,
其中,一个程序是只是一个普通的shell命令。在Makefile中,我们做
没有引进任何类似的抽象,但我们专注于我们的文件
要生产以及我们如何生产它们。这工作很好,因为
在UNIX中,任何事物都是文件,因此每次治疗
通过的程序的从的输入读取输入数据来完成
文件
的,做了一些计算,写一些的输出结果
文件

Writing a Makefile is similar to writing a shell script with a slight change of perspective. In a shell script, we describe a procedural solution to a problem: we can start to describe the whole procedure in very abstract terms using undefined functions, and we refine this description until we reached the most elementary level of description, where a procedure is just a plain shell command. In a Makefile, we do not introduce any similar abstraction, but we focus on the files we want to produce and how we can produce them. This works well because in UNIX, everything is a file, therefore each treatment is accomplished by a program which reads its input data from input files, do some computation and write the results in some output files.

如果我们要计算复杂的东西,我们要使用大量的
这是由它们的输出被用作程序处理输入文件
输入到其他程序,依此类推,直到我们生产我们的最终
包含我们的结果文件。如果我们的计划转化为prepare我们
最终文件成一堆在shell脚本程序,那么,
该处理的当前状态做出的的:计划执行人
知道它是在,因为它正在执行一个给定的程序,
其中隐含保证这样那样的计算是
已经完成,也就是说,这等中间文件分别
已经prepared。现在,它的数据描述计划执行人的地方

If we want to compute something complicated, we have to use a lot of input files which are treated by programs whose outputs are used as inputs to other programs, and so on until we have produced our final files containing our result. If we translate the plan to prepare our final file into a bunch of procedures in a shell script, then the current state of the processing is made implicit: the plan executor knows "where it is at" because it is executing a given procedure, which implicitly guarantees that such and such computations were already done, that is, that such and such intermediary files were already prepared. Now, which data describes "where the plan executor is at"?

无害观察 描述的数据里的计划
执行者是为precisely集的中间文件这
已经prepared,而这也正是其由数据
明确当我们写Makefile文件。

这无伤大雅的观察其实是概念上的差异
shell脚本和Makefile文件之间这也解释了所有的优点
Makefile文件超过在编工作,类似工作shell脚本。
当然,要完全AP preciate这些优势,我们必须写
正确的Makefile文件,这可能是困难的初学者。

This innocuous observation is actually the conceptual difference between shell scripts and Makefiles which explains all the advantages of Makefiles over shell scripts in compilation jobs and similar jobs. Of course, to fully appreciate these advantages, we have to write correct Makefiles, which might be hard for beginners.

当我们描述了一个汇编工作有一个Makefile文件,我们可以很容易地
中断它,稍后恢复。这是的结果
无害观察的。类似的效果只能与实现
在shell脚本相当大的努力,但它只是在建
制作

When we describe a compilation job with a Makefile, we can easily interrupt it and resume it later. This is a consequence of the innocuous observation. A similar effect can only be achieved with considerable efforts in a shell script, while it is just built in make.

您观察到的Makefile文件将与混乱对象的源树
文件。但是Makefile文件实际上可以parametrised来存储这些
在一个专用的目录中的目标文件。我 BSD猫头鹰工作
对于 bsdmake ,并用

You observed that Makefiles will clutter the source tree with object files. But Makefiles can actually be parametrised to store these object files in a dedicated directory. I work with BSD Owl macros for bsdmake and use

MAKEOBJDIR='/usr/home/michael/obj${.CURDIR:S@^/usr/home/michael@@}'

这样所有的目标文件最终在〜/ OBJ 和不污染我的
源。看到这个
<一href=\"http://stackoverflow.com/questions/18116685/how-to-write-a-makefile-using-different-directories-for-targets-and-sources/25953462#25953462\">answer
了解更多详情。

so that all object files end under ~/obj and do not pollute my sources. See this answer for more details.

高级Makefile文件让我们同时拥有多个目录
包含若干构建具有鲜明的编译一个项目
选项​​。例如,具有启用的不同功能,或调试
版本等,这也是后果的无害观察
该Makefile文件实际上是在设定的中介铰接
文件。这种技术在BSD猫头鹰的测试套件说明。

Advanced Makefiles allow us to have simultaneously several directories containing several builds of a project with distinct compilation options. For instance, with distinct features enabled, or debug versions, etc. This is also consequence of the innocuous observation that Makefiles are actually articulated around the set of intermediary files. This technique is illustrated in the testsuite of BSD Owl.

我们可以轻松地构建并行程序,因为这是一个标准
的许多版本的功能,使。这也是的后果
无害观察的:因为​​那里的计划执行人是是一个
在一个Makefile明确的数据,它有可能为制作来推理
它。在shell脚本实现类似的效果将需要
巨大的努力。

We can easily build a program in parallel since this is a standard function of many versions of make. This is also consequence of the innocuous observation: because "where the plan executor is at" is an explicit data in a Makefile, it is possible for make to reason about it. Achieving a similar effect in a shell script would require a great effort.

的任何版本所做的并行模式才能正常工作,如果
在dependances正确指定。这可能是相当
复杂的实现,但
bsdmake 拥有的的功能,
字面上anhilates的问题。这就是所谓的
META 模式。它
使用第一,非平行通,汇编作业的计算
实际的通过监视文件访问的依赖关系,并使用此
在以后的并行信息的基础之上。

The parallel mode of any version of make will only work correctly if the dependances are correctly specified. This might be quite complicated to achieve, but bsdmake has the feature which literally anhilates the problem. It is called the META mode. It uses a first, non-parallel pass, of a compilation job to compute actual dependencies by monitoring file access, and uses this information in later parallel builds.

由于特殊的立体的 - 即,是作为另一后果
的的无害观察的 - 用来写Makefile中,我们可以
轻松挂接到我们的编译系统的各个方面扩展它们。

Because of the special perspective — that is, as another consequence of the innocuous observation — used to write Makefiles, we can easily extend them by hooking into all aspects of our build system.

举例来说,如果我们决定,我们所有的数据库I / O样板code
应该由一个自动工具来写的,我们只是在写
的Makefile文件应该自动工具的使用作为输入写哪些
样板code。无外乎,仅此而已。我们可以添加此
说明pretty多,我们喜欢,制作会得到它
无论如何。在做一个shell脚本生成这样的扩展会
比需要的更难。

For instance, if we decide that all our database I/O boilerplate code should be written by an automatic tool, we just have to write in the Makefile which files should the automatic tool use as inputs to write the boilerplate code. Nothing less, nothing more. And we can add this description pretty much where we like, make will get it anyway. Doing such an extension in a shell script build would be harder than necessary.

这可扩展性便于对Makefile文件code重用一个很大的激励。

This extensibility ease is a great incentive for Makefile code reuse.

这篇关于为什么我们描述构建Makefile文件,而不是shell脚本程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆