我从事的项目被组织在一个带有根 Makefile 的文件夹中,并且有很多子项目,每个子项目都是包含自己的 makefile 的子文件夹。
根 Makefile 调用 make 进入每个子目录(make -C
命令)。目标文件与源文件在同一级别生成。
我想命令 root make 命令将目标文件生成(和检索)重定向到指定的 build_dir。有没有一种简单的方法可以做到这一点?(而不是修改每个子项目中的每个 Makefile)。
我从事的项目被组织在一个带有根 Makefile 的文件夹中,并且有很多子项目,每个子项目都是包含自己的 makefile 的子文件夹。
根 Makefile 调用 make 进入每个子目录(make -C
命令)。目标文件与源文件在同一级别生成。
我想命令 root make 命令将目标文件生成(和检索)重定向到指定的 build_dir。有没有一种简单的方法可以做到这一点?(而不是修改每个子项目中的每个 Makefile)。
这是一种 hack,但您可以结合使用编译器包装器和vpath
.
假设我们有foo.c
:
#include <stdio.h>
int main() {
printf("hi there\n");
return 0;
}
和bar.c
:
int bar() {
return 1;
}
放入vpath %.o obj
Makefile 将告诉make
在obj/
目录中查找目标文件。但是我们需要告诉编译器将目标文件写入obj/
目录。gcc
没有这样的选项——但我们不必使用gcc
,我们可以编写自己的编译器包装器,gcc
使用修改后的命令行调用。
cc-wrapper
:
#!/bin/bash
OUTDIR=obj
#
function push() {
# usage: push ARRAYNAME ARG
# adds ARG to the end of ARRAY
eval $1[\${#$1[@]}]="\$2"
}
ARGS=()
change_dir=false
mkdir -p "${OUTDIR}"
for (( i = 1; i <= $#; i++)); do
eval arg="\${$i}"
if $change_dir; then
arg="${OUTDIR}/${arg}"
change_dir=false
fi
if [ -e "${OUTDIR}/${arg}" ]; then
arg="${OUTDIR}/${arg}"
fi
if [ "${arg}" = "-o" ]; then
change_dir=true
fi
push ARGS "${arg}"
done
echo gcc "${ARGS[@]}"
exec gcc "${ARGS[@]}"
这是一个丑陋的 shell 脚本,但它所做的只是修改一些参数:
-o
,则添加obj/
到此参数的开头obj/
,则添加obj/
到开头然后调用gcc
.
那么Makefile是:
CC=./cc-wrapper
vpath foo obj
vpath %.o obj
foo: foo.o bar.o
clean::
rm -rf foo.o bar.o foo obj
现在,您的所有对象都进入obj/
并make
正确跟踪依赖关系。
需要进行一些调整才能使其为生产做好准备——您可能希望用 Python 等可理解的语言重写脚本——但这应该可以帮助您入门。
没有任何解决方案可以阻止您修改每个 Makefile。
Makefile
s 并make
没有魔法。Makefile
包含用于编译每个源文件的命令行。因此,为了能够在指定目录中生成所有目标文件,您必须修改每个Makefile
以更改此命令行添加选项来告知放置目标文件的位置。
你的意思是类似于后备目标的东西
%:
make -C $(dir $@) $(notdir $@)
这样你就可以
make somedir/sometarget
?