web-dev-qa-db-fra.com

Comment utiliser une liste de variables comme cible dans un Makefile?

Supposons que je travaille sur un makefile et que j'ai la déclaration de variable suivante en haut:

FILES = file1.cpp file2.cpp file3.cpp

Supposons maintenant que je veuille compiler chacun de ceux avec une commande spéciale sans spécifier chaque cible comme ceci:

file1.o : file1.cpp
    custom_command file1.cpp
file2.o : file2.cpp
    custom_command file2.cpp
file3.o : file3.cpp
    custom_command file3.cpp

Existe-t-il une meilleure façon de le faire en utilisant la variable $(FILES) que j'ai déclarée ci-dessus?

Quelque chose comme:

$(FILES:.cpp=.o) : $(FILES)
    custom_command $(FILES)

... seulement il doit le faire pour chaque fichier de la variable $(FILES).

25
Nathan Osman

Oui. Il existe ce qu'on appelle des règles de modèle . Un exemple est le plus facile à comprendre:

%.o: %.cpp
       $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

(rappelez-vous que les Makefiles nécessitent des onglets ). Cette règle décrit comment créer un fichier objet à partir d'un fichier cpp.

Si vous ne voulez pas d'une règle aussi large, vous pouvez utiliser ce que l'on appelle des modèles statiques:

objects = file1.o file2.o file3.o

all: $(objects)

$(objects): %.o: %.cpp
        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

Voici la section sur règles de modèle statiques et règles de modèle dans le manuel GNU Make).

44
Chris

Vous pouvez faire cela, comme suit:

SRCS=a.c b.c
OBJS=$(SRCS:.c=.o)

$(OBJS): $(SRCS)
        cc -c -o a.o a.c
        cc -c -o b.o b.c

mais vous devez vous rappeler que les dépendances sont complètes - cela suppose que a.o dépend de b.c ce qui n'est probablement pas le cas.

Ce que vous recherchez probablement, c'est une règle unique sur la façon de transformer un type de fichier en un autre:

SRCS=a.c b.c
OBJS=$(SRCS:.c=.o)

all: $(OBJS)

.c.o:
        gcc -c -o $@ $<

.c.o est une telle règle qui indique quelles commandes exécuter pour transformer un .c fichier dans un .o fichier. Dans la commande réelle, $@ est remplacé par la cible spécifique et $< est remplacé par le nom du premier prérequis.

Il existe de nombreuses autres variables automatiques que vous pouvez utiliser, recherchez-les avec info make ou cherchez un bon livre sur make si vous n'avez pas les choses info disponibles.

8
paxdiablo
SRCS = a.c b.c
OBJS = $(SRCS:.c=.o)

.c.o:
        ${CC} ${CFLAGS} -c -o $@ $<

Bien que $< n'est pas tout à fait portable (IIRC, bsdmake a le sens de $^ et $< exactement remplacé par ce que gmake utilise), c'est la recette par défaut pour .c.o qui serait en vigueur dans l'une ou l'autre implémentation.

1
user502515