Visual Studio перестраивает неизмененные проекты
Итак, как гласит заголовок, у меня есть решение VS2010 с ~50 проектами в нем прямо сейчас. Если я внесу изменения в проект "верхнего уровня", на который ничего не ссылается, VS все равно перестроит все 50 проектов. Я использую Visual Studio 2010 Ultimate без каких-либо дополнений. Я использую ILMerge для объединения всех проектов в один файл.
Я проверил это, проверив временные метки dll нижнего уровня и убедился, что они действительно перестроены, хотя их код не был затронут.
Я прочитал все отзывы и комментарии для:
Visual Studio 2008 продолжает перестраивать
Визуальная студия продолжает строить все
Странный глюк сборки VS2010 происходит в моем решении
Причины для проектов C# для перестройки в Visual Studio
Но большинство из них просто предлагают предложения по разгрузке проектов, чтобы ускорить время сборки, но ничего конкретного для исправления. Я пытаюсь выяснить, почему VS считает, что эти зависимые проекты нужно перестраивать, когда они этого не делают, и исправлять это.
Я включил "Инструменты> Параметры> Проекты и решения> Построить и запустить> Создавать только запускаемые проекты и зависимости при запуске", но безрезультатно.
Кроме того, если я просто перестрою проект "среднего уровня", который имеет только 8 (in) прямых зависимостей, он все равно создает все 8 проектов, даже если ILMerge не вызывается и ни один из зависимых проектов не был изменен.
Спасибо всем за любые идеи, которые вы можете предоставить.
добавленной
Чтобы проверить некоторые предложения, я создал новый проект WinForms с нуля. Затем я создал два новых проекта в этом решении. Я скопировал весь код и ресурсы (не файл проекта) из моих двух проектов "самого низкого уровня" в два совершенно новых проекта (я сделал это, поместив файлы и папки из Проводника в проект в Visual Studio).
Самый низкий проект, назовем его B, не ссылался ни на какой другой проект. Следующий проект, A, ссылается только на B. Поэтому, как только я добавлю в проекты необходимые ссылки.NET и внешние сборки, решение будет построено.
Затем у меня была новая ссылка на проект WinForm A, и я сделал полную сборку. Итак, цепочка ссылок:
WinForm -> A -> B
Затем я изменил только WinForm и сделал стандартную сборку (F6). Как и прежде, Visual Studio перестроил все три проекта.
После некоторого систематического удаления исходных файлов в проекте B я обнаружил, что если я удалю Resources.Designer.cs
а также Resources.resx
(и закомментировал код, который использовал .Properties.Resources
объект этих ресурсов), то модификация WinForm больше не будет перестраивать все решение и будет перестраивать только WinForm.
Добавление Resources.resx
а также Resources.Designer.cs
вернуться к проекту B (но оставив закомментированный код, закомментированный так, чтобы ресурсы не использовались ничем), вновь представило бы полное поведение сборки.
Чтобы проверить, не повреждены ли мои файлы ресурсов, я снова удалил их, а затем создал новый (через "Свойства проекта" -> "Ресурсы") и повторно добавил тот же ресурс, что и раньше, который представлял собой один файл Excel. При такой настройке полная перестройка все равно будет происходить.
Затем я удалил один ресурс, но оставил файл ресурса в проекте B. Даже если ресурсы не добавлены, но файл ресурсов все еще находится в проекте, произойдет полное (ненужное) восстановление.
Похоже, что добавление файла ресурсов в проект (.NET 3.5) приведет к тому, что Visual Studio 2010 всегда будет перестраивать этот проект. Это ошибка или предполагаемое / ожидаемое поведение?
Спасибо всем еще раз!
18 ответов
Хотя я не думаю, что это исправление, это обходной путь, который сработал для моей ситуации...
Первоначально у меня было около 5 проектов из 50, которые содержали Resources
раздел. Эти проекты всегда будут перестраиваться, и поэтому все, от чего они зависят, также будет перестраиваться. Одним из этих 5 проектов была библиотека "базового" уровня, на которую ссылались 48 других проектов, таким образом, 96% моего проекта будут перестраиваться каждый раз, даже если в этом нет необходимости.
Мой обходной путь - использовать внедрение зависимостей, интерфейсы и выделенный проект "Ресурсы". Вместо того, чтобы эти 5 проектов ссылались на свои собственные Resources
объект, я создал интерфейс в каждом проекте, который будет поставлять нужные ресурсы. Затем классы, которым требовались эти ресурсы, потребовали бы передачи интерфейса во время их создания в конструкторе (внедрение конструктора).
Затем я создал отдельный проект "Ресурсы", в котором был настоящий раздел "Ресурсы", как обычно. Этот проект содержал только сами ресурсы и класс для каждого интерфейса, который был необходим для предоставления этих ресурсов через интерфейс. Этот проект будет ссылаться на любой другой проект, имеющий зависимость от ресурсов, и реализовывать интерфейс, который необходим проекту.
Наконец, в моем проекте "Верхний уровень", на который ничего не ссылалось (и где фактически был создан exe-файл и живет мой корень композиции), я ссылался на проект "Ресурсы", подключил DI, и мы поехали.
Это означает, что только два проекта ("Ресурсы" и "Верхний уровень") будут перестраиваться каждый раз, и если я сделаю частичную сборку (Shift-F6), они вообще не будут перестроены.
Опять же, это не очень хорошая работа, но каждый раз, когда создается 48 проектов, сборка занимает около 3 минут, поэтому я терял от 30 до 90 минут в день из-за ненужных перестроений. Рефакторинг занял некоторое время, но я думаю, что это были хорошие инвестиции.
Вот упрощенная схема. Обратите внимание, что зависимости от Main.exe
в Proj1
а также Proj2
не показаны, чтобы уменьшить беспорядок.
С этим дизайном я могу сделать сборку Proj1
или же Proj2
без запуска полной перестройки, так как они не имеют никаких зависимостей от Resources
раздел. Только Main
знает о Resources
реализация.
Откройте "Инструменты" - "Параметры", выберите "Проекты и решения" - "Построить и запустить" в дереве, а затем установите "Детализация вывода сборки проекта MSBuild" на "Диагностика". Это выведет причину построения проекта, т.е.
Проект 'ReferencedProject' не обновлен. Элемент проекта "c:\some.xml" имеет атрибут "Копировать в выходной каталог", установленный на "Всегда копировать".
Проект "MyProject" не обновлен. Входной файл "c:\ReferencedProject.dll" изменяется после выходного файла "c:\MyProject.pdb".
В этом случае исправление заключается в копировании файла some.xml, только если он более новый.
События до и после сборки также могут запускать сборку.
Это происходит, когда у проекта есть файл, который на самом деле не существует.
Проект не может определить, был ли файл изменен (потому что его там нет), поэтому он перестраивается.
Просто посмотрите на все файлы в проекте и найдите тот, у которого нет расширяемой стрелки рядом с ним.
У меня была такая же проблема в VS 2015.
Что сделал трюк для меня это:
- Один проект ссылался на саму копию в каком-то другом бине проекта (магия, да). Подобные вещи могут быть найдены при переключении на вывод диагностической сборки (в опциях сборки), а затем при попытке построить проекты один за другим из верхней части иерархии проектов - если вы видите проект, который перестраивается, даже если ничего не было изменено, посмотрите, что он Рекомендации.
- Я изменил все файлы "всегда копировать" во всех проектах на "копировать, если новее". В основном, во всех.csproj файлах заменить
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
в<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- Затем я отключил туннелирование NTFS, как описано в этой статье, с помощью этого сценария powershell:
New-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "MaximumTunnelEntries" -Value 0 -PropertyType "DWord"
После этого мне нужно было перестроить, и, похоже, сейчас работает.
В моем случае виновником была установка "Копировать локально" для dll, на которую ссылаются, равной true, и "Копировать в выходной каталог", задавая для файла значение Копировать всегда.
Для проектов.Net Core все вышеперечисленные решения не работают. Я нашел решение. Если вы используете Visual Studio 2019:
- Создайте решение дважды
- Включить
Tools
->Options
->Projects and Solutions
->SDK-Style Projects
->Logging Level
->Verbose
- Очистить окно вывода
- Создайте свой стартовый проект
- Осмотрите окно вывода. Вся строка, начинающаяся с
FastUpToDate
- Вы найдете некоторые элементы проекта, которые делают ваш проект устаревшим.
- Исправьте эти проблемы и повторите попытку, начиная с шага 1. Если ваши исправления верны, вы добьетесь
Build: 0 succeeded, 0 failed, {n} up-to-date, 0 skipped
в последней строке вывода сборки.
Команда MSBuild собирает документацию о расследовании проблем с инкрементностью сборки здесь: https://github.com/Microsoft/MSBuild/wiki/Rebuilding%20when%20nothing%20changed
У меня была такая же проблема, и она оказалась связана с парой проектов, которые имели локальную ссылку на копию в dll в своем собственном каталоге вывода.
Ключом к обнаружению этого было наличие диагностического вывода, установленного для вывода сборки, а также знание того, что искать в журнале. Поиск: "не в курсе" был ключом.
Другая проблема, которая часто возникает, - когда у какого-либо элемента в вашем решении есть модифицированная печать, которая находится в будущем. Это может произойти, если вы установите часы вперед, а затем установите правильное время. У меня такое было при установке Linux.
В этом случае вы можете рекурсивно коснуться всех файлов, используя git bash (да, в Windows):
find . -exec touch {} \;
Наконец-то я нашел еще одного преступника, которого мне было трудно найти, увеличив степень детализации журнала сборки.
В некоторых случаях MSBuild ищет vc120.pdb
в выходной папке, и если этот файл не существует, он перестроит весь проект. Это происходит, даже если вы отключили генерацию символов отладки.
Обходной путь здесь состоит в том, чтобы включить символы отладки и позволить этому файлу генерироваться, затем отключить настройку снова, не удаляя файл PDB.
Судя по вашим наблюдениям, у вас есть проекты, выражающие зависимости от других проектов таким образом, что это не очевидно. Потерянные зависимости могут оставаться в файлах проекта, не будучи видимыми в пользовательском интерфейсе. Вы просматривали неправильно работающий файл проекта после его открытия в текстовом редакторе? Проверены зависимости построения решения?
Если вы не можете ничего найти, попробуйте воссоздать один из ваших проектов с нуля, чтобы увидеть, есть ли в новом проекте такая же проблема. Если чистый проект собирается правильно, вы будете знать, что у вас есть нежелательные зависимости, выраженные где-то. Насколько я знаю, они должны быть в файле (ах) проекта или файла решения, если у вас нет make-файлов или других необычных шагов сборки.
Вот ответ от VS2010 всегда перестраивает решение?
Эта проблема решается путем изменения файлов проекта, очистки решения, удаления всех папок бина вручную, перезапуска Visual Studio и восстановления всего.
В моем случае (смешанное C#, C++/CLI и нативное решение C++) некоторые проекты C++ были перекомпонованы, даже если ничего не изменилось. Я потратил целую вечность, пытаясь понять, что происходит. В итоге из опции "Командная строка" я понял, что путь вывода PDB (опция /Fd) не может обработать настройку папки $(IntDir). Я удалил это - пустое значение будет делать по умолчанию правильно - и моя проблема ушла.
У меня были такие же проблемы с тобой. Я обнаружил, что это произошло из некоторых удаленных файлов. Когда я удалил файлы из своего проекта, проблемы исчезли. С уважением.
У меня возникла проблема с перестройкой проектов Visual Studio при обновлении с Visual Studio 2015 до 2017 года, и я добавляю этот ответ для тех, кто может столкнуться с подобными проблемами, поскольку, похоже, он нигде не документирован.
В моем случае проблема заключалась в том, что все проекты в решении имели один и тот же промежуточный выходной путь (obj). Файл GeneratedInternalTypeHelper.cs генерируется всеми проектами, содержащими XAML. Вплоть до Visual Studio 2015 процесс сборки, по-видимому, не проверял дату файла для этого файла и, следовательно, никаких проблем с ним не возникало. В VS2017 проверяется дата файла этого файла, и поскольку более поздний проект в процессе сборки перезапишет его (с тем же содержимым), более ранний проект будет перестроен, повторно запустив более позднюю сборку, до бесконечности.
Решением в этом случае является обеспечение того, чтобы все проекты имели разные промежуточные выходные каталоги, что устранит проблему.
Как заметили другие, вероятная причина в том, что CopyToOutputDirectory имеет значение Always. Это можно исправить одновременно во всех файлах проекта, применив приведенный ниже сценарий PowerShell:
$folder = "C:\My\Solution\Folder"
$csvFiles = Get-ChildItem $folder *.csproj -rec
foreach ($file in $csvFiles)
{
(Get-Content $file.PSPath -Encoding UTF8 -Raw) |
Foreach-Object { $_ -replace "<CopyToOutputDirectory>Always</CopyToOutputDirectory>", "<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>" } |
Set-Content $file.PSPath -Encoding UTF8 -NoNewline
}
Для этой категории проблем сборки установка подробного вывода MSBuild на "диагностику" действительно является необходимым первым шагом. В большинстве случаев заявленной причины повторных сборок будет достаточно для принятия мер, НО иногда MSBuild ошибочно заявляет, что некоторые файлы изменены и их необходимо скопировать.
В этом случае вам нужно либо отключить туннелирование NTFS, либо скопировать выходную папку в другое место. Вот это в нескольких словах.
Файлы, которые не существуют, являются проблемой и, очевидно, файлы также не производят вывод. Это может случиться, если у вас есть файл ресурсов в статической библиотеке. (С++)