Шаг перед сборкой в ​​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 работает так, как мне нужно.

Другие вопросы по тегам