我确信这是完全正常的事情,但我无法弄清楚如何做到这一点。
我有一个编译器,它生成通常形式的make依赖项:
M/A.o : M/A.hs
M/B.o : M/A.o
所以我编写了一个规则来将%.hs编译成%.o,添加一个规则来链接二进制文件,包含依赖项文件,一切都很好。但是我希望有几个带有不同标志的二进制目标。例如。我想用-DTESTING构建构建/测试,并使用-prof构建构建/配置文件。所以我需要将.o文件保存在一个单独的树中,在那里它们将使用特殊标志进行编译。
我能想到的直接方式是让依赖关系看起来像这样:
build/test/M/A.o : M/A.hs
build/test/M/B.o : build/test/M/A.o
build/profile/M/A.o : M/A.hs
... etc.
然后规则使得%.hs构建/测试/%。o用-DTESTING等编译。我认为这会起作用,但它很笨拙,意味着预处理deps文件以添加所有构建/任何/前缀这些东西,无论多种构造都会增加它的大小。
VPATH似乎是为这类事情设计的,我的想法是我可以根据目标设置VPATH和编译器标志,它几乎可以工作,但是:
%.o: %.hs
@mkdir -p build/M
cp $< build/$@
VPATH = build
main: M/A.o M/B.o
cat $^ >$@
M/A.o : M/A.hs
M/B.o : M/B.hs
主要目标第一次想要运行'cat M / A.o M / B.o&gt; main',这似乎与gnu make文档相反,说明$ ^应该包括包含发现依赖关系的VPATH目录。奇怪的是,如果我删除'main'并再次制作,这次它使用正确的路径。这是GNU make,3.81。
这里发生了什么?是否有更好的方法来构建不同的标志? VPATH似乎是一个笨拙的工具,肯定有更好的方法吗?
答案 0 :(得分:1)
Make工作正常。它首次尝试cat M/A.o M/B.o >main
,因为它无法找到所需的先决条件,但它知道M/A.o' and
M / Bo (<em>not</em>
build / M / Ao'和{{1}的规则并且期望这就是规则将产生的。如果您删除build/M/B.o
并重试,则会通过VPATH找到main
build / M / B.o`。
让我们分阶段修改这个makefile。首先我们更改VPATH,以便它可以找到build/M/A.o' and
个文件(Make擅长使用那里来构建这里,而不是反之亦然,并且这就是VPATH的优点,并稍微改变规则:
.hs
现在是不同的对象目录。
build/%.o: %.hs
cp $< $@
VPATH = M
main: build/A.o build/B.o
cat $^ > $@
然后我们简化了最后两条规则,这样就可以轻松添加更多目标文件和二进制目标:
build/test/%.o build/project/%.o: %.hs
cp $< $@
VPATH = M
test: build/test/A.o build/test/B.o
cat $^ > $@
project: build/project/A.o build/project/B.o
cat $^ > $@
现在针对不同的编译器标志:
OBJECTS = A.o B.o
test: $(addprefix build/test/,$(OBJECTS))
project: $(addprefix build/project/,$(OBJECTS))
test project:
cat $^ > $@
最后是依赖关系。这有点棘手。假设您希望依赖项build/test/%.o: FLAGS += test_flags
build/project/%.o: FLAGS += proj_flags
build/test/%.o build/project/%.o: %.hs
@echo building $@ from $^ using flags $(FLAGS)
cp $< $@
应用于您拥有的许多对象。这是一种方法:
B.o : A.hs
要生成这样的行,我将原始行(例如OBJECT_PATHS = build/test/ build/project/
# The following is from the included file generated by the compiler
$(addsuffix B.o,$(OBJECT_PATHS)) : A.hs
)通过B.o: A.hs
进行管道处理,并注意如果要将其放入makefile命令中,请不要忘记将sed 's/\(.*\):\(.*\)/\1:\2/'
符号加倍,以便为shell保留它们。
我知道要吸收很多东西。一步一步,让我们知道它是如何工作的。
答案 1 :(得分:0)
如果您现在还没有解决问题或遇到进一步的问题,最好给autotools(automake和autoconf)一个机会。他们将快速构建一个Makefile,支持更多可配置和灵活的树外构建。