从.sln en-asse到其各自的输出目录构建通配符驱动的项目组

时间:2019-06-18 11:28:29

标签: c# visual-studio msbuild visual-studio-2017 visual-studio-2017-build-tools

我们有一个通过VisualStudio2017创建和维护的解决方案,其中将我们的 .csprojs 放置在虚拟文件夹内,如下所示:

Solution.sln
  \- VirtualFolder1
       \- Foo.Common.Bar.csproj -> Bar\bin
       \- Foo.Common.Ping.csproj -> Ping\bin
       \- Foo.Common.Pong.csproj -> Pong\bin
  \- VirtualFolder2
       \- Foo.Utils.Bar.csproj -> Utils.Bar\bin
       \- Foo.Utils.Ping.csproj -> Utils.Ping\bin
       \- Foo.Utils.Pong.csproj -> Utils.Pong\bin

按预期,每个.csproj文件已经包含一个部分,用于定义输出路径应位于的位置:

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>[Bar/bin or Ping/bin etc]</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <LangVersion>7.1</LangVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>[Bar/bin or Ping/bin etc]</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <LangVersion>7.1</LangVersion>
  </PropertyGroup>

我们要将所有 .Common .csproj .Utils .csproj 项目都构建到各自的输出文件夹无需在我们的msbuild-script(由JenkinsCI btw调用)中一一指定。为了达到这一目的,我们尝试:

<ItemGroup>      
  <ALL_PROJECTS_IN_SOLUTION_EXCEPT_TESTS
    Include="$(_codeFolderpath)\**\*.csproj"
  />
</ItemGroup>

<MSBuild
  Projects="@(ALL_PROJECTS_IN_SOLUTION_EXCEPT_TESTS)"
  Properties="Platform=$(Platform);Configuration=$(Configuration)"
  BuildInParallel="true"
/>

但这会导致我们所有.csproj出现以下错误:

The OutputPath property is not set for project [...].csproj

鉴于OutputPath是在我们的.csproj文件中定义的(如上所示),这很奇怪。

如果我们指定'Output'属性,那么问题当然就解决了,但是我们真正想要的是这些项目将自己输出到各自的适当输出目录中(如上所示)。如何实现这一目标?

1 个答案:

答案 0 :(得分:1)

看起来您有一个单独的项目(构建项目),用于构建.Common .csproj和.Utils .csproj项目。您上面编写的脚本是在Build Project的目标中定义的。 (希望我没有误会。)

根据您的错误消息The OutputPath property is not set...,Common。 .csproj或Utils中没有定义OutputPath属性。 .csproj。

如果是这样,我建议您使用这样的文件夹结构:

Solution.sln
  \- VirtualFolder1
       \- Foo.Common.Bar.csproj -> Foo.Common.Bar\bin
       \- Foo.Common.Ping.csproj -> Foo.Common.Ping\bin
       \- Foo.Common.Pong.csproj -> Foo.Common.Pong\bin
  \- VirtualFolder2
       \- Foo.Utils.Bar.csproj -> Foo.Utils.Bar\bin
       \- Foo.Utils.Ping.csproj -> Foo.Utils.Ping\bin
       \- Foo.Utils.Pong.csproj -> Foo.Utils.Pong\bin

因为要获得所需的结构,我认为可能还有更复杂的工作:

1..csproj文件中没有OutputPath,我们可以在目录上方的目录中创建一个Directory.Build.props文件来控制输出路径。

2。在MSBuild任务中传递OutputPath属性。在这种情况下,您需要获取.common.csproj和.utils.csproj项目的别名,并添加以下条件:

<MSBuild
      Projects="@(ALL_PROJECTS_IN_SOLUTION_EXCEPT_TESTS)"
      Properties="Platform=$(Platform);Configuration=$(Configuration);OutputPath=xxx\ThirdName\bin"
      BuildInParallel="true"
      Condition="judge if the common.csproj files"
    />
    <MSBuild
      Projects="@(ALL_PROJECTS_IN_SOLUTION_EXCEPT_TESTS)" 
      Properties="Platform=$(Platform);Configuration=$(Configuration);OutputPath=xxx\SecondName.ThirdName\bin"
      BuildInParallel="true"
      Condition="judge if the utils.csproj files"
    />

因此,这两个方向都可能有助于实现您的特定目标,但是这项工作将远远超出我们的预期。

一种解决方法: 是什么原因必须将它们放在Utils.Bar\bin文件夹而不是Foo.Utils.Bar\bin文件夹中?后者是Foo.Utils.Bar.csproj文件的预定义属性。因此,我们可以轻松地使用$(ProjectDir)或$(ProjectName)来表示它。您可以创建一个Directory.Build.props文件,在下面添加脚本:

<Project>
 <PropertyGroup>
  <OutputPath>$(ProjectDir)bin\$(Configuration)</OutputPath>
</PropertyGroup>
</Project>

通过这种方式,在VS中加载项目文件时,您需要做的是build the solution。您不再需要构建Build项目。并且由于您使用的是我尚未尝试过的虚拟路径,因此也许可以使用<OutputPath>AbsolutePathOfMyOutput\$(ProjectName)bin\$(Configuration)</OutputPath>

更新 :(直到今天才注意到您所做的编辑。)

根据您的修改,您已在.csproj中设置了输出路径。

这里有两个建议:

1。如果使用VS ID构建它们:每次在VS IDE外部通过记事本或其他方式对xx.csproj进行一些修改之后,建议您在构建它们之前右键单击项目unload and reload the project file

2。请检查您收到的整个错误消息是否看起来像这样:

error : The OutputPath property is not set for project 'ConsoleApp1.csproj'.  Please check to make sure that
 you have specified a valid combination of Configuration and Platform for this project.  Configuration=''  Platform='An
yCPU'.

由于在OutputPath property中为PropertyGroupDebug|AnyCPU定义了Release|AnyCPU。如果尚未将相应的参数传递给msbuild.exe,则该过程将无法进行从这些ProppertyGroups中读取OutPutPath属性。

例如:您在Debug|AnyCPURelease|AnyCPU中定义OutPutPath。然后,您传递的Configuration and Platform的实际值是Debug|X86, or Null|AnyCPU or CustomDebug|AnyCPU,并且在这种Combination(PropertyGroup)中尚未定义OutPutPath时,会得到错误信息{{1} }。

要解决此问题:请确保您通过正确的配置,并且平台组合可以解决该问题。或在您实际使用的组合中定义OutPutPath。