我有两个二进制文件(bin_a,bin_b)和这两个二进制文件共享的库(lib)。 二进制文件取决于库。
main makefile:
include makeenv.mk
all: $(BIN_A) $(BIN_B)
.PHONY: clean
clean:
$(MAKE) -C lib clean
$(MAKE) -C bin_a clean
$(MAKE) -C bin_b clean
makeenv.mk:
BIN_A=$(ROOT)/bin_a/bin_a
BIN_B=$(ROOT)/bin_b/bin_b
LIB=$(ROOT)/lib/liblib.so
first_target: all
$(BIN_A):
$(MAKE) -C $(ROOT)/bin_a
$(BIN_B):
$(MAKE) -C $(ROOT)/bin_b
$(LIB):
$(MAKE) -C $(ROOT)/lib
bin_a /生成文件:
include ../makeenv.mk
all: bin_a
bin_a: $(LIB)
gcc -I $(ROOT) -L $(ROOT)/lib -l lib -o $@ bin_a.c
.PHONY: clean
clean:
rm -f bin_a
bin_b /生成文件:
include ../makeenv.mk
all: bin_b
bin_b: $(LIB)
gcc -I $(ROOT) -L $(ROOT)/lib -l lib -o $@ bin_b.c
.PHONY: clean
clean:
rm -f bin_b
LIB /生成文件:
include ../makeenv.mk
TARGET=liblib.so
all: $(TARGET)
$(TARGET): lib.c
gcc -shared -fPIC -o $@ $^
sleep 5
.PHONY: clean
clean:
rm -f liblib.so
如果我输入make,那么一切都很好:
make -C /tmp/mak/bin_a
make[1]: Entering directory `/tmp/mak/bin_a'
make -C /tmp/mak/lib
make[2]: Entering directory `/tmp/mak/lib'
gcc -shared -fPIC -o liblib.so lib.c
sleep 5
make[2]: Leaving directory `/tmp/mak/lib'
gcc -I /tmp/mak -L /tmp/mak/lib -l lib -o bin_a bin_a.c
make[1]: Leaving directory `/tmp/mak/bin_a'
make -C /tmp/mak/bin_b
make[1]: Entering directory `/tmp/mak/bin_b'
gcc -I /tmp/mak -L /tmp/mak/lib -l lib -o bin_b bin_b.c
make[1]: Leaving directory `/tmp/mak/bin_b'
但是,如果我想并行构建它,那么库就构建了两次:
make -C /tmp/mak/bin_a
make -C /tmp/mak/bin_b
make[1]: Entering directory `/tmp/mak/bin_a'
make -C /tmp/mak/lib
make[1]: Entering directory `/tmp/mak/bin_b'
make -C /tmp/mak/lib
make[2]: Entering directory `/tmp/mak/lib'
gcc -shared -fPIC -o liblib.so lib.c
make[2]: Entering directory `/tmp/mak/lib'
gcc -shared -fPIC -o liblib.so lib.c
sleep 5
sleep 5
make[2]: Leaving directory `/tmp/mak/lib'
make[2]: Leaving directory `/tmp/mak/lib'
gcc -I /tmp/mak -L /tmp/mak/lib -l lib -o bin_a bin_a.c
gcc -I /tmp/mak -L /tmp/mak/lib -l lib -o bin_b bin_b.c
make[1]: Leaving directory `/tmp/mak/bin_a'
make[1]: Leaving directory `/tmp/mak/bin_b'
问题是:为什么?
如何修复这些makefile以使并行运行?
谢谢!
答案 0 :(得分:1)
toplevel makefile并不知道子makefile会转到每个构建$(LIB)
,而子makefile自然不会知道其他makefile正在做什么。
所以你有一个竞争条件,他们都发现$(LIB)
需要重建,然后都安排建设。这是Recursive Make Considered Harmful (pdf)论文中的主要论据之一。
将makeenv.mk
更改为:
BIN_A=$(ROOT)/bin_a/bin_a
BIN_B=$(ROOT)/bin_b/bin_b
LIB=$(ROOT)/lib/liblib.so
first_target: all
$(BIN_A): $(LIB)
$(MAKE) -C $(ROOT)/bin_a
$(BIN_B): $(LIB)
$(MAKE) -C $(ROOT)/bin_b
$(LIB):
$(MAKE) -C $(ROOT)/lib
在这种情况下,可能足以让你得到你想要的东西(但我必须尝试并仔细检查先决条件列表以确定)。
或者,您可以阅读我之前列出的论文,并停止使用递归制作这类事情。
答案 1 :(得分:0)
试
subdirs=lib bin_a bin_b
.PHONY : all $(subdirs)
bin_a bin_b : lib
$(subdirs) :
$(MAKE) -C $@ $(MAKECMDGOALS)
这对我有用。 或者我试过
all : makeall
bin_a bin_b : lib
makeall :
$(MAKE) -C lib
$(MAKE) -C bin_a
$(MAKE) -C bin_b
$(MAKE) -C moredirs
在我的手中,困难在于并行并使制作过程保持定义的顺序。如果你有一个大型项目,你迫不及待地想做单线程make。你几乎要做-j 24。 如果有任何改进,请告诉我。