在Visual Studio中没有目标的项目文件的Directory.Build.targets

时间:2019-03-17 16:03:42

标签: visual-studio msbuild

如果我的项目文件没有任何目标,并且我在适当的目录中具有Directory.Build.targets文件(具有适当的目标),则Visual Studio无法构建项目。 VS的版本为2019RC,但我认为这不是特定版本的问题

那是预期的行为,为什么?

UPDATE-项目的完整结构。通常,这是从“ Power Query SDK”的“数据连接器项目”模板-https://marketplace.visualstudio.com/items?itemName=Dakahn.PowerQuerySDK

修改的项目

项目名称为PQExtensionTest。它具有典型的文件夹结构-PQExtensionTest解决方案目录,位于PQExtensionTest.sln文件中,以及带有PQExtensionTest.mroj和Directory.build.targets文件的PQExtensionTest项目目录。

PQExtensionTest.sln文件:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2046
MinimumVisualStudioVersion = 10.0.40219.1
Project("{4DF76451-A46A-4C0B-BE03-459FAAFA07E6}") = "PQExtensionTest", "PQExtensionTest\PQExtensionTest.mproj", "{6DEC2A2E-C380-4701-AA12-5052284223E4}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|x86 = Debug|x86
        Release|x86 = Release|x86
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {6DEC2A2E-C380-4701-AA12-5052284223E4}.Debug|x86.ActiveCfg = Debug|x86
        {6DEC2A2E-C380-4701-AA12-5052284223E4}.Debug|x86.Build.0 = Debug|x86
        {6DEC2A2E-C380-4701-AA12-5052284223E4}.Release|x86.ActiveCfg = Release|x86
        {6DEC2A2E-C380-4701-AA12-5052284223E4}.Release|x86.Build.0 = Release|x86
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
    GlobalSection(ExtensibilityGlobals) = postSolution
        SolutionGuid = {50EB6857-946A-4D05-B65C-B99E4D39BEDD}
    EndGlobalSection
EndGlobal

PQExtensionTest.mroj文件:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ProjectGuid>{6dec2a2e-c380-4701-aa12-5052284223e4}</ProjectGuid>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="PQExtensionTest.pq">
      <SubType>Code</SubType>
    </Compile>
    <Content Include="PQExtensionTest.query.pq">
      <SubType>Code</SubType>
    </Content>
  </ItemGroup>
</Project>

Directory.Build.targets文件:

<Project DefaultTargets="BuildExtension" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{a9cd1ca9-92e5-493d-8065-377910605c30}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <RootNamespace>MyRootNamespace</RootNamespace>
    <AssemblyName>MyAssemblyName</AssemblyName>
    <EnableUnmanagedDebugging>False</EnableUnmanagedDebugging>
    <AllowNativeQuery>False</AllowNativeQuery>
    <AsAction>False</AsAction>
    <FastCombine>False</FastCombine>
    <ClearLog>False</ClearLog>
    <ShowEngineTraces>False</ShowEngineTraces>
    <ShowUserTraces>False</ShowUserTraces>
    <LegacyRedirects>False</LegacyRedirects>
    <SuppressRowErrors>False</SuppressRowErrors>
    <SuppressCellErrors>False</SuppressCellErrors>
    <MaxRows>1000</MaxRows>
    <ExtensionProject>Yes</ExtensionProject>
    <Name>PQExtensionTest</Name>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
    <DebugSymbols>false</DebugSymbols>
    <!--Should be true, fix this when the debugger is implemented -->
    <OutputPath>bin\Debug\</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
    <DebugSymbols>false</DebugSymbols>
    <OutputPath>bin\Release\</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="mscorlib" />
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <UsingTask TaskName="BuildExtension" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
    <ParameterGroup>
      <InputDirectory ParameterType="System.String" Required="true" />
      <OutputFile ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="System.IO.Compression" />
      <Reference Include="System.IO.Compression.FileSystem" />
      <Using Namespace="System.Globalization" />
      <Using Namespace="System.IO.Compression " />
      <Code Type="Fragment" Language="cs"><![CDATA[    
    using(FileStream fileStream = File.Create(OutputFile))
    using(ZipArchive archiveOut = new ZipArchive(fileStream, ZipArchiveMode.Create, false))
    {
        foreach(string fullPath in Directory.EnumerateFiles(InputDirectory))
        {
            string filename = Path.GetFileName(fullPath);

            archiveOut.CreateEntryFromFile(fullPath, filename, CompressionLevel.Optimal);
        }
    }
]]></Code>
    </Task>
  </UsingTask>
  <Target Name="BuildExtension" DependsOnTargets="ExtensionClean">
    <ItemGroup>
      <PQFiles Include="@(Compile)" Condition="'%(Extension)' == '.pq'" />
    </ItemGroup>
    <ItemGroup>
      <NonPQFiles Include="@(Compile)" Condition="'%(Extension)' != '.pq'" />
    </ItemGroup>
    <MakeDir Directories="$(IntermediateOutputPath)" />
    <MakeDir Directories="$(OutputPath)" />
    <Copy SourceFiles="@(NonPQFiles)" DestinationFolder="$(IntermediateOutputPath)" />
    <Copy SourceFiles="@(PQFiles)" DestinationFiles="@(PQFiles->'$(IntermediateOutputPath)%(RecursiveDir)%(FileName).m')" />
    <BuildExtension InputDirectory="$(IntermediateOutputPath)" OutputFile="$(OutputPath)\$(ProjectName).mez" />
  </Target>
  <Target Name="ExtensionClean">
    <!-- Remove obj folder -->
    <RemoveDir Directories="$(BaseIntermediateOutputPath)" />
    <!-- Remove bin folder -->
    <RemoveDir Directories="$(OutputPath)" />
<Message Text="MyM: $(aProperty)" />
   </Target>

1 个答案:

答案 0 :(得分:1)

  

那是预期的行为,为什么?

要视情况而定。

1 。首先,根据this doc,Directory.Build.targets仅在Microsoft.Common.props调用后才能工作。

因此,如果您尚未在项目文件中导入Microsoft.Common.props(targets),则构建将失败。

在这种情况下,这是我们无法在项目文件中没有目标的情况下构建项目的预期行为。

2 。正如您提到的I have Directory.Build.targets file (with appropriate targets),请确保您的项目文件中有<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />。没有它,构建将无法适应您的情况(项目文件中没有自定义目标)。

确保已在项目文件中导入Microsoft.CSharp.targets。对于Directory.Build.Targets中的目标,添加标签<BeforeTargets><AfterTargets>以使其起作用。

Directory.Build.Targets的示例:

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
...
  </PropertyGroup>
  <Target Name="Test" AfterTargets="build">
    <Message Text="..."/>
  </Target>
</Project>

只有满足这些条件后,您才能成功构建自己的情况。因此,请进行检查。

更新:

对于自定义.proj文件。我们必须直接在.proj文件中定义一个目标,或者将目标与其他目标文件一起导入。

由于proj文件中没有目标,并且导入的目标中也没有目标将运行,因此msbuild将引发错误MSB4040(Project中没有目标)。因为如果没有要运行的目标,则对于msbuild进程没有意义。这是设计使然。

Update2

在test.sln中,我在解决方案目录中有一个Directory.build.props:

<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="Today">
    <Message Text="JustForTest"/>
  </Target>
</Project>

在项目目录中有一个非常简单的.csproj文件:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
</Project>

如果我构建test.csproj,则该构建可以成功并运行“今日目标”以输出“ JustForTest”。而且,如果我评论了Import Microsoft.Common.Props,则MSB4040的构建将失败。原因是在.net中,如果没有Microsoft.Common.Props,则不能隐式导入Directory.build.props 。

Update3

我已经检查了microsoft.common.props和microsoft.Csharp.targets的内容。 在M.C.P文件中,有关于Directory.build.props的定义和调用。在M.C.T文件中时,它定义了C#的标准构建过程。因此,我同意您的项目文件中一定有一个名为Directory.build.props的东西,但不能是microsoft.Csharp.targets或microsoft.VB.targets。 enter image description here