web-dev-qa-db-fra.com

Étape de pré-construction dans Makefile

Comment puis-je exécuter un script, qui doit exécuter avant toutes les autres commandes de Makefile? Et ce sera bien (mais pas obligatoire) au script n'est pas exécuté s'il n'y a rien à construire.

J'ai cherché SO et Google, mais je ne trouve rien.

J'ai cette solution de contournement:

# myscript.bat output is empty
CHEAT_ARGUMENT = (Shell myscript.bat)
CFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT)
AFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT)

Mais c'est très moche. Y a-t-il une autre façon d'exécuter "étape de pré-construction" In Makefile?

28
zxcat

Je propose deux solutions. Les premiers imitateurs que NetBeans IDE génère:

CC=gcc

.PHONY: all clean

all: post-build

pre-build:
    @echo PRE

post-build: main-build
    @echo POST

main-build: pre-build
    @$(MAKE) --no-print-directory target

target: $(OBJS)
    $(CC) -o $@ $(OBJS)

clean:
    rm -f $(OBJS) target

La seconde est inpire de ce que Eclipse IDE génère:

CC=gcc

.PHONY: all clean
.SECONDARY: main-build

all: pre-build main-build

pre-build:
    @echo PRE

post-build:
    @echo POST

main-build: target

target: $(OBJS)
    $(CC) -o $@ $(OBJS)
    @$(MAKE) --no-print-directory post-build

clean:
    rm -f $(OBJS) target

Notez que, dans la première, les bandes de pré et post sont toujours appelées, que la construction principale soit déterminée à être à jour ou non.

Dans le second cas, l'étape post-construction n'est pas exécutée si l'état de la construction principale est à jour. Bien que l'étape de pré-construction soit toujours exécutée dans les deux.

27
Amro

Selon votre version make, quelque chose comme ce qui suit devrait au moins éviter de courir des dizaines de fois si CFLAGS et Aflags sont évalués des dizaines de fois:

CHEAT_ARG := $(Shell myscript)

Notez le côlon.

Cela fonctionne exactement une fois. Jamais plus d'une fois, mais aussi jamais moins d'une fois. Choisissez vos propres compromis.

11
ndim

Ce que vous proposez semble un peu "un-faux-faux". Pourquoi ne pas simplement exécuter la commande dans la cible de maquillage dont vous avez besoin pour aller avant?

Exemple, si vous en avez besoin pour exécuter avant de relier foo:

foo: ${OBJS}
    my-command-goes-here
    ${CC} -o $@ ${OBJS} ${LIBS}
3
asveikau

Merci pour des réponses. NDIM m'a beaucoup aidé, Asveika. Le fichier final est un exécutable binaire, je peux donc utiliser maintenant quelque chose comme ceci:

run-script:
    myscript
$(AXF_FILE): run-script $(OBJ_DIRS) $(OBJ_FILES)
    $(LINK) #......

Il va courir myscultin une fois. {AXF_FILE} La valeur dépend de MyScript et je dois l'exécuter avant. Et dans ce cas, MyScript court toujours, non seulement lorsque la reconstruction est nécessaire. Après, la réponse la plus simple est venu à mon esprit:

all: run-script $(AXF_FILE)

C'est tout;) (bien sûr, toute cible peut être utilisée à la place de "tout")


Edit : Cette méthode exécute script après -$ (AXF_FILE) est aussi calculé. Il est donc possible d'obtenir une mauvaise valeur de AXF_FILE. Maintenant, seule la première réponse par NDIM fonctionne comme dont j'ai besoin.

1
zxcat