Skip to content

Commit

Permalink
Allow granular opt out of assembly info generation
Browse files Browse the repository at this point in the history
  • Loading branch information
nguerrera committed Oct 25, 2016
1 parent 411cadb commit 563d9f1
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,23 @@ Copyright (c) .NET Foundation. All rights reserved.
-->
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<GeneratedAssemblyInfoFile Condition="'$(GeneratedAssemblyInfoFile)' ==''">$(IntermediateOutputPath)$(MSBuildProjectName).AssemblyInfo$(DefaultLanguageSourceExtension)</GeneratedAssemblyInfoFile>
<GeneratedAssemblyInfoFile Condition="'$(GeneratedAssemblyInfoFile)' ==''">$(IntermediateOutputPath)$(MSBuildProjectName).AssemblyInfo$(DefaultLanguageSourceExtension)</GeneratedAssemblyInfoFile>
<GenerateAssemblyInfo Condition="'$(GenerateAssemblyInfo)' == ''">true</GenerateAssemblyInfo>
</PropertyGroup>

<PropertyGroup Condition="'$(GenerateAssemblyInfo)' == 'true'">
<GenerateAssemblyCompanyAttribute Condition="'$(GenerateAssemblyCompanyAttribute)' == ''">true</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyConfigurationAttribute Condition="'$(GenerateAssemblyConfigurationAttribute)' == ''">true</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCopyrightAttribute Condition="'$(GenerateAssemblyCopyrightAttribute)' == ''">true</GenerateAssemblyCopyrightAttribute>
<GenerateAssemblyDescriptionAttribute Condition="'$(GenerateAssemblyDescriptionAttribute)' == ''">true</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyFileVersionAttribute Condition="'$(GenerateAssemblyFileVersionAttribute)' == ''">true</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute Condition="'$(GenerateAssemblyInformationalVersionAttribute)' == ''">true</GenerateAssemblyInformationalVersionAttribute>
<GenerateAssemblyProductAttribute Condition="'$(GenerateAssemblyProductAttribute)' == ''">true</GenerateAssemblyProductAttribute>
<GenerateAssemblyTitleAttribute Condition="'$(GenerateAssemblyTitleAttribute)' == ''">true</GenerateAssemblyTitleAttribute>
<GenerateAssemblyVersionAttribute Condition="'$(GenerateAssemblyVersionAttribute)' == ''">true</GenerateAssemblyVersionAttribute>
<GenerateNeutralResourcesLanguageAttribute Condition="'$(GenerateNeutralResourcesLanguageAttribute)' == ''">true</GenerateNeutralResourcesLanguageAttribute>
</PropertyGroup>

<!--
Note that this must run before every invocation of CoreCompile to ensure that all compiler
runs see the generated assembly info. There is at least one scenario involving Xaml
Expand All @@ -40,34 +53,34 @@ Copyright (c) .NET Foundation. All rights reserved.
Inputs="$(MSBuildAllProjects)"
Outputs="$(GeneratedAssemblyInfoFile)">
<ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyCompanyAttribute" Condition="'$(Company)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyCompanyAttribute" Condition="'$(Company)' != '' and '$(GenerateAssemblyCompanyAttribute)' == 'true'">
<_Parameter1>$(Company)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyConfigurationAttribute" Condition="'$(Configuration)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyConfigurationAttribute" Condition="'$(Configuration)' != '' and '$(GenerateAssemblyConfigurationAttribute)' == 'true'">
<_Parameter1>$(Configuration)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyCopyrightAttribute" Condition="'$(Copyright)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyCopyrightAttribute" Condition="'$(Copyright)' != '' and '$(GenerateAssemblyCopyrightAttribute)' == 'true'">
<_Parameter1>$(Copyright)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyDescriptionAttribute" Condition="'$(Description)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyDescriptionAttribute" Condition="'$(Description)' != '' and '$(GenerateAssemblyDescriptionAttribute)' == 'true'">
<_Parameter1>$(Description)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyFileVersionAttribute" Condition="'$(FileVersion)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyFileVersionAttribute" Condition="'$(FileVersion)' != '' and '$(GenerateAssemblyFileVersionAttribute)' == 'true'">
<_Parameter1>$(FileVersion)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyInformationalVersionAttribute" Condition="'$(Version)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyInformationalVersionAttribute" Condition="'$(Version)' != '' and '$(GenerateAssemblyInformationalVersionAttribute)' == 'true'">
<_Parameter1>$(Version)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyProductAttribute" Condition="'$(Product)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyProductAttribute" Condition="'$(Product)' != '' and '$(GenerateAssemblyProductAttribute)' == 'true'">
<_Parameter1>$(Product)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyTitleAttribute" Condition="'$(AssemblyTitle)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyTitleAttribute" Condition="'$(AssemblyTitle)' != '' and '$(GenerateAssemblyTitleAttribute)' == 'true'">
<_Parameter1>$(AssemblyTitle)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyVersionAttribute" Condition="'$(AssemblyVersion)' != ''">
<AssemblyAttribute Include="System.Reflection.AssemblyVersionAttribute" Condition="'$(AssemblyVersion)' != '' and '$(GenerateAssemblyVersionAttribute)' == 'true'">
<_Parameter1>$(AssemblyVersion)</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Resources.NeutralResourcesLanguage" Condition="'$(NeutralLanguage)' != ''">
<AssemblyAttribute Include="System.Resources.NeutralResourcesLanguageAttribute" Condition="'$(NeutralLanguage)' != '' and '$(GenerateNeutralResourcesLanguageAttribute)'">
<_Parameter1>$(NeutralLanguage)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.IO;
using Microsoft.NET.TestFramework;
using Microsoft.NET.TestFramework.Assertions;
using Microsoft.NET.TestFramework.Commands;
using Xunit;
using FluentAssertions;
using static Microsoft.NET.TestFramework.Commands.MSBuildTest;

namespace Microsoft.NET.Build.Tests
{
public class GivenThatWeWantToControlGeneratedAssemblyInfo
{
private TestAssetsManager _testAssetsManager = TestAssetsManager.TestProjectsAssetsManager;

[Theory]
[InlineData("AssemblyInformationVersionAttribute")]
[InlineData("AssemblyFileVersionAttribute")]
[InlineData("AssemblyVersionAttribute")]
[InlineData("AssemblyCompanyAttribute")]
[InlineData("AssemblyConfigurationAttribute")]
[InlineData("AssemblyCopyrightAttribute")]
[InlineData("AssemblyDescriptionAttribute")]
[InlineData("AssemblyTitleAttribute")]
[InlineData("NeutralResourcesLanguageAttribute")]
[InlineData("All")]
public void It_respects_opt_outs(string attributeToOptOut)
{
var testAsset = _testAssetsManager
.CopyTestAsset("HelloWorld", identifier: Path.DirectorySeparatorChar + attributeToOptOut)
.WithSource()
.Restore();

var buildCommand = new BuildCommand(Stage0MSBuild, testAsset.TestRoot);
buildCommand
.Execute(
"/p:Version=1.2.3-beta",
"/p:FileVersion=4.5.6.7",
"/p:AssemblyVersion=8.9.10.11",
"/p:Company=TestCompany",
"/p:Configuration=Release",
"/p:Copyright=TestCopyright",
"/p:Description=TestDescription",
"/p:Product=TestProduct",
"/p:AssemblyTitle=TestTitle",
"/p:NeutralLanguage=fr",
attributeToOptOut == "All" ?
"/p:GenerateAssemblyInfo=false" :
$"/p:Generate{attributeToOptOut}=false"
)
.Should()
.Pass();

var expectedInfo = new SortedDictionary<string, string>
{
{ "AssemblyInformationalVersionAttribute", "1.2.3-beta" },
{ "AssemblyFileVersionAttribute", "4.5.6.7" },
{ "AssemblyVersionAttribute", "8.9.10.11" },
{ "AssemblyCompanyAttribute", "TestCompany" },
{ "AssemblyConfigurationAttribute", "Release" },
{ "AssemblyCopyrightAttribute", "TestCopyright" },
{ "AssemblyDescriptionAttribute", "TestDescription" },
{ "AssemblyProductAttribute", "TestProduct" },
{ "AssemblyTitleAttribute", "TestTitle" },
{ "NeutralResourcesLanguageAttribute", "fr" },
};

if (attributeToOptOut == "All")
{
expectedInfo.Clear();
}
else
{
expectedInfo.Remove(attributeToOptOut);
}

expectedInfo.Add("TargetFrameworkAttribute", ".NETCoreApp,Version=v1.0");

var assemblyPath = Path.Combine(buildCommand.GetOutputDirectory("netcoreapp1.0", "Release").FullName, "HelloWorld.dll");
var actualInfo = AssemblyInfo.Get(assemblyPath);

actualInfo.Should().Equal(expectedInfo);
}
}
}
59 changes: 59 additions & 0 deletions test/Microsoft.NET.TestFramework/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.PortableExecutable;
using System.Reflection.Metadata;

namespace Microsoft.NET.TestFramework
{
public static class AssemblyInfo
{
public static IDictionary<string, string> Get(string assemblyPath)
{
var dictionary = new SortedDictionary<string, string>();

using (var stream = File.OpenRead(assemblyPath))
using (var peReader = new PEReader(stream))
{
var metadataReader = peReader.GetMetadataReader();
var assemblyDefinition = metadataReader.GetAssemblyDefinition();

// AssemblyVersion is not actually a custom attribute
if (assemblyDefinition.Version != new Version(0, 0, 0, 0))
{
dictionary.Add("AssemblyVersionAttribute", assemblyDefinition.Version.ToString());
}

foreach (var handle in assemblyDefinition.GetCustomAttributes())
{
var attribute = metadataReader.GetCustomAttribute(handle);
var constructor = metadataReader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
var type = metadataReader.GetTypeReference((TypeReferenceHandle)constructor.Parent);
var name = metadataReader.GetString(type.Name);

var signature = metadataReader.GetBlobReader(constructor.Signature);
var value = metadataReader.GetBlobReader(attribute.Value);
var header = signature.ReadSignatureHeader();

const ushort prolog = 1; // two-byte "prolog" defined by ECMA-335 (II.23.3) to be at the beginning of attribute value blobs
if (value.ReadUInt16() != prolog || header.Kind != SignatureKind.Method || header.IsGeneric)
{
throw new BadImageFormatException();
}

if (signature.ReadCompressedInteger() == 1 && // must have 1 parameter
signature.ReadSignatureTypeCode() == SignatureTypeCode.Void && // return type must be void
signature.ReadSignatureTypeCode() == SignatureTypeCode.String) // first parameter must be string
{
dictionary.Add(name, value.ReadSerializedString());
}
}
}

return dictionary;
}
}
}
4 changes: 2 additions & 2 deletions test/Microsoft.NET.TestFramework/Commands/BuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public override CommandResult Execute(params string[] args)
return command.Execute();
}

public DirectoryInfo GetOutputDirectory(string targetFramework)
public DirectoryInfo GetOutputDirectory(string targetFramework, string configuration = "Debug")
{
string output = Path.Combine(ProjectRootPath, "bin", "Debug", targetFramework);
string output = Path.Combine(ProjectRootPath, "bin", configuration, targetFramework);
return new DirectoryInfo(output);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
<PackageReference Include="Newtonsoft.Json">
<Version>$(NewtonsoftJsonVersion)</Version>
</PackageReference>
<PackageReference Include="System.Reflection.Metadata">
<Version>1.3.0</Version>
</PackageReference>
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 563d9f1

Please sign in to comment.