Цель для нового языка поверх Microsoft.Common.CurrentVersion.targets

Я пишу простое расширение, позволяющее MSBuild компилировать исходные файлы Solidity.

Моя цель - когда мой solidproj компилируется, он запускает определенный исполняемый файл, который создает несколько файлов bin и abi, которые следует скопировать в целевой каталог. Звучит просто, однако на практике это не так.

В настоящее время у меня есть следующие цели:

<?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>

Ошибка MSB3030 Не удалось скопировать файл «obj\Debug\Solidity9.exe», так как он не найден. Solidity9 C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets 4118

Как я могу попросить его скопировать все это специальное расширение на вывод?

Весь проект находится на github здесь.


person Alex Zhukovskiy    schedule 28.03.2018    source источник


Ответы (1)


В итоге я создал все шаги сборки с нуля:

  <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" />

Еще нужно решить проблемы с транзитивными зависимостями, но это уже другой вопрос

person Alex Zhukovskiy    schedule 30.03.2018