bazel-contrib / rules_dotnet

.NET rules for Bazel
Apache License 2.0
190 stars 84 forks source link

Can't set AssemblyVersion etc attributes #423

Open peakschris opened 8 months ago

peakschris commented 8 months ago

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?

purkhusid commented 7 months ago

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 commented 1 month ago

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

peakschris commented 1 month ago

I wrote an 'assemblyinfo' 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 commented 1 month ago

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
    )