FINAL UPDATE:
Problem solved thanks to @Useless!
Changed $(EXET): $(OBJS)
to $(EXET): $(OSRC)
.
UPDATE: Sept 29, 2020
Following @MadScientist's suggestions, I edited and removed the unnecessary parts from the Makefile. However, the line OSRC := $(addprefix $(ODIR)/, $(OBJS))
doesn't seem to have any effect because the *.o
object files are now compiled into the workspace folder, not the dedicated ./obj
folder, which is my origin problem.
#############################################################
## THIS IS A TEST PROJECT ##
#############################################################
vpath %.cpp src
vpath %.h hdr
#############################################################
## BUILD TASKS ##
#############################################################
HDIR := hdr
#SRCS := src
ODIR := obj
EXET := a
OBJS := main.o mainhdr.o testcode.o
OSRC := $(addprefix $(ODIR)/, $(OBJS))
CXX := g++
CXXFLAGS := -I$(HDIR) -g -Wall -std=c++17
## BUILD DIRECTIVE:
all: $(EXET)
$(EXET): $(OBJS)
$(CXX) $(CXXFLAGS) $^ -o $@
$(ODIR)/%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $^ -o $@
#############################################################
## CLEAN TASK ##
#############################################################
.PHONY: clean
clean:
rm -r $(EXET) *.o
ORIGINAL QUESTION:
I've been pulling my hair out trying to no avail to get Make to link prebuilt objects from a specific directory. I got my Makefile to compile the object files into a different directory, but I'm basically stuck after that.
#############################################################
## THIS IS A TEST PROJECT ##
#############################################################
.SUFFIXES:
.SUFFIXES: .o .h .cpp
vpath %.cpp src
vpath %.h hdr
vpath %.o out
%.h : %.cpp
#############################################################
## BUILD TASKS ##
#############################################################
HDIR := hdr
#SRCS := src #UNUSED
ODIR := obj
EXE := a
OBJS := main.o mainhdr.o testcode.o
## This line added in reference to this thread:
## https://stackoverflow.com/questions/9178285/how-can-makefile-use-separate-directories-for-source-code-and-binaries
## But it doesn't seem to work either
OSRC := $(addprefix $(ODIR)/, $(OBJS))
CPP := g++
CPPFLAGS := -I$(HDIR) -c -g -Wall -std=c++17
## BUILD DIRECTIVE:
all: $(EXE)
## PROBLEM: Doesn't seem to work when prefixed with the output dir:
#$(EXE): $(ODIR)/$(OBJS)
$(EXE): $(OBJS)
$(CPP) -o %@ %^
## This compiles the objects into the output dir just fine.
%.o: %.cpp
# $(CPP) $(CPPFLAGS) $< -o $@
$(CPP) $(CPPFLAGS) $< -o $(ODIR)/$@
#############################################################
## CLEAN TASK ##
#############################################################
.PHONY: clean
clean:
rm -r $(EXE) $(ODIR)/*.o
## End of Makefile ##########################################
Debugging effort so far:
I added the
.o
filetype to.SUFFIXES:
but I doubt that it does anything. Make only seems to care about the headers and source files.I did some more research and I added this part later:
## This line added in reference to this thread:
## https://stackoverflow.com/questions/9178285/how-can-makefile-use-separate-directories-for-source-code-and-binaries
## But it doesn't seem to work either
OSRC := $(addprefix $(ODIR)/, $(OBJS))
However, it doesn't seem to have any effect at all. Make just couldn't find the object directory either.
- Even though it works, this line bothers me somehow:
$(CPP) $(CPPFLAGS) $< -o $(ODIR)/$@
Shouldn't it be fixed somehow to be consistent with the $(addprefix)
directive?
Quick references from GNU Make in case I'm missing something:
$@ target
%< first prerequisite
$^ prerequisites
The following is simple test code:
// cat hdr/mainhdr.h
#ifndef MAINHDR_H
#define MAINHDR_H
#include "testcode.h"
#define BIGCONST 777
void testFunc();
#endif
// cat hdr/testcode.h
#ifndef TESTCODE_H
#define TESTCODE_H
#include <iostream>
#include <string>
#define SMALLCONST 25
class NameTag {
private:
std::string f;
std::string l;
public:
NameTag(std::string first="", std::string last="");
void setFirstN(std::string );
void setLastN(std::string );
std::string getFirstN() const;
std::string getLastN() const;
void operator=(const NameTag &);
};
#endif
// cat src/main.cpp
#include "mainhdr.h"
int main () {
testFunc();
return 0;
}
// cat src/mainhdr.cpp
#include "mainhdr.h"
void testFunc() {
std::cout << "THIS IS A TEST STRING!\n";
std::cout << "BIGCONST = " << BIGCONST << std::endl;
std::cout << "SMALLCONST = " << SMALLCONST << std::endl;
NameTag someDude("Good", "Dude");
std::cout << someDude.getFirstN() << " " << someDude.getLastN() << std::endl;
}
// cat src/testcode.cpp
#include "testcode.h"
NameTag::NameTag(std::string first, std::string last) {
f = first;
l = last;
}
void NameTag::setFirstN(std::string first) {
f = first;
}
void NameTag::setLastN(std::string last) {
l = last;
}
std::string NameTag::getFirstN() const {
return f;
}
std::string NameTag::getLastN() const {
return l;
}
void NameTag::operator=(const NameTag &right) {
f = right.f;
l = right.l;
}