Что такое хорошая структура каталогов для больших проектов C++ с помощью Make-файла?

Что такое хорошая структура каталогов для больших проектов C++ с помощью Make-файла?

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

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

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

48
задан Olivier Lalonde 2 March 2010 в 03:34
поделиться

5 ответов

Не существует какой-либо конкретной или обязательной структуры каталогов.

Вы можете настроить его как хотите. Решить вашу проблему несложно. Просто дайте команду 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
ответ дан 26 November 2019 в 18:48
поделиться

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

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

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 для сборки всего. Это облегчит развитие.

57
ответ дан 26 November 2019 в 18:48
поделиться

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

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

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

12
ответ дан 26 November 2019 в 18:48
поделиться

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

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

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

6
ответ дан 26 November 2019 в 18:48
поделиться

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

Краткая, краткая версия: Несмотря на то, что рекурсивная идиома make очень распространена, она менее чем оптимальна и становится все хуже по мере того, как проекты становятся больше и сложнее. Представлена ​​альтернатива.

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

3
ответ дан 26 November 2019 в 18:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: