你可以试试这样的方法:
$ cat Makefile
OBJS := foo bar baz...
EXES := qux quux quuz...
.PHONY: all
all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)
$(OBJS): ...
<compile>
$(EXES): ...
<link>
并称之为:
$ make -j20 -l30 concurrent-linkers=2
基本上,它将构建分为两个make调用,一个用于编译,一个用于链接,使用不同的
-j
flock
标记文件将使其成为)并将其委托给链接作业。但如果你能忍受这个。。。
$ cat Makefile
OBJS := a b c d e f
EXES := u v w x y z
.PHONY: all
all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)
$(OBJS) $(EXES):
@printf 'building $@...\n' && sleep 2 && printf 'done\n' && touch $@
$ make -j20 -l30 concurrent-linkers=2
building a...
building d...
building b...
building c...
building e...
building f...
done
done
done
done
done
done
make -j 2 u v w x y z
make[1]: warning: -jN forced in submake: disabling jobserver mode.
make[1]: Entering directory 'foobar'
building u...
building v...
done
done
building w...
building x...
done
done
building y...
building z...
done
done
make[1]: Leaving directory 'foobar'
如你所见
$(OBJS)
目标是并行构建的,而
$(EXES)
目标一次最多建立2个。
编辑
如果makefile是由CMake生成的,则至少有两个选项:
-
调整CMake文件,以便CMake生成两个不同的makefile:一个用于编译,一个用于链接。然后编写一个简单的包装makefile,如下所示:
.PHONY: myAll myCompile
myAll: myCompile
$(MAKE) -j $(concurrent-linkers) -f Makefile.link
myCompile:
$(MAKE) -f Makefile.compilation
-
说服CMake(如果还没有)生成定义两个make变量的makefile:一个(
OBJS
)设置为所有对象文件和一个(
EXES
)设置为所有可执行文件的列表。然后编写一个简单的包装makefile,如下所示:
.DEFAULT_GOAL := myAll
include CMake.generated.Makefile
.PHONY: myAll
myAll: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)
如果CMake生成两个虚假目标,一个用于所有对象文件,另一个用于所有可执行文件,则存在非常相似的解决方案:
.DEFAULT_GOAL := myAll
include CMake.generated.Makefile
.PHONY: myAll
myAll: cmake-target-for-compilation
$(MAKE) -j $(concurrent-linkers) cmake-target-for-link