У меня есть проект, который копирует определенные файлы в выходную папку при сборке. Проблема в том, что эти файлы могут изменяться независимо от реального проекта, после чего Visual Studio заявляет, что все обновлено, и не выполняет мои задачи копирования.
Есть ли способ сообщить Visual Studio о необходимости запуска задания назначения/копирования, если определенные входные файлы изменились?
Оригинальным решением было следующее (документация):
<Target Name = "CopyDependencies" BeforeTargets = "Build"
Inputs = "AbsolutePath\To\SomeFile.txt"
Outputs = "$(OutDir)\SomeFile.txt">
<Copy SourceFiles = "AbsolutePath\To\SomeFile.txt" DestinationFolder = "$(OutDir)" />
</Target>
но это приводит к
1>------ Up-To-Date check: Project: MyProject.vcxproj, Configuration: Debug Win32 ------
1>All outputs are up-to-date.
даже если я напишу SomeFile.txt
после последней сборки.
Я также попытался вручную создать файл CC.write.1.tlog
(прежде чем тратить время на написание кода для его автоматической генерации) с помощью:
^ABSOLUTE\PATH\TO\SOMEFILE.TXT
ABSOLUTE\PATH\TO\OUTDIR\SOMEFILE.TXT
чтобы посмотреть, заставит ли это VS рассматривать файл как входные данные в своем обновленном алгоритме, но это также терпит неудачу.
@JonathanDodds Приятно, но я не против того, чтобы время от времени происходила дополнительная ненужная работа. Конечно, предпочтительнее битых компиляций.
Как у вас бывают битые компиляции?
@jonathan Из-за того, что устаревшие файлы являются частью выходных данных, несмотря на то, что я сообщил системе сборки, что некоторые из ее входных данных изменились.
О, так вы не имеете в виду буквально ошибку компилятора. И вы не имеете в виду, что сборка завершается с ошибкой. Вы имеете в виду, что сборка завершается успешно, но является «плохой», поскольку ваш внешний файл не обновляется в выходном каталоге. Это правильно? Это меняет понимание проблемы. Если исходный файл устарел и выполняется шаг Compile
, копируется ли внешний файл?
@Jonathan Нет необходимости в пугающих кавычках, результат просто неправильный - я сообщаю msbuild о зависимостях сборки (которые msbuild понимает совершенно правильно). Visual Studio, в которой просто есть оптимизация, приводящая к некорректному поведению. И да, задача копирования работает отлично, если она запущена.
Я пытаюсь понять, что происходит. Когда вы пишете «сломанные компиляции», для меня это означает, что есть одна или несколько ошибок компилятора. Результат, который вы считаете неправильным (т. е. «плохим»), отличается от результата, который представляет собой сообщение об ошибке (например, ошибка компилятора). Последний представляет собой сломанную компиляцию. Первого нет. Я подозреваю, что «оптимизация Visual Studio и создание неправильного поведения» — это не то, что происходит. Я подозреваю, что цель CopyDependencies
запускается только тогда, когда выполняются оба следующих условия: SomeFile.txt
устарела и необходимо выполнить этап компиляции.
Я скопировал вашу цель в свой файл .vcxproj
и могу воспроизвести ту же проблему у себя. Я нашел обходной путь, позволяющий избежать пропуска целевых «CopyDependities», поскольку все выходные файлы являются актуальными по отношению к входному файлу, даже если вы записываете в SomeFile.txt после последней сборки.
Установите для свойства DisableFastUpToDateCheck
значение true в группе свойств Globals файла проекта, чтобы переопределить поведение Visual Studio.
<PropertyGroup Label = "Globals">
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
Как отметил доктор ,
Логическое значение, применимое только к Visual Studio. Диспетчер сборки Visual Studio использует процесс FastUpToDateCheck, чтобы определить, необходимо ли перестроить проект, чтобы он был актуальным. Этот процесс выполняется быстрее, чем использование MSBuild для определения этого. Установка для свойства DisableFastUpToDateCheck значения true позволяет обойти диспетчер сборки Visual Studio и заставить его использовать MSBuild для определения актуальности проекта.
Кроме того, вы можете запустить команду msbuild, чтобы наблюдать за процессом сборки и увидеть, как MSBuild определяет, обновлен ли проект.
ОБНОВЛЯТЬ
Я думаю, это было бы обходным путем, но это влияет на производительность.
Да, отключение быстрой проверки актуальности VS сделает ваши сборки намного медленнее. Вместо этого вы можете использовать UpToDateCheckInput
и UpToDateCheckOutput
для описания файла ввода/вывода, о котором иначе MSBuild не узнал бы.
<ItemGroup>
<UpToDateCheckInput Include = "bsolutePath\To\SomeFile.txt"" />
<UpToDateCheckOutput Include = "$(OutDir)\SomeFile.txt"" />
</ItemGroup>
В вашем случае вы также можете использовать UpToDateCheckBuilt
, поскольку есть как вход, так и выход. Если определенные входные файлы изменились, они перестраиваются.
<ItemGroup>
<UpToDateCheckBuilt Include = "$(OutDir)\SomeFile.txt"" Original = "AbsolutePath\To\SomeFile.txt" />
</ItemGroup>
Документы указаны:
Я думаю, что это было бы обходным путем, но это влияет на производительность, что меня не слишком устраивает в редких крайних случаях.
Привет @Voo, да, это сделает ваши сборки намного медленнее. Я нашел другой обходной путь. Обновил ответ.
Если у вас есть копия проекта, который уже был создан и с тех пор ничего не изменилось, кроме
AbsolutePath\To\SomeFile.txt
, желательно, чтобы новыйSomeFile.txt
был скопирован, а все остальные шаги сборки были пропущены как «обновленные», то есть не будет этапа компиляции?