如果我的项目文件没有任何目标,并且我在适当的目录中具有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>
答案 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。