Zoeken…


Bouwen van verschillende bronmappen naar verschillende doelmappen

Belangrijkste kenmerken van deze Makefile:

  • Automatische detectie van C-bronnen in opgegeven mappen
  • Meerdere bronmappen
  • Meerdere bijbehorende doelmappen voor object- en afhankelijkheidsbestanden
  • Automatisch genereren van regels voor elke doelmap
  • Aanmaken van doelmappen wanneer deze niet bestaan
  • Afhankelijkheidsbeheer met gcc : bouw alleen wat nodig is
  • Werkt op Unix en DOS systemen
  • Geschreven voor GNU Make

Deze Makefile kan worden gebruikt om een project met dit soort structuur te bouwen:

\---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 ! 

Hoe deze Makefile te gebruiken Om deze Makefile aan uw project aan te passen, moet u:

  1. Wijzig de TARGET variabele zodat deze overeenkomt met uw doelnaam
  2. Wijzig de naam van de mappen Sources en Build in SOURCEDIR en BUILDDIR
  3. Verander het detailniveau van de Makefile in de Makefile zelf of in call
  4. Wijzig de naam van de mappen in DIRS zodat deze overeenkomen met uw bronnen en mappen DIRS
  5. Wijzig indien nodig de compiler en de vlaggen

Zippende lijsten

GNU maken

Deze pairmap functie heeft drie argumenten:

  1. Een functienaam
  2. Eerste door spaties gescheiden lijst
  3. Tweede door spaties gescheiden lijst

Voor elke ingepakte tuple in de lijsten roept het de functie aan met de volgende argumenten:

  1. Tuple-element uit de eerste lijst
  2. Tuple-element uit de tweede lijst

Het wordt uitgebreid met een door spaties gescheiden lijst van functie-uitbreidingen.

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)))

Dit is bijvoorbeeld:

LIST1 := foo bar baz
LIST2 := 1 2 3

func = $1-$2

all:
    @echo $(call pairmap,func,$(LIST1),$(LIST2))

.PHONY: all

Zal foo-1 bar-2 baz-3 afdrukken.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow