Какова хорошая структура каталогов для больших проектов C ++, использующих Makefile? - PullRequest
48 голосов
/ 02 марта 2010

Какова хорошая структура каталогов для больших проектов C ++, использующих Makefile?

Вот так выглядит моя структура каталогов на данный момент:

lib/ (class implementations *.cpp)
include/ (class definitions *.h)
tests/ (main.cpp for quick tests)

Теперь я не уверен, как должен выглядеть мой Makefile ... он не работает, когда файлы .cpp и .h не находятся в одном каталоге Может кто-нибудь указать мне на общую структуру каталогов с сопровождающим Makefile, чтобы я не изобретать колесо?

Ответы [ 5 ]

57 голосов
/ 02 марта 2010

Разделение .cpp файла .h не всегда является хорошим решением. Обычно я разделяю их оба, когда они используются в качестве библиотеки (открытый заголовок в include и закрытый заголовок с исходным кодом).

Если это библиотека, эта структура в порядке.

lib/ (class implementations *.cpp .h)
include/ (class definitions *.h) <- Only those to be installed in your system
tests/ (main.cpp for quick tests)
doc/ (doxygen or any kind of documentation)

Если это приложение

src/ (source for the application)
lib/ (source for the application library *.cpp *.hpp)
include/ (interface for the library *.h)
tests/ (main.cpp for quick tests) <- use cppunit for this part
doc/ (doxygen or any kind of documentation)

Используйте флаг -I $ (PROJECT_BASE) / include для указания пути включения для компиляции

Если это большой проект, для сборки можно использовать такие инструменты, как autoconf / automake или cmake . Это облегчит разработку.

12 голосов
/ 02 марта 2010

Нет определенной или необходимой структуры каталогов.

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

Вы бы просто использовали в путях Makefile:

%.o : %.cpp

заменить на

bin/%.o : %.cpp

Таким образом, он проверит, существует ли двоичный файл в каталоге bin и т. Д., Вы можете применить то же самое к местам компиляции файлов.

Существуют способы добавления / удаления / изменения путейисходные и объектные файлы.

Ознакомьтесь с gnu make manual , в частности с разделом 8.3 Функции для имен файлов и с предыдущей 8.2 Функции дляПодстановка и анализ строк .

Вы можете сделать что-то вроде:

получить список объектов из списка исходных файлов в текущем каталоге:

OBJ     = $(patsubst %.cpp, %.o, $(wildcard *.cpp))

Вывод:

Application.o Market.o ordermatch.o

Если двоичные объекты находятся в подкаталоге bin, а исходный код находится в текущем каталоге, вы можете применить префикс bin к сгенерированным объектным файлам:

OBJ     = $(addprefix bin/,$(patsubst %.cpp, %.o, $(wildcard *.cpp)))

Вывод:

bin/Application.o bin/Market.o bin/ordermatch.o

и т. Д.

12 голосов
/ 02 марта 2010

Если у вас много исходных файлов, также может быть хорошей идеей дальнейшее подразделение вашего исходного каталога. Например, один подкаталог для основных функций вашего приложения, один для графического интерфейса и т. Д.

src/core
src/database
src/effects
src/gui
...

Это также заставляет вас избегать ненужных отношений между вашими «модулями», что является необходимым условием для создания хорошего и многократно используемого кода.

6 голосов
/ 02 марта 2010

Нет "хорошей структуры каталогов".Выберите структуру, с которой вам удобно, и придерживайтесь ее.Некоторым нравится размещать исходные файлы (заголовки и файлы реализации) в каталоге src/, поэтому в корневом каталоге проекта есть только make-файл, readme и немного другое.Некоторые, например, помещают вспомогательные библиотеки в каталог lib/, юнит-тесты в test/ или src/test/, документацию в doc/ и т.д.отдельные каталоги, хотя.Лично мне не очень нравится разбивать файлы на каталоги.Я обычно размещаю весь свой источник в одном каталоге, а всю документацию - в другом.В любом случае, если я полагаюсь на хорошие инструменты поиска, нет необходимости в сложной структуре каталогов.

make может иметь дело со структурой, в которой make-файл находится в другом каталоге, чем исходный.Единственное, что он будет вызывать правила из каталога make-файла - у компиляторов обычно нет проблем с компиляцией исходного кода, который находится в некотором подкаталоге.Вам не нужно указывать относительные пути в ваших #include s;просто укажите путь включения с флагами компилятора (флаг gcc -I и т. д.).

3 голосов
/ 02 марта 2010

Если вы не видели его раньше, прочитайте Рекурсивный маркер считается вредным .

Короткая, короткая версия: Несмотря на то, что рекурсивная идиома очень распространена, она менее чем оптимальна и становится все хуже с ростом проектов и усложнением. Альтернатива представлена.

Ссылка по теме: Какой у вас опыт работы с нерекурсивными программами?

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