Иногда необходимо, чтобы некоторые команды выполнялись всегда, при любом запуске make, в самом начале или в самом конце работы.

Чтобы наша цель выполнялась в нужное время, нужно как-то привязаться с к цели, которая первой выполняется при запуске make. Это обеспечит то, что наша команда выполнится. Далее, нужно привязяться таким образом, чтобы наша цель выполнялась до (или после) всех целей, от которых зависит первая цель.

Выполнение Makefile по умолчанию начинается с первой цели по порядку. qmake первыми целями генерирует следующее:

Первые цели

first: all all: Makefile $(DESTDIR_TARGET)


1

2

3

4

 

first: all

all: Makefile  $(DESTDIR_TARGET)

 

Глядя на эти правила, придумать цель, которая всегда будет выполняться, и будет выполняться в самом конце, несложно. Эту цель можно сделать зависимой от all (значит, она выполнится после all), и сделать first зависимой от нее (а значит, она выполнится).

Правило для команды, всегда выполняемой в самом конце - qmake

QMAKE_EXTRA_TARGETS += after_build firsthook firsthook.target = first firsthook.depends = after_build after_build.depends = all after_build.CONFIG = phony after_build.commands = @echo after_build && @echo ============


1

2

3

4

5

6

7

8

9

10

 

QMAKE_EXTRA_TARGETS += after_build firsthook

 

firsthook.target = first

firsthook.depends = after_build

 

after_build.depends = all

after_build.CONFIG = phony

after_build.commands = @echo after_build && @echo ============

 

Результирующий Makefile:

Правило для команды, всегда выполняемой в самом конце - Makefile

first: all all: Makefile $(DESTDIR_TARGET) after_build: all FORCE @echo after_build && @echo ============ first: after_build


1

2

3

4

5

6

7

8

9

 

first: all

all: Makefile  $(DESTDIR_TARGET)

 

after_build: all FORCE

    @echo after_build && @echo ============

 

first: after_build

 

Конечно, все поломается, если make будет вызван как make all, но Qt Creator по умолчанию запускает make без параметров. Так что меня такой способ устраивает.

Да, еще – до последних команд дело не дойдет, если make завершится с ошибкой в каком-либо правиле посередине. Нюанс, с которым ничего поделать нельзя.

Если с командой, выполняемой в конце, все достаточно просто, то с командой, выполняемой в начале выполнения make, дела обстоят сложнее. Во-первых, для того, чтобы такая цель гарантированно выполнилась до выполнения всего остального, Makefile и $(DESTDIR_TARGET) должны от нее зависеть. Далее, эта цель не может быть phony, потому как в противном случае у Makefile и $(DESTDIR_TARGET) будет необновленная зависимость, что приведет к запуску команд одного из этих правил (скорее всего, Makefile, и значит, произойдет вызов qmake). Раз цель не может быть phony, то должен существовать одноименный файл. И этот файл должен быть старым, иначе qmake запустится. И, наконец, чтобы команды выполнялись всегда, цель должна быть зависимой от FORCE.

Правило для команды, всегда выполняемой в самом начале - qmake

# создаем файл-заглушку !exists($$OUT_PWD/.beforebuild) { system(@echo aaa > $$system_path($${OUT_PWD}/.beforebuild)) } QMAKE_EXTRA_TARGETS += before_build makefilehook makefilehook.target = $(MAKEFILE) makefilehook.depends = .beforebuild POST_TARGETDEPS += .beforebuild before_build.target = .beforebuild before_build.depends = FORCE before_build.commands = @echo our command


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

 

# создаем файл-заглушку

!exists($$OUT_PWD/.beforebuild) {

  system(@echo aaa > $$system_path($${OUT_PWD}/.beforebuild))

}

 

QMAKE_EXTRA_TARGETS += before_build makefilehook

 

makefilehook.target = $(MAKEFILE)

makefilehook.depends = .beforebuild

 

POST_TARGETDEPS += .beforebuild

 

before_build.target = .beforebuild

before_build.depends = FORCE

before_build.commands = @echo our command

 

В Makefile получается следующее:

Правило для команды, всегда выполняемой в самом начале - Makefile

$(DESTDIR_TARGET): $(OBJECTS) .beforebuild $(LINKER) $(LFLAGS) -o $(DESTDIR_TARGET) $(OBJECTS) $(LIBS) .beforebuild: FORCE @echo our command $(MAKEFILE): .beforebuild


1

2

3

4

5

6

7

8

9

 

$(DESTDIR_TARGET):  $(OBJECTS) .beforebuild

    $(LINKER) $(LFLAGS) -o $(DESTDIR_TARGET) $(OBJECTS)  $(LIBS)

 

.beforebuild: FORCE

    @echo our command

 

$(MAKEFILE): .beforebuild

 

И не забывайте – файл .beforebuild существует, и он всегда старше Makefile!