Makefile,“配置”文件和其他编译工具——它们如何工作?他们为什么要这样工作?

发布于 2024-10-26 05:21:05 字数 962 浏览 1 评论 0原文

我对 UNIX/Linux 世界还是个新手,尤其是相关工具,例如 GCC 编译器。也就是说,我对 makefile 和类似的东西还是很陌生(我在 Windows 上使用 MinGW),因为到目前为止,我的大部分开发都是使用 Visual Studio 和 Eclipse 等 IDE 进行的。

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

configure
make
INSTALL
install-sh  (or a variant)

这里有很多我不明白的事情,我的主要问题是:

  1. 这些之间有什么区别,为什么我们需要每一个? (在 IDE 世界中,您拥有的只是一个项目文件;仅此而已。所以我很困惑为什么我们这里不仅仅是一个 makefile。)

  2. 这些文件是如何生成的?对于小型项目,您可能可以手动编写它们,但对于像 GCC 这样的大型项目,甚至尝试都是荒谬的。我发现编辑这些文件很痛苦,并且我得出的结论是我不应该手动修改它们。但如果是这样,那么人们通常使用什么工具来添加和修改这些文件?

  3. 为什么他们不在 makefile 中使用通配符?为什么每个目标文件都有一行?这是因为限制,还是有优势?

  4. 使用每个文件调用编译器的 shell 脚本与执行相同操作的 makefile 有什么区别?在 Windows 中,我很想在文件夹内创建一个批处理文件,然后用它编译所有内容——不需要多个文件。有什么区别?为什么不只用一个 .sh 文件来编译所有内容?

额外问题:

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

随着我对此类项目结构的了解越来越多,我可能会有更多问题,但就目前而言,这些是我最大的问题。 :)

I'm still new to the UNIX/Linux world, and, in particular, to related tools, such as the GCC compiler. Namely, I'm still new to makefiles and things like that (I use MinGW on Windows), since so far, most of my development has been with IDEs like Visual Studio and Eclipse.

When I open a typical project folder, I see files like these:

configure
make
INSTALL
install-sh  (or a variant)

There's quite a few things I don't understand here, and my main questions are these:

  1. What's the difference between these, and why do we need each one? (In the IDE world, all you have is a project file; that's it. So I'm confused why we have more than just a makefile here.)

  2. How are these files generated? For small projects, you could probably write them by hand, but for big projects like GCC, it would be ridiculous to even try. I've found editing these files to be a pain, and I've come to the conclusion that I'm not supposed to be modifying them by hand. But if so, then what tools do people typically use for adding and modifying these files?

  3. Why don't they use wildcards inside a makefile? Why is there a single line for every single object file? Is this because of a restriction, or is there an advantage to it?

  4. What's the difference between having a shell script that calls the compiler with every file, and having a makefile that does the same thing? In Windows, I'd be very tempted to just create a batch file inside the folder, and compile everything with that -- no need for more than just one file. What's the difference? Why isn't there just a single .sh file, to compile everything?

Bonus question:

  • Is there a "standard" makefile format? I've seen different make tools that don't accept each other's formats... how do I know what to use? Is GCC just the usual tool here, or is there some standard everyone should follow?

I'll probably have more questions as I learn more about the structure of projects like this, but for now, these are my biggest questions. :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月亮坠入山谷 2024-11-02 05:21:05
  1. 在您的普通包中,这些文件都有各自的用途。这与“每个程序应该做一件事并做好那件事”的unix哲学是一致的。在大多数项目中,您会看到如下文件:

    • 配置
    • configure.ac
    • Makefile
    • Makefile.in
    • Makefile.am
    • 安装sh
    • 安装

    configure(通常)是一个 shell 脚本,用于在构建任何内容之前检查系统是否具有所有必需的功能。 Makefile.inMakefile 的模板。配置测试的结果被替换到Makefile.in中以生成Makefile。这是为了处理人们在模糊路径中拥有东西(编译器、头文件、库)、交叉编译(例如,在 x86 上为 ARM 构建)、可选库支持(某些程序具有可以打开或关闭的附加功能)、使用不同的选项进行编译,等等。编写一个万能的 Makefile 实际上真的很难

    正如您所注意到的,configure 脚本本身是一团糟。它不适合凡人的眼睛看到,也不适合凡人的手编辑。它实际上是使用名为 autoconf 的程序编译 configure.ac 的结果。 autoconfm4 宏处理器的宏包和包装器,它是当时处理此类事情的唯一好工具(autoconf 确实是相当古老的软件,但已经非常成熟了)。 autoconf 使开发人员可以轻松编写测试来检查构建软件所需的标头、库或程序(并且这会因程序而异)。

    如果你再深入一点,你会发现 Makefile.in 也有点难看。这是因为编写好的 Makefile 通常需要大量样板文件,这启发了另一个工具 automakeautomakeMakefile.am (通常很短且是声明性的)编译为 Makefile.in (非常庞大),然后编译为 < code>Makefile by configure(本质上)。

    install-sh 是与 automake 一起分发但复制到其他包中的脚本。如果系统上的 install 版本很糟糕(install 将文件复制到安装目录中),它会作为替代品存在。一些非常旧的系统的 install 版本已损坏,而 automake 对于删除旧系统的警告非常保守)。其他一些履行类似角色的脚本有 compiledepcompylwrap

    INSTALL 只是一个描述如何安装软件包的文档。它通常是由 automake 复制到包中的样板内容。

  2. 我已经在上面回答了这个问题,但总结如下:

    • configure.ac ==[autoconf]==>配置
    • Makefile.am ==[automake]==> Makefile.in ==[配置]==>生成文件

    负责的程序位于箭头内。要详细了解这一点,我推荐这个 autotools 教程。不要被页数吓倒,大部分都是逐个出现的图表。

  3. 有时会使用Makefile中的通配符。例如,GNU Make 支持 $(wildcard) 函数,您可以在其中编写如下内容:

    SOURCES := $(通配符 src/*.c)

    不使用像 $(wildcard) 这样的功能的主要原因是它们是扩展,并且 automake 非常努力地生成 Makefile 可与任何 POSIX 兼容make 配合使用。无论如何,项目成熟后,要编译的文件列表不会发生太大变化。

    显式列出文件的第二个原因是程序获得可选功能时。通配符不再适用,您必须列出编译附加功能的条件。

  4. Makefile 跟踪文件之间的依赖关系,而 shell 脚本则无法跟踪文件之间的依赖关系(并非没有重要意义) 。无论如何,努力)。

如果您有如下 Makefile 规则:

foo.out: foo.in
        generate-foo foo.in

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

你的奖金问题似乎有点不恰当。最常见的 make 可能是 GNU Make,尽管我猜测 BSD make 会紧随其后,其次是 Solaris、AIX 提供的各种专有 make 版本等等。

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

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

  1. In your average package, those files each have an individual purpose. This is concordant with the unix philosophy of "each program should do one thing and do that thing well". In most projects, you'll see files like:

    • configure
    • configure.ac
    • Makefile
    • Makefile.in
    • Makefile.am
    • install-sh
    • INSTALL

    configure is (usually) a shell script that checks your system for all required features before building anything. Makefile.in is a template for a Makefile. The results of the configure tests are substituted into Makefile.in to generate Makefile. This is to deal with people having things (compilers, headers, libraries) in obscure paths, cross-compiling (e.g., building for ARM on x86), optional library support (some programs have additional features that can be switched on or off), compiling with different options, and so on. Writing a one-size-fits-all Makefile is actually really hard.

    As you've noticed, the configure script itself is a mess. It's not meant to be seen by mortal eyes, nor edited by mortal hands. It's actually the result of compiling configure.ac, using a program called autoconf. autoconf is a package of macros for and a wrapper around the m4 macro processor, which was about the only good tool for this sort of thing at the time (autoconf is really quite old software, but has aged remarkably well). autoconf lets the developer easily write tests to check for headers, libraries or programs that are required to build the software (and this changes from program to program).

    If you dig a little deeper, you'll notice that Makefile.in also tends to be a little ugly. This is because writing good Makefiles is often a lot of boilerplate, and that's inspired another tool, automake. automake compiles Makefile.am (which is often short and declarative) into Makefile.in (which is enormous), which is then compiled into Makefile by configure (essentially).

    install-sh is a script that is distributed with automake but copied into other packages. It exists as a replacement if the version of install on the system is crap (install copies files into the installation directory. Some really old systems had broken versions of install, and automake is pretty conservative about dropping warnings for old systems). Some other scripts that fulfil similar roles are compile, depcomp and ylwrap.

    INSTALL is just a document that describes how to install the package. It's usually boilerplate content copied into the package by automake.

  2. I've answered this inline above, but here is the summary:

    • configure.ac ==[autoconf]=> configure
    • Makefile.am ==[automake]=> Makefile.in ==[configure]=> Makefile

    Where the program responsible is inside the arrow. To understand this in detail, I recommend this autotools tutorial. Don't be put off by the page count, most of it is diagrams appearing piece by piece.

  3. Wildcards in Makefiles are sometimes used. GNU Make, for example, supports a $(wildcard) function, where you can write something like:

    SOURCES := $(wildcard src/*.c)

    The main reason features like $(wildcard) aren't used is that they are extensions, and automake tries very hard to generate Makefiles that will work with any POSIX-compliant make. After a project becomes mature, the list of files to compile doesn't change all that much, anyway.

    A second reason files are listed explicitly is when programs get optional features. Wildcards are no longer appropriate, and you instead have to list the conditions under which additional features are to be compiled in.

  4. A Makefile tracks dependencies between files, where a shell script cannot (not without significant effort, anyway).

If you have a Makefile rule like:

foo.out: foo.in
        generate-foo foo.in

It tells make that if foo.in is newer than foo.out, a new foo.out can be created by executing generate-foo foo.in. This saves lots of redundant work on big projects, where you might only change one or two files between recompilations.

Your bonus question appears a little ill-posed. The most common make is probably GNU Make, although I'd guess that the BSD make would be a close second, followed by the various proprietary make versions supplied with Solaris, AIX and so on.

These all accept the same basic structure in Makefile (because POSIX says so), but might have vendor-specific extensions to the syntax.

GCC is not a build tool like make. GCC is a command-line compiler, akin to cl.exe on windows.

月朦胧 2024-11-02 05:21:05

造成不同情况的原因有很多,但最终都归结为可移植性。在 Unix 战争期间,每个平台都是不同的,人们试图制作可以在尽可能多的平台上运行的软件。因此必须找到共同点。 sh 就是这样的通用性之一,因此编写配置脚本以使用最大程度可移植的 sh。最大的可移植性意味着使用最少的功能集。不同的 make 实现在它们支持的功能方面差异很大,因此编写 Makefile 时使用尽可能少的功能。如今情况稍有好转,但可移植性问题仍然是您所看到的许多事情的推动因素。

There are a lot of reasons for different things, but in the end it boils down to portability. During the unix wars, every platform was different, and people tried to make software that would work on as many as possible. So common denominators had to be found. sh was one such commonality, so configure scripts were written to use maximally portable sh. Maximal portability implies using a minimal set of features. Different implementations of make vary greatly in the features they support, so Makefiles were written that used as few features as possible. Things are slightly better today, but portability concerns still drive a lot of the things you are seeing.

多彩岁月 2024-11-02 05:21:05
  1. configure 是一个设置构建环境并可能生成 makefile 的脚本。使用 make 构建项目,使用 make installinstall.sh 或类似工具安装编译后的文件。如果您想在本地测试某些内容,您可能希望将最后一部分排除在外,因此它是单独的。
  2. 您可以使用GNU 自动工具
  3. 你能举出具体的例子吗? Makefile 确实支持通配符,并且有时会使用它们。
  4. 如果您更改源文件中的某些内容,然后决定重建项目,Makefile 将仅处理所需文件的依赖关系和自动重新编译。使用批处理文件,您将重新编译所有内容,而使用 Makefile,您只需编译更改的内容。
  1. configure is a script that sets up the build environment and possibly generates the makefile. With make you build the project, with make install or install.sh or similar, you install the compiled files. If you want to test something locally, you might want to leave the final part out and so it's seperate.
  2. You can use GNU autotools.
  3. Can you give specific examples? Makefiles do support wildcards and they are used from time to time.
  4. Makefile handles dependencies and automatic recompilation of only the needed files if you change something in a source file and then decide to rebuild the project. With a batch file you'd be recompiling everything, with Makefiles you're only compiling what was changed.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文