The project I work on is organised in one folder with a root Makefile, and a lot of sub-project each one being a subfolder containing its own makefile.
The root Makefile invokes make into each subdirectory (make -C command). Object files are generated at the same level as the source files.
I would like to order the root make command to redirect object file generation(and retrieving) into a specified build_dir. Is there a simple way of doing this ? (Instead of modifiying every Makefiles in every sub-project).
It's kind of a hack, but you can do this with a combination of a compiler wrapper and vpath.
Suppose we have foo.c:
#include <stdio.h>
int main() {
    printf("hi there\n");
    return 0;
}
and bar.c:
int bar() {
    return 1;
}
Putting vpath %.o obj inside the Makefile will tell make to look inside the obj/ directory for object files. But we need to tell the compiler to write object files into the obj/ directory. gcc has no such option—but we don’t have to use gcc, we can write our own compiler wrapper that calls gcc with a modified command line.
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[@]}"
It’s an ugly shell script, but all it's doing is modifying some arguments:
-o, add obj/ to the start of this oneobj/, add obj/ to the startand then calling gcc.
Then the Makefile is:
CC=./cc-wrapper
vpath foo obj
vpath %.o obj
foo: foo.o bar.o
clean::
    rm -rf foo.o bar.o foo obj
Now, all your objects go in obj/ and make tracks dependencies correctly.
It'll take some tuning to make this ready for production—you'll probably want to rewrite the script in a comprehensible language like Python—but this should help you get started.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With