我还是UNIX / Linux世界的新手,尤其是相关工具,比如GCC编译器。也就是说,我仍然是makefiles和类似东西的新手(我在Windows上使用MinGW),因为到目前为止,我的大多数开发都是使用像Visual Studio和Eclipse这样的IDE。
当我打开一个典型的项目文件夹时,我会看到这样的文件:
configure
make
INSTALL
install-sh (or a variant)
这里有很多我不明白的事情,我的主要问题是:
这些之间有什么区别,为什么我们需要每一个? (在IDE世界中,你所拥有的只是一个项目文件;就是这样。所以我很困惑为什么我们这里不仅仅是一个makefile。)
这些文件是如何生成的?对于小型项目,您可以手工编写它们,但对于像GCC这样的大型项目,即使尝试也是荒谬的。我发现编辑这些文件很痛苦,我得出的结论是我不应该手动修改它们。但如果是这样,那么人们通常使用哪些工具来添加和修改这些文件?
为什么他们不在makefile中使用通配符?为什么每个目标文件都有一行?这是因为限制,还是有优势呢?
有一个shell脚本调用编译器和每个文件,并且 makefile 执行相同的操作有什么区别?在Windows中,我很想在文件夹中创建批处理文件,并使用它编译所有内容 - 不需要只有一个文件。有什么不同?为什么不只有一个.sh
文件来编译所有内容?
奖金问题:
make
工具不接受彼此的格式......我怎么知道使用什么? GCC只是通常的工具,还是每个人都应遵循一些标准?我可能会有更多问题,因为我对此类项目的结构有了更多了解,但就目前而言,这些是我最大的问题。 :)
答案 0 :(得分:15)
在普通包装中,这些文件各有特定目的。这与unix的理念是一致的,即“每个程序应该做一件事并做好事”。在大多数项目中,您将看到如下文件:
configure
configure.ac
Makefile
Makefile.in
Makefile.am
install-sh
INSTALL
configure
(通常)是一个shell脚本,它在构建任何内容之前检查系统是否具有所有必需的功能。 Makefile.in
是Makefile
的模板。配置测试的结果将替换为Makefile.in
以生成Makefile
。这是为了处理人们在不明确的路径中有事物(编译器,标题,库),交叉编译(例如,在x86上为ARM构建),可选的库支持(某些程序具有可以打开或关闭的附加功能),使用不同的选项进行编译,等等。写一个万能的Makefile
实际上真的很难。
正如您所注意到的,configure
脚本本身就是一团糟。它既不是凡人的眼睛所见,也不是凡人的手所编辑。它实际上是使用名为configure.ac
的程序编译autoconf
的结果。 autoconf
是m4
宏处理器周围的宏包和包装器,它是当时唯一的好工具(autoconf
是非常古老的软件,但已经非常好了)。 autoconf
允许开发人员轻松编写测试以检查构建软件所需的头文件,库或程序(这在程序之间有所不同)。
如果你深入挖掘一下,你会注意到Makefile.in
也有点难看。这是因为写好Makefile
s通常是很多样板,这激发了另一个工具automake
。 automake
将Makefile.am
(通常是简短的和声明性的)编译成Makefile.in
(这是巨大的),然后由Makefile
(基本上)编译成configure
install-sh
是一个与automake
一起分发但复制到其他包中的脚本。如果系统上install
的版本是废话(install
将文件复制到安装目录中,它就作为替代。一些非常旧的系统已经破坏了install
的版本,{{1关于删除旧系统的警告是非常保守的)。其他一些履行类似角色的脚本是automake
,compile
和depcomp
。
ylwrap
只是一个描述如何安装软件包的文档。它通常是由INSTALL
复制到包中的样板内容。
我已经在上面回答了这个问题,但这里是摘要:
automake
configure.ac ==[autoconf]=> configure
负责程序在箭头内。为了详细了解这一点,我建议使用此autotools tutorial。不要被页数计算,大部分都是逐个出现的图表。
有时会使用Makefile.am ==[automake]=> Makefile.in ==[configure]=> Makefile
中的通配符。例如,GNU Make支持Makefile
函数,您可以在其中编写如下内容:
$(wildcard)
未使用SOURCES := $(wildcard src/*.c)
等功能的主要原因是它们是扩展程序,$(wildcard)
非常难以生成可与任何}一起使用的automake
1} em> POSIX兼容Makefile
。在项目成熟之后,无论如何,要编译的文件列表都不会发生太大变化。
明确列出文件的第二个原因是程序获得可选功能。通配符不再合适,您必须列出编译其他功能的条件。
A make
跟踪文件之间的依赖关系,而shell脚本无法跟踪(无论如何都不会付出太大的努力)。
如果您有Makefile
规则,请执行以下操作:
Makefile
告诉foo.out: foo.in
generate-foo foo.in
如果make
较新而不是foo.in
,则可以通过执行foo.out
创建新的foo.out
。这节省了大型项目的大量冗余工作,您可能只在重新编译之间更改一个或两个文件。
你的奖金问题似乎有些不合时宜。最常见的generate-foo foo.in
可能是GNU Make,虽然我猜测BSD make会紧随其后,其次是Solaris,AIX等提供的各种专有make
版本。
这些都接受make
中相同的基本结构(因为POSIX这样说),但可能具有特定于供应商的语法扩展。
GCC不是Makefile
之类的构建工具。 GCC是一个命令行编译器,类似于Windows上的make
。
答案 1 :(得分:5)
不同的事情有很多原因,但最终归结为可移植性。在unix战争期间,每个平台都是不同的,人们试图制作尽可能多的软件。因此必须找到共同的分母。 sh就是这样的共性,所以配置脚本被编写为使用最大可移植的sh。最大可移植性意味着使用最少的一组功能。 make的不同实现在它们支持的功能上有很大差异,因此编写了尽可能少使用的Makefile。今天的情况略好一些,但是可移植性问题仍然会引发很多你所看到的事情。
答案 2 :(得分:2)
configure
是一个脚本,用于设置构建环境并可能生成makefile。使用make
构建项目,使用make install
或install.sh
或类似项目,安装已编译的文件。如果你想在本地测试一些东西,你可能想把最后的部分留下来,所以它是分开的。