1

I want my object files to be created in a subdirectory and not where Makefile lives. So, I saw this answer, which I couldn't apply to my case, so I tried this:

OBJS    = main.o    IO.o    alloc.o communication.o
OBJSDIR    =   obj
SOURCE  = main.cpp  src/IO.cpp  src/alloc.cpp   src/communication.cpp
HEADER =    headers/IO.h    headers/alloc.h headers/communication.h
OUT     =       test
CXX     = ../../mpich-install/bin/mpic++
CXXFLAGS    =   -I../../intel/mkl/include   -Wl,--start-group    -Wl,--end-group    -lpthread   -lm -ldl    -Wall
LDFLAGS   =       ../../intel/mkl/lib/intel64/libmkl_scalapack_lp64.a       -Wl,--start-group       ../../intel/mkl/lib/intel64/libmkl_intel_lp64.a ../../intel/mkl/lib/intel64/libmkl_core.a  ../../intel/mkl/lib/intel64/libmkl_sequential.a    -Wl,--end-group ../../intel/mkl/lib/intel64/libmkl_blacs_intelmpi_lp64.a -lpthread       -lm     -ldl

all:    $(OBJSDIR)  $(OUT)

$(OBJSDIR):
    mkdir   $(OBJSDIR)

$(OUT): $(OBJS)
    $(CXX)  $(OBJS) -o  $(OUT)  $(CXXFLAGS) $(LDFLAGS)
#   make    -f  Makefile    clean

# create/compile the individual files >>separately<<
$(OBJSDIR)/main.o:    main.cpp
    $(CXX)  -c  main.cpp    $(CXXFLAGS)

$(OBJSDIR)/IO.o:    src/IO.cpp
    $(CXX)  -c  src/IO.cpp  $(CXXFLAGS)

$(OBJSDIR)/alloc.o:    src/alloc.cpp
    $(CXX)  -c  src/alloc.cpp   $(CXXFLAGS)

$(OBJSDIR)/communication.o:    src/communication.cpp
    $(CXX)  -c  src/communication.cpp   $(CXXFLAGS)

.PHONY: clean
clean:
    rm  -rf *.o

and I am getting:

gsamaras@pythagoras:~/konstantis/cholesky$ make
../../mpich-install/bin/mpic++ -I../../intel/mkl/include        -Wl,--start-group        -Wl,--end-group        -lpthread       -lm     -ldl    -Wall   -c -o main.o main.cpp
make: *** No rule to make target 'IO.o', needed by 'test'.  Stop.

I have a src folder, where all the .cpp files live (except from main.cpp, that lives in the same directory as the Makefile) and a headers directory, where all the header files live.


EDIT

I modified the first two lines, as such:

OBJSDIR    =   obj
OBJS    = $(OBJSDIR)/main.o $(OBJSDIR)/IO.o $(OBJSDIR)/alloc.o  $(OBJSDIR)/communication.o

and I am getting:

g++: error: obj/main.o: No such file or directory
...

The problem lies into the fact that the object files are still generated in the main directory!

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • You've taught make how to build `$(OBJSDIR)/IO.o` not `IO.o`. So your prerequisite need to list `$(OBJSDIR)/IO.o` and not `IO.o`. Your rules for the `.o` files also aren't going to generate the correct output files. They will generate `src/*.o` files to match their input files. (This is what that `-o` flag you mentioned is for.) – Etan Reisner Jul 21 '15 at 22:57
  • Hmm, check my edit @EtanReisner. OK, I see your edit, but I still can't figure it out. :/ – gsamaras Jul 21 '15 at 23:01

1 Answers1

1

You want to change the lines that invoke your compiler from:

$(OBJSDIR)/IO.o:    src/IO.cpp
    $(CXX)  -c  src/IO.cpp  $(CXXFLAGS)

to:

$(OBJSDIR)/IO.o:    src/IO.cpp
    $(CXX)  -c  src/IO.cpp  $(CXXFLAGS) -o $@

Note that $@ is the automatic variable that corresponds to the target file being created. So in the above case it will be obj/IO.o. -o specifies the output filename.

Furthermore while it is unrelated to your question one of the nice things about placing all the build artifacts into a separate directory is cleaning is much easier:

clean:
    rm -rf $(OBJSDIR) $(OUT)

Also, as a final note if you ever wish to do a parallel build you will have an issue as your object files rely on the build directory. There are a couple solutions to this including calling mkdir -p objs before every compiler invocation or setting up the directory as a dependency that is only built if it does not exist.

Community
  • 1
  • 1
missimer
  • 4,022
  • 1
  • 19
  • 33