2011-11-15 3 views
2

Je le makefile suivant:l'aide cible spécifique variable makefile

OUTPUTDIR = build 

all: v12target v13target 
v12target: INTDIR = v12 
v12target: DoV12.avrcommontargets 
v13target: INTDIR = v13 
v13target: DoV13.avrcommontargets 

%.avrcommontargets: $(OUTPUTDIR)/%.elf 
    @true 

$(OUTPUTDIR)/%.elf: $(OUTPUTDIR)/$(INTDIR)/main.o 
    @echo TODO build ELF file from object file: destination [email protected], source $^ 
    @echo Compiled elf file for $(INTDIR) > [email protected] 

$(OUTPUTDIR)/$(INTDIR)/%.o: %.c 
    @echo TODO call GCC to compile C file: destination [email protected], source $< 
    @echo Compiled object file for $<, revision $(INTDIR) > [email protected] 

$(shell rm -rf $(OUTPUTDIR)) 
$(shell mkdir -p $(OUTPUTDIR)/v12 2> /dev/null) $(shell mkdir -p $(OUTPUTDIR)/v13 2> /dev/null) 

.SECONDARY: 

L'idée est qu'il existe plusieurs configurations de code différentes qui doivent être compilées à partir du même code source. La cible "all" dépend de v12target et v13 target, qui définissent un certain nombre de variables pour cette construction particulière. Cela dépend aussi d'un modèle "avrcommontargets", qui définit comment faire la compilation. avrcommontargets dépend alors du fichier ELF, qui à son tour dépend des fichiers objets, qui sont construits à partir du code source C.

Chaque fichier C compilé résulte en un fichier objet (* .o). Comme chaque configuration (v12, v13, etc.) aboutit à une sortie différente, le fichier C doit être construit plusieurs fois avec la sortie placée dans des sous-répertoires différents. Par exemple, "build/v12/main.o", "build/v13/main.o", etc.

Exemple de sortie:

TODO call GCC to compile C file: destination build//main.o, source main.c 
TODO build ELF file from object file: destination build/DoV12.elf, source build//main.o 
TODO build ELF file from object file: destination build/DoV13.elf, source build//main.o 

Le problème est que le fichier objet ne va pas dans le sous-répertoire correct. Par exemple, "build // main.o" au lieu de "build/v12/main.o". Cela empêche alors le main.o d'être correctement reconstruit pour générer la version v13 de main.o.

Je suppose que le problème est que $ (INTDIR) est une variable spécifique à la cible, et peut-être cela ne peut pas être utilisé dans les cibles de modèle que j'ai définies pour% .elf et% .o.

La sortie correcte serait:

TODO call GCC to compile C file: destination build/v12/main.o, source main.c 
TODO build ELF file from object file: destination build/DoV12.elf, source build/v12/main.o 
TODO call GCC to compile C file: destination build/v13/main.o, source main.c 
TODO build ELF file from object file: destination build/DoV13.elf, source build/v13/main.o 

Que dois-je faire pour régler ce makefile pour qu'il génère la sortie correcte?

Répondre

1

Vous redirigée les lignes « fichier Elf Compilé » de votre sortie, qui ressemblent à:

Compiled elf file for v13 

Alors que la substitution de variable spécifique à la cible fonctionne en général, il semble qu'il se fait après la sélection des cibles - ce qui est assez juste, car faire autrement serait assez difficile à mettre en œuvre. Vous pouvez utiliser $(foreach) et $(eval) pour produire une règle par cible. Cependant, je tiens à souligner à nouveau que vous êtes en train de réorganiser des constructions arborescentes ici. La meilleure alternative est de continuer avec les autotools. Le deuxième meilleur est de compléter votre logique de construction hors-arbre et d'utiliser une arborescence de construction par cible, avec un petit script configure sh insérant les drapeaux de compilation dans un Makefile.

Élaborant sur la deuxième solution:

Laisser tourner régulièrement de faire des sous-répertoires, un par cible. Avoir un commutateur dans votre makefile principal qui contrôle l'exécution des sous-marques. Votre Makefile principal ressemble à:

TARGETS = v12 v13 

CFLAGS_v12 = -foo 
CFLAGS_v13 = -bar 

ifeq ($(TARGET),) 
all : 
    mkdir --parents $(TARGETS) 
    $(foreach t,$(TARGETS),SRCDIR=.. CFLAGS="$(CFLAGS_$t)" TARGET=$t $(MAKE) -C $t -f ../Makefile &&) true 
clean : 
    rm -rf $(TARGETS) 
else 
all : main.elf 
endif 

%.elf : %.o 
    echo "Linking [email protected] from $< with $(CFLAGS)" 

%.o : $(SRCDIR)/%.c 
    echo "Compiling [email protected] from $< with $(CFLAGS)" 

.PHONY : all 
+0

Merci pour la réponse ... Pour être précis, j'ai ce makefile appelé avec AVR Studio 5 et aussi Visual C++ (type de projet makefile). AVR Studio 5 vous oblige à taper le chemin d'accès à un fichier makefile externe. VC++ me demande de taper des commandes comme "make all", "make clean", etc. pour les différents types de construction. Mon point est que j'ai besoin que tout soit lancé à partir d'un makefile de quelque sorte où "make all" construira chaque configuration. Je ne sais pas comment je pourrais le faire avec autotools ... - c'est peut-être parce que je ne le connais pas bien. –

+0

Une autre considération est que j'essaie de me limiter aux utilitaires inclus avec WinAVR (http://winavr.sourceforge.net/), que je ne pense pas comprend autotools. Je ne suis pas sûr si essayer d'obtenir un autotools compatible construit pour ce petit projet vaudra la peine pour chaque développeur qui veut le construire - nous n'utilisons pas autotools ou GNU faire ailleurs dans notre produit. –

+0

@JamesJohnston: Assez juste, le temps pour le temps de ré-invention de la roue :-). – thiton

Questions connexes