2017-10-19 36 views
0

Comment créer des cibles bidon non dépendantes dans un Makefile GNU?Comment créer des cibles bidon non dépendantes dans un Makefile GNU?

Exigences:

  1. Une règle qui vérifie une configuration spécifique - peut être plus complexe que l'exemple ci-dessous.
  2. Si cette règle échoue, la construction de cibles spécifiques devrait échouer.
  3. Si cette règle réussit, la création de cibles spécifiques doit être effectuée uniquement si leurs sources sont modifiées.
  4. La règle ne peut pas être globale, puisque cette règle ne devrait même pas être exécuté pour des cibles non spécifiques

Ceci est réalisable si la règle est insérée avant que la règle de compilation de chaque cible spécifique. Puisqu'ils peuvent être de nombreuses cibles spécifiques, je préfère créer une cible bidon pour cette règle, et spécifier cette cible bidon comme une dépendance pour toutes ces cibles spécifiques. Cela a un effet secondaire indésirable qui, lorsque la cible bidon réussit, ces cibles spécifiques sont reconstruites même lorsque leurs sources ne sont pas modifiées. En d'autres termes, comment spécifier une cible bidon pour NE PAS forcer la reconstruction de la cible dépendante si sa source est à jour.

$ make --version | grep Make 
GNU Make 3.82 

$ make -f try.mk clean setup 
rm -f try.out? 
touch try.C#Dummy create source 

$ make -f try.mk 
touch try.out1 #Dummy compile 
touch try.out2 #Dummy compile 
touch try.out3 #Dummy compile 

$ make -f try.mk 
touch try.out3 #Dummy compile 

try.out3 devrait PAS ont obtenu compilé ci-dessus/dernière marque.

$ cat try.mk 
#try.mk 
base=try 

all: $(base).out1 $(base).out2 $(base).out3 #... 

clean: 
    rm -f $(base).out? 

setup: 
    touch $(base).C#Dummy create source 

.PHONY: all clean platform_ok 

#------------------------------------------------------------ 
#Specific targets 
#------------------------------------------------------------ 

#Attempt 1: works, but platform check is a rule, and hence needs to be inserted wherever it is needed. 
$(base).out1: $(base.c) 
    @if [ $(shell uname -i) == x86_64 ]; then exit 0; else exit 1; fi 
    touch $(base).out1 #Dummy compile 

#Attempt 2: works, but platform check is global, which gets executed even when building Non-OS specific targets 
$(eval platform_check:=$(shell (if [ $(shell uname -i) == x86_64 ]; then echo 0; else echo 1; fi))) 
$(base).out2: $(base).c 
    @exit $(platform_check) 
    touch $(base).out2 #Dummy compile 

#Attempt 3: works partially when platform check is a phony target, but target gets rebuilt even if source is uptodate. 
$(base).out3: $(base).c platform_ok 
    touch $(base).out3 #Dummy compile 
platform_ok: 
    @if [ $(shell uname -i) == x86_64 ]; then exit 0; else exit 1; fi 

#------------------------------------------------------------ 
#Non-Specific targets 
#------------------------------------------------------------ 
#... 

Répondre

0

Je voudrais aller un peu différent à ce sujet:

base=try 
ARCH := $(shell test `uname -i` = "x86_64"; echo $$?) 

ifeq ($(ARCH),0) 
define PLATFORM_64 = 
out3 
endef 
endif 

define ALL = 
out1 
out2 
$(PLATFORM_64) 
endef 

all: $(addprefix $(base)., $(ALL)) 

et je perdrais tout à fait platform_ok:

$(base).out3: $(base).c 
    touch $(base).out3 #Dummy compile 
+0

Merci pour la solution de rechange, mais il ne ne répond pas à la 4ème exigence (la règle ne devrait même pas être exécutée pour des cibles non spécifiques). Dans votre réponse, ARCH est toujours calculé. Juste fyi, mon problème actuel a un contrôle plus compliqué, que je veux éviter d'être exécuté pour d'autres cibles (non spécifiques). –

2

suffit d'utiliser une cible en tant que condition sine qua non de faux ordre uniquement. Faire exécutera toujours cette règle si elle se trouve dans le graphe de dépendance, mais les cibles en fonction il ne sera exécuté que si leurs normales conditions sont plus récentes:

base=try 

all: $(base).out1 $(base).out2 $(base).out3 #... 

clean: 
    rm -f $(base).out? 

setup: 
    touch $(base).C#Dummy create source 

.PHONY: all clean platform_ok 

#------------------------------------------------------------ 
#Specific targets 
#------------------------------------------------------------ 

$(base).out1: $(base).c | platform_ok 
    touch $(base).out1 #Dummy compile 

$(base).out2: $(base).c | platform_ok 
    touch $(base).out2 #Dummy compile 

$(base).out3: $(base).c | platform_ok 
    touch $(base).out3 #Dummy compile 

platform_ok: 
    @if [ $(shell uname -i) == x86_64 ]; then exit 0; else exit 1; fi 
+0

Merci, man page pour make n'a pas ça. Ajout du lien pour les prérequis sur commande uniquement, pour donner des informations supplémentaires sur ce sujet, pour d'autres personnes qui pourraient avoir rencontré un problème similaire. https://www.gnu.org/software/make/manual/make.html#Prerequisite-Types –