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èmes Unix et DOS
  • É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:

  1. Changer la TARGET variable pour correspondre à votre nom cible
  2. Modifier le nom des dossiers Sources et Build dans SOURCEDIR et BUILDDIR
  3. Modifier le niveau de verbosité du Makefile dans le Makefile lui-même ou dans make call
  4. Modifier le nom des dossiers dans DIRS pour correspondre à vos sources et créer des dossiers
  5. Si nécessaire, changez le compilateur et les drapeaux

Listes compressées

GNU make

Cette fonction pairmap prend trois arguments:

  1. Un nom de fonction
  2. Première liste séparée par des espaces
  3. Deuxième liste séparée par des espaces

Pour chaque tuple zippé dans les listes, il appellera la fonction avec les arguments suivants:

  1. Tuple élément de la première liste
  2. 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