3
\$\begingroup\$

I would like some input on the Makefile I'm using for my C++ project. It is my first Makefile and I learned how to do what I want through various readings on the web. The directory structure is as follows :

project directory
|___ src/ (source files)
|___ include/ (header files)
|___ tests/ (source files each containing "int main(int argc, char **argv)"
|___ build/ (object files and dependency files)
|___ bin/ (compiled programs)
|___ Makefile

The main reason I'm asking for input is that recently I did some changes, including adding a member to one of my classes and this caused my program to crash with segfaults ; it turns out that doing a make clean and recompiling from scratch resolved the problem as explained in this answer.

Apparently the automatic dependency generation failed in some way and some parts of my program were not recompiled when I changed the header... At least that is what I understand. So if the dependency generation (g++ -MMD) is not done right I would like to know how to improve it. Here is the Makefile :

# Makefile 

# Compiler
CXX      := -g++
# Compiler flags
CXXFLAGS := -pedantic-errors -Wall -Wextra -std=c++17 -g -O0

# Library flags
LDFLAGS  := -L/usr/lib -lstdc++ -lm
# Librairy flags for petsc
LDFLAGS_PETSC = ... # long list of library flags
LDFLAGS += $(LDFLAGS_PETSC)

# List of include directories
# use -isystem to supress warnings for this folder
INCLUDE := -Iinclude/ -isysteminclude/lepton/ -Iinclude/gauss-legendre-quadrature/
INCLUDE_PETSC := -I/home/intendant/software/petsc/include \
                 -I/home/intendant/software/petsc/arch-linux2-cxx-debug/include
INCLUDE += $(INCLUDE_PETSC)
# Include boost if downloaded from boost.org instead of installed through apt-get
# INCLUDE_BOOST := -I/opt/boost_1_67_0/
# INCLUDE += $(INCLUDE_BOOST)

# List of source files 
SRC_DIR := src
SOURCES := $(wildcard $(SRC_DIR)/*.cpp) \
           $(wildcard $(SRC_DIR)/lepton/*.cpp) \
           $(wildcard $(SRC_DIR)/gauss-legendre-quadrature/*.cpp)
# NOTE: gauss_legendre renamed from .c to .cpp after download

# List of source files for tests and mains
MAIN_DIR := tests
MAIN_SOURCES = $(wildcard $(MAIN_DIR)/*.cpp)

# List of executables
TARGET_DIR := bin
TARGETS = $(MAIN_SOURCES:$(MAIN_DIR)/%.cpp=$(TARGET_DIR)/%.out)
TARGET_NAMES = $(MAIN_SOURCES:$(MAIN_DIR)/%.cpp=%)

# List of objects files for src/ and tests/ files
OBJ_DIR  := build
OBJECTS  := $(SOURCES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
MAIN_OBJECTS := $(MAIN_SOURCES:$(MAIN_DIR)/%.cpp=$(OBJ_DIR)/%.o)

# Create variable containing list of dependencies (generated by gcc)
DEP = $(OBJECTS:%.o=%.d)

# Remove warnings when building lepton library
build/lepton/%.o: CXXFLAGS += -w

# Default target should be cfm
main: build $(TARGET_DIR)/cfm.out
# Build all executables
all: build $(TARGETS) 

# Include all .d files
-include $(DEP)

# Make object files from source files (-MMD generates dependencies .d files)
$(OBJECTS): $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
    @mkdir -p $(@D)
    $(CXX) $(CXXFLAGS) $(INCLUDE) -MMD -o $@ -c $<

# Make object files from main source files (-MMD generates dependencies .d files)
$(MAIN_OBJECTS): $(OBJ_DIR)/%.o : $(MAIN_DIR)/%.cpp
    @mkdir -p $(@D)
    $(CXX) $(CXXFLAGS) $(INCLUDE) -MMD -o $@ -c $<

# Link object files with appropriate main to create app
$(TARGETS): $(TARGET_DIR)/%.out: $(OBJ_DIR)/%.o $(OBJECTS) 
    @mkdir -p $(@D)
    @echo "Linking "$@"..."
    @$(CXX) $(CXXFLAGS) $(INCLUDE) -o $@ $^ $(LDFLAGS)

# Convenience rule to type "make program" instead of "make bin/program.out"
$(TARGET_NAMES): %: $(TARGET_DIR)/%.out

.PHONY: all build clean debug release main $(TARGET_NAMES)

build:
    @mkdir -p $(TARGET_DIR)
    @mkdir -p $(OBJ_DIR)

debug: CXXFLAGS += -DDEBUG -g  -O0
debug: all

release: CXXFLAGS += -O2
release: all

clean:
    -@rm -rf $(OBJ_DIR)/*
    -@rm -rf $(TARGET_DIR)/*
\$\endgroup\$
2
  • \$\begingroup\$ Unfortunately the question falls into code not working as intended category, which it strictly off-topic here. That said, I strongly recommend to roll out an explicit %.d: %.cpp (with -MMD and without -c) rule. \$\endgroup\$
    – vnp
    Jun 8, 2018 at 6:17
  • \$\begingroup\$ in case you just want the task to be done consider using github.com/igagis/prorab \$\endgroup\$
    – igagis
    Feb 26, 2019 at 19:10

0

Browse other questions tagged or ask your own question.