Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > GNU toolchain > Установка зависимости одного файла от остальных


Автор: Gluttton 3.6.2012, 22:14
Доброго времени суток!

Стоит задача: автоматически включать в код информацию о времени его последней компиляции.
Как вариант решения видится следующее:
Цитата

tree
.
├── configure.ac
├── main.cpp
├── Makefile.am
├── sum.cpp
├── sum.h
└── version.h


Пусть сначала выводится информация о времени сборки, а затем (для примера), выводится сумма двух чисел переданных через командрую строку. При этом функция вычисления суммы реализована в отдельном файле.
Цитата

cat main.cpp

#include "sum.h"
#include "version.h"
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char * argv [])
{
    printf ("%s\n", get_build_date () );
    printf ("%s\n", get_build_time () );

    printf ("%i\n", Sum (atoi (argv [1]), atoi (argv [2]) ) );
}


Цитата

cat sum.cpp

#include "sum.h"

int Sum (int a, int b)
{
    return a + b;
}


Цитата

cat sum.h

int Sum (int a, int b);


Цитата

cat configure.ac

AC_INIT([main.cpp])
AM_INIT_AUTOMAKE([example], [0.1])
AC_PROG_CC
AC_PROG_CXX
AC_CONFIG_FILES([Makefile])
AC_OUTPUT


Цитата

cat Makefile.am

bin_PROGRAMS = example
example_SOURCES = main.cpp sum.cpp
AM_CPPFLAGS = -O2 -g3 -Wall
INCLUDES = -I$(top_srcdir)/include


Выполним сборку:
Цитата

aclocal
autoconf
automake --add-missing
./configure
make


Запустим приложение:
Цитата

./example 2 3
Jun  3 2012
22:07:44
5


Теперь если изменить файл main.cpp, то время последней компиляции обновиться (т.к. будет изменен файл main.o), а если мы внесем изменения в файл sum.cpp - то нет.
Вопрос, как достичь автоматического обновления информации о времени последней компиляции при изменении любого файла?

Автор: bsa 6.6.2012, 11:29
для этого нужно создать в makefile правило, выполняемое все время. В этом правиле нужно создавать хидер с текущим временем. Этот хидер, где-нибудь включать. При каждом вызове make будет пересоздаваться хидер, а все файлы, его включающие, будут пересобираться.

Автор: Gluttton 23.6.2012, 20:42
bsa, спасибо! Почти так и сделал.
Помимо описанной выше задачи, дополнительно проверяю ревизию в системе контроля версий - Mercurial:

Цитата

cat main.cpp

#include "sum.h"
#include "version.h"
#include <stdio.h>
#include <stdlib.h>


int main (int argc, char * argv [])
{
    printf ("Build date:     %s\n", get_build_date () );
    printf ("Build time:     %s\n", get_build_time () );
    printf ("Version number: %s\n", get_version    () );
    printf ("Version hash:   %s\n", get_hash       () );

    printf ("%i\n", Sum (atoi (argv [1]), atoi (argv [2]) ) );
}



Цитата

cat Makefile.am

bin_PROGRAMS = example


.PHONY: FORCE


example_SOURCES = \
        main.cpp \
        sum.cpp


AM_CPPFLAGS = \
        -O2 \
        -g3 \
        -Wall


INCLUDES = \
        -I$(top_srcdir)/include


BUILT_SOURCES = version.h


CLEANFILES    = \
        version.h \
        version.stamp


FORCE:


version.h: FORCE
        @\
        VERSION_FILE=$(builddir)/version.h; \
        IS_NEED_UPDATE=0; \
        \
        test -f version.stamp || stat -c %Y Makefile.am > version.stamp; \
        for i in `ls *.cpp`; do \
                if [[ `stat -c %Y $$i` -gt `cat version.stamp` ]]; then \
                        stat -c %Y $$i > version.stamp; \
                        IS_NEED_UPDATE=1; \
                        echo -e "Newest file has been detected: $$i.\n"; \
                fi; \
        done; \
        \
        HG_ACTUAL_REVISION="$(shell hg id -n)"; \
        if [ -e $$VERSION_FILE ]; then \
                HG_OLD_REVISION=`cat $$VERSION_FILE | grep get_version | cut -d '"' -f 2`; \
                if [ "$$HG_OLD_REVISION" != "$$HG_ACTUAL_REVISION" ]; then \
                        echo -e "Newest version has been detected: $$HG_ACTUAL_REVISION.\n"; \
                        IS_NEED_UPDATE=1; \
                fi; \
        else \
                IS_NEED_UPDATE=1; \
                echo -e "File $$VERSION_FILE is absent.\n"; \
        fi; \
        \
        if [[ $$IS_NEED_UPDATE -eq 1 ]]; then \
                printf "#ifndef VERSION_H\n#define VERSION_H\n\n"                                         >  $$VERSION_FILE; \
                printf "static const char * get_version    () {return \"%s\";};\n" "$$HG_ACTUAL_REVISION" >> $$VERSION_FILE; \
                printf "static const char * get_hash       () {return \"%s\";};\n" "$(shell hg id -i)"    >> $$VERSION_FILE; \
                printf "static const char * get_build_date () {return __DATE__;};\n"                      >> $$VERSION_FILE; \
                printf "static const char * get_build_time () {return __TIME__;};\n"                      >> $$VERSION_FILE; \
                printf "#endif//VERSION_H"                                                                >> $$VERSION_FILE; \
        fi


И теперь даже если я изменю только файл sum.cpp, то это повлечет за собой перекомпиляцию main.o и время компиляции отобразиться корректно.
А если ничего менять не буду, то при повторном выполнении команды make компиляция вызываться не будет.

P.S. В данном примере меня устраивает анализ файлов по ls *.cpp, но на реальном проекте нужно использовать find.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)