【问题标题】:How to create a MSBuild Target that will only run if necessary如何创建仅在必要时运行的 MSBuild 目标
【发布时间】:2015-10-06 03:25:23
【问题描述】:

我一直在尝试使用 MSBuild 创建自定义目标。我目前正在尝试添加对使用 JAWS 脚本编译器编译文件的支持。这是我目前所拥有的。

Scripts.props

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <DEVDOCS_DIR>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\..\..\..\DevDocs'))</DEVDOCS_DIR>
        <BUILTIN_MASTER>$(DEVDOCS_DIR)\jsd\enu\builtin_master.jsd</BUILTIN_MASTER>
        <TOOLBOX_DIR>$(DEVDOCS_DIR)\Toolbox</TOOLBOX_DIR>
        <JAWS_VER>17.0</JAWS_VER>
        <!-- If perl.exe is not in your path, set the following variable to the full path and file name of perl.exe.
        Optionally you could set the PERL_EXE environment variable. -->
        <PERL_EXE Condition="'$(PERL_EXE)'==''">perl.exe</PERL_EXE>
        <!-- If scompile.exe is not in your path, set the following variable to the full path and file name of scompile.exe.
        Optionally you could set the SCOMPILE_EXE environment variable. -->
        <SCOMPILE_EXE Condition="'$(SCOMPILE_EXE)'==''">scompile.exe</SCOMPILE_EXE>
    </PropertyGroup>
</Project>

Scripts.targets

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="GenerateBuiltinJSD">
        <Exec Command="&quot;$(PERL_EXE)&quot; compilejsd.pl -v Jaws/$(JAWS_VER) -o &quot;$(MSBuildProjectDirectory)\builtin.jsd&quot; &quot;$(BUILTIN_MASTER)&quot;" WorkingDirectory="$(TOOLBOX_DIR)" />
    </Target>
    <Target Name="CompileScripts">
        <Exec Command="&quot;$(SCOMPILE_EXE)&quot; /d &quot;%(ScriptSourceFiles.FullPath)&quot;" Outputs="%(ScriptSourceFiles.RootDir)%(ScriptSourceFiles.Directory)%(ScriptSourceFiles.Filename).jsb" WorkingDirectory="$(MSBuildProjectDirectory)" />
    </Target>
    <Target Name="Clean">
        <ItemGroup>
            <JSBFiles Include="$(MSBuildProjectDirectory)\*.jsb" />
        </ItemGroup>
        <Delete Files="@(JSBFiles)" />
    </Target>
    <Target Name="Build">
        <CallTarget Targets="GenerateBuiltinJSD;CompileScripts" />
    </Target>
</Project>

Scripts.vcxproj

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <ItemGroup>
    <ScriptSourceFiles Include="Default.jss" />
  </ItemGroup>
  <ItemGroup>
    <ScriptMessageFiles Include="Default.jsm" />
  </ItemGroup>
  <ItemGroup>
    <ScriptHeaderFiles Include="HJConst.jsh" />
  </ItemGroup>
  <ItemGroup>
    <ScriptDocumentationFiles Include="default.jsd" />
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{B2C4363D-D228-425D-AB04-38997EA229C0}</ProjectGuid>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Label="Configuration">
    <PlatformToolset>v120</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="PropertySheets">
    <Import Project="Scripts.props" />
  </ImportGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <Import Project="$(MSBuildProjectDirectory)\Scripts.targets" />
</Project>

这在一定程度上有效。问题是,当我进行构建时,它会重新构建所有脚本文件,即使相关的源文件没有更改。

我的问题是如何修改它以便仅在必要时构建每个文件?

【问题讨论】:

    标签: visual-studio-2013 msbuild


    【解决方案1】:

    您询问的功能称为Incremental Build,希望MSBuild 实用程序支持它。如果没有更改源文件,您所要做的就是为您计划跳过的目标指定输入和输出。

    为目标指定输入和输出:使用目标元素的输入和输出属性。例如:

    <Target Name="Build"
        Inputs="@(CSFile)"
        Outputs="hello.exe">
    

    MSBuild 可以将输入文件的时间戳与输出文件的时间戳进行比较,并确定是跳过、构建还是部分重建目标。

    要成功完成任务,您必须正确生成目标的输入输出。这可以通过使用特殊目标来实现,该目标将填充所需的项目,或者您可以显式使用转换:

    <Target Name="CompileScripts"
            Inputs="@(ScriptSourceFiles)"
            Outputs="@(ScriptSourceFiles->'%(RootDir)%(Directory)%(FileName).jsb')">
        <Exec Command="&quot;$(SCOMPILE_EXE)&quot; /d &quot;%(ScriptSourceFiles.FullPath)&quot;" Outputs="%(ScriptSourceFiles.RootDir)%(ScriptSourceFiles.Directory)%(ScriptSourceFiles.Filename).jsb" WorkingDirectory="$(MSBuildProjectDirectory)" />
    </Target>
    

    (另请注意,您应该使用$(OutDir) 属性而不是引用%(RootDir) 项目元数据,因为它更直接,但您应该确保在执行目标时指定并存在此属性)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-08
      • 2021-09-30
      • 2019-12-12
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多