Make:从一个全局Makefile构建不同的应用程序

时间:2013-06-10 11:34:00

标签: makefile gnu-make

我目前面临以下问题:

如何创建一个全局Makefile来构建不同的应用程序(可能使用 来自我的源代码树的相同或不同的库? 目前我只有一个应用程序,我所做的就是:

include $(ROOT)/SETUP.MAK

SUBDIRS = \
        lib1 \
        lib2 \
        app1

include $(ROOT)/RULES.MAK

应用程序是按原样构建的。但是现在我会有更多 应用程序和其他库。我不想创造 每个应用程序的单独Makefile,因为库/代码库是 同样适用于不同的应用。这就是我试过的:

include $(ROOT)/SETUP.MAK

ifeq ($(strip $(MAKECMDGOALS)),proj1)
SUBDIRS = \
        lib1 \
        lib2 \
        app1
endif

ifeq ($(strip $(MAKECMDGOALS)),proj2)
SUBDIRS = \
        lib1 \
        lib2 \
        lib3 \
        app2
endif

.PHONY: proj1
proj1: $(SUBDIRS)

.PHONY: proj2
proj2: $(SUBDIRS)

include $(ROOT)/RULES.MAK

但问题是make进入第一个目录“lib1”并尝试构建 “lib1”,但“lib1”中没有“proj1”的规则。 这是如何正确完成的?我在命令行用“make proj1”调用make。

注意:SUBDIRS的制作规则位于文件RULES.MAK

编辑1: 以下是SUBDIRS的规则:

# entering dir c; calculating deps; leaving dir c; entering dir c; making blah; leaving dir c
$(SUBDIRS) :
# call as make NOT_RECURSIVE=1 to avoid recursion
ifndef NOT_RECURSIVE
ifneq ($(MAKEFILE_DIR),./) # some makefile path given
    $(VERBOSE) $(MKDIR) $@
ifneq ($(call isabspath, $(MAKEFILE_DIR)),) # absolute makefile path
    @$(MAKE) -C $@ -f $(MAKEFILE_DIR)$@/$(MAKEFILE_NOTDIR) $(MAKECMDGOALS)
else # relative makefile path
    @$(MAKE) -C $@ -f ../$(MAKEFILE_DIR)$@/$(MAKEFILE_NOTDIR) $(MAKECMDGOALS)
endif
else # no makefile path given
    @$(MAKE) -C $@ $(MAKECMDGOALS)
endif
endif

2 个答案:

答案 0 :(得分:1)

如果你打电话给make proj1,make会输入这个条件:

ifeq ($(strip $(MAKECMDGOALS)),proj1)
SUBDIRS = \
        lib1 \
        lib2 \
        app1
endif

因此SUBDIRS被定义为“lib1 lib2 app1”。 不知道SETUP.MAK的内容,但是在没有给出makefile路径的情况下 输入最后一个if子句:

else # no makefile path given
@$(MAKE) -C $@ $(MAKECMDGOALS)

通过以下方式解释此命令:make -C lib1 proj1 你的Makefile没有任何proj1规则。 你应该在lib1 / Makefile中创建一个通用的all规则,从lib1 / Makefile创建你的lib(.a / .so),不要指定项目的名称。

尝试

else # no makefile path given
@$(MAKE) -C $@ 

(或删除IF条款中的其他$(MAKECMDGOALS)

答案 1 :(得分:1)

你正在以一种非常不像Make的方式使用Make,并给自己造成很多不必要的麻烦。

看看lib1。目前,您使用的规则

lib1:
    $(MAKE) -C lib1 proj1

(我们现在假设“没有给出makefile文件路径”模式。)我假设lib1/中的文件加起来一个库,并且该库不必使用特定的库构建考虑到项目。因此,无需将“proj1”传递给在lib1/中运行的Make流程。并且Make不需要明确的目标;如果在没有目标的情况下调用,Make将尝试构建默认目标,这通常是makefile中的第一个目标,在这种情况下应该是库(lib1/lib1.a或其他东西)。所以我们可以简化规则:

lib1:
    @$(MAKE) -C lib1

或更好:

lib1:
    @$(MAKE) -C $@

事实上,我们可以将它推广到我们使用相同方式的所有子目录:

lib1 lib2 lib3 app1 app2:
    @$(MAKE) -C $@

如果我们使用“SUBDIRS”来表示我们这样处理的所有子目录,并拼出proj先决条件,那么全局makefile会变得更加简单:

SUBDIRS = lib1 lib2 lib3 app1 app2

.PHONY: proj1
proj1: lib1 lib2 app1

.PHONY: proj2
proj2: lib1 lib2 lib3 app2

可以进一步改进,但这个答案越来越长。 (至于“给出的makefile路径”模式,你可以简化那个很好的处理,并且摆脱大部分或全部的分支,但它似乎与SETUP.MAK中设置的参数纠缠在一起,也许还有细节你的操作系统。)所以也许最好留下他们一天。