Шаг перед сборкой в make-файле
Как я могу запустить скрипт, который должен выполняться перед всеми другими командами makefile? И будет приятно (но не обязательно), чтобы скрипт не выполнялся, если нечего строить.
Я искал SO и Google, но ничего не могу найти.
У меня есть этот обходной путь:
# myscript.bat output is empty
CHEAT_ARGUMENT = (shell myscript.bat)
CFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT)
AFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT)
Но это очень некрасиво. Есть ли другой способ запустить "pre-build step" в make-файле?
5 ответов
Я предлагаю два решения. Первое имитирует то, что генерирует среда IDE NetBeans:
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
Второй основан на том, что Eclipse IDE генерирует:
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
Обратите внимание, что в первом случае предварительные и последующие сборки всегда вызываются независимо от того, определена ли основная сборка как обновленная или нет.
Во втором шаг после пост-сборки не выполняется, если состояние основной сборки обновлено. Хотя этап предварительной сборки всегда выполняется в обоих случаях.
В зависимости от вашего make
версия, что-то вроде следующего должно по крайней мере избежать десятки раз, если CFLAGS и AFLAGS оцениваются десятки раз:
CHEAT_ARG := $(shell myscript)
Обратите внимание на двоеточие.
Это выполняется ровно один раз. Никогда не более одного раза, но также никогда не реже, чем один раз. Выберите свои собственные компромиссы.
Вы можете добавить специальную цель в ваш Makefile, и все ваши правила сборки зависят от этого:
run-script:
myscript
.o.c: run-script
$(CC) $(CFLAGS) -o $@ $<
.o.S: run-script
$(AS) $(AFLAGS) -o $@ $<
В зависимости от того, что в действительности делает ваш скрипт, запуск его один раз за этап перед Makefile (этап конфигурирования в терминах autoconf) может иметь еще больший смысл (и меньше работать).
То, что вы предлагаете, кажется немного "неприличным". Почему бы просто не запустить команду в какой-либо цели make-файла, в которой она должна быть раньше?
Пример, если вам нужно запустить его перед установкой ссылки foo
:
foo: ${OBJS}
my-command-goes-here
${CC} -o $@ ${OBJS} ${LIBS}
Спасибо за ответы. мне очень помог, асвейкау. Конечный файл - один исполняемый двоичный файл, так что теперь я могу использовать что-то вроде этого:
run-script:
myscript
$(AXF_FILE): run-script $(OBJ_DIRS) $(OBJ_FILES)
$(LINK) #......
Это будет запускать myscript один раз. Значение {AXF_FILE} зависит от myscript, и я должен запустить его раньше. И в этом случае myscript запускается всегда, а не только когда требуется перестроение. После того, как самый простой ответ пришел мне в голову:
all: run-script $(AXF_FILE)
Вот и все;) (Конечно, вместо "все" можно использовать любую цель)
Редактировать: этот метод выполняет скрипт после вычисления $(AXF_FILE). Таким образом, возможно получить неправильное значение AXF_FILE. Теперь только первый ответ от ndim работает так, как мне нужно.