Ben Wainwright
Ben Wainwright

Reputation: 4611

One makefile to compile all the source in a specified directory

I am currently working through a c++ textbook; I'd like to have separate folders for exercises in the book, and a single makefile in the root, so that in the root directory I can type

make directoryName

and it will compile all the sources in that directory, and output a binary into the root. Here is what I have so far:

FLAGS= -Wall -Wextra -Wfloat-equal
OUT=helloworld.out

%: $(wildcard $@/*.cpp) 
    g++ $@/$(wildcard *.cpp) -o $(OUT) $(FLAGS)

But when I try to run it, all I get is

pc-157-231:Section2$ make helloWorld
make: `helloWorld' is up to date.

Any help appreciated

Edit Note; the problem is not that I haven't changed the target file; I did...

Upvotes: 5

Views: 861

Answers (2)

dascandy
dascandy

Reputation: 7292

I have written a replacement for make that makes this very easy, but it is otherwise very experimental / not-officially-supported etc. You can download it from https://github.com/dascandy/bob .

You would probably be able to write this as:

FLAGS= -Wall -Wextra -Wfloat-equal    

# Take all cpp files in a folder & compile it to executable with that folder name as name.
(.*)/.*\.cpp => \1.out
  g++ -o $@ $^ $(FLAGS)

or alternatively, with intermediate objects (better for large projects, but probably useless for small exercises)

FLAGS= -Wall -Wextra -Wfloat-equal    

# Read as, compile any CPP file to a file with the same root but .o as extension
(.*)\.cpp => \1.o
  g++ -c -o $@ $^ $(FLAGS)

# read as, take all objects in a subfolder together and compile into executable with folder name as name.
(.*)/.*\.o => \1.out
  g++ -o $@ $^

The tool itself requires Boost.Filesystem to be installed.

If you want to have a default target that compiles all executables, add these lines:

.*.out => all
  echo -n

(the echo is because it expects all rules to have a command)

Upvotes: 0

kfx
kfx

Reputation: 8537

Your problem is that automatic GNU make variables such as $@ only have a value within the body of the rule. From GNU make documentation.

[Automatic variables] cannot be accessed directly within the prerequisite list of a rule. A common mistake is attempting to use $@ within the prerequisites list; this will not work. (source)

Additonally, you do not need the $(wildcard ...) function in your rule (both in body and in prerequisite list), although it's not a mistake either:

Wildcard expansion happens automatically in rules. (source)

Upvotes: 1

Related Questions