2016-07-26 46 views
1

我正在创建一个自定义的MSBuild脚本,该脚本旨在将Import编辑到多个C#项目中。该脚本根据Platform属性添加了要复制的多个属性,引用和文件,以使最终输出能够利用一组本机二进制文件。换句话说,它会根据平台选择正确的本机二进制文件和相关数据。为不支持的平台引发错误

目前,我正在做这样的事情:

<PropertyGroup Condition="'$(Platform)' == 'x86'"> 
    <bin1>..\..\lib\mybinaries\x86\bin1.dll</bin1> 
    <bin2>..\..\lib\mybinaries\x86\bin2.dll</bin2> 
</PropertyGroup> 
<PropertyGroup Condition="'$(Platform)' == 'x64'"> 
    <bin1>..\..\lib\mybinaries\x64\bin1.dll</bin1> 
    <bin2>..\..\lib\mybinaries\x64\bin2.dll</bin2> 
</PropertyGroup> 

<ItemGroup> 
    <Reference Include="bin2.dll"> 
    <SpecificVersion>False</SpecificVersion> 
    <HintPath>$(bin2)</HintPath> 
    <Private>True</Private> 
    </Reference> 
</ItemGroup> 
<ItemGroup> 
    <None Include="$(bin1)"> 
    <CopyToOutputDirectory>Always</CopyToOutputDirectory> 
    </None> 
</ItemGroup> 

当一个项目内建有UNSUPPORT平台(如任何CPU),我想构建引发错误。我怎样才能做到这一点?

我调查了一下,看看是否有办法在构建目标之外引发错误,但我无法找到它。即使我确实找到了一个,我也会担心如果开发者以某种方式让他们的系统选择了不受支持的平台,会发生什么。 (例如Visual Studio可能会开始拒绝打开该项目。)

我可以覆盖BeforeBuild目标,但如果导入此文件的C#项目会覆盖该目标本身,则会崩溃。 (或者我的会覆盖他们的,这取决于Import<Target Name="BeforeBuild">的顺序。)在这种情况下,不会引发错误。这使得它非常脆弱,而且不够健壮。

我该如何做到这一点,使用户不可能打破它?还是有一个完全不同的替代方法,我可以考虑包括有条件的二进制文件?

+0

也许你正在寻找类似'<目标名称= “MyPlatformCheck” BeforeTargets = “生成”/>'?这将在构建之前运行,并使用内置的msbuild功能和自定义名称,因此很难覆盖。可能有更好的目标可以使用,例如'PrepareBuild'左右,但我不知道从头顶上的那些人。 – stijn

+0

@stijn我没有意识到有可能让Build取决于自定义任务。如果你能把它变成答案,我会接受它。 – jpmc26

回答

2

一种惯用的方法是要么使用Target elementBeforeTargets属性,或使用Project elementInitialTargets属性。因此,您可以使用所需的所有逻辑编写自定义目标,然后自动调用它。这也使得用户难以打破它。

如果您使用BeforeTargets,您会希望找到一个在构建中提前调用的目标,最好是Build和Clean。要弄清楚最简单的方法是使用诊断日志(命令行中的msbuild /v:d myproject)构建项目。然后你会看到你不是唯一想要检查平台有效性的人:第一个要求C++项目的目标是微软自己的_CheckForInvalidConfigurationAndPlatform。所以,如果你使用

<Target Name="PlatformCheck" BeforeTargets="_CheckForInvalidConfigurationAndPlatform"> 
    <Error Text="Bad Platform" Condition="'$(bin1)' == ''"/> 
</Target> 

然后PlatformCheck将成为第一个被称为的目标之一。

或者,如果你喜欢的另一种方式,那么它的

<Project ToolsVersion="4.0" xmlns="..." InitialTargets="PlatformCheck"> 
+0

更新版本的MSBuild的任务列表可以在这里找到:https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-task-reference。我结束了使用'AssignProjectConfiguration'。尝试依赖'Build'在这个过程中太迟了;你会在这之前丢失DLL错误。 – jpmc26

1

我会用一个带有错误任务的目标。但是如果你想避免拥有一个自定义的Target,你可以使用一个肮脏的技巧来让构建突破一个属性,如果你只是定义一个肯定会失败的路径。

这将是类似的东西:

<PropertyGroup Condition="'$(Platform)' == 'x86'"> 
    <bin1>..\..\lib\mybinaries\x86\bin1.dll</bin1> 
    <bin2>..\..\lib\mybinaries\x86\bin2.dll</bin2> 
</PropertyGroup> 
<PropertyGroup Condition="'$(Platform)' == 'x64'"> 
    <bin1>..\..\lib\mybinaries\x64\bin1.dll</bin1> 
    <bin2>..\..\lib\mybinaries\x64\bin2.dll</bin2> 
</PropertyGroup> 
<PropertyGroup Condition="'$(bin1)' == ''"> 
    <bin1>ERROR: platform '$(Platform)' is not supported, please set it to x86 or x64</bin1> 
</PropertyGroup> 

构建将失败,因为这不是一个有效的路径,并同时生成日志将是混乱的,它将包含的文件 - 这里面明确信息未找到。 :)

同样,我建议你定义一个目标......