【问题标题】:Canonical 'simple project' makefile规范的“简单项目”生成文件
【发布时间】:2011-06-28 12:24:06
【问题描述】:

您的小型 C/C++ 项目已经到了将所有代码放在一个文件中不再可行的地步。您想拆分几个组件。所以你创建了一个src/ 目录,然后……你必须编写一个真正的Makefile。比hello: hello.o 更多的东西。哦……是$@ 还是$< 还是$^?废话。你不记得(我从不记得)。

您是否有一个“一刀切”的简单 Makefile 可以处理简单的源代码树?如果是这样,里面有什么,为什么?我正在寻找最小、最简单的 Makefile,它可以很好地编译一个充满 C 文件的目录,而无需每次添加文件时都编辑 Makefile。到目前为止,这是我所拥有的:

CXX = clang++
CXXFLAGS = ...
LDFLAGS = ...
EXENAME = main

SRCS = $(wildcard src/*.cc)
OBJS = $(patsubst src%.cc,build%.o, $(SRCS))

all: $(EXENAME)

build/%.o: src/%.cc
    @mkdir -p $(dir $@)
    $(CXX) -c -o $@ $^ $(CXXFLAGS)

$(EXENAME): $(OBJS)
    $(CXX) -o $@ $^ $(LDFLAGS) 

clean:
    rm -rf $(EXENAME) build/

此 Makefile 将 src/ 目录中的所有 .cc 文件构建到 build/ 目录中的 .o 文件中,然后将它们链接到父目录中。

你会做什么不同的事情?

【问题讨论】:

  • 我会使用 cmake。一旦你有几个头文件,直接维护一个 Makefile 就根本不会扩大。自动工具方式笨重,需要太多步骤。 Cmake 是一个真正的万能工具。
  • 我肯定会使用 cmake 处理超过 10 个文件;对于比这更小的东西,它似乎有点沉重。
  • 它出奇地不重,而且它确实只是做了必要的工作量。在第一次调用之后,您只需继续调用make,即使您更改了 CMake 文件——它找出依赖关系的方式有很多魔力 :-)(但是是的,它确实创建了一个目录对于太小的情况,您可能会发现太多的结构。)
  • 这个问题有什么意义? “我给你看我的,如果你给我看你的”?你有什么特别的问题吗?
  • @eriktous 我正在寻找一个体面的解决方案来解决构建一个充满 C 文件的目录的问题。我觉得它可以做得比我做的更好。

标签: makefile


【解决方案1】:

我会重新考虑您决定不提供明确的来源清单的决定——我认为从长远来看这可能会给您带来麻烦。但是,如果这是您的决定,那么这个 makefile 非常好。

%.o 规则中,我将使用$< 而不是$^,以便稍后您可以添加类似的依赖项

build/foo.o: bar.h

准备好后,您可以查看Advanced Auto-Dependency Generation

【讨论】:

  • 为什么会给我带来麻烦?
  • @nornagon:拥有两个(或更多)具有共同代码的不同可执行文件通常很有用。保持不常见的代码不纠结需要在 makefile(s) 中明确的源列表,或者镜像依赖关系图的目录结构——前者通常更容易。但是,如果您遇到这个问题,很容易从一种方案转换到另一种方案。
【解决方案2】:

我从未使用过 CMake,所以对此我真的无话可说。我能提供的最好的是我们在学校有一个名为“makemake”的程序,它会自动生成 Makefiles - http://www.cs.rit.edu/~swm/makemake/ 这不是一个非常先进的程序,但它可以完成工作。从好的方面来说,它非常易于使用 - 只需在目录中执行“makemake > Makefile”,您就有了一个 Makefile,它将构建和链接该目录中的所有源文件(C 和 C++)。从好的方面来说,如果您添加了更多文件,您只需再次运行 makemake,您就会拥有一个新的 makefile。不利的一面是,无法将您已完成的任何自定义目标从一个生成的 makefile 保留到下一个。

至于“一刀切”的 makefile,虽然您绝对可以这样做,但它首先偏离了“make”命令的目的 - 即跟踪文件的上次修改时间,并且因此仅重新编译最近更改的文件,或依赖于刚刚更改的头文件(尽管要生成正确的文件,您可以使用 'makedepend' - http://www.x.org/archive/X11R7.5/doc/man/man1/makedepend.1.html )。你可以使用你目前拥有的东西加上 makedepend 来制作一个自我更新的 makefile。

【讨论】:

    【解决方案3】:

    使用自动制作工具。它易于进行更改,并且对开发人员的负担更小。它就像将 SOURCES、LDLIBS、LDFLAGS 指定为变量一样简单。起初它可能看起来有点奇怪。但随着您在它上面做的更多,它会成为您的最爱。

    【讨论】:

    • 我非常讨厌自动工具。此外,对于 6 文件项目来说,这方式有点过头了。
    • 我讨厌 autotools,因为大多数时候,我最终在 autotools 的 生成 文件中的 SLOC 比在我的程序本身中的 SLOC 多。这是完全不平衡和荒谬的。