Règles d’inférence
Les règles d’inférence dans les commandes d’approvisionnement NMAKE pour mettre à jour les cibles et déduire des dépendances pour les cibles. Les extensions d’une règle d’inférence correspondent à une cible unique et dépendante qui ont le même nom de base. Les règles d’inférence sont définies par l’utilisateur ou prédéfinies ; Les règles prédéfinies peuvent être redéfinies.
Si une dépendance obsolète n’a pas de commandes et si .SUFFIXES
elle contient l’extension du dépendant, NMAKE utilise une règle dont les extensions correspondent à la cible et à un fichier existant dans le répertoire actif ou spécifié. Si plusieurs règles correspondent à des fichiers existants, la .SUFFIXES
liste détermine laquelle utiliser ; la priorité de liste descend de gauche à droite. Si un fichier dépendant n’existe pas et n’est pas répertorié comme cible dans un autre bloc de description, une règle d’inférence peut créer la dépendance manquante d’un autre fichier portant le même nom de base. Si la cible d’un bloc de description n’a pas de dépendances ou de commandes, une règle d’inférence peut mettre à jour la cible. Les règles d’inférence peuvent générer une cible de ligne de commande même si aucun bloc de description n’existe. NMAKE peut appeler une règle pour une dépendance déduite même si une dépendance explicite est spécifiée.
Définition d’une règle
L’from_ext représente l’extension d’un fichier dépendant et to_ext représente l’extension d’un fichier cible.
.from_ext.to_ext:
commands
Les extensions ne respectent pas la casse. Les macros peuvent être appelées pour représenter from_ext et to_ext ; les macros sont développées pendant le prétraitement. La période (.
) qui précède from_ext doit apparaître au début de la ligne. Le signe deux-points (:
) est précédé de zéro ou plusieurs espaces ou onglets. Il peut être suivi uniquement par des espaces ou des onglets, un point-virgule (;
) pour spécifier une commande, un signe numérique (#
) pour spécifier un commentaire ou un caractère de ligne. Aucun autre espace n’est autorisé. Les commandes sont spécifiées comme dans les blocs de description.
Chemins de recherche dans les règles
{from_path}.from_ext{to_path}.to_ext:
commands
Une règle d’inférence s’applique à une dépendance uniquement si les chemins spécifiés dans la dépendance correspondent exactement aux chemins d’accès de règle d’inférence. Spécifiez le répertoire du dépendant dans from_path et le répertoire de la cible dans to_path ; aucun espace n’est autorisé. Spécifiez un seul chemin pour chaque extension. Un chemin d’accès sur une extension nécessite un chemin d’accès sur l’autre. Pour spécifier le répertoire actif, utilisez un point (.
) ou des accolades vides ({ }
). Les macros peuvent représenter from_path et to_path ; elles sont appelées pendant le prétraitement.
Exemple de chemins de recherche
{dbi\}.cpp{$(ODIR)}.obj::
$(CC) $(CFLAGS) $(YUDBI) $<
{ilstore\}.cpp{$(ODIR)}.obj::
$(CC) $(CFLAGS) $<
{misc\}.cpp{$(ODIR)}.obj::
$(CC) $(CFLAGS) $(YUPDB) $<
{misc\}.c{$(ODIR)}.obj::
$(CC) $(CFLAGS) $<
{msf\}.cpp{$(ODIR)}.obj::
$(CC) $(CFLAGS) $<
{bsc\}.cpp{$(ODIR)}.obj::
$(CC) $(CFLAGS) $(YUPDB) $<
{mre\}.cpp{$(ODIR)}.obj::
$(CC) $(CFLAGS) $(YUPDB) $<
{namesrvr\}.cpp{$(ODIR)}.obj::
$(CC) $(CFLAGS) $(YUPDB) $<
{src\cvr\}.cpp{$(ODIR)}.obj::
$(CC) $(CFLAGS) $<
Règles en mode batch
{from_path}.from_ext{to_path}.to_ext::
commands
Les règles d’inférence en mode Batch fournissent un seul appel de la règle d’inférence lorsque les commandes N passent par cette règle d’inférence. Sans règles d’inférence en mode batch, les commandes N doivent être appelées. N est le nombre de dépendants qui déclenchent la règle d’inférence.
La seule différence syntactique de la règle d’inférence standard est qu’une règle d’inférence en mode batch se termine par un double-deux-points (::
).
Remarque
L’outil appelé doit être en mesure de gérer plusieurs fichiers. La règle d’inférence en mode batch doit être utilisée $<
comme macro pour accéder aux fichiers dépendants.
Les règles d’inférence en mode batch peuvent accélérer le processus de génération. Il est plus rapide de fournir des fichiers au compilateur en mode batch, car le pilote du compilateur n’est appelé qu’une seule fois. Par exemple, le compilateur C et C++ s’exécute plus rapidement lors de la gestion d’un ensemble de fichiers, car il peut rester résident en mémoire pendant l’ensemble du processus.
L’exemple suivant montre comment utiliser des règles d’inférence en mode batch :
#
# sample makefile to illustrate batch-mode inference rules
#
O = .
S = .
Objs = $O/foo1.obj $O/foo2.obj $O/foo2.obj $O/foo3.obj $O/foo4.obj
CFLAGS = -nologo
all : $(Objs)
!ifdef NOBatch
{$S}.cpp{$O}.obj:
!else
{$S}.cpp{$O}.obj::
!endif
$(CC) $(CFLAGS) -Fd$O\ -c $<
$(Objs) :
#end of makefile
NMAKE produit la sortie suivante sans règles d’inférence en mode batch :
E:\tmp> nmake -f test.mak -a NOBatch=1
Microsoft (R) Program Maintenance Utility Version 7.00.0000
Copyright (C) Microsoft Corp 1988-2001. All rights reserved.
cl -nologo -Fd.\ -c .\foo1.cpp
foo1.cpp
cl -nologo -Fd.\ -c .\foo2.cpp
foo2.cpp
cl -nologo -Fd.\ -c .\foo3.cpp
foo3.cpp
cl -nologo -Fd.\ -c .\foo4.cpp
foo4.cpp
NMAKE produit le résultat suivant avec les règles d’inférence en mode batch :
E:\tmp> nmake -f test.mak -a
Microsoft (R) Program Maintenance Utility Version 7.00.0000
Copyright (C) Microsoft Corp 1988-2001. All rights reserved.
cl -nologo -Fd.\ -c .\foo1.cpp .\foo2.cpp .\foo3.cpp .\foo4.cpp
foo1.cpp
foo2.cpp
foo3.cpp
foo4.cpp
Generating Code...
Règles prédéfinies
Les règles d’inférence prédéfinies utilisent des macros de commande et d’options fournies par NMAKE.
Règle | Commande | Action par défaut | Règle batch | Plateforme |
---|---|---|---|---|
.asm.exe |
$(AS) $(AFLAGS) $< |
ml $< |
non | x86 |
.asm.obj |
$(AS) $(AFLAGS) /c $< |
ml /c $< |
Oui | x86 |
.asm.exe |
$(AS) $(AFLAGS) $< |
ml64 $< |
non | x64 |
.asm.obj |
$(AS) $(AFLAGS) /c $< |
ml64 /c $< |
Oui | x64 |
.c.exe |
$(CC) $(CFLAGS) $< |
cl $< |
non | all |
.c.obj |
$(CC) $(CFLAGS) /c $< |
cl /c $< |
Oui | all |
.cc.exe |
$(CC) $(CFLAGS) $< |
cl $< |
non | all |
.cc.obj |
$(CC) $(CFLAGS) /c $< |
cl /c $< |
Oui | all |
.cpp.exe |
$(CPP) $(CPPFLAGS) $< |
cl $< |
non | all |
.cpp.obj |
$(CPP) $(CPPFLAGS) /c $< |
cl /c $< |
Oui | all |
.cxx.exe |
$(CXX) $(CXXFLAGS) $< |
cl $< |
non | all |
.cxx.obj |
$(CXX) $(CXXFLAGS) /c $< |
cl /c $< |
Oui | all |
.rc.res |
$(RC) $(RFLAGS) /r $< |
rc /r $< |
non | all |
Règles et dépendants inférés
NMAKE suppose une dépendance déduite pour une cible si une règle d’inférence applicable existe. Une règle s’applique si :
to_ext correspond à l’extension de la cible.
from_ext correspond à l’extension d’un fichier qui a le nom de base de la cible et qui existe dans le répertoire actif ou spécifié.
from_ext est en
.SUFFIXES
; aucune autre from_ext dans une règle de correspondance n’a une priorité plus élevée.SUFFIXES
.Aucune dépendance explicite n’a une priorité plus élevée
.SUFFIXES
.
Les dépendants déduits peuvent provoquer des effets secondaires inattendus. Si le bloc de description de la cible contient des commandes, NMAKE exécute ces commandes au lieu des commandes de la règle.
Priorité dans les règles d’inférence
Si une règle d’inférence est définie plusieurs fois, NMAKE utilise la définition de priorité la plus élevée. La liste suivante montre l’ordre de priorité le plus élevé au plus bas :
Règle d’inférence définie dans un makefile ; les définitions ultérieures ont la priorité.
Une règle d’inférence définie dans
Tools.ini
; les définitions ultérieures ont la priorité.Règle d’inférence prédéfinie.