Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

This is the current Makefile that I use with my C projects. Here is what I would like to be reviewed:

  1. Reusability - is this Makefile easy to use for multiple separate projects with minimal modification?

  2. Organization - is this Makefile organized in a logical and readable way?

  3. Dynamics - are there Make features (or compiler options/warnings) that I am not taking advantage of that could make my Makefile more powerful?

  4. Miscellaneous - what other things could I improve?


CXX = g++-4.9
CC = gcc-4.9
DOXYGEN = doxygen
CFLAGS = -fdiagnostics-color=always -std=gnu11 -s -c -g3 -O3 -time
WARNINGS = -Werror -Wall -Wextra -pedantic-errors -Wformat=2 -Wno-import -Wimplicit -Wmain -Wchar-subscripts -Wsequence-point -Wmissing-braces -Wparentheses -Winit-self -Wswitch-enum -Wstrict-aliasing=2 -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wdisabled-optimization -Wunused-macros -Wno-unused
LDFLAGS =
LIBRARIES = -lcurl
SOURCES = main.c test.c
OBJECTS = $(SOURCES:.c=.o)
EXECUTABLE = test

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@ $(LIBRARIES)

debug: CFLAGS += -DDEBUG -g
debug: $(SOURCES) $(EXECUTABLE)

.c.o:
    $(CC) $< -o $@ $(CFLAGS) $(WARNINGS)

.PHONY: doc clean       
doc: 
    $(DOXYGEN) doxygen.config    
clean:
    rm -rf $(EXECUTABLE) $(OBJECTS)
share|improve this question
    
Question is why would you use and (more importantly) create by hand Makefiles? For any project that exceeds few files (and spans over more than one directory) Makefiles become very cumbersome and it seems to manage them sanely you need some other software (to i.e. generate them from some more sane description). I can really recommend scons.org, way more flexible than any other build system I have ever had a chance to use. And should work on any platform that Python works on. –  elmo Apr 15 at 8:36
1  
Writing good Makefiles by hand is really not a simple task, especially when you are aiming for Reusability and Portability. I know that, when you are at the point you are at the moment, you don't want to hear about "meta-generators" like the one elmo suggested, but they really are a big help. While elmo pointed to SCONS, I familiarized myself with CMake, and did put together some boilerplate of my own, named JAWS. Check it out, it does what you want (including the Doxygen part), and much more... –  DevSolar Apr 15 at 9:51
    
@DevSolar If you expanded on that a bit in an answer, that would be something that I would give an upvote, and maybe even a reward bounty (but that would have to give an in-depth explanation of some stuff :))! –  syb0rg Apr 15 at 13:24
    
@syb0rg: I'd rather work on some polish for JAWS if you don't mind. ;-) Anything specific you think is missing? –  DevSolar Apr 15 at 13:57
    
@DevSolar I'm still going through it, I'm somewhat new to the world of the GNU build system. If you would join me in our chat room to talk about some stuff, that would be awesome! –  syb0rg Apr 15 at 14:07
add comment

3 Answers 3

up vote 10 down vote accepted

I would make source file discovery dynamic:

 SOURCES   = $(wildcard *.c)

In addition to all I usually add debug and release versions.

CFLAGS = -fdiagnostics-color=always -std=gnu11 -s -c -time
all:     CFLAGS += -DTYPE=ALL
debug:   CFLAGS += -DTYPE=DEBUG    -g3
release: CFLAGS += -DTYPE=RELEASE  -O3

I have a generic build file that I have all my rules built-into.

https://github.com/Loki-Astari/ThorMaker
https://github.com/Loki-Astari/ThorMaker/blob/master/tools/Makefile

Note: It is not perfect or great (but does what I need).
But have a look and pull anything you need.

This allows my actual makefiles to be very simple:

# The Target I want to build
# My generic Makefile build apps and lib based
# on the extension extension of the target.
TARGET                  = myLib.slib

# Then include the Generic Makefile
# In uses THORSANVIL_ROOT as the root of where you are
THORSANVIL_ROOT         = $(realpath ../)
include ${THORSANVIL_ROOT}/build/tools/Makefile
share|improve this answer
add comment

Dependencies: right now your makefile will let changes in .h to remain unnoticed.

DEPS := $(SOURCES:.c=.d)

.c.d:
    $(CC) -o $< -MM $(CFLAGS)

-include $(DEPS)

PS: it is highly recommended to remove -c from CFLAGS and mention it explicitly in the .c.o rule.

share|improve this answer
add comment

The first rule should just be

all: $(EXECUTABLE)

In turn, $(EXECUTABLE) will require $(OBJECTS), and each object will require its corresponding .c file.

Also, all should be a .PHONY target, since you are not actually going to produce a file named all.

Both of the remarks above apply equally to the debug target as well.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.