D'accord, je suis coincé là-dessus et je n'ai aucune idée de ce que je fais mal. Tout se passait bien en travaillant sur un makefile plus compliqué, mais tout à coup, j'ai eu l'erreur "Missing separator". J'ai pu l'isoler dans un scénario très simple:
define Push_dir
$(info ${1})
endef
define pop_dir
$(info ${1})
endef
define include_submake
$(call Push_dir,${1})
$(call pop_dir,${1})
endef
include test.mk
INITIAL_SUBMAKE:= includeme.mk
$(call include_submake,${INITIAL_SUBMAKE})
process:
@echo Processed...
Et la sortie:
C:\project>make -f Simple process
includeme.mk
includeme.mk
Simple:4: *** missing separator. Stop.
includeme.mk
n'existe pas réellement. Je n'ai aucune idée de ce qui ne va pas ici, j'ai essayé une multitude de choses. Si j'entoure l'appel à include_submake dans info comme suit:
$(info $(call include_submake,${INITIAL_SUBMAKE}))
L'erreur de séparateur manquante disparaît. De plus, si dans le include_submake
définir, je n’appelle que l’une des fonctions, cela fonctionne bien. De plus, si j'appelle directement les fonctions au lieu de les appeler include_submake
, cela fonctionne également:
include test.mk
INITIAL_SUBMAKE:= includeme.mk
$(call Push_dir,${INITIAL_SUBMAKE})
$(call pop_dir,${INITIAL_SUBMAKE})
process:
@echo Processed...
C:\project>make -f Simple process
includeme.mk
includeme.mk
Processed...
Je sens que je néglige quelque chose de fondamental ici. Merci de votre aide.
L'erreur missing separator
est due à une valeur de retour non vide de include_submake
, qui correspond à un caractère de saut de ligne dans votre cas. Make autorise uniquement les caractères d'espacement (c'est-à-dire un espace ou une tabulation) dans une expression qui n'est pas supposée faire partie d'une règle ou d'une autre directive.
Réécrivez vos fonctions en utilisant plain-old Effectuez une affectation de variable et l'erreur devrait disparaître:
Push_dir = \
$(info $1)
pop_dir = \
$(info $1)
include_submake = \
$(call Push_dir,$1) \
$(call pop_dir,$1)
define
vs assignation de variable simpleRépondre à une question du premier commentaire. Personnellement, je préférerais utiliser la directive define
dans plusieurs cas.
eval
Comme le suggère le GNU Make manual, la directive define
est très utile en conjonction avec la fonction eval
. Exemple tiré du manuel (c'est moi qui souligne):
PROGRAMS = serveur client Server_OBJS = server.o serveur_priv.o server_access.o Server_LIBS = protocole privé Client_OBJS = client.o client_api.o client_mem.o client_LIBS = protocole # Tout ce qui suit est générique . PHONY: tous Tous: $ (PROGRAMMES) définir PROGRAM_template $ (1): $$ ($ (1) _OBJS) $$ ($ (1) _LIBS:% = - l%) ALL_OBJS + = $$ ($ (1) _OBJS ) endef $ (pour chaque programme, $ (PROGRAMMES), $ (eval $ (appelez PROGRAM_template, $ (prog)))) $ (PROGRAMMES): $ (LINK.o) $ ^ $ (LDLIBS) -o $ @ Clean: Rm -f $ (ALL_OBJS) $ (PROGRAMMES)
Les variables verbatim conviennent parfaitement aux cas où vous souhaitez générer un fichier à partir de GNU Make. Par exemple, envisagez de générer un fichier d’en-tête basé sur certaines informations de Makefile.
# Args: # 1. Identifiant d'en-tête.définir header_template /* Ce fichier est généré par GNU Make $ (MAKE_VERSION). */ # ifndef $ (inclusion_guard) # définir $ (inclusion_guard) $ (foreach inc, $ ($ 1.includes) , # include <$ (inc) .h>) /* Autre chose ... */ # endif/* $ (inclusion_guard) */ endef# 1. Identifiant unique d'en-tête. inclusion_guard =\ __GEN_ $ 1_H # Échappement Shell. sh_quote =\ '$ (subst', '""', $ 1) ' foo.includes: = bar baz HEADERS: = foo.h $ (HEADERS):% .h: @Printf "% s" $ (appel sh_quote, $ (appel header_template , $ (* F))) & gt $ @
Dans notre projet, nous utilisons notre propre système de construction appelé Mybuild , et il est entièrement implémenté au dessus de GNU Make. En tant que hacks de bas niveau que nous avons utilisés pour améliorer la syntaxe médiocre du langage intégré de Make, nous avons développé un script spécial qui permet d’utiliser une syntaxe étendue pour les définitions de fonctions. Le script lui-même est écrit dans Make aussi, il s’agit donc d’une sorte de méta-programmation dans Make.
En particulier, on peut utiliser des fonctionnalités telles que:
$(assert ...)
ou $(lambda ...)
$(eq s1,s2)
(vérification d'égalité de chaîne)Ceci est un exemple de la façon dont une fonction peut être écrite en utilisant la syntaxe étendue. Notez que cela devient une fonction Make valide et peut être appelé comme d'habitude après un appel à $(def_all)
.
# Inverse la liste spécifiée. # 1. La liste # Retour: # La liste avec ses éléments dans l’ordre inverse.définir l'inverse# Commencez par la liste vide. $ (pli, 1 $, # Ajoute chaque nouvel élément (2 $) à # Le résultat des calculs précédents.$ (lambda 2 $ 1 $)) endef $ (def_all)
En utilisant ces nouvelles fonctionnalités, nous avons pu implémenter des choses vraiment cool (enfin, au moins pour Make :-)), notamment:
N'hésitez pas à utiliser n'importe quelle partie de le code dans vos propres projets!
J'ai rencontré le même problème. J'ai inséré 'tab', supprimé 'tab', réinséré pour en être sûr. Même message d'erreur.
Mais, j'ai fait tout cela à l'intérieur de XCodem qui, à ma grande surprise, a inséré des espaces blancs, pas "\ t". Une fois que j'ai utilisé un éditeur différent, ces erreurs «fantômes» ont disparu.
HTH ...