我正在在Linux上使用make构建多个可执行文件。每个可执行文件都有自己的文件夹,该文件包含一个小的makefile,其中包含共享的makefile.rules。因此,要构建项目,我用父makefile分别调用每个makefile。
喜欢这个:
# Find Makefiles
MKFLS += $(subst Makefile,,$(shell find */ -name Makefile ))
# Standard build rules, pass down to subordinate make files
all debug install: tags
@$(foreach folder,$(MKFLS), $(MAKE) -C $(folder) $@ || exit;)
我将共享代码放在静态库中。每个文件都有自己的文件夹和makefile。在使用以下方式为exe或lib构建可执行库和静态库时,我正在建立依赖关系:
$(CC) $(CFLAGS) -c -MMD -MP -o $@ $<
然后包括生成的文件(仅针对该exe或lib):
-include $(OBJECTS:.o=.d)
现在,如果库的源文件或内部头文件之一发生更改,我想确保可执行文件能够生成。我尝试包括该库的生成的.d文件,但这没有用。
首先,每个可执行文件都定义了静态库及其生成位置:
# My Libraries
LOCALLIBS += $(UTILSLIB)/libone.a
LIBSRC += $(UTILSDIR)/onelib
LOCALLIBS += $(UTILSLIB)/libtwo.a
LIBSRC += $(UTILSDIR)/twolib
然后在包含的全局规则Makefile中:
# Rules For Library Dependencies
# Include library dependencies if they exist
-include $(shell find $(LIBSRC) -name \*.d )
# Rule to make libraries that are part of this source tree
$(LOCALLIBS):
$(foreach folder,$(LIBSRC), $(MAKE)-C $(folder) $(MAKECMDGOALS) || exit;)
@touch $(LOCALLIBS)
我不认为依赖项会贯穿静态库。因此,即使libone.a被构建,可执行文件也不会被构建。将需要第二次运行。我可以尝试使我的可执行文件依赖于libone.a中的对象,但是现在我的makefile变得凌乱和复杂。
所以...。有没有办法解决这个问题?什么是正确的方法?
要获得所需的结果,必须提供目标文件,库和可执行文件的必备清单。
您已经有了目标文件的方法。您生成了依赖项列表文件:
$(CC) $(CFLAGS) -c -MMD -MP -o $@ $<
然后包括它们:
-include $(OBJECTS:.o=.d)
到目前为止,很好。 (我认为这已经可以正常工作了–您没有给我们足够的Makefile来进行测试。)
此方法将不是适用于库。它适用于目标文件,因为源文件包含头文件列表(如#include
指令),并且编译器($(CC)
)知道如何将它们转换为必备列表。库构建工具($(AR)
或您正在使用的任何工具)没有要读取的此类文件,也没有构建此类列表的方法。但是不要紧;对于每个库,您必须在其中指定想要的内容列表[[以某种方式,因此您的库规则应类似于以下内容:
libone.a: alpha.o beta.o
$(AR) -cvq $@ $^. # or whatever you use
这会照顾图书馆。现在是可执行文件。假设您有一个可执行文件prime
,它需要alpha
和gamma
中的代码。该规则将如下所示:
prime: gamma.o libone.a $(CXX) -o $@ $^. # or whatever you use
就是这样。可执行文件prime
不依赖于gamma.h
。如果更改gamma.h
,Make将注意到gamma.o
已过时,因此prime
也已过时。并且prime
不依赖于alpha.h
;如果更改alpha.h
,Make将注意到alpha.o
已过时,因此libone.a
也已过时,因此prime
也已过时。(一旦您做了很多工作,可能会有进一步的改进。)