У нас была похожая проблема, и мы подошли к ней очень похоже на то, что @Toby Allen упоминает в своем ответе через спецификации клиента. Однако со временем это становится очень болезненным (настройка нового члена команды становится все более и более трудной, поскольку спецификации клиентов становятся все более и более запутанными; автоматизация также становится намного более сложной, поскольку все ... "в движении" :-)).
Со временем мы разработали нашу стратегию, чтобы вместо этого использовать структуру каталогов и ветвления. Структура каталогов следующая:
//depot
/products
/(product_name)
/doc
/lib
/(3rd_party_libname)
(DLLs)
/(another_3rd_party_libname)
(DLLs)
/src
/Project1
(files, csproj, vbproj, etc)
/Project2
(files, csproj, vbproj, etc)
/Project3
(files, csproj, vbproj, etc)
Solution1.sln (includes src/Project1)
Solution2.sln (includes src/Project1, src/Project2)
Solution3.sln (includes src/Project1, src/Project3)
/(another_product_name)
/doc
/lib
/src
(solutions)
/shared
/(shared_lib_name)
/doc
/lib
/src
(solutions)
/(another_shared_lib_name)
/doc
/lib
/src
(solutions)
Обратите внимание, что одна и та же структура повторяется по всей структуре (doc / lib / src / solutions). Lib содержит «внешние» библиотеки - сторонние библиотеки, которые включены в ссылки на проекты. Src содержит плоский список всех проектов, которые являются частью определенного продукта. Решения затем используются для «объединения» проектов любым количеством способов. Я считаю каталог src контейнером с «тем, что доступно», затем решения выбираются из этого контейнера и объединяют проекты (по мере необходимости).
Библиотеки, которые совместно используются несколькими продуктами, попадают в общий каталог. Попав в общий каталог, они рассматриваются как независимые от продуктов - у них свой цикл выпуска и они никогда не присоединяются к продуктам в качестве источника. Разделяемые библиотеки объединяются в продукты путем разветвления сборок / сборок выпусков совместно используемых библиотек в каталог lib -> продукта -> с точки зрения продукта нет разницы между сторонней библиотекой и разделяемой библиотекой. Это позволяет нам контролировать, какой продукт использует какую версию совместно используемой библиотеки (когда продукту нужны новые функции, он должен явно переходить в более новую версию совместно используемой библиотеки, как если бы он включал новый выпуск сторонней библиотеки, со всеми плюсами и минусами, которые идут с этим).
Таким образом, наша структура имеет концепцию двух «типов» разделяемых библиотек:
- проекты, локальные для продукта, используемые несколькими решениями (включены в плоский список проектов в каталоге src, на них могут ссылаться несколько решений)
- проекты, используемые несколькими продуктами (добавляются в общий каталог, рассматриваются как сторонние библиотеки с выпусками, независимыми от продуктов)