Эффективное использование GNU Make

       

"Разнесение" разных версий программы по отдельным директориям


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

Для решения этой проблемы я помещаю результаты компиляции каждой версии программы в свой отдельный каталог. Так, например, отладочная версия программы (включая все объектные файлы) помещается в каталог debug, а рабочая версия программы - в каталог release:

  • example_6-multiconfig-multidir /
  • debug /
  • release /
  • main.cpp
  • main.h
  • Editor /
  • Editor.cpp
  • Editor.h
  • TextLine /
    • TextLine.cpp
    • TextLine.h
    • Makefile
    • make_debug
    • make_release

    • Главная сложность заключалась в том, чтобы заставить программу make помещать результаты работы в разные директории. Попробовав разные варианты, я пришел к выводу, что самый легкий путь - использование флажка --directory при вызове make. Этот флажок заставляет утилиту перед началом обработки make-файла, сделать каталог, указанный в командной строке, "текущим".

      Вот, например, как выглядит командный файл make_release, собирающий рабочую версию программы (результаты компиляции помещается в каталог release):

      mkdir release make compile_flags="-O3 -funroll-loops -fomit-frame-pointer" \ --directory=release \ --makefile=../Makefile

      Команда mkdir введена для удобства - если удалить каталог release, то при следующей сборке он будет создан заново. В случае "составного" имени каталога (например, bin/release) можно дополнительно использовать флажок -p. Флажок --directory заставляет make перед началом работы сделать указанную директорию release текущей. Флажок --makefile укажет программе make, где находится make-файл проекта. По отношению к "текущей" директории release, он будет располагаться в "родительском" каталоге.

      Командный файл для сборки отладочного варианта программы (make_debug) выглядит аналогично. Различие только в имени директории, куда помещаются результаты компиляции (debug) и другом наборе флагов компиляции:

      mkdir debug make compile_flags="-O0 -g" \ --directory=debug \ --makefile=../Makefile Вот окончательная версия make-файла для сборки "гипотического" проекта текстового редактора:

      # # example_6-multiconfig-multidir/Makefile # # Пример "разнесения" разных версий программы по отдельным директориям # program_name := iEdit source_dirs := . Editor TextLine source_dirs := $(addprefix ../,$(source_dirs)) search_wildcards := $(addsuffix /*.cpp,$(source_dirs)) $(program_name): $(notdir $(patsubst %.cpp,%.o, $(wildcard $(search_wildcards) ) ) ) gcc $^ -o $@ VPATH := $(source_dirs) %.o: %.cpp gcc -c -MD $(compile_flags) $(addprefix -I,$(source_dirs)) $< include $(wildcard *.d)

      В этом окончательном варианте я "вынес" имя исполняемого файла программы в отдельную переменную program_name. Теперь для того чтобы адаптировать этот make-файл для сборки другой программы, в нем достаточно изменить всего лишь несколько первых строк.

      После запуска командных файлов make_debug и make_release директория с последним примером выглядит так:

      • example_6-multiconfig-multidir /
      • debug /
      • iEdit
      • main.o
      • main.d
      • Editor.o
      • Editor.d
      • TextLine.o
      • TextLine.d
    • release /
      • iEdit
      • main.o
      • main.d
      • Editor.o
      • Editor.d
      • TextLine.o
      • TextLine.d
      • main.cpp
      • main.h
      • Editor /
        • Editor.cpp
        • Editor.h
        • TextLine /
          • TextLine.cpp
          • TextLine.h
          • makefile
          • make_debug
          • make_release Видно, что объектные файлы для рабочей и отладочной конфигурации программы помещаются в разные директории. Туда же попадают готовые исполняемые файлы и файлы зависимостей.
          • В этой главе я изложил свою методику работы с make-файлами. Остальные главы носят более или менее "дополнительный" характер.

            • В Приложении A я описываю проблемы, которые могут возникнуть при редактировании make-файлов в разных операционных системах
            • В Приложении B я описываю свой личный способ организации дерева каталогов для сложных проектов.
            • В Приложении C я делюсь некоторыми мыслями по поводу использования компилятора GCC



            Содержание раздела