MSBuild - Проектные цели для решения не работают
У меня есть решение с несколькими проектами, включая веб-приложение. Я хочу, чтобы MSBuild выполнял цель "WebPublish" для проекта веб-приложения и "цель по умолчанию" для всех других проектов в решении.
В этой статье MSDN говорится, что я могу сделать это, указав командную строку
msbuild SlnFolders.sln /t:NotInSlnfolder:Rebuild;NewFolder\InSolutionFolder:Clean
Но я никогда не мог заставить это работать - MSBuild возвращает ошибку, что-то вроде цели "NotInSlnFolder:Rebuild" не существует. Неважно, какую цель указать, Build, Rebuild или Clean - это не работает ни в коем случае.
Как я могу достичь своей цели, указав конкретные цели проекта для решения?
Документация MSDN не работает. Или я что-то пропустил?
2 ответа
ПРИМЕЧАНИЕ. Этот обходной путь официально не поддерживается корпорацией Microsoft, поэтому нет гарантии, что он будет работать вечно.
Короткий ответ
В папке с файлом SLN создайте файл before.{YourSolution}.sln.targets
со следующим содержанием: (замените то, что в фигурных скобках, на все, что вам нужно.)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="{MyCompany_MyProduct_WebApp:WebPublish}">
<MSBuild
Condition="'%(ProjectReference.Identity)' == '{$(SolutionDir)MyCompany.MyProduct.WebApp\MyCompany.MyProduct.WebApp.csproj}'"
Projects="@(ProjectReference)"
Targets="{WebPublish}"
BuildInParallel="True"
ToolsVersion="4.0"
Properties="BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)"
SkipNonexistentProjects="%(ProjectReference.SkipNonexistentProjects)" />
</Target>
</Project>
После этого вы можете выполнить командную строку:
msbuild {YourSolution}.sln /t:{MyCompany_MyProduct_WebApp:WebPublish}
Длинный ответ
Если вы добавите переменную среды MSBUILDEMITSOLUTION
При значении 1 MSBuild не будет удалять временные файлы, созданные для решения и проектов.
Это позволит вам найти {YourSolution}.sln.metaproj
а также {YourSolution}.sln.metaproj.tmp
файлы, сгенерированные в папке решения, которые являются просто стандартными файлами проекта MSBuild.
Для MSBuild 3.5 сгенерированный файл {YourSolution}.sln.cache
и сохраняется независимо от переменных среды. Анализируя эти файлы, вы поймете низкоуровневые детали процесса и увидите доступные возможности настройки.
После выполнения MSBuild с определенной целью проекта в файле.Metaproj вы обнаружите, что список целей проекта жестко закодирован и поддерживаются только стандартные цели (Build, Rebuild, Clean, Compile, Publish; примечание: Publish и WebPublish не то же самое). MSBuild 3.5 генерирует только цели "Очистить", "Перестроить" и "Опубликовать", а также цель только с именем проекта, что означает "Сборка".
Вы также можете увидеть, что NotInSlnfolder:Rebuild
это просто имя автоматически сгенерированной цели. На самом деле MSBuild не разбирает его и не заботится об именах и местоположении проекта. Также обратите внимание, что автоматически генерируемые целевые имена указывают имя проекта с иерархией папок решения, если оно в одной, например SolFolder\SolSubfolder\ProjectName:Publish
,
Еще одна критически важная вещь, которую вы найдете: имя цели MSBuild не поддерживает точки. Все точки в названиях проектов заменены подчеркиванием. Например, для проекта с именем MyCompany.MyProduct.Components
вам нужно будет указать в командной строке:
/t:MyCompany_MyProduct_Components:Rebuild
Вот почему даже стандартная целевая сборка проекта не работала - в моем названии проекта были точки.
Анализ файла {YourSolution}.sln.metaproj.tmp
, вы обнаружите, что во время выполнения он пытается импортировать цели из файла с именем before.{YourSolution}.sln.targets
а также after.{YourSolution}.sln.targets
, если эти файлы существуют. Это имеет ключ к обходу этого ограничения / ошибки MSBuild.
Вы можете открыть файл решения в текстовом редакторе и проверить, существует ли следующая строка или нет, если нет, то вы можете добавить
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
внутри <Project>
тег.
Надеюсь, это поможет вам.