Задержка или повторение обязательного условия в GNU make - PullRequest
2 голосов
/ 01 декабря 2008

Я пытаюсь встроить номер моей версии Subversion в проект C ++, и у меня возникают проблемы при настройке GNU make для этого. Мой make-файл сейчас выглядит примерно так:

check-svnversion:
  ../shared/update-svnversion-h.pl

../shared/svnversion.h: check-svnversion

shared/svnversion.o: ../shared/svnversion.h

.PHONY: check-svnversion

svnversion.o зависит от svnversion.cpp (через правило шаблона) и svnversion.h (указано явно, потому что проверка зависимостей по какой-то причине не подхватывает его). svnversion.h создается и поддерживается сценарием update-svnversion-h.pl (который в основном просто запускает svnversion и объединяет вывод в файл C ++).

В настоящее время мне нужно дважды запустить make, чтобы получить файл в актуальном состоянии. В первый раз make запускает update-svnversion-h.pl (поскольку он указан как предварительное условие), но впоследствии не проверяет отметку времени svnversion.h, чтобы увидеть, что она была изменена на update-svnversion-h.pl, поэтому она не преобразует svnversion.o. Во второй раз он проверяет отметку времени, все равно запускает update-svnversion-h.pl (который ничего не делает в этот раз, поскольку svnversion.h обновлен), затем перекомпилирует svnversion.cpp, чтобы сделать svnversion.o.

Есть ли способ заставить GNU make дважды оценить одно предварительное условие или отложить проверку временной метки на предварительном условии до тех пор, пока команды этого требования не будут завершены?

В качестве альтернативы, есть ли лучший способ вставить номер ревизии в мой исходный код? (Ради скорости я стараюсь избегать решений, которые потребовали бы перекомпиляции при каждой сборке.)

Ответы [ 4 ]

2 голосов
/ 28 сентября 2009

Вот цель, которую я поместил в мои файлы make. Он создает несколько функций, которые возвращают различные телеметрии сборки в виде строк. Приятно то, что телеметрия представляет собой последний раз связанный, а не когда объект построен.

##
## on every build, record the working copy revision string
##
svn_version.c: $(C_SRC:.c=.o) Makefile
    @echo -n 'const char* build_date(void);\n'  > $@
    @echo -n 'const char* build_date(void)\n{ static const char* build_date = __DATE__ ; '  >> $@
    @echo 'return build_date; }\n'                                                          >> $@
    @echo -n 'const char* build_time(void);\n'                                              >> $@
    @echo -n 'const char* build_time(void)\n{ static const char* build_time = __TIME__ ; '  >> $@
    @echo 'return build_time; }\n'                                                          >> $@
    @echo -n 'const char* svnid_build(void);\n'                                             >> $@
    @echo -n 'const char* svnid_build(void)\n{ static const char* SVN_Version = "\\n<SVN_PID>'    >> $@
    @svnversion -cn .                                                                       >> $@
    @echo '</svn_pid>\\n"; return SVN_Version; }\n'                                         >> $@
    @echo -n 'const char* svnid_build_str_only(void);\n'                                    >> $@
    @echo -n 'const char* svnid_build_str_only(void)\n{ static const char* SVN_Version = "' >> $@
    @svnversion -cn .                                                                       >> $@
    @echo '"; return SVN_Version; }\n'                                                      >> $@
    @$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $(@:.c=.o) $@

Обязательно замените зависимость от ваших объектных файлов в вашей конечной цели просто 'svn_version.c'. Ex.

final-target: svn_version.c
    $(CC) $(C_SRC:.c=.o) $(<:.c=.o) -o $@
2 голосов
/ 02 декабря 2008

Это похоже на то, что autotools делает для своего заголовка config.h.

Беглый взгляд на remake-hdr.am от automake показывает, как он работает:

%CONFIG_H%: %STAMP%
## Recover from removal of CONFIG_HEADER
    @if test ! -f $@; then \
      rm -f %STAMP%; \
      $(MAKE) $(AM_MAKEFLAGS) %STAMP%; \
    else :; fi


%STAMP%: %CONFIG_H_DEPS% $(top_builddir)/config.status
    @rm -f %STAMP%
    cd $(top_builddir) && $(SHELL) ./config.status %CONFIG_H_PATH%

И config.status создает файл штампа.

Основное различие между этим примером automake и вашим примером заключается в том, что automake касается файла штампа, в то время как в вашем примере это даже не настоящий файл.

1 голос
/ 02 декабря 2008

Я решил это, применив правило check-svnversion, удалив svnversion.o, чтобы принудительно перекомпилировать его при необходимости. Это не совсем элегантно, но работает; оно похоже на решение для автоинструментов, описанное в ответе CesarB .

../shared/svnversion.h: check-svnversion

check-svnversion:
    ../shared/update-svnversion-h.pl
    @#Force recreation of svnversion.o.  Otherwise, make won't notice that
    @#svnversion.h has changed until the next time it's invoked.
    @if [ ../shared/svnversion.h -nt shared/svnversion.o ] ; then rm shared/svnversion.o ; fi

shared/svnversion.o: ../shared/svnversion.h

.PHONY: check-svnversion
1 голос
/ 01 декабря 2008

Вы можете использовать подстановку ключевых слов Subversion, чтобы вставить номер версии в ваш код.

Это подробно [в книге], но вкратце вы должны будете установить свойство svn:keywords для файла, чтобы оно включало Rev, а затем поместить $Rev$ где-нибудь в вашем коде. SVN автоматически заменит это на $Rev: #$, где # - номер редакции. Вы должны проанализировать полученную строку, чтобы получить действительное число, но это должен быть простой анализ (просто отбросьте первые шесть символов и последний символ).

Обратите внимание, что это последняя измененная ревизия этого файла, а не последняя измененная ревизия репо. Это немного сложнее и подробно описано на странице книги.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...