Я нахожусь в процессе реорганизации физического (на диске) макета большой кроссплатформенный проект C ++ со многими сторонними зависимостями, построенными с использованием CMake.
Поскольку нам нужна поддержка Windows, платформы, на которой нет хорошо известного менеджера пакетов, мы давно решили включить сторонние библиотеки, на которые мы полагаемся, в дерево исходных текстов. Однако на других поддерживаемых нами платформах, таких как Linux и Mac OS X, многие из этих сторонних библиотек доступны в виде пакетов или уже присутствуют в системе, и их легко найти в CMake.
Текущий макет проекта выглядит следующим образом:
root/
src/
3rd-party-lib1/ (build system modified to output to build/)
3rd-party-lib2/ (build system modified to output to build/)
project-module1/ (our own code)
project-module2/ (our own code)
build/ (CMake is invoked from here)
3rd-party-lib1-bin/
3rd-party-lib2-bin/
Сторонние библиотеки были настроены так, что при сборке они выводят свои двоичные файлы в root/build/<lib>/
,
Проблемы с этим макетом являются множественными:
src/
Каталог содержит смесь нашего собственного кода и стороннего кода, что сбивает с толку.src/
каталог очень большой. Так как src/
содержит сторонние библиотеки, он очень большой по сравнению с фактическим объемом исходного кода, что делает резервное копирование нашего собственного кода немного более сложным, чем требуется (мы не можем просто заархивировать весь src/
каталог больше).Альтернативный макет будет следующим:
root/
3rdparty/
3rd-party-lib1/ (100% original, contains built artifacts)
3rd-party-lib2/ (100% original, contains built artifacts)
src/
project-module1/ (our own code)
project-module2/ (our own code)
build/ (CMake is invoked from here)
Наши файлы CMake должны быть изменены, чтобы искать сторонние заголовочные файлы и библиотеки в нужном месте для каждой библиотеки.
Каковы оптимальные методы работы со сторонними библиотеками в нативных кроссплатформенных проектах? Какой макет приведет к тому, что наши разработчики получат на своих платформах самый удивительный опыт сборки? Также приветствуются конкретные примеры успешных макетов из существующих проектов.
Мой опыт подсказывает следующее как лучшие практики:
Когда сторонняя библиотека с открытым исходным кодом используется полностью как есть, передайте локальную копию загруженного сжатого архива внутри основного git-репо, чтобы избежать проблем с сетевым подключением, препятствующих сборке программного обеспечения.
Когда сторонняя библиотека с открытым исходным кодом практически используется как есть, но ее необходимо настроить (это
обычно встречается при кросс-компиляции: многие пакеты нуждаются в незначительной корректировке этапов настройки), сохраняют сжатый архив и файл «унифицированного diff» в основном репозитории git и применяют исправление на шаге PATCH_COMMAND в ExternalProject_Add.
Когда сторонняя библиотека с открытым исходным кодом (будет) сильно изменена или расширена вашей организацией, используйте отдельный репозиторий git для хранения указателей на репозиторий upstream (проще всего, когда он также использует git, но можно также управлять восходящим svn) , Зафиксируйте изменения вашей организации в отдельной ветви от ветви, используемой для зеркалирования восходящего потока. Если вы хотите, вы можете ввести подмодульные отношения между основным git-репо и этим, хотя, поскольку DOWNLOAD_COMMAND может извлекать данные напрямую из произвольного git-репо, технически это делать не нужно.
Разумно обрабатывать небольшие, реже сторонние проприетарные двоичные файлы для одной целевой платформы, архивируя их также в основном git-репо. Однако сторонние двоичные файлы, которые доступны для различных платформ, являются большими или часто развивающимися, должны храниться в их собственном git-репо и извлекаться через DOWNLOAD_COMMAND, как указано выше.
Других решений пока нет …