Alix Blaine
Alix Blaine

Reputation: 831

Makefile with multiple separate *.cpp files to output separate *.exe files in different dir

I am stuck, writing my Makefile. Directory structure:

.\
  Makefile
  .\src\*.cpp(s)
  .\bin

Desire: What I want to achieve with one Makefile.

Run: make

Output (Terminal):

g++ -g -Wall   -c -o src/program1.o src/program1.cpp
g++ -g -Wall   -c -o src/program2.o src/program2.cpp
g++ -g -Wall   -c -o src/program3.o src/program3.cpp
g++ -g -Wall   -c -o src/program4.o src/program4.cpp 

Output (in /bin/)

program1.exe
program2.exe
program3.exe
program4.exe

EDIT:

CXX  = g++
CXXFLAGS = -Wall -g3 -O0
SRC  := ${wildcard src/*.cpp}
OBJS := $(SRC:.cpp=.o)
BIN := $(SRC:src/%.cpp=bin/%)

.PHONY: all

all: $(BIN)

$(BIN): $(OBJS)
    $(CXX) -c $(CXXFLAGS) -o $(OBJS)

bin/%: src/%.o
    $(CXX) -o $@ $^

Error:

g++: warning: linker input file unused because linking not done

Upvotes: 0

Views: 539

Answers (2)

MadScientist
MadScientist

Reputation: 101081

The introductory parts of the GNU make manual describe that all: $(BIN) creates a target all that depends on a target bin. That means make will try to create bin. Then you have $(BIN): $(OBJS) which says bin depends on all the object files, so make will try to create all the object files. Then there's a recipe for that rule that says, after you've created the object files run this command, which links together all the object files into a single program (bin).

So make is doing exactly what you asked it to do.

The problem is that is apparently not what you want it to do.

In your question you write, then take the original filenames of each *.cpp and add that to the executable which I don't fully understand, but I assumed that you want to link all the objects into a single executable, which is what your makefile does.

But then later you write: How can I output to bin directory and generate the correct executables?, but you never define what "correct executables" means, and this makes it sound like you want to turn each individual object file into its own executable; that's clearly not what your makefile does.

So before you can tell make what you want, first you have understand clearly what you want so you can write it in your makefile. And if you need us to help you write it into your makefile, you need to explain it clearly in your question so we can understand it.

Cheers!

ETA

OK so you want every source file to compile into an object file, then every object file to compile to a separate binary.

First compute the names of all the binaries you want to build:

SRCS := $(wildcard src/*.cpp)

BINS := $(SRCS:src/%.cpp=bin/%)

Now make a rule that depends on all the binaries:

all: $(BINS)

Now make a pattern rule that tells make how to build each one of those binaries:

bin/% : src/%.o
        $(CXX) $(CXXFLAGS) -o $@ $^ $(LDLIBS)

Now you're actually done, because make already has a built-in rule that knows how to build a .o file into the same directory where the .c file lives, so it can figure out how to build the src/x.o files on its own.

Upvotes: 2

Victor Eijkhout
Victor Eijkhout

Reputation: 5852

Try something like:

SRC:=${wildcard src/*.cpp}
OBJ:=$(patsubst %.cpp,%.o,${patsubst src/%,bin/%,${SRC}}}

to get the list of the object files, and the rule:

obj/%.o : src/%.cpp
    ${CXX} -o $@ -c $<

for compiling into the right location.

EDIT You have now clarified that each file is a separate main.

SRC:=${wildcard src/*.cpp}
BIN:=$(patsubst %.cpp,,${patsubst src/%,bin/%,${SRC}}}

to get the list of the object files, and the rule:

bin/% : src/%.cpp
    ${CXX} -o $@ $<

will write each output as an executable in bin. To kick it off:

all : ${BIN}

Upvotes: 0

Related Questions