Skip to content

Conversation

@jonathanpeppers
Copy link
Member

Context: https://github.com/jonathanpeppers/android-pipe/blob/c313259b782bff40204e1a1ca988659dc7d3180b/csharp/Benchmark.csproj#L25

When using BenchmarkDotNet in a .NET 6 Android app for the first time,
I hit this build error:

Microsoft.Android.Sdk.AssemblyResolution.targets(106,5): error XAPRAS7009: System.InvalidOperationException: PE image does not have metadata.
at System.Reflection.PortableExecutable.PEReader.GetMetadataBlock()
at System.Reflection.PortableExecutable.PEReader.GetMetadata()
at System.Reflection.Metadata.PEReaderExtensions.GetMetadataReader(PEReader peReader, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)
at System.Reflection.Metadata.PEReaderExtensions.GetMetadataReader(PEReader peReader)
at Xamarin.Android.Tasks.ProcessAssemblies.DeduplicateAssemblies(List`1 output, Dictionary`2 symbols)
at Xamarin.Android.Tasks.ProcessAssemblies.RunTask()
at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in C:\src\xamarin-android\external\xamarin-android-tools\src\Microsoft.Android.Build.BaseTasks\AndroidTask.cs:line 17

I could also reproduce the issue in a test.

The problem is that Microsoft.Diagnostics.Tracing.TraceEvent.props
includes Windows native .dll files:

<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.dll">
  <Link>x86\KernelTraceControl.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.Win61.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.Win61.dll">
  <Link>x86\KernelTraceControl.Win61.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\msdia140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\msdia140.dll">
  <Link>x86\msdia140.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\msvcp140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\msvcp140.dll">
  <Link>x86\msvcp140.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\vcruntime140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\vcruntime140.dll">
  <Link>x86\vcruntime140.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\KernelTraceControl.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\KernelTraceControl.dll">
  <Link>amd64\KernelTraceControl.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\msdia140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\msdia140.dll">
  <Link>amd64\msdia140.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\msvcp140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\msvcp140.dll">
  <Link>amd64\msvcp140.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140.dll">
  <Link>amd64\vcruntime140.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>
<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140_1.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140_1.dll">
  <Link>amd64\vcruntime140_1.dll</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <Visible>False</Visible>
</None>

This isn't great... We don't really want users to be able to use
@(None) to include random .dll files...

I could workaround the problem by using this in the .csproj:

<None Remove="@(None->WithMetadataValue('Extension', '.dll'))" />

Reviewing the .binlog, I found the only way to identify
%(CopyToOutputDirectory) items was to do:

<ResolvedFileToPublish Remove="@(_SourceItemsToCopyToPublishDirectory)" />

Even though @(_SourceItemsToCopyToPublishDirectory) has a private
name, it seems like the only way to fix this? If it was ever renamed,
we have a test and the above code would change to a no-op.

The test now passes, excluding these files from the build.

@jonathanpeppers
Copy link
Member Author

I think this broke a warning we were emitting for app.config files:

image

Will look into it.

@jonathanpeppers jonathanpeppers marked this pull request as draft November 19, 2021 20:01
Context: https://github.com/jonathanpeppers/android-pipe/blob/c313259b782bff40204e1a1ca988659dc7d3180b/csharp/Benchmark.csproj#L25

When using BenchmarkDotNet in a .NET 6 Android app for the first time,
I hit this build error:

    Microsoft.Android.Sdk.AssemblyResolution.targets(106,5): error XAPRAS7009: System.InvalidOperationException: PE image does not have metadata.
    at System.Reflection.PortableExecutable.PEReader.GetMetadataBlock()
    at System.Reflection.PortableExecutable.PEReader.GetMetadata()
    at System.Reflection.Metadata.PEReaderExtensions.GetMetadataReader(PEReader peReader, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)
    at System.Reflection.Metadata.PEReaderExtensions.GetMetadataReader(PEReader peReader)
    at Xamarin.Android.Tasks.ProcessAssemblies.DeduplicateAssemblies(List`1 output, Dictionary`2 symbols)
    at Xamarin.Android.Tasks.ProcessAssemblies.RunTask()
    at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in C:\src\xamarin-android\external\xamarin-android-tools\src\Microsoft.Android.Build.BaseTasks\AndroidTask.cs:line 17

I could also reproduce the issue in a test.

The problem is that `Microsoft.Diagnostics.Tracing.TraceEvent.props`
includes Windows native `.dll` files:

    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.dll">
      <Link>x86\KernelTraceControl.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.Win61.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.Win61.dll">
      <Link>x86\KernelTraceControl.Win61.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\msdia140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\msdia140.dll">
      <Link>x86\msdia140.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\msvcp140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\msvcp140.dll">
      <Link>x86\msvcp140.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\vcruntime140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\vcruntime140.dll">
      <Link>x86\vcruntime140.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\KernelTraceControl.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\KernelTraceControl.dll">
      <Link>amd64\KernelTraceControl.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\msdia140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\msdia140.dll">
      <Link>amd64\msdia140.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\msvcp140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\msvcp140.dll">
      <Link>amd64\msvcp140.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140.dll">
      <Link>amd64\vcruntime140.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>
    <None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140_1.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140_1.dll">
      <Link>amd64\vcruntime140_1.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Visible>False</Visible>
    </None>

This isn't great... We don't really want users to be able to use
`@(None)` to include random `.dll` files...

I could workaround the problem by using this in the `.csproj`:

    <None Remove="@(None->WithMetadataValue('Extension', '.dll'))" />

Reviewing the `.binlog`, I found the only way to identify
`%(CopyToOutputDirectory)` items was to do:

    <ResolvedFileToPublish Remove="@(_SourceItemsToCopyToPublishDirectory)" />

Even though `@(_SourceItemsToCopyToPublishDirectory)` has a private
name, it seems like the only way to fix this? If it was ever renamed,
we have a test and the above code would change to a no-op.

The test now passes, excluding these files from the build.
@jonathanpeppers jonathanpeppers force-pushed the copytopublishdirectory-items branch from 3960ae7 to 82ce550 Compare November 29, 2021 19:54
@jonathanpeppers jonathanpeppers marked this pull request as ready for review November 29, 2021 19:55
@jonpryor jonpryor merged commit c31b45b into dotnet:main Nov 30, 2021
jonathanpeppers added a commit that referenced this pull request Nov 30, 2021
Context: https://github.com/jonathanpeppers/android-pipe/blob/c313259b782bff40204e1a1ca988659dc7d3180b/csharp/Benchmark.csproj#L25

When using BenchmarkDotNet in a .NET 6 Android app for the first time,
I hit this build error:

	Microsoft.Android.Sdk.AssemblyResolution.targets(106,5): error XAPRAS7009: System.InvalidOperationException: PE image does not have metadata.
	  at System.Reflection.PortableExecutable.PEReader.GetMetadataBlock()
	  at System.Reflection.PortableExecutable.PEReader.GetMetadata()
	  at System.Reflection.Metadata.PEReaderExtensions.GetMetadataReader(PEReader peReader, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)
	  at System.Reflection.Metadata.PEReaderExtensions.GetMetadataReader(PEReader peReader)
	  at Xamarin.Android.Tasks.ProcessAssemblies.DeduplicateAssemblies(List`1 output, Dictionary`2 symbols)
	  at Xamarin.Android.Tasks.ProcessAssemblies.RunTask()
	  at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in C:\src\xamarin-android\external\xamarin-android-tools\src\Microsoft.Android.Build.BaseTasks\AndroidTask.cs:line 17

I could also reproduce the issue in a test.

The problem is that `Microsoft.Diagnostics.Tracing.TraceEvent.props`
includes Windows native `.dll` files:

	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.dll">
	  <Link>x86\KernelTraceControl.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.Win61.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\KernelTraceControl.Win61.dll">
	  <Link>x86\KernelTraceControl.Win61.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\msdia140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\msdia140.dll">
	  <Link>x86\msdia140.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\msvcp140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\msvcp140.dll">
	  <Link>x86\msvcp140.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\x86\vcruntime140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\x86\vcruntime140.dll">
	  <Link>x86\vcruntime140.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\KernelTraceControl.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\KernelTraceControl.dll">
	  <Link>amd64\KernelTraceControl.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\msdia140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\msdia140.dll">
	  <Link>amd64\msdia140.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\msvcp140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\msvcp140.dll">
	  <Link>amd64\msvcp140.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140.dll">
	  <Link>amd64\vcruntime140.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>
	<None Condition="Exists('$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140_1.dll')" Include="$(MSBuildThisFileDirectory)..\lib\native\amd64\vcruntime140_1.dll">
	  <Link>amd64\vcruntime140_1.dll</Link>
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	  <Visible>False</Visible>
	</None>

This isn't great; we don't really want users to be able to use
`@(None)` to include random `.dll` files…

I could workaround the problem by using this in the `.csproj`:

	<None Remove="@(None->WithMetadataValue('Extension', '.dll'))" />

Reviewing the `.binlog`, I found the only way to identify
`%(CopyToOutputDirectory)` items was to do:

	<ResolvedFileToPublish Remove="@(_SourceItemsToCopyToPublishDirectory)" />

Even though `@(_SourceItemsToCopyToPublishDirectory)` has a private
name, it seems like the only way to fix this?  If it was ever
renamed, we have a test and the above code would change to a no-op.

The test now passes, excluding these files from the build.
@jonathanpeppers jonathanpeppers deleted the copytopublishdirectory-items branch November 30, 2021 17:15
@github-actions github-actions bot locked and limited conversation to collaborators Jan 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants