具有不同构建配置的 MSBuild 项目,不使用 sln
MSBuild projects with different build-configs, without using sln
Related
我的 VS 解决方案中有两个项目,BookApp.Web
和 BookApp.Domain
。
BookApp.Web
引用 BookApp.Domain
.
BookApp.Web
具有以下构建配置:debug
、staging
、prod-eu
、prod-us
和 prod-as
。我们有三个用于生产的数据中心和一个暂存环境。
BookApp.Domain
目前只有两个构建配置,debug
.
在 Visual Studio 中构建解决方案时,我可以使用构建配置器来确保无论为 Web 项目选择什么构建配置,调试配置始终用于域项目。
但是,在我的持续集成服务器上使用 MSBuild 进行构建时,出现了问题。我在我的 rollout.msbuild 文件中使用它:
<MSBuild Projects="BookApp.Web\BookApp.Web.csproj" Properties="Configuration=Prod-us" />
当我 运行 这样做时,MSBuild 期望所有相关项目具有相同的生成配置。由于情况并非如此(并且不应该是 IMO),它失败并显示此错误消息:
The OutputPath property is not set for project 'BookApp.Domain.csproj'. Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Prod-us' Platform='AnyCPU'.
对 related question 的回答建议为每个构建配置创建单独的 .sln 解决方案,并 运行 使用 MSBuild 将其整合。对我来说这听起来不是个好主意。
将所有构建配置复制到 Domain 项目也不理想。
是否有更好的方法告诉 MSBuild 使用不同的构建配置?
看看这个答案,它解释了如何通过 MSBuild 任务将配置从一个项目传递到另一个项目,并使用配置的元数据为目标项目传递所需的配置
here
更新
我使用 class 库 (Sample.Domain) 和 ConsoleApplication(SampleApp.Console) 创建了一个解决方案。我在 SamplApp.Console 中添加了两个配置:prod-us;prod-eu,Sample.Domain 保留了 debug;release。
然后我更改了 ConsoleApplication 的 csproj 文件,如下所示:
项目参考资料
<!--<ItemGroup>
<ProjectReference Include="..\Sample.Domain\Sample.Domain.csproj">
<Project>{73e8a7fd-0a24-47c5-a527-7601550d4b92}</Project>
<Name>Sample.Domain</Name>
</ProjectReference>
</ItemGroup>-->
<ItemGroup>
<ProjectReference Include="..\Sample.Domain\Sample.Domain.csproj" >
<Targets>Build</Targets>
</ProjectReference>
</ItemGroup>
在传递给 MSBuild 的配置上添加了一个开关案例,以配置输出文件和参考文件的一些属性:
<Choose>
<When Condition="'$(Configuration)' != 'Debug'">
<PropertyGroup>
<OutputProperty>$(OutputPath)$(Configuration)</OutputProperty>
<FileCopy>$(OutputProperty)</FileCopy>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<OutputProperty>$(OutputPath)</OutputProperty>
<FileCopy>$(OutputProperty)</FileCopy>
</PropertyGroup>
</Otherwise>
</Choose>
创建了一个 Target 来切换传递给 MSBuild 的 Configuration,这样 Debug 就会将 Debug 传递给 Sample.Domain,其他一切都会传递给 Release
<Target Name="MultiConfiguration" >
<CreateProperty Value="Debug">
<Output TaskParameter="Value" PropertyName="LibConfiguration" Condition="'$(Configuration)' == 'Debug'"/>
</CreateProperty>
<CreateProperty Value="Release">
<Output TaskParameter="Value" PropertyName="LibConfiguration" Condition="'$(Configuration)' != 'Debug' "/>
</CreateProperty>
</Target>
构建目标使用我们添加的属性,因此引用文件的输出和副本将根据配置值具有正确的值
<!--Build Process-->
<Target Name="Build" DependsOnTargets="Clean;MultiConfiguration;ComputeProjectReference" >
<Csc Sources="@(Compile)" References="@(NewAssemblies)" TargetType="exe" OutputAssembly="$(OutputProperty)$(AssemblyName).exe"/>
</Target>
<Target Name="ComputeProjectReference" Inputs="@(ProjectReference)" Outputs="%(ProjectReference.Identity)__Forced">
<MSBuild Projects="@(ProjectReference)" Targets="%(ProjectReference.Targets)" Properties="Configuration=$(LibConfiguration);Platform=AnyCPU;OutputPath=bin$(LibConfiguration)">
<Output TaskParameter="TargetOutputs" ItemName="ResolvedProjectReferences"/>
</MSBuild>
</Target>
<Target Name="AfterProjectReference" AfterTargets="ComputeProjectReference">
<CreateItem Include="@(ResolvedProjectReferences)">
<Output TaskParameter="Include" ItemName="CopyFiles" />
</CreateItem>
<Copy SourceFiles="@(CopyFiles)" DestinationFolder="$(FileCopy)" SkipUnchangedFiles="false" />
<ItemGroup>
<NewAssemblies Include="$(OutputProperty)\%(CopyFiles.FileName)%(CopyFiles.Extension)" />
</ItemGroup>
</Target>
调用调试配置是这样完成的
msbuild SampleApp.Console.csproj
调用 (Release;prod-us;prod-eu;...) 是这样完成的
msbuild SampleApp.Console.csproj /p:Configuration="prod-us" /p:OutputPath="bin"
我确定它可以优化,并且可能更容易一些,但它确实有效。
Related
我的 VS 解决方案中有两个项目,BookApp.Web
和 BookApp.Domain
。
BookApp.Web
引用 BookApp.Domain
.
BookApp.Web
具有以下构建配置:debug
、staging
、prod-eu
、prod-us
和 prod-as
。我们有三个用于生产的数据中心和一个暂存环境。
BookApp.Domain
目前只有两个构建配置,debug
.
在 Visual Studio 中构建解决方案时,我可以使用构建配置器来确保无论为 Web 项目选择什么构建配置,调试配置始终用于域项目。
但是,在我的持续集成服务器上使用 MSBuild 进行构建时,出现了问题。我在我的 rollout.msbuild 文件中使用它:
<MSBuild Projects="BookApp.Web\BookApp.Web.csproj" Properties="Configuration=Prod-us" />
当我 运行 这样做时,MSBuild 期望所有相关项目具有相同的生成配置。由于情况并非如此(并且不应该是 IMO),它失败并显示此错误消息:
The OutputPath property is not set for project 'BookApp.Domain.csproj'. Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Prod-us' Platform='AnyCPU'.
对 related question 的回答建议为每个构建配置创建单独的 .sln 解决方案,并 运行 使用 MSBuild 将其整合。对我来说这听起来不是个好主意。
将所有构建配置复制到 Domain 项目也不理想。
是否有更好的方法告诉 MSBuild 使用不同的构建配置?
看看这个答案,它解释了如何通过 MSBuild 任务将配置从一个项目传递到另一个项目,并使用配置的元数据为目标项目传递所需的配置
here
更新
我使用 class 库 (Sample.Domain) 和 ConsoleApplication(SampleApp.Console) 创建了一个解决方案。我在 SamplApp.Console 中添加了两个配置:prod-us;prod-eu,Sample.Domain 保留了 debug;release。
然后我更改了 ConsoleApplication 的 csproj 文件,如下所示:
项目参考资料
<!--<ItemGroup>
<ProjectReference Include="..\Sample.Domain\Sample.Domain.csproj">
<Project>{73e8a7fd-0a24-47c5-a527-7601550d4b92}</Project>
<Name>Sample.Domain</Name>
</ProjectReference>
</ItemGroup>-->
<ItemGroup>
<ProjectReference Include="..\Sample.Domain\Sample.Domain.csproj" >
<Targets>Build</Targets>
</ProjectReference>
</ItemGroup>
在传递给 MSBuild 的配置上添加了一个开关案例,以配置输出文件和参考文件的一些属性:
<Choose>
<When Condition="'$(Configuration)' != 'Debug'">
<PropertyGroup>
<OutputProperty>$(OutputPath)$(Configuration)</OutputProperty>
<FileCopy>$(OutputProperty)</FileCopy>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<OutputProperty>$(OutputPath)</OutputProperty>
<FileCopy>$(OutputProperty)</FileCopy>
</PropertyGroup>
</Otherwise>
</Choose>
创建了一个 Target 来切换传递给 MSBuild 的 Configuration,这样 Debug 就会将 Debug 传递给 Sample.Domain,其他一切都会传递给 Release
<Target Name="MultiConfiguration" >
<CreateProperty Value="Debug">
<Output TaskParameter="Value" PropertyName="LibConfiguration" Condition="'$(Configuration)' == 'Debug'"/>
</CreateProperty>
<CreateProperty Value="Release">
<Output TaskParameter="Value" PropertyName="LibConfiguration" Condition="'$(Configuration)' != 'Debug' "/>
</CreateProperty>
</Target>
构建目标使用我们添加的属性,因此引用文件的输出和副本将根据配置值具有正确的值
<!--Build Process-->
<Target Name="Build" DependsOnTargets="Clean;MultiConfiguration;ComputeProjectReference" >
<Csc Sources="@(Compile)" References="@(NewAssemblies)" TargetType="exe" OutputAssembly="$(OutputProperty)$(AssemblyName).exe"/>
</Target>
<Target Name="ComputeProjectReference" Inputs="@(ProjectReference)" Outputs="%(ProjectReference.Identity)__Forced">
<MSBuild Projects="@(ProjectReference)" Targets="%(ProjectReference.Targets)" Properties="Configuration=$(LibConfiguration);Platform=AnyCPU;OutputPath=bin$(LibConfiguration)">
<Output TaskParameter="TargetOutputs" ItemName="ResolvedProjectReferences"/>
</MSBuild>
</Target>
<Target Name="AfterProjectReference" AfterTargets="ComputeProjectReference">
<CreateItem Include="@(ResolvedProjectReferences)">
<Output TaskParameter="Include" ItemName="CopyFiles" />
</CreateItem>
<Copy SourceFiles="@(CopyFiles)" DestinationFolder="$(FileCopy)" SkipUnchangedFiles="false" />
<ItemGroup>
<NewAssemblies Include="$(OutputProperty)\%(CopyFiles.FileName)%(CopyFiles.Extension)" />
</ItemGroup>
</Target>
调用调试配置是这样完成的 msbuild SampleApp.Console.csproj
调用 (Release;prod-us;prod-eu;...) 是这样完成的 msbuild SampleApp.Console.csproj /p:Configuration="prod-us" /p:OutputPath="bin"
我确定它可以优化,并且可能更容易一些,但它确实有效。