【问题标题】:Use ProjectName when building an entire solution with MSBuild使用 MSBuild 构建整个解决方案时使用 ProjectName
【发布时间】:2018-10-01 13:55:00
【问题描述】:

而不是构建到默认的文件夹结构,就像

Solution.sln
Project1
    bin    <- project 1 output
    obj    <- project 1 intermediate output
Project2
    bin    <- project 2 output
    obj    <- project 2 intermediate output

我想像这样构建它

Solution.sln
bin    <- project 1 AND 2 output
obj
    Project1   <- project 1 intermediate output
    Project2   <- project 2 intermediate output

我可以的

msbuild "/p:OutputPath=../bin" "/p:IntermediateOutputPath=../obj/" Test123.sln

但是,使用"/p:IntermediateOutputPath=../obj/$(ProjectName)/" 不起作用。它不是为每个项目创建一个文件夹,而是创建一个字面上称为 $(ProjectName) 的文件夹(我读过大部分,但并非所有这些宏实际上都是 Visual Studio 的东西,而不是 MSBuild 魔术)。

构建时如何在属性值(例如IntermediateOutputPath)中使用项目特定值(例如ProjectName)?

(一些背景资料:

在解决方案级别拥有一个bin 文件夹可以节省不必要的输出文件复制,在大型解决方案中这些文件很快就会累积超过 100 MB。此外,它还可以保持源文件夹的清洁,因此它们可以是只读的。

我仍然想要单独的 obj 文件夹,因为谁知道里面有什么 - 不同项目的文件名可能相同。)

【问题讨论】:

  • 我怀疑您是否可以直接从命令行执行此操作而无需修改项目文件。但是,您的实际问题并不清楚:您是否只希望该单个 bin 目录用于命令行构建?还是总是? wrt 我读的最多,但并非所有这些宏实际上都是 Visual Studio 的东西,而不是 msbuild 魔术:不知道你从哪里得到的,但事实并非如此。您的问题似乎是 $(ProjectName) 作为文字字符串传递,并且不会被 msbuild 解释

标签: build msbuild solution


【解决方案1】:

您可以覆盖Microsoft.Common.targets 文件的CustomAfterMicrosoftCommonTargets 属性。它允许将自定义目标注入项目并执行一些操作。


构建过程的入口是Make.targets:

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"; DefaultTargets="EntryMSBuild">

    <ItemGroup>
        <Project Include="**\*.csproj"/>
    </ItemGroup>

    <Target Name="EntryMSBuild">

        <Message Text="-----Entry-----" Importance="high"/>
        <Message Text="    Rebuild    " Importance="high"/>
        <Message Text="-----Entry-----" Importance="high"/>

        <MSBuild Projects="@(Project)" Targets="rebuild" Properties="CustomBeforeMicrosoftCommonTargets=$(MSBuildThisFileDirectory)Setting.targets"/>
    </Target>

</Project>

Setting.targets 中为每个项目定义了IntermediateOutputPathOutputPath

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <PropertyGroup>
        <IntermediateOutputPath>..\Global\obj\$(MSBuildProjectName)</IntermediateOutputPath>
    </PropertyGroup>

    <PropertyGroup>
        <OutputPath>..\Global\bin\</OutputPath>
    </PropertyGroup>

</Project>

结果,你得到了想要的结构:

Solution.sln
bin    <- project 1 AND 2 output
obj
    Project1   <- project 1 intermediate output
    Project2   <- project 2 intermediate output

.net46.netstandard2.0 下的两个项目的解决方案上进行了测试。 MSBuild15.6.82.30579


您不需要将自定义目标存储在 C:\Program Files[(x86)]\microsoft visual studio\2017\xxx\msbuild\15.0 或任何预定义路径下。您覆盖 CustomBeforeMicrosoftCommonTargets 已在 Microsoft.Common.targets 中定义并默认注入项目的属性。

来自Microsoft.Common.targets评论:

此文件定义了 .NET 标准构建过程中的步骤 项目。它包含所有常见的步骤 不同的 .NET 语言,例如 Visual Basic 和 Visual C#。

【讨论】:

  • 看起来很有希望,但如果我正确理解这一点(和that),我需要将自定义目标放在 `c:\program files[ (x86)]\microsoft visual studio\2017\ xxx\msbuild\15.0`,这意味着想要构建解决方案的每个人都需要对该文件夹的写入权限,并且它会影响机器上构建的所有项目。那是对的吗?有没有办法在不更改 msbuild 安装文件夹中的任何内容的情况下做到这一点?
  • 您可以在第 25 页的Supplement to Inside the Microsoft Build Engine book 中找到许多有用的信息。
  • 让它工作。我的错误是你设置属性的路径显然必须是绝对的,比如msbuild "/p:CustomBeforeMicrosoftCommonTargets=d:\dev\...\Setting.targets" Solution123.sln
猜你喜欢
  • 2012-12-16
  • 2011-05-08
  • 1970-01-01
  • 2011-09-09
  • 2015-11-15
  • 2012-09-21
  • 2010-12-13
  • 2023-03-17
  • 1970-01-01
相关资源
最近更新 更多