Проблема с использованием MSBuild для сборки и копирования всех выходных данных в общую папку
Мы пытаемся написать сценарий msbuild, который построит решение и скопирует все скомпилированные двоичные файлы и зависимости в определенную выходную папку. В то время как сценарий сборки, который у нас есть, создает и копирует двоичные файлы в общую папку, но мы не копируем зависимости. Это, вероятно, связано с тем, как мы использовали задачу msbuild для построения решения, и мы принимаем targetoutputs задачи в itemgroup и перебираем элемент группы копировать все скомпилированные библиотеки DLL и исполняемые файлы в общей папке. Но это не включает в себя библиотеки DLL зависимостей, которые помещаются в отдельную папку bin каждого проекта.
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ParentSolutionFile />
</PropertyGroup>
<ItemGroup>
<Assemblies Include="*.dll, *.exe" />
</ItemGroup>
<Target Name="BuildAll">
<CombinePath BasePath="$(MSBuildProjectDirectory)" Paths="SourceSolutionsxxx.sln">
<Output TaskParameter="CombinedPaths" PropertyName="ParentSolutionFile" />
</CombinePath>
<Message Text="$(ParentSolutionFile)" />
<MSBuild Projects="$(ParentSolutionFile)">
<Output TaskParameter="TargetOutputs" ItemName="Assemblies" />
</MSBuild>
<Message Text="%(Assemblies.Identity)" />
<Copy SourceFiles="%(Assemblies.Identity)" DestinationFolder="$(MSBuildProjectDirectory)Binary" OverwriteReadOnlyFiles="True" SkipUnchangedFiles="True" />
</Target>
Каким будет предпочтительный способ копирования всех двоичных файлов вместе с необходимыми зависимостями в общую выходную папку?
2 ответа:
Разве переопределение OutputPath не делает трюк в одиночку?
<MSBuild Projects="$(ParentSolutionFile)" Properties="OutputPath=$(MSBuildProjectDirectory)\Binary"> <Output TaskParameter="TargetOutputs" ItemName="Assemblies" /> </MSBuild>
И оставить задачу копирования все вместе?
Процесс сборки поместит конечный результат в каталог, представленный OutputPath - по крайней мере, если вы создаете проекты c#. Для C/C++ внутренняя структура и имена переменных совершенно разные.
Таким образом, теоретически можно передать путь вывода в MsBuild-задаче, которая строит решение.<MsBuild Projects="$(ParentSolutionFile)" Properties="OutputPath=$(MSBuildProjectDirectory)\Binary"/>
Однако csproj-файлы безоговорочно перезапишут это значение следующим кодом:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <OutputPath>bin\Debug\</OutputPath>
Я решил эту проблему, введя свою собственную сборку система в каждом csproj-файле.
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="..\..\..\build\buildsystem.targets" />
Путь находится относительно csproj-файла. Абсолютный путь тоже хорош, или переменная. Фокус в том, чтобы заставить его работать на всех машинах разработки, а также на агентах сборки.
Теперь в buildsystem.цели, просто переопределите
OutputPath
так, как вам нравится. Опять же, хитрость заключается в том, чтобы гарантировать, что вы получите то же самое - или, по крайней мере, хорошо определенное - местоположение независимо от того, кто его строит (dev, build agent) и независимо от того, как сборка была инициирована (VS, command линия).Простой способ обработки различий состоит в том, чтобы импортировать условно.
<Import Project="..\..\..\build\buildsystem.targets" Condition="'$(BuildingInsideVisualStudio)'!='true'"/>
Это не даст вам никаких изменений, если вы инициируете сборку из VS и любые изменения, которые вы кодируете, если вы строите из командной строки.
-- Йеспер