rules_dotnet icon indicating copy to clipboard operation
rules_dotnet copied to clipboard

Can't set AssemblyVersion etc attributes

Open peakschris opened this issue 1 year ago • 4 comments

I need to set AssemblyVersion on the libraries we are building. Actually, three attributes:

            [assembly: AssemblyVersion("blah")]
            [assembly: AssemblyFileVersion("blah")]
            [assembly: AssemblyInformationalVersionAttribute("blah")]

In our existing msbuild, these are set in a .cs file and that's pulled into the assembly with /property:BuildVersionFile=above.cs

I understand the attributes can also be supplied directly to msbuild as attributes.

This is a new blocker for us... Can this be supported?

peakschris avatar Mar 14 '24 22:03 peakschris

I think that makes sense that you could provide these attributes to the targets. Does it not work to just supply the AssemblyInfo.cs to the srcs attribute?

purkhusid avatar Mar 20 '24 10:03 purkhusid

Did you use some workaround for this? Is it not enough to supply the AssemblyInfo.cs into the srcs ?

purkhusid avatar Oct 07 '24 09:10 purkhusid

I wrote an 'assembly_info' rule that generates an assemblyinfo.cs file from a template for the current version of the product, and then wrote wrappers for each csharp_ rule. The wrapper calls the rule and adds the generated file into the build of every csharp library in our product.

peakschris avatar Oct 07 '24 10:10 peakschris

In case you would like to upstream anything, or if it is helpful to others, this is what I set up:

This is based on code I found here: https://github.com/SeleniumHQ/selenium/blob/trunk/dotnet/private/generated_assembly_info.bzl

AssemblyInfo.cs.template:

using System;
using System.Reflection;

[assembly: System.Reflection.AssemblyCompanyAttribute("{ASSEMBLY_COMPANY}")]
[assembly: System.Reflection.AssemblyCopyrightAttribute("{ASSEMBLY_COPYRIGHT}")]
[assembly: System.Reflection.AssemblyDescriptionAttribute("{ASSEMBLY_DESCRIPTION}")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("{ASSEMBLY_VERSION}")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("{ASSEMBLY_INFORMATIONAL_VERSION}")]
[assembly: System.Reflection.AssemblyProductAttribute("{ASSEMBLY_PRODUCT}")]
[assembly: System.Reflection.AssemblyTitleAttribute("{ASSEMBLY_TITLE}")]
[assembly: System.Reflection.AssemblyVersionAttribute("{ASSEMBLY_VERSION}")]
{ASSEMBLY_KEYFILE}

generated_assembly_info.bzl

# Label of the template file to use.
_TEMPLATE = ":AssemblyInfo.cs.template"

def _generated_assembly_info_impl(ctx):
    substitutions = {
        "{ASSEMBLY_VERSION}": ctx.attr.version,
        "{ASSEMBLY_COMPANY}": ctx.attr.company,
        "{ASSEMBLY_COPYRIGHT}": ctx.attr.copyright,
        "{ASSEMBLY_DESCRIPTION}": ctx.attr.description,
        "{ASSEMBLY_PRODUCT}": ctx.attr.product,
        "{ASSEMBLY_TITLE}": ctx.attr.title,
        "{ASSEMBLY_INFORMATIONAL_VERSION}": ctx.attr.informational_version,
    }
    if (ctx.attr.keyfile):
        substitutions["{ASSEMBLY_KEYFILE}"] = r'[assembly: System.Reflection.AssemblyKeyFileAttribute("' + ctx.file.keyfile.path + r'")]'
    else:
        substitutions["{ASSEMBLY_KEYFILE}"] = r""
    ctx.actions.expand_template(
        template = ctx.file.template,
        output = ctx.outputs.source_file,
        substitutions = substitutions,
    )

generated_assembly_info = rule(
    implementation = _generated_assembly_info_impl,
    attrs = {
        "version": attr.string(mandatory = True),
        "company": attr.string(mandatory = True),
        "copyright": attr.string(mandatory = True),
        "description": attr.string(mandatory = True),
        "product": attr.string(mandatory = True),
        "title": attr.string(mandatory = True),
        "informational_version": attr.string(mandatory = True),
        "template": attr.label(
            default = Label(_TEMPLATE),
            allow_single_file = True,
        ),
        "keyfile": attr.label(
            allow_single_file = True,
        ),
    },
    outputs = {"source_file": "%{name}.AssemblyInfo.cs"},
)

my_csharp_library.bzl

load("@rules_dotnet//dotnet:defs.bzl", "csharp_library")
load("generated_assembly_info.bzl", "generated_assembly_info")

def my_csharp_library(
        name,
        srcs,
        out = None,
        visibility = ["//visibility:public"],
        use_keyfile = True,
        **kwargs):
    assembly_name = out
    keyfileName = None

    if (use_keyfile):
        keyfileName = "//src/build/net/key:TcNetKey.snk"

    if (not assembly_name):
        assembly_name = name

    generated_assembly_info(
        name = assembly_name + "_assembly_info",
        company = ASSEMBLY_COMPANY,
        copyright = ASSEMBLY_COPYRIGHT,
        description = name,
        informational_version = ASSEMBLY_INFORMATIONAL_VERSION,
        product = ASSEMBLY_PRODUCT,
        title = name,
        version = ASSEMBLY_VERSION,
        keyfile = keyfileName,
    )

    csharp_library(
        name = name,
        out = out,
        srcs = srcs + [
            assembly_name + "_assembly_info",
        ],
        visibility = visibility,
        keyfile = keyfileName,
        **kwargs
    )

peakschris avatar Oct 07 '24 10:10 peakschris