3

我从事的项目被组织在一个带有根 Makefile 的文件夹中,并且有很多子项目,每个子项目都是包含自己的 makefile 的子文件夹。

根 Makefile 调用 make 进入每个子目录(make -C命令)。目标文件与源文件在同一级别生成。

我想命令 root make 命令将目标文件生成(和检索)重定向到指定的 build_dir。有没有一种简单的方法可以做到这一点?(而不是修改每个子项目中的每个 Makefile)。

4

3 回答 3

2

这是一种 hack,但您可以结合使用编译器包装器和vpath.

假设我们有foo.c

#include <stdio.h>

int main() {
    printf("hi there\n");
    return 0;
}

bar.c

int bar() {
    return 1;
}

放入vpath %.o objMakefile 将告诉makeobj/目录中查找目标文件。但是我们需要告诉编译器将目标文件写入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 等可理解的语言重写脚本——但这应该可以帮助您入门。

于 2012-11-22T18:12:13.217 回答
1

没有任何解决方案可以阻止您修改每个 Makefile。

Makefiles 并make没有魔法。Makefile包含用于编译每个源文件的命令行。因此,为了能够在指定目录中生成所有目标文件,您必须修改每个Makefile以更改此命令行添加选项来告知放置目标文件的位置。

于 2012-11-22T10:45:29.410 回答
0

你的意思是类似于后备目标的东西

%:
    make -C $(dir $@) $(notdir $@)

这样你就可以

make somedir/sometarget

?

于 2012-11-22T10:45:04.637 回答