如何使用 GNU make 编译多个简单项目

Posted

技术标签:

【中文标题】如何使用 GNU make 编译多个简单项目【英文标题】:How to compile multiple simple projects with GNU make 【发布时间】:2020-06-21 11:21:25 【问题描述】:

我正在尝试从编程书中实现各种项目。我的意图是让每个项目都在自己的文件夹中进行练习,然后有一个生成文件,用make all 之类的东西编译所有项目。文件夹结构是这样的:

.
├── Makefile
├── bin
│   ├── prog1
│   ├── prog2
│   └── prog3
└── src
    ├── prog1
    │   ├── Makefile
    │   └── main.c
    ├── prog2
    │   ├── Makefile
    │   └── main.c
    └── prog3
        ├── Makefile
        └── main.c

我想学习如何建立这样的结构。特别是顶层makefile访问src中所有文件夹的部分调用make,然后将可执行文件复制并重命名到bin文件夹中。

【问题讨论】:

您希望目标文件 (main.o) 也进入 bin 文件夹吗?而且我假设您想要名为例如的可执行文件bin/prog1/prog1,对吗?另外,你能把你目前想出的makefile贴出来吗? 我只希望完成的可执行文件位于bin,它们应该只命名为bin/prog1。 (好像我想将 bin 文件夹添加到我的 PATH 中)。 【参考方案1】:

您的布局示意图显示了每个练习的生成文件,以及您似乎实际询问的***生成文件。*** makefile 最好避免重复每个练习的 makefile 的行为,因为这样的重复会给您带来额外的维护负担。此外,您最终可能会进行涉及多个源文件的练习,并且可能会进行一些需要构建多个工件的练习。这就是每个练习的 makefile 包含构建与其关联的练习所需的所有内容(到特定于练习的目录中)以及*** makefile 依赖于这些的原因。

遵循该方案将为*** makefile 留下明确定义的角色:执行每个练习构建(通过递归运行 make),并将生成的二进制文件复制到 bin/。这不是唯一设置协作 makefile 系统的方法,但它相当容易,并且可以让您专注于练习而不是构建系统。

然后,让我们假设每个单独的练习可以通过更改到其目录并运行make 来构建,结果是在同一目录中的可执行文件,与目录具有相同的名称。也就是说,从***目录中,执行cd src/prog2; make 将生成所需的可执行文件src/prog2/prog2。在这种情况下,顶层 makefile 只需要所有练习的名称和一些规则:

EXERCISES = prog1 prog2 prog3
BINARIES =  $(EXERCISES:%=bin/%)

all: $(BINARIES)

$(BINARIES):
        make -C src/$$(basename $@)
        cp src/$$(basename $@)/$$(basename $@) $@

注意:它使用特定于 GNU 的 make 实现的功能从练习名称中计算所需二进制文件的名称。我认为这是可以接受的,因为您标记了 [gnu-make],但无论如何,这是一个方便的功能,而不是必需的。

【讨论】:

【参考方案2】:

有不同的方法来解决这个问题,但这样的事情应该适用于您的示例:

PROGS := bin/prog1 bin/prog2 bin/prog3

all: $(PROGS)

$(PROGS):
    $(MAKE) -C src/$(@F)
    mkdir -p $(@D)
    cp src/$(@F)/main $@

.PHONY: clean

clean:
    rm -f $(PROGS)
    for t in $(PROGS); do make -C src/`basename $$t` clean; done

我们定义了我们要构建的目标列表 (PROGS)。我们说这些目标是all 的先决条件,然后我们继续定义它们应该如何构建,即:我们递归下降到src/ 加上目标的文件名部分以在那里运行make。我们创建目标的目录以确保它在那里,并将main 从我们下降的目录复制到目标的路径。

为了更好地衡量,还有一个clean 目标,它删除所有PROGS 并在src/ 中递归运行make clean

【讨论】:

以上是关于如何使用 GNU make 编译多个简单项目的主要内容,如果未能解决你的问题,请参考以下文章

如何查看 GNU make 运行的命令?

如何在Windows中安装和使用“make”?

大型项目使用Automake/Autoconf完成编译配置(标准的编译过程已经变成了简单的三部曲:configure/make/make install,)

gcc,g++,make,cmake的区别

如何区分 make/makefile/cmake/nmake

关于Linux开源项目基础组件make编译流程