Writing the ultimate makefile

I'm trying to write a makefile that, given a list of source and header files (or just *) and compilation flags, automatically determines the dependencies of each object file and uses this information to build the real makefile, running it from standard input.

I'm surprisingly close to this goal. I can generate a rule for each .o file as you would expect, but I still need to insert the additional targets "all" and "clean". Unfortunately, this forces me to write something like this:

 
echo "[new targets]" "sed "[regexp stuff]""


This creates nested quotes within the sed command. The arguments to sed need to be in quotes themselves, as the regular expressions contain spaces.

How can I work around this? The solution needs to work on Windows with mingw and msys installed in addition to Linux. I will post the finished makefile if there is a solution.
On shell commands, \" usually works.And if you need a backslash, use \\.
Example (try this in a shell): echo "\""
Output: "
closed account (S6k9GNh0)
Telion, if make can't do this itself, why use make in the first place?
Take a look at BSDmake on FreeBSD. It's exactly that.
http://www.cplusplus.com/articles/jTbCpfjN/

BTW, you don't really want to use * as you may have files that you don't want in the project. It's best to be explicit about the source files or object files.
Last edited on
Make can hardly do this by itself. I have repeatedly been told that you have to specify dependencies by hand with make unless you use the autotools (this turned out to be incorrect, of course). I just learned that you can actually have makefiles create dependencies for you automatically, but the solution is convoluted.

So of course, I went on to finish my own even more convoluted solution. This makefile compiles all source files in the directory (although you can change that if your project is not defined by a directory) and supports incremental builds properly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FLAGS = -std=c++11 -s -O3 -Wall -Wextra
CFLAGS = $(FLAGS) -c
LFLAGS = $(FLAGS)
SOURCES = *.cpp
HEADERS = *.h
EXECUTABLE = a.exe

all: Makefile.out
	$(MAKE) -f Makefile.out

Makefile.out: Makefile_depend.txt Makefile
	echo "OBJS=" | tr -d "\r" | tr "\n" " " > Makefile.out
	sed "s:\([A-Za-z0-9 ,;~!@#^&(){}]*\).*:\1.o :" <Makefile_depend.txt | tr -d "\r" | tr -d "\n" >>Makefile.out
	echo -e "\nall: $(EXECUTABLE)" >> Makefile.out
	echo -e "$(EXECUTABLE): \$$(OBJS)\n\tg++ \$$(OBJS) -o $(EXECUTABLE) $(LFLAGS)" >>Makefile.out
	sed "s:\([A-Za-z0-9 ,;~!@#^&(){}]*\).*:&\n\tg++ \1.cpp $(CFLAGS) -o \1.o:" <Makefile_depend.txt >>Makefile.out

Makefile_depend.txt: $(SOURCES) $(HEADERS)
	gcc -MM $(SOURCES) | sed "s:^.*[A-Za-z0-9 ,;~!@#^&(){}]$$:& \?:" | tr -d "\r\n" | tr -d "\\" | tr "\?" "\n" >Makefile_depend.txt

clean: Makefile_depend.txt
	sed "s:\([A-Za-z0-9 ,;~!@#^&(){}]*\).*:\1.o :" <Makefile_depend.txt | tr -d "\r\n" | xargs rm -f
	rm -f $(EXECUTABLE)
	rm -f Makefile_depend.txt Makefile.out


Isn't that the most beautiful makefile you've ever seen? ;) It doesn't use the include statement at all, instead creating a secondary makefile called Makefile.out and putting all the build statements in there. It does not handle sources in other directories well, though, but the cleaner include-based implementations run into exactly the same problem. The regular expressions could use some work too.
Last edited on
Of course... you could always just use an IDE so you don't have to deal with any of this in the first place. ;P
Depends on if he plans on joining a company though. According to several articles I have read from Carmack, they use makefiles and scripts to automate their compilation process at like 3 am so they could get straight into debugging the code when the arrived at work. I believe this was also talked about as their method for when they did Doom 3. Fact is that while not widely used, some companies still like having guys that know how to do things like this themselves in case an IDE makefile requires special tweaking for a project.
That's true. It's a skill like any other, I suppose.
www.cmake.org -> CMake builds make files for you depending on arguments etc.
Topic archived. No new replies allowed.