Search code examples
msbuildnuget.net-standardeditorconfig

How to copy contentFiles of NuGet package references via MSBuild Copy task


We have several repositories and each one has its own .editorconfig. Obviously, these are not synced, which is why I would like to distribute the .editorconfig from our framework solution (along with other files) via NuGet package to all our repositories/solutions and copy it via a simple Copy build Task to the solution directory.

I attempted to do the following:

Create a project "EditorConfigDistribution", which is supposed to contain the master .editorconfig file.

<Project Sdk="Microsoft.NET.Sdk">
  ...
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <NoDefaultExcludes>true</NoDefaultExcludes>
  </PropertyGroup>

   <ItemGroup>
    <Content Include=".editorconfig">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Pack>true</Pack>
      <PackageCopyToOutput>false</PackageCopyToOutput>
      <PackagePath>contentFiles\any\any\content</PackagePath>
    </Content>
  </ItemGroup>
</Project>

This all works as expected and I do get the desired .editorconfig file in my project from the other solutions and it is referenced as shortcut in a folder content/.editorconfig (see EditorConfigConsumer Project Structure). The file is only a reference to C:\Users\<user>\.nuget\packages\editorconfigdistribution\1.0.0\contentFiles\any\any\content\.editorconfig.

Now, I want to copy that .editorconfig file via build task:

<Project Sdk="Microsoft.NET.Sdk">
  ...
  <ItemGroup>
    <PackageReference Include="EditorConfigDistribution" Version="1.0.0">
    </PackageReference>
  </ItemGroup>

  <Target Name="CopyEditorConfig" BeforeTargets="BeforeBuild">
    <ItemGroup>
      <EditorConfigFileToCopy Include="$(MSBuildProjectDirectory)\content\.editorconfig" />
    </ItemGroup>
    <Copy SourceFiles="@(EditorConfigFileToCopy)" DestinationFolder="$(MSBuildProjectDirectory)\.." SkipUnchangedFiles="true" UseHardlinksIfPossible="false" />
  </Target>
</Project>

However, I do get the following error:

Error MSB3030: Could not copy the file "C:\Users\weberma9\source\repos\<some_path>\EditorConfigConsumer\content\.editorconfig" because it was not found. (20, 5)

I can understand that the file (since it is a shortcut) cannot be found, but I just cannot figure out a way to reference that shortcut correctly in my build task. What do I need to change in that line <EditorConfigFileToCopy Include="$(MSBuildProjectDirectory)\content\.editorconfig" />?

Of course, if you have better approaches to my general problem - I'm glad to hear about it.


Solution

  • I was able to find a solution for my problem: I not only provide the .editorconfig, but also the Copy-Build task via my EditorConfigDistribution project, which looks like this now:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <NoDefaultExcludes>true</NoDefaultExcludes>
      </PropertyGroup>
    
      <ItemGroup>
        <None Include="..\..\.editorconfig">
          <Link>Rules\.editorconfig</Link>
          <Pack>true</Pack>
          <PackageCopyToOutput>false</PackageCopyToOutput>
          <PackagePath>Rules\</PackagePath>
        </None>
      </ItemGroup>
    
      <ItemGroup>
        <None Include="build\**">
          <Pack>true</Pack>
          <PackageCopyToOutput>false</PackageCopyToOutput>
          <PackagePath>build\</PackagePath>
        </None>
      </ItemGroup>
    </Project>
    

    The .props file is straightforward and due to the convention that <package_id>.props and <package_id>.target are added to projects that consume the package (see Include MSBuild props and targets in a package), it will always be executed before 'BeforeBuild'.

    EditorConfigDistribution.props (placed in build folder):

    <Project>
      <Target Name="CopyEditorConfig" BeforeTargets="BeforeBuild">
        <ItemGroup>
          <EditorConfigFilesToCopy Include="$(MSBuildThisFileDirectory)..\Rules\.editorconfig" />
        </ItemGroup>
        <Copy SourceFiles="@(EditorConfigFilesToCopy)" DestinationFolder="$(SolutionDir).." SkipUnchangedFiles="true" UseHardlinksIfPossible="false" />
      </Target>
    </Project>