tags:

views:

2716

answers:

4

I am new to makefiles. I learned makefile creation and other related concepts from "Managing projects with GNU make" book. The makefile is ready now and I need to make sure the one which I created is OK. Here is the makefile

#Main makefile which does the build

#makedepend flags
DFLAGS = 

#Compiler flags
#if mode variable is empty, setting debug build mode
ifeq ($(mode),release)
   CFLAGS = -Wall
else
   mode = debug
   CFLAGS = -g -Wall
endif

CC = g++
PROG = fooexe

#each module will append the source files to here
SRC := main.cpp

#including the description
include bar/module.mk
include foo/module.mk

OBJ := $(patsubst %.cpp, %.o, $(filter %.cpp,$(SRC)))

.PHONY:all
all: information fooexe

information:
ifneq ($(mode),release)
ifneq ($(mode),debug)
    @echo "Invalid build mode." 
    @echo "Please use 'make mode=release' or 'make mode=debug'"
    @exit 1
endif
endif
    @echo "Building on "$(mode)" mode"
    @echo ".........................."

#linking the program
fooexe: $(OBJ)
    $(CC) -o $(PROG) $(OBJ)

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

depend:
    makedepend -- $(DFLAGS) -- $(SRC)

.PHONY:clean
clean:
    find . -name "*.o" | xargs rm -vf
    rm -vf fooexe

Questions

  1. The above given makefile works well with release and debug builds. But is it in the correct format? Or do you see any flaws in that?
  2. Above makefile does debug build by default when invoked using make. For release builds, make mode=release is required. Is this the correct approach?
  3. Is the debug and release compiler flags supplied to g++ is correct? For debug, I use -g -Wall and for release, just -Wall. Is this right?

Any help would be great.

+3  A: 
  1. It is one reasonable format. It is tied specifically to GNU Make, but that's a relatively minor problem if you have chosen to use GNU Make on every platform.
    • If there is a flaw, it is that you could end up linking object files built in debug mode to create the final build.
    • Some might argue that a 'mode=release' option is non-standard; they'd be right, but there isn't a standard alternative that I'm aware of. You just need to be aware that your convention might not suit everyone (but it doesn't have to - it just has to suit you and your users).
  2. Building a debug build by default is probably sensible - and more sensible than building the release build by default.
  3. Dropping the -g flag for the release build is not automatically bad, but if your code ever produces a core dump, it is easier to make head or tail of the core dump if the program file includes debugging information. The primary cost of debugging information is extra sections in the program file that do not need to be loaded into system memory - the runtime cost is small.
    • You should consider whether to include optimization flags in there. With the GCC tool set, you can use both -g and -O. It is harder to debug optimized code, but it gives you (often significant) performance benefits.
Jonathan Leffler
"If there is a flaw, it is that you could end up linking object files built in debug mode to create the final build". I am not clear with that statement. Before making release build, I will clean all existing object files and do a release build. So that I get correct release files linked. Is that OK? Thanks for the answer.
Appu
Suppose you run 'make', then edit one source file, and then run 'make mode=release'; the majority of the object files were compiled in debug mode, even though it is a 'release' build. If, as you hint, you do 'make mode=release clean all', then you should be good. That's why I didn't say "It is a flaw"; I indicated that it is a possible problem to be aware of. (Also, there isn't a simple solution - you need a more sophisticated build tracker that records how the object files were created, including compiler options. See 'ccache' http://ccache.samba.org/ for an example.)
Jonathan Leffler
Thanks Jonathan. It is clear now.
Appu
A: 

For me, Makefiles are a thing of the past and for good. I prefer to use Scons for all the new projects when possible. It's much saner and python scripting capabilities make it easily extendable.

piotr
Same thing for me except I use CMake. Scons seem as nice as CMake, I'll take a look at it.
brunoqc
This is irrelevant to the question..
Lipis
+3  A: 

I would suggest following modes:

for debugger: -O0 -g -Wall
for development and internal release: -O2 -g -Wall
for release outside the company: -O2 -Wall

Rationale:

  • It is very important to develop and test the code in "production mode". You can find that in some cases code that works without optimization crashes in optimized mode because of the bug in your code. (Believe me this happens a lot) -- So use -O2
  • In most of cases you still can debug quite well even with optimized code, so add -g. However, if this is too hard to find the bug in such mode you can compile for debugger with -O0
  • Only if you have problems including debug information in code, you should remove -g. It is good idea to have -g for the code in production environment, because if something crashes you can get much more information.
Artyom
Thanks. It was really helpful
Appu
+1  A: 

I'd take Artyom's advice about the flags and make use of -O.

My major piece of advice would be to make the default mode "release". No user outside your company is going to know about your make mode=release convention and 99.99% of them will want it built for release.

I like that you've got -Wall on in all modes. If you want to get really pedantic... -Wall -std=c++98 -pedantic -Wextra -Wconversion is a good start. -std=c++98 may not be necessary if you're wedded to g++, but if you have any illusions of portability you'll want that.

Schwern