Build 我可以用一个makefile来构建一个分层项目吗?

Build 我可以用一个makefile来构建一个分层项目吗?,build,makefile,build-automation,Build,Makefile,Build Automation,我有几百个非平面目录结构的文件。我的Makefile列出了每个源文件,考虑到项目的大小和项目中有多个开发人员的事实,当我们忘记放入新的源文件或取出旧的源文件时,这些源文件可能会造成麻烦。我想概括一下我的Makefile,这样make就可以简单地构建所有的.cpp和.h文件,而不必指定所有的文件名,因为对于不同类型的文件有一些通用规则 我的问题:如果目录中有大量的文件,并且有很多子文件夹,我如何告诉make在不必将每个子文件夹指定为路径的一部分的情况下全部构建它们?我如何使它,使我可以做到这一点,

我有几百个非平面目录结构的文件。我的Makefile列出了每个源文件,考虑到项目的大小和项目中有多个开发人员的事实,当我们忘记放入新的源文件或取出旧的源文件时,这些源文件可能会造成麻烦。我想概括一下我的Makefile,这样make就可以简单地构建所有的.cpp和.h文件,而不必指定所有的文件名,因为对于不同类型的文件有一些通用规则

我的问题:如果目录中有大量的文件,并且有很多子文件夹,我如何告诉make在不必将每个子文件夹指定为路径的一部分的情况下全部构建它们?我如何使它,使我可以做到这一点,只有一个Makefile在根目录


编辑:几乎回答了我的问题,但它要求您指定所有文件名:\

我将首先使用通配符函数的组合:

VPATH/VPATH

以及文件功能

对于排除(即:Jonathan Leffler提到的备份),使用vpath中没有的单独文件夹进行备份,并使用良好的隐式规则


您仍然需要定义要对哪些文件夹执行操作,但不需要定义其中的每个文件。

我对此有两种看法。一方面,如果Make系统编译并链接它找到的所有内容,那么您将很快发现是否有人在源目录中留下了冲突垃圾。另一方面,无冲突的垃圾会大量繁殖,你将无法轻易地将其与实时代码区分开来


我认为这取决于许多特定于您的商店的东西,例如源代码控制系统,以及您是否计划再进行一个具有重叠代码库的项目。也就是说,如果您真的想编译给定目录下的每个源文件,然后将它们全部链接起来,我建议使用简单的递归:要生成对象,请在此处编译所有源文件,将生成的对象(具有完整路径)添加到顶部源目录的列表中,然后递归到此处的所有目录中。要链接,请使用列表。

我确信纯gmake解决方案是可能的,但是使用外部命令修改makefile或生成外部文件(您在makefile中包含该文件)可能要简单得多

大致如下:

all: myprog

find_sources:
    zsh -c 'for x in **/*.cpp; echo "myprog: ${x/.cpp/.o}" >> deps.mk'

include deps.mk

make find_sources && make

注意:确切的zsh行可能需要一些转义才能在make文件中工作,例如$$而不是$。它也可以被bash+find取代。

一种独立于平台的方式(我的意思是独立于Windows或Linux中的shell)是:

请注意,空格和分号在这里很重要,指定绝对路径也很重要,最后还要指定相应Makefile的路径(在这种情况下,我只在祖父母文件夹上使用一个Makefile)

但也有一种更好的方法,它涉及虚假目标,它可以更好地显示进度和错误,并在一个文件夹出现问题时停止构建,而不是继续到其他目标:

.PHONY: subdirs $(DIRS)

subdirs: $(DIRS)

$(DIRS):
    $(MAKE) -C $@ build -f ../../Makefile
all : prepare subdirs
...
build :
... build here

同样,我在这里只使用一个Makefile,它应该适用于所有子项目。对于孙子文件夹中的每个子项目,使用根目录中的一个Makefile创建目标“build”。

您不希望生成过程生成随机文件—正在编辑的文件、临时文件等的备份。您希望列出应该生成的文件。您可能还没有意识到这一点,但您确实希望列出要构建的内容。备份和临时文件不会有.cpp或.h扩展名,是吗?是否将.cpp~解释为.cpp?嗯,所以我只需要运行一个小shell脚本作为我的目标之一?我正考虑这么做,但我希望make中可能有我所缺少的东西。虽然没有我所希望的那么干净,但这似乎是阻力最小的途径,直到我找到一个实质上优于make的构建系统。谢谢有一种更简洁的方法可以做到这一点。使用“deps.mk”作为目标,而不是“find_sources”。然后你就可以运行“make”。
.PHONY: subdirs $(DIRS)

subdirs: $(DIRS)

$(DIRS):
    $(MAKE) -C $@ build -f ../../Makefile
all : prepare subdirs
...
build :
... build here