Search code examples
c++makefiledirectoryobject-files

Makefile does not find object file


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!


Solution

  • 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.