Подтвердить что ты не робот

Какая хорошая структура каталогов для больших проектов на С++ с использованием Makefile?

Какая хорошая структура каталогов для больших проектов на С++ с использованием Makefile?

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

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

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

4b9b3361

Ответ 1

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

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

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, чтобы построить все. Это облегчит развитие.

Ответ 2

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

Вы можете настроить его в любом случае. Ваша проблема просто решить. Просто проинструктируйте 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

И так далее.

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ссылки по теме: Каков ваш опыт в отношении нерекурсивного создания?