C++. Сборник рецептов - [37]

Шрифт
Интервал

Например, чтобы из исходных файлов из примера 1.3 собрать исполняемый файл с помощью GCC в Unix, создайте такой make-файл, как показанный в примере 1.23.

Пример 1.23. make файл для hellobeatles.exe с использованием GCC

# Укажите исходные файлы, целевой файл, директории сборки

># и директорию установки

>SOURCES = hellobeatles.cpp

>OUTPUTFILE = hellobeatles

>LIBJOHNPAUL = libjohnpaul.a

>LIBGEORGERINGO = libgeorgeringo.so

>JOHNPAULDIR = ../johnpaul

>GEORGERINGODIR = ../georgeringo

>INSTALLDIR = ../binaries


>#

># Добавьте в путь поиска заголовочных файлов родительскую директорию

>#

>CPPFLAGS += -I..


>#

># Цель по умолчанию

>#

>.PHONY: all

>all: $(HELLOBEATLES)


>#

># Цель для сборки исполняемого файла.

>#

>$(OUTPUTFILE): $(subst .cpp,.о,$(SOURCES)) \

> $(JOHNPAULDIR)/$(LIBJOHNPAUL) \

> $(GEORGERINGODIR)/$(LIBGEORGERINGO)

>    $(CXX) $(LDFLAGS) -o $@ $^


>.PHONY: install

>install:

>    mkdir -p $(INSTALLDIR)

>    cp -p $(OUTPUTFILE) $(INSTALLDIR)


>.PHONY: clean

>clean:

>    rm -f *.o

>    rm -f $(OUTPUTFILE)


>#Сгенерируйте зависимости .cpp-файлов от .hpp-файлов

>include $(subst .cpp,.d,$(SOURCES))


>%.d: %.cpp

>    $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \

>    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@..$$$$ > $@; \

>    rm -f $@.$$$$

Далее в директории, содержащей johnpaul, georgeringo, hellobeatles и binaries, создайте главный make-файл, как показано в примере 1.24.

Пример 1.24. Главный make-файл для исходного кода из примеров 1.1, 1.2 и 1.3

># Все цели в этом make-файле — фиктивные

>PHONY: all johnpaul georgeringo hellobeatles


># Цель по умолчанию

>all: hellobeatles


># Цели johnpaul, georgeringo и hellobeatles представляют

># директории, командный сценарий вызывает make в каждой из них

>johnpaul georgeringo hellobeatles

>$(MAKE) --directory=$@ $(TARGET)


># Это правило указывает что цель по умолчанию make-файла

># в директории hellobeatles зависит от целей по умолчанию

># make-файлов из директорий johnpaul и georgeringo

>.PHONY: hellobeatles

>hellobeatles: johnpaul georgeringo

Чтобы собрать hellobeatles, перейдите в директорию, содержащую главный make-файл, и введите >make. Чтобы скопировать файлы libjohnpaul.a, libgeorgeringo.so и hellobeatles в директорию binaries, введите >make TARGET=install. Чтобы очистить проект, введите >make TARGET=clean.

Обсуждение

Подход к управлению сложными проектами, продемонстрированный в этом рецепте, известен как рекурсивный make (recursive make). Он позволяет организовать проект в виде набора модулей, каждый со своим собственным make-файлом, и указать зависимости между этими модулями. Он не ограничен одним главным make-файлом с набором дочерних make-файлов: эта методика может применяться для обработки многоуровневых древовидных структур. В то время, пока рекурсивный make был стандартной методикой управления большими проектами с помощью make, появились другие методы, которые теперь рассматриваются как более качественные. За подробностями снова обратитесь к Managing Projects with GNU make, Third Edition Роберта Мекленбурга (O'Reilly).

Пример 1.23 — это прямое применение методик, продемонстрированных в рецептах 1.15, 1,16 и 1.17. В нем есть один очень интересный момент. Как показано в рецепте 1.15, при компиляции hellobeatles.cpp из командной строки необходимо использовать опцию -I.., говорящую компилятору, где искать заголовочные файлы johnpaul.hpp и georgeringo.hpp. Одним из возможных решений является написание явного правила сборки hellobeatles.o с помощью командного сценария, содержащего опцию -I.. подобно этому.

>hellobeatles.o: hellobeatles.cpp

>g++ -с -I.. -о hellobeatles.o hellobeatles.cpp

Вместо этого я использовал точку настройки >CPPFLAGS, описанную в рецепте 1.15, и указал, что всегда, когда происходит компиляция объектного файла из файла .cpp, в командную строку должна быть добавлена опция -I..:

>CPPFLAGS += -I..

Вместо оператора присвоения >= я использовал >+=, так что новое значение будет добавляться к тому значению >CPPFLAGS, которое могло быть указано в командной строке или в переменной среды.

Теперь давайте посмотрим на то, как работает пример 1.24. Наиболее важным правилом является то, которое заставляет make вызываться для каждой из директорий johnpaul, georgeringo и hellobeatles.

>johnpaul georgeringo hellobeatles:

>$(MAKE) --directory=$@ $(TARGET)

Чтобы понять это правило, вы должны знать три вещи. Во-первых, переменная >MAKE раскрывается как имя запущенного в данный момент экземпляра make. Обычно это будет >make, но на некоторых системах это может быть >gmake. Во-вторых, опция командной строки --directory= заставляет make вызваться с ><path> в качестве текущей директории. В-третьих, правило с несколькими целями эквивалентно набору правил, каждое из которых имеет по одной цели и которые содержат одинаковые командные сценарии. Так что приведенное выше правило эквивалентно следующим.

>johnpaul:

>    $(MAKE) --directory=$@ $(TARGET)


>georgeringo:

>    $(MAKE) --directory=$@ $(TARGET)


>hellobeatles:

>    $(MAKE) --directory=$@ $(TARGET)

В свою очередь это эквивалентно:

>johnpaul:

>    $(MAKE) --directory=johnpaul $(TARGET)


>georgeringo:

>    $(MAKE) --directory=georgeringo $(TARGET)


>hellobeatles:

>    $(MAKE) -directory=hellobeatles $(TARGET)


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.