У меня большой файл решения c # (~ 100 проектов), и я пытаюсь улучшить время сборки. Я думаю, что «Копировать Локальный» во многих случаях расточителен для нас, но я задаюсь вопросом о лучших практиках.
В нашем .sln у нас есть приложение A в зависимости от сборки B, которая зависит от сборки C. В нашем случае, есть десятки «B» и несколько «C». Поскольку все они включены в .sln, мы используем ссылки на проекты. Все сборки в настоящее время встроены в $ (SolutionDir) / Debug (или Release).
По умолчанию Visual Studio помечает эти ссылки на проекты как «Копировать локально», что приводит к тому, что каждый «C» копируется в $ (SolutionDir) / Debug один раз для каждого «B», который собирается. Это кажется расточительным. Что может пойти не так, если я просто отключу «Копировать локальный»? Что делают другие люди с большими системами?
СЛЕДОВАТЬ ЗА:
Множество ответов предлагают разбить сборку на более мелкие файлы .sln ... В приведенном выше примере я сначала собрал бы базовые классы "C", а затем основную часть модулей "B", а затем несколько приложений ". А». В этой модели мне нужно иметь не-проектные ссылки на C из B. Проблема, с которой я сталкиваюсь, заключается в том, что «Debug» или «Release» запекаются на пути подсказки, и я заканчиваю сборку выпусков сборки «B» против отладочных сборок "C".
Для тех из вас, кто разделил сборку на несколько файлов .sln, как вы справляетесь с этой проблемой?
источник
<Private>True</Private>
в csproj?.sln
на более мелкие , ломает Automagic расчета Взаимозависимости VS по<ProjectReference/>
с. Я сам перешел от нескольких меньших.sln
s к одному большому.sln
только потому, что таким образом VS вызывает меньше проблем ... Итак, может быть, продолжение предполагает не обязательно лучшее решение исходного вопроса? ;-)Ответы:
В предыдущем проекте я работал с одним большим решением со ссылками на проект, а также столкнулся с проблемой производительности. Решение было три раза:
Всегда устанавливайте для свойства Copy Local значение false и применяйте это с помощью пользовательского шага msbuild.
Установите выходной каталог для каждого проекта в один и тот же каталог (предпочтительно относительно $ (SolutionDir)
Цели cs по умолчанию, которые поставляются с платформой, рассчитывают набор ссылок, которые будут скопированы в выходной каталог проекта, который в настоящее время создается. Поскольку для этого требуется вычислить транзитивное замыкание по отношению «Ссылки», это может стать ОЧЕНЬ дорогостоящим. Мой обходной путь для этого состоял в том, чтобы переопределить
GetCopyToOutputDirectoryItems
цель в общем файле целей (например,Common.targets
), который импортируется в каждый проект после импортаMicrosoft.CSharp.targets
. В результате каждый файл проекта будет выглядеть следующим образом:Это сократило время сборки в данный момент времени с пары часов (в основном из-за ограничений памяти) до пары минут.
Переопределенный
GetCopyToOutputDirectoryItems
можно создать, скопировав строки 2,438–2,450 и 2,474–2,524 изC:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets
вCommon.targets
.Для полноты итоговое определение цели становится:
Имея этот обходной путь, я обнаружил, что в одном решении может быть реализовано более 120 проектов, и это дает основное преимущество, заключающееся в том, что порядок компоновки проектов все еще может быть определен VS вместо того, чтобы делать это вручную путем разделения вашего решения. ,
источник
Я предлагаю вам прочитать статьи Патрика Смаккья на эту тему:
Вы также можете прочитать эту статью, чтобы уменьшить количество проектов и сократить время компиляции.
источник
Я предлагаю использовать копию local = false почти для всех проектов, кроме того, что находится в верхней части дерева зависимостей. И для всех ссылок в одной вверху установите копию local = true. Я вижу много людей, предлагающих поделиться выходным каталогом; Я думаю, что это ужасная идея, основанная на опыте. Если ваш стартовый проект содержит ссылки на dll, на который ссылается любой другой проект, вы в какой-то момент столкнетесь с нарушением прав доступа \ общего доступа, даже если copy local = false для всего, и ваша сборка не удастся. Эта проблема очень раздражает и ее трудно отследить. Я полностью рекомендую держаться подальше от выходного каталога сегмента и вместо того, чтобы проект находился наверху цепочки зависимостей, записывать необходимые сборки в соответствующую папку. Если у вас нет проекта на «вершине» тогда я бы предложил копию после сборки, чтобы получить все в нужном месте. Кроме того, я бы постарался запомнить простоту отладки. Любые exe-проекты я все еще оставляю copy local = true, чтобы отладка F5 работала.
источник
Ты прав. CopyLocal абсолютно убьет ваше время сборки. Если у вас большое исходное дерево, вам следует отключить CopyLocal. К сожалению, это не так просто, как должно быть, чтобы отключить его чисто. Я ответил на этот точный вопрос об отключении CopyLocal в разделе Как переопределить параметр CopyLocal (Private) для ссылок в .NET из MSBUILD . Проверьте это. А также Лучшие практики для больших решений в Visual Studio (2008).
Вот еще немного информации о CopyLocal, как я ее вижу.
CopyLocal был действительно реализован для поддержки локальной отладки. Когда вы готовите свое приложение для упаковки и развертывания, вы должны собрать свои проекты в одной выходной папке и убедиться, что у вас есть все необходимые ссылки.
Я написал о том, как работать с большими деревьями исходников, в статье MSBuild: Лучшие практики для создания надежных сборок, часть 2 .
источник
По моему мнению, иметь решение с 100 проектами - БОЛЬШАЯ ошибка. Вероятно, вы могли бы разделить свое решение на допустимые логические небольшие блоки, что упростит как обслуживание, так и сборку.
источник
Я удивлен, что никто не упомянул использование жестких ссылок. Вместо копирования файлов создается жесткая ссылка на исходный файл. Это экономит дисковое пространство, а также значительно ускоряет сборку. Это можно включить в командной строке со следующими свойствами:
/ Р: CreateHardLinksForAdditionalFilesIfPossible = истина; CreateHardLinksForCopyAdditionalFilesIfPossible = истина; CreateHardLinksForCopyFilesToOutputDirectoryIfPossible = TRUE; CreateHardLinksForCopyLocalIfPossible = TRUE; CreateHardLinksForPublishFilesIfPossible = TRUE
Вы также можете добавить это в центральный файл импорта, чтобы все ваши проекты также могли получить это преимущество.
источник
Если вы получили структуру зависимостей, определенную с помощью ссылок на проекты или зависимостей уровня решения, можно безопасно отключить «Копировать локально», я бы даже сказал, что это лучший метод, так как это позволит вам использовать MSBuild 3.5 для параллельного запуска сборки ( via / maxcpucount) без различных процессов, спотыкающихся друг на друга при попытке скопировать ссылочные сборки.
источник
Наша «лучшая практика» - избегать решений по многим проектам. У нас есть каталог с именем "matrix" с текущими версиями сборок, и все ссылки из этого каталога. Если вы изменили какой-либо проект и можете сказать «теперь изменение завершено», вы можете скопировать сборку в каталог «matrix». Таким образом, все проекты, которые зависят от этой сборки, будут иметь текущую (= последнюю) версию.
Если у вас мало проектов в решении, процесс сборки будет намного быстрее.
Вы можете автоматизировать шаг «Скопировать сборку в каталог матрицы», используя макросы Visual Studio или «Меню -> Инструменты -> Внешние инструменты ...».
источник
Вам не нужно менять значения CopyLocal. Все, что вам нужно сделать, это предварительно определить общий $ (OutputPath) для всех проектов в решении и установить для $ (UseCommonOutputDirectory) значение true. Смотрите это: http://blogs.msdn.com/b/kirillosenkov/archive/2015/04/04/using-a-common-intermediate-and-output-directory-for-your-solution.aspx
источник
Установите CopyLocal = false, чтобы сократить время сборки, но может вызвать различные проблемы во время развертывания.
Существует много сценариев, когда вам нужно, чтобы параметр «Копировать локально» оставался равным True, например,
Возможные проблемы, описанные в SO-вопросах
« Когда для copy-local должно быть задано значение true, а когда - нет? »,
« Сообщение об ошибке« Невозможно загрузить один или несколько запрошенных типов. Получите свойство LoaderExceptions для получения дополнительной информации ». "
И Арон-stainback «s ответ на этот вопрос.
Мой опыт установки CopyLocal = false не был успешным. См. Мой пост в блоге «НЕ меняйте« Копировать локальные »ссылки на проект на false, если не понимаете подпоследовательности».
Время решения проблем перевешивает преимущества установки copyLocal = false.
источник
CopyLocal=False
наверняка вызовет некоторые проблемы, но есть решения для них. Кроме того, вы должны исправить форматирование вашего блога, он едва читаем, и утверждение «я был предупрежден <случайным консультантом> из <случайной компании> о возможных ошибках во время развертываний» не является аргументом. Вам нужно развиваться.Я склонен создавать общий каталог (например, \ bin), поэтому я могу создавать небольшие тестовые решения.
источник
Вы можете попытаться использовать папку, в которую будут скопированы все сборки, которые совместно используются проектами, а затем сделать переменную среды DEVPATH и установить
<developmentMode developerInstallation="true" />
в файле machine.config на каждой рабочей станции разработчика. Единственное, что вам нужно сделать, это скопировать любую новую версию в вашу папку, куда указывает переменная DEVPATH.
Также разделите ваше решение на несколько небольших решений, если это возможно.
источник
Это может быть не лучшей практикой, но так я работаю.
Я заметил, что Managed C ++ выгружает все свои двоичные файлы в $ (SolutionDir) / 'DebugOrRelease'. Таким образом, я также выбросил все свои проекты на C #. Я также отключил «Копировать локальные» всех ссылок на проекты в решении. У меня было заметное улучшение времени сборки в моем маленьком 10 проектном решении. Это решение представляет собой смесь C #, управляемого C ++, нативного C ++, C # webservice и проектов установщика.
Может быть, что-то сломано, но так как я работаю только так, я этого не замечаю.
Было бы интересно узнать, что я нарушаю.
источник
Обычно вам нужно только копировать Local, если вы хотите, чтобы ваш проект использовал DLL, которая находится в вашей корзине, и то, что находится где-то еще (GAC, другие проекты и т. Д.)
Я хотел бы согласиться с другими людьми, что вы должны также попытаться, если это вообще возможно, сломать это решение.
Вы также можете использовать Configuration Manager для создания различных конфигураций сборки в рамках одного решения, которое будет создавать только определенные наборы проектов.
Было бы странно, если бы все 100 проектов опирались друг на друга, поэтому вы можете разбить его или использовать Configuration Manager, чтобы помочь себе.
источник
У вас могут быть ссылки на ваши проекты, указывающие на отладочные версии библиотек. Чем в вашем скрипте msbuild вы можете установить
/p:Configuration=Release
, тем самым у вас будет выпущенная версия вашего приложения и всех сателлитных сборок.источник
Если вы хотите иметь центральное место для ссылки на DLL, используя локальное копирование, произойдет сбой без GAC, если вы не сделаете этого.
http://nbaked.wordpress.com/2010/03/28/gac-alternative/
источник
Если ссылка не содержится в GAC, мы должны установить для параметра Local Local значение true, чтобы приложение работало. Если мы уверены, что ссылка будет предварительно установлена в GAC, тогда для нее можно установить значение false.
источник
Ну, я, конечно, не знаю, как решаются проблемы, но у меня был контакт с решением для сборки, которое помогло себе так, что все созданные файлы были помещены на виртуальный диск с помощью символических ссылок .
c: \ папка решений \ obj -> ramdisk r: \ папка решений \ obj \
Вы также можете дополнительно указать Visual Studio, какой временный каталог он может использовать для сборки.
На самом деле это было не все, что он сделал. Но это действительно поразило мое понимание производительности.
100% использование процессора и огромный проект за 3 минуты со всеми зависимостями.
источник