2

I am looking for a generic makefile, which will will build all C++ files in the current directory and all sub-directories (e.g, source, test files, gtest, etc)

I have spent a few hours trying out several and finally settled on the solution from make file with source subdirectories.

I need to make three changes to it:

  1. Gtest uses *.cc for its C++ files and I have others which use *.cpp
  2. I need to be able to define multiple search paths.
  3. Add compiler flags, like -W all

I have managed to break the makefile, shown below, such that running make gives me

make: *** No rule to make target %.cpp=%.o', needed bymyProgram'. Stop.

How can I make it do those three things?

# Recursively get all *.cpp in this directory and any sub-directories
SRC = $(shell find . -name *.cc) $(shell find . -name *.cpp)

INCLUDE_PATHS = -I ../../../ -I gtest -I dummies

#This tells Make that somewhere below, you are going to convert all your source into 
#objects
# OBJ =  src/main.o src/folder1/func1.o src/folder1/func2.o src/folder2/func3.o

OBJ = $(SRC:%.cc=%.o %.cpp=%.o)

#Tells make your binary is called artifact_name_here and it should be in bin/
BIN = myProgram

# all is the target (you would run make all from the command line). 'all' is dependent
# on $(BIN)
all: $(BIN)

#$(BIN) is dependent on objects
$(BIN): $(OBJ)
    g++ 

#each object file is dependent on its source file, and whenever make needs to create
# an object file, to follow this rule:
%.o: %.cc
    g++ -c $(INCLUDE_PATHS) $< -o $@

[Update] Thanks for the help so far. To address a few of the comments, I have no control over the mixed *.cc and *.cpp fiel extensions, and I can say that there won't ever be a source file in the directory tree which I do not wish to include in the build.

I am still having trouble with the SRC, as no input files are found. I guess that I should look more into the find command as it has been a while since I used Linux.

Community
  • 1
  • 1
Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551
  • 1
    Variable expansion can only have *one* pattern replacement. Not two. So your `OBJ = $(SRC:%.cc=%.o %.cpp=%.o)` is your problem there. Add a second line with the second replacement if you want to do both. Also only running find once instead of twice is more efficient. – Etan Reisner Nov 24 '14 at 16:31
  • 2
    You're trying to build all `.o` files as if they all came from a `.cc` - but that's not the case. Some came from `.cpp` files. Easiest would be to just use a single extension everywhere. Is that not possible? – Barry Nov 24 '14 at 16:33
  • Think about what you are doing. If I want to keep a file in the directory, but not include it in the project, how will you handle this? – Thomas Matthews Nov 24 '14 at 17:10

2 Answers2

3

That is a rather poor makefile: it does not build header dependencies for you, so you are likely to end up with corrupted builds.

I shamelessly recommend this one.

Community
  • 1
  • 1
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
1

Etan points out your problem. But you don't have to perform two replacements, just:

OBJ := $(addsuffix .o,$(basename $(SRCS)))

And, you should always be using :=, not =, for assignment when using the shell function.

MadScientist
  • 92,819
  • 9
  • 109
  • 136