2
votes

I have following Makefile, and I would like to configure it to produce debug build by default and release build by specifying corresponding target.

The problem I am trying to solve right now is following, - project contains unit tests, and I want them to be included in default build, but excluded from release, so I am added release target to Makefile:

FC      = ifort
FFLAGS  = -c -free -module modules -g3 -warn all -warn nounused
LDFLAGS = -save-temps -dynamiclib

INTERFACES = src/Foundation.f units/UFoundation.f units/Asserts.f units/Report.f
EXCLUDES   = $(patsubst %, ! -path './%', $(INTERFACES))
SOURCES    = $(INTERFACES) \
             $(shell find . -name '*.f' $(EXCLUDES) | sed 's/^\.\///' | sort)
OBJECTS    = $(patsubst %.f, out/%.o, $(SOURCES))
EXECUTABLE = UFoundation

all: $(SOURCES) $(EXECUTABLE)

release: SOURCES := $(filter-out units/%.f, $(SOURCES))
release: OBJECTS := $(filter-out units/%.o, $(OBJECTS))
release: EXECUTABLE := 'Foundation.dlyb'
release: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    @echo 'Linking to $@...'
    @$(FC) $(LDFLAGS) $(OBJECTS) -o out/$@

out/%.o: %.f
    @echo 'Compiling $@...'
    @mkdir -p modules
    @mkdir -p $(dir $@)
    @$(FC) $(FFLAGS) -c $< -o $@

clean:
    @echo "Cleaning..."
    @rm -rf modules out $(EXECUTABLE)

Unfortunate, it doesn't help - result of 'make' and 'make release' are the same (make release compiles unit test files as in default). I already looked to similar questions, like How can I configure my makefile for debug and release builds?, but without any success to solve the issue.

1

1 Answers

5
votes

Debug and release targets get build with different macros (e.g. NDEBUG) and different optimization levels. You normally do not want to mix debug and release object files, hence they need to be compiled into different directories.

I often use a different top-level build directory for different build modes this way:

BUILD := debug
BUILD_DIR := build/${BUILD}

And compiler flags this way:

cppflags.debug :=
cppflags.release := -DNDEBUG
cppflags := ${cppflags.${BUILD}} ${CPPFLAGS}

cxxflags.debug := -Og
cxxflags.release := -O3 -march=native
cxxflags := -g -pthread ${cxxflags.${BUILD}} ${CXXFLAGS}

And then build your objects into BUILD_DIR.

When you invoke it as make BUILD=release that overrides BUILD := debug assignment made in the makefile.