makefile
Makefile avancé
Recherche…
Construire à partir de différents dossiers sources vers différents dossiers cibles
Principales caractéristiques de ce Makefile:
- Détection automatique des sources C dans les dossiers spécifiés
- Plusieurs dossiers sources
- Plusieurs dossiers cibles correspondants pour les fichiers d'objet et de dépendance
- Génération automatique de règles pour chaque dossier cible
- Création de dossiers cibles lorsqu'ils n'existent pas
- Gestion des dépendances avec
gcc
: Construisez seulement ce qui est nécessaire - Fonctionne sur
Unix
systèmesUnix
etDOS
- Écrit pour GNU Make
Ce Makefile peut être utilisé pour construire un projet avec ce type de structure:
\---Project
+---Sources
| +---Folder0
| | main.c
| |
| +---Folder1
| | file1_1.c
| | file1_1.h
| |
| \---Folder2
| file2_1.c
| file2_1.h
| file2_2.c
| file2_2.h
\---Build
| Makefile
| myApp.exe
|
+---Folder0
| main.d
| main.o
|
+---Folder1
| file1_1.d
| file1_1.o
|
\---Folder2
file2_1.d
file2_1.o
file2_2.d
file2_2.o
Makefile
# Set project directory one level above of Makefile directory. $(CURDIR) is a GNU make variable containing the path to the current working directory
PROJDIR := $(realpath $(CURDIR)/..)
SOURCEDIR := $(PROJDIR)/Sources
BUILDDIR := $(PROJDIR)/Build
# Name of the final executable
TARGET = myApp.exe
# Decide whether the commands will be shwon or not
VERBOSE = TRUE
# Create the list of directories
DIRS = Folder0 Folder1 Folder2
SOURCEDIRS = $(foreach dir, $(DIRS), $(addprefix $(SOURCEDIR)/, $(dir)))
TARGETDIRS = $(foreach dir, $(DIRS), $(addprefix $(BUILDDIR)/, $(dir)))
# Generate the GCC includes parameters by adding -I before each source folder
INCLUDES = $(foreach dir, $(SOURCEDIRS), $(addprefix -I, $(dir)))
# Add this list to VPATH, the place make will look for the source files
VPATH = $(SOURCEDIRS)
# Create a list of *.c sources in DIRS
SOURCES = $(foreach dir,$(SOURCEDIRS),$(wildcard $(dir)/*.c))
# Define objects for all sources
OBJS := $(subst $(SOURCEDIR),$(BUILDDIR),$(SOURCES:.c=.o))
# Define dependencies files for all objects
DEPS = $(OBJS:.o=.d)
# Name the compiler
CC = gcc
# OS specific part
ifeq ($(OS),Windows_NT)
RM = del /F /Q
RMDIR = -RMDIR /S /Q
MKDIR = -mkdir
ERRIGNORE = 2>NUL || true
SEP=\\
else
RM = rm -rf
RMDIR = rm -rf
MKDIR = mkdir -p
ERRIGNORE = 2>/dev/null
SEP=/
endif
# Remove space after separator
PSEP = $(strip $(SEP))
# Hide or not the calls depending of VERBOSE
ifeq ($(VERBOSE),TRUE)
HIDE =
else
HIDE = @
endif
# Define the function that will generate each rule
define generateRules
$(1)/%.o: %.c
@echo Building $$@
$(HIDE)$(CC) -c $$(INCLUDES) -o $$(subst /,$$(PSEP),$$@) $$(subst /,$$(PSEP),$$<) -MMD
endef
.PHONY: all clean directories
all: directories $(TARGET)
$(TARGET): $(OBJS)
$(HIDE)echo Linking $@
$(HIDE)$(CC) $(OBJS) -o $(TARGET)
# Include dependencies
-include $(DEPS)
# Generate rules
$(foreach targetdir, $(TARGETDIRS), $(eval $(call generateRules, $(targetdir))))
directories:
$(HIDE)$(MKDIR) $(subst /,$(PSEP),$(TARGETDIRS)) $(ERRIGNORE)
# Remove all objects, dependencies and executable files generated during the build
clean:
$(HIDE)$(RMDIR) $(subst /,$(PSEP),$(TARGETDIRS)) $(ERRIGNORE)
$(HIDE)$(RM) $(TARGET) $(ERRIGNORE)
@echo Cleaning done !
Comment utiliser ce Makefile Pour adapter ce Makefile à votre projet, vous devez:
- Changer la
TARGET
variable pour correspondre à votre nom cible - Modifier le nom des dossiers
Sources
etBuild
dansSOURCEDIR
etBUILDDIR
- Modifier le niveau de verbosité du Makefile dans le Makefile lui-même ou dans make call
- Modifier le nom des dossiers dans
DIRS
pour correspondre à vos sources et créer des dossiers - Si nécessaire, changez le compilateur et les drapeaux
Listes compressées
GNU make
Cette fonction pairmap
prend trois arguments:
- Un nom de fonction
- Première liste séparée par des espaces
- Deuxième liste séparée par des espaces
Pour chaque tuple zippé dans les listes, il appellera la fonction avec les arguments suivants:
- Tuple élément de la première liste
- Tuple élément de la deuxième liste
Il étendra à une liste séparée par des espaces des extensions de fonction.
list-rem = $(wordlist 2,$(words $1),$1)
pairmap = $(and $(strip $2),$(strip $3),$(call \
$1,$(firstword $2),$(firstword $3)) $(call \
pairmap,$1,$(call list-rem,$2),$(call list-rem,$3)))
Par exemple, ceci:
LIST1 := foo bar baz
LIST2 := 1 2 3
func = $1-$2
all:
@echo $(call pairmap,func,$(LIST1),$(LIST2))
.PHONY: all
Va imprimer foo-1 bar-2 baz-3
.
Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow