Makefile parallèle nécessite un ordre de dépendance

j'ai le fichier makefile suivant:

CXXFLAGS = -std=c++0x -Wall
SRCS     = test1.cpp test2.cpp
OBJDIR   = object
OBJS     = $(SRCS:%.cpp=$(OBJDIR)/%.o)

all: test1 
release: clean test1

test1: $(OBJS)
    $(CXX) -o $@ $(OBJS)

$(OBJDIR)/%.o: %.cpp
    $(CXX) $(CXXFLAGS) -MD -c -o $@ $<

-include $(SRCS:.cpp=.d)

clean:
    rm -rf $(OBJDIR)/*

.PHONY: all clean release 

maintenant si j'essaye d'invoquer "make-j4 release" la cible propre est souvent exécutée au milieu des fichiers de construction qui provoquent l'échec de la compilation. Ma question Est de savoir comment s'assurer que la cible clean est terminée avant de commencer la construction de la version.

21
demandé sur Mike Kinghan 2011-12-14 01:02:56

5 réponses

Ma préférence est pour

release:
    $(MAKE) clean
    $(MAKE) test1

ceci oblige les deux cibles à être faites consécutivement sans perturber leur parallélisme interne (s'il y en a).

25
répondu Neil 2011-12-13 21:55:38

vous pouvez diviser l'exécution en non-parallèle (pour release) et les phases parallèles (pour les autres cibles).

ifneq ($(filter release,$(MAKECMDGOALS)),)
.NOTPARALLEL:
endif

release: clean
    $(MAKE) test1

.NOTPARALLEL la cible supprimera l'exécution parallèle si release cible est mentionné dans la ligne de commande. release la cible elle-même va recommencer à faire après nettoyage et construire test1 en parallèle.

UPD.

une solution plus intelligente permettrait également de réinvestir chaque cible au cas où il y aurait plus de une cible donnée sur la ligne de commande, de sorte qu'une présence de release la cible ne forcerait pas le reste à exécuter non-parallèle aussi.

ifneq ($(words $(MAKECMDGOALS)),1)
.NOTPARALLEL:
$(sort all $(MAKECMDGOALS)):
    @$(MAKE) -f $(firstword $(MAKEFILE_LIST)) $@
else
# ...
endif

mise à Jour James Johnston

la solution intelligente ci-dessus ne fonctionne pas sur les versions de GNU make qui ne prennent pas en charge les serveurs de travail. Par exemple, les versions MinGW/native de GNU make publiées avant la version 4.0 ne prennent pas en charge les serveurs de tâches. (Cygwin / MSYS construit GNU make do. Le code ci-dessous utilise la .FEATURES variable introduit dans make 3.81 Pour détecter si les serveurs de tâches sont pris en charge. Le symptôme de ne pas utiliser cette solution quand elle est nécessaire est que votre construction "parallèle" sera sérialisée.

# Check if job server supported:
ifeq ($(filter jobserver, $(.FEATURES)),)
# Job server not supported: sub-makes will only start one job unless
# you specify a higher number here.  Here we use a MS Windows environment
# variable specifying number of processors.
JOBSARG := -j $(NUMBER_OF_PROCESSORS)
else
# Job server is supported; let GNU Make work as normal.
JOBSARG :=
endif

# .FEATURES only works in GNU Make 3.81+.
# If GNU make is older, assume job server support.
ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))),3.81)
# If you are using GNU Make < 3.81 that does not support job servers, you
# might want to specify -jN parameter here instead.
JOBSARG :=
endif

ifneq ($(words $(MAKECMDGOALS)),1)
.NOTPARALLEL:
# The "all" target is required in the list,
# in case user invokes make with no targets.
$(sort all $(MAKECMDGOALS)):
    @$(MAKE) $(JOBSARG) -f $(firstword $(MAKEFILE_LIST)) $@
else

# Put remainder of your makefile here.

endif
9
répondu Eldar Abusalimov 2017-05-23 11:46:40

Dans la libération cas, vous devez vous assurer que clean se termine avant la compilation. Ainsi vous (juste) l'ajoutez comme une dépendance à la règle de compilation (et non à la cible bidon). Plusieurs façons de le faire, comme des variables spécifiques à la cible, ou:

$(OBJDIR)/%.o: %.cpp $(if $(filter release,${MAKECMDGOALS}),clean)
    ...
1
répondu bobbogo 2013-02-28 13:45:13

Je ne sais pas exactement dans quelles versions cette fonctionnalité est prise en charge, mais vous pouvez utiliser le order-only caractéristique:

my_target: dep1 dep2 | must_run_1st must_run_2nd

toutes les dépendances restantes du | les caractères sont traités comme normaux. Dépendances à droite de | sont exécutées 'ordre'

Cette fonctionnalité est décrite à la page:

https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html

dans votre cas, la définition suivante des règles suffire:

release: | clean test1
test1: | clean
1
répondu theorifice 2017-03-31 23:07:21

pour une solution sans invocation récursive de la marque, vous pouvez essayer ceci.

ifneq ($(filter release,$(MAKECMDGOALS)),)
test1: clean
endif
-1
répondu eriktous 2011-12-14 12:05:13