Makefile, "configure"文件和其他编译工具-它们如何工作?他们为什么按照自己的方式工作?

标签 makefile mingw configure makefile-project

我还是UNIX/Linux领域的新手,尤其是相关工具,例如GCC编译器。也就是说,我仍然不熟悉makefile和类似的东西(我在Windows上使用MinGW),因为到目前为止,我的大部分开发工作都是使用Visual Studio和Eclipse之类的IDE进行的。

当我打开一个典型的项目文件夹时,我看到如下文件:

configure
make
INSTALL
install-sh  (or a variant)

这里有很多我不了解的事情,我的主要问题是:
  • 这些之间有什么区别,为什么我们每个都需要? (在IDE世界中,您所拥有的只是一个项目文件;仅此而已。所以我很困惑,为什么我们这里不仅仅包含一个makefile。)
  • 这些文件是如何生成的?对于小型项目,您可能可以手工编写它们,但是对于GCC这样的大型项目,即使尝试也很荒谬。我发现编辑这些文件很麻烦,并且得出的结论是我不应该手工修改它们。但是,如果是这样,人们通常会使用哪些工具来添加和修改这些文件?
  • 他们为什么不在Makefile中使用通配符?为什么每个目标文件只有一行?这是因为限制,还是有好处?
  • 有一个shell脚本来调用每个文件的编译器,而makefile可以执行相同的操作,这有什么区别?在Windows中,我很想在文件夹内创建一个批处理文件,然后用该文件进行编译-不需要多个文件。有什么不同?为什么不只有一个.sh文件来编译所有内容?

  • 奖励问题:
  • 是否有“标准” makefile格式?我见过不同的make工具,它们不接受彼此的格式...我怎么知道要使用什么? GCC只是这里常用的工具,还是每个人都应该遵循的一些标准?

  • 随着我对此类项目结构的了解越来越多,我可能还会有更多问题,但是现在,这是我最大的问题。 :)

    最佳答案

  • 在您的平均软件包中,这些文件每个都有各自的用途。这与“每个程序应做一件事情并做好该事情”的Unix哲学相一致。在大多数项目中,您将看到以下文件:
  • configure
  • configure.ac
  • Makefile
  • Makefile.in
  • Makefile.am
  • install-sh
  • INSTALL
  • configure(通常)是一个shell脚本,用于在构建任何东西之前检查系统的所有必需功能。 Makefile.inMakefile的模板。配置测试的结果将替换为Makefile.in以生成Makefile。这是为了处理那些事物(编译器, header ,库)位于模糊路径中,交叉编译(例如,在x86上为ARM构建),可选库支持(某些程序具有可打开或关闭的附加功能)的人们,使用不同的选项进行编译,依此类推。编写一个适合所有人的Makefile实际上非常困难。

    正如您所注意到的,configure脚本本身就是一团糟。它既不应该被凡人的眼睛所看到,也不能被凡人的双手所编辑。这实际上是使用名为configure.ac的程序编译autoconf的结果。 autoconf是宏包和m4宏处理器的包装,这是当时解决此类问题的唯一好工具(autoconf确实是很老的软件,但是已经老化了很多)。 autoconf使开发人员可以轻松地编写测试来检查构建软件所需的 header ,库或程序(并且程序之间的变化)。

    如果深入研究,您会发现Makefile.in也往往有点丑陋。这是因为编写好的Makefile常常是很多样板,这启发了另一个工具automakeautomakeMakefile.am(通常是简短的声明式)编译为Makefile.in(这是巨大的),然后通过Makefile(本质上)将其编译为configure
    install-sh是与automake一起分发但已复制到其他程序包中的脚本。如果系统上install的版本是废话,则它可以作为替代品存在(install将文件复制到安装目录中。某些真正的较旧系统的install版本已损坏,而automake对于删除旧系统的警告非常保守)。扮演类似角色的其他一些脚本是compiledepcompylwrap
    INSTALL只是描述如何安装软件包的文档。通常是automake将样板内容复制到包中。
  • 我已经在上面内联了,但是这里是摘要:
  • configure.ac ==[autoconf]=> configure
  • Makefile.am ==[automake]=> Makefile.in ==[configure]=> Makefile

  • 负责程序位于箭头内。要详细了解这一点,我建议使用autotools tutorial。不要被页数拖延,大多数都是逐张出现的图。
  • 有时会使用Makefile中的通配符。例如,GNU Make支持$(wildcard)函数,您可以在其中编写类似以下内容的代码:
    SOURCES := $(wildcard src/*.c)
    未使用诸如$(wildcard)之类的功能的主要原因是它们是扩展名,并且automake极力尝试生成可与任何POSIX兼容Makefile一起使用的make。项目成熟后,要编译的文件列表不会发生太大变化。

    文件被明确列出的第二个原因是程序获得可选功能时。通配符不再适用,您必须列出要在其中编译附加功能的条件。
  • Makefile跟踪文件之间的依赖关系,而Shell脚本不能(无论如何也不用费劲)。

  • 如果您有Makefile规则,例如:
    foo.out: foo.in
            generate-foo foo.in
    

    它告诉make如果foo.infoo.out更新,则可以通过执行foo.out创建新的generate-foo foo.in。这样可以节省大型项目上的大量冗余工作,在大型项目中,您只能在重新编译之间更改一个或两个文件。

    您的奖金问题似乎有些不适。最常见的make可能是GNU Make,尽管我猜想BSD make将紧随其后,其次是Solaris,AIX等提供的各种专有make版本。

    这些都在Makefile中接受相同的基本结构(因为POSIX这样说),但是可能具有特定于供应商的语法扩展。

    GCC不是像make这样的构建工具。 GCC是一个命令行编译器,类似于Windows上的cl.exe

    关于Makefile, "configure"文件和其他编译工具-它们如何工作?他们为什么按照自己的方式工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5388986/

    相关文章:

    在深度嵌套的源/makefile 中正确包含 (POSIX) 库

    c - 如何在 Windows 上编译 memcached?

    compilation - iOS 编译几个库(armv7、i386)。配置脚本 : C preprocessor fails sanity check

    hadoop - 配置 MapReduce 程序以仅在现有程序中运行 reducer

    c++ - 让 mingw-get 正确安装 - mingw/msys 路径缺失以及更多!

    openssl - 无法为 iOS 使用 ssl 构建 curl

    c - Makefile,clang OK,gcc错误

    Vala 的 Makefile

    linux - 我如何检查某些目录是否存在然后在 makefile 中执行

    c++ - 在 VSCode 上使用 F5 调试失败,提示 "Unable to establish a connection to GDB"