Microsoft.Common.CurrentVersion.targets 之上的新语言目标

Target for new language on top of Microsoft.Common.CurrentVersion.targets

我正在编写一个简单的扩展以允许 MSBuild 编译 solidity 源文件。

我的目标是,当我的 solidproj 被编译时,它会运行特定的可执行文件,该可执行文件会生成多个 binabi 文件,这些文件应该被复制到目标目录。这听起来很容易,但实际上并非如此。

我目前有以下目标:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...

  <Import Project="$(MSBuildToolsPath)\Microsoft.Common.CurrentVersion.targets" />
  <Target Name="CreateManifestResourceNames" />
  <Target Name="CoreCompile">
    <Exec Command='$(RunCommand) "-o @(OutDir) @(SolCompile)" $(RunCommandArguments)' WorkingDirectory="$(RunWorkingDirectory)" />
  </Target>
</Project>

它几乎可以工作,除了它希望编译单个 exe 文件

<!-- Copy the build product (.dll or .exe). -->
<Copy
    SourceFiles="@(IntermediateAssembly)"
    DestinationFolder="$(OutDir)"
    SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
    OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
    Retries="$(CopyRetryCount)"
    RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
    UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
    UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
    Condition="'$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'"
        >

  <Output TaskParameter="DestinationFiles" ItemName="MainAssembly"/>
  <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>

</Copy>

Error MSB3030 Could not copy the file "obj\Debug\Solidity9.exe" because it was not found. Solidity9 C:\Program Files (x86)\Microsoft Visual Studio17\Professional\MSBuild.0\Bin\Microsoft.Common.CurrentVersion.targets 4118

如何让它将这个特定扩展的所有内容复制到输出中?

整个项目在githubhere.

我最终从头开始创建所有构建步骤:

  <ItemGroup>
    <CopyUpToDateMarker Include="$([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', '$(IntermediateOutputPath)', '$(MSBuildProjectFile).CopyComplete'))" />
  </ItemGroup>

  <UsingTask
    TaskName="GetOutdatedFiles"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >

    <ParameterGroup>
      <FileList ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
      <UpToDateMarker ParameterType="System.String" Required="true" />
      <Result ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System"/>
      <Code Type="Fragment" Language="cs">
        <![CDATA[
          var modifiedFiles = new List<ITaskItem>();
          if(!File.Exists(UpToDateMarker))
          {
            Result = FileList;
          }
          else 
          {
            DateTime markerTimeStamp = File.GetLastWriteTime(UpToDateMarker);
            Result = FileList.Where(file => DateTime.Parse(file.GetMetadata("ModifiedTime")) > markerTimeStamp).ToArray();
          }
          ]]>
      </Code>
    </Task>
  </UsingTask>

  <Target Name="Build" DependsOnTargets="CoreBuild;AfterBuild" />

  <Target Name="CoreBuild">
    <Error Condition="'$(OutDir)' == ''" Text="The OutDir property is missing" />
    <Error Condition="'$(IntermediateOutputPath)' == ''" Text="The IntermediateOutputPath property is missing" />

    <GetOutdatedFiles FileList="@(SolCompile)" UpToDateMarker="@(CopyUpToDateMarker)">
      <Output TaskParameter="Result" ItemName="ChangedFiles"/>
    </GetOutdatedFiles>

    <Exec Command='$(RunCommand) "%(ChangedFiles.Identity)" -o "$(IntermediateOutputPath)" $(RunCommandArguments)' WorkingDirectory="$(RunWorkingDirectory)" Condition="'@(ChangedFiles)' != ''"/>
  </Target>

  <Target Name="AfterBuild">
    <ItemGroup>
      <BinFiles Include="$(IntermediateOutputPath)/*.bin"/>
      <AbiFiles Include="$(IntermediateOutputPath)/*.abi"/>
    </ItemGroup>

    <Copy SourceFiles="@(BinFiles)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true">
      <Output TaskParameter="CopiedFiles" ItemName="BinFilesCopiedInThisBuild"/>
    </Copy>
    <Copy SourceFiles="@(AbiFiles)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true">
      <Output TaskParameter="CopiedFiles" ItemName="AbiFilesCopiedInThisBuild"/>
    </Copy>
    <Touch Files="@(CopyUpToDateMarker)" AlwaysCreate="true" Condition="'@(BinFilesCopiedInThisBuild)'!='' or '@(AbiFilesCopiedInThisBuild)'!=''" />
  </Target>

  <Target Name="Clean">
    <Delete Files="@(CopyUpToDateMarker)" />
    <RemoveDir Directories="$(OutDir)" />
  </Target>

  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />

仍然需要解决传递依赖的问题,但这是另一个问题