sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Why the product version has a long suffix?

Open GF-Huang opened this issue 4 years ago • 36 comments

image

GF-Huang avatar Jun 16 '21 15:06 GF-Huang

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost avatar Jun 16 '21 15:06 ghost

Can you clarify to what you're referring. Where do you see this version? For things like AssemblyInformationalVersion we often embed the commit hash from git.

joeloff avatar Jul 21 '21 21:07 joeloff

Can you clarify to what you're referring. Where do you see this version? For things like AssemblyInformationalVersion we often embed the commit hash from git.

Right click the final output assembly -> properties -> details tab.

GF-Huang avatar Jul 21 '21 21:07 GF-Huang

Are you referring to .NET itself or to an assembly you created?

joeloff avatar Jul 21 '21 21:07 joeloff

Are you referring to .NET itself or to an assembly you created?

I use VS2019 to create a .NET WPF App, the app output .exe product version field contains this thing:

image

GF-Huang avatar Jul 21 '21 21:07 GF-Huang

There's a property called GenerateAssemblyFileVersionAttribute that defaults to true. If you want to manage the file version, you can set this to false.

joeloff avatar Jul 21 '21 21:07 joeloff

There's a property called GenerateAssemblyFileVersionAttribute that defaults to true. If you want to manage the file version, you can set this to false.

Not work, suffix still.

image

GF-Huang avatar Jul 28 '21 00:07 GF-Huang

You can try creating a binlog and then searching for the version. That looks very much like a commit SHA. Are you using any versioning packages, e.g. Nerdbank.GitVersioning?

joeloff avatar Jul 28 '21 01:07 joeloff

You can try creating a binlog and then searching for the version.

How to do this?

That looks very much like a commit SHA. Are you using any versioning packages, e.g. Nerdbank.GitVersioning?

Never.

GF-Huang avatar Jul 28 '21 01:07 GF-Huang

with msbuild, or dotnet build you can pass /bl. There's a special msbuild binlog viewer available to view the files: https://msbuildlog.com/

joeloff avatar Jul 28 '21 02:07 joeloff

How to do in visual studio 2019?

GF-Huang avatar Jul 28 '21 02:07 GF-Huang

There's an extension available called Project System Tools, but I've never used it.

joeloff avatar Jul 28 '21 03:07 joeloff

Set IncludeSourceRevisionInInformationalVersion or GenerateAssemblyInformationalVersionAttribute, not GenerateAssemblyFileVersionAttribute.

KalleOlaviNiemitalo avatar Aug 07 '21 16:08 KalleOlaviNiemitalo

I am experiencing this as well upgrading from .NET 6 to .NET 8 RC2.

We have a number of things in our product that do not expect this git commit hash to be appended to the Assembly Version which are broken by the behaviour.

I can work around this by setting <IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion> in the csproj files or in a props file, but my concern is that at some point the default for this property has been changed from false to true in a way that doesn't seem to have been documented anywhere.

I only found out about IncludeSourceRevisionInInformationalVersion by stumbling upon this GitHub issue after many other fruitless web searches.

--- Additional keywords/phrases so search engines pick this up

Git Commit hash is being appended to dotnet assembly version Git Commit Sha is being appended to C# assembly version dotnet assembly version metadata is being set to Git Commit hash How do I stop the Git Commit hash from being appended to my dotnet assembly version

borland avatar Oct 31 '23 22:10 borland

Issue for documenting this as a breaking change: https://github.com/dotnet/docs/issues/37674

at some point the default for this property has been changed from false to true

The feature was added in https://github.com/dotnet/sdk/pull/2028 five years ago and the default value of IncludeSourceRevisionInInformationalVersion was already true, but it did not take effect because the SourceControlInformationFeatureSupported and SourceRevisionId properties were not set. Now that Source Link is included, it sets those.

KalleOlaviNiemitalo avatar Nov 01 '23 04:11 KalleOlaviNiemitalo

@tmat

Just to add some ammo here, I really think the version information in the assembly by default should be rolled back. Essentially, incremental build (or caching) is fundamentally broken. And things like reference assemblies and deterministic builds are less useful.

In our (internal) build system, we use reference assemblies to give "interface-aware" cache hits. So, if you change a comment in a file, we will only compile that project and replay the rest of the build from cache. This is similar to the VS "Build Acceleration" feature recently added. To implement this, you need to ensure the ref assembly is the same. With this change, it never will be in CI or locally when unrelated commits happen (build + pull + build incrementality is broken). Ultimately this is because the hash or MVID for the ref assembly is no longer stable. Both of these features are impacted by this. Ours is 100% useless, VS Build Acceleration is less affected since HEAD isn't going to change as much locally. The same is true in MSBuild incremental, it also uses the MVID and swaps out ref assemblies for real ones to avoid compilations.

It's less important, but incremental build in MSBuild is also (more) incomplete now. MSBuild will not rebuild when you make an unrelated commit. People probably don't care, but it should rebuild as the assembly and ref assembly will be different even when deterministic build is enabled. Essentially the git commit is an untracked input to CoreCompile.

AndyGerlicher avatar May 02 '24 21:05 AndyGerlicher

@AndyGerlicher If Source Link is enabled, the git sha is included in the PDB. The hash of the PDB is stored in the binary. Therefore, the binary content already depends on the sha regardless of whether the version includes it or not. In that case you should treat the commit sha as an input to the build. Other git information, such as origin URL and all applicable ".gitignore" files also need to be included because their presence affects source embedding.

One way to avoid this dependency while still provide good debugging and tooling support is to disable Source Link and enable embedding all source files to PDB.

That said, reference assemblies are different. They don't have any source information, so it'd make sense to entirely disable Source Link for reference assemblies.

tmat avatar May 03 '24 03:05 tmat

I agree just disabling that for reference assemblies would be sufficient for most cases. Although then you would have assembly version differences between the two which seems odd. And I still think changing the version from the current default to a totally new format is not a great change though, esp. not guarded by TFM. Behavior changes on upgrading the SDK should be very minimal if you don't opt-in or change the TFM.

Also, I would like to emphasize that I really believe source link is the correct decision for the debugging experience. It's such a great experience compared to what it used to be. However, I don't think adding the assembly version affects it in any way and is more of a personal/repo preference (that happens to break caching, version parsing, etc.).

AndyGerlicher avatar May 03 '24 16:05 AndyGerlicher

That said, reference assemblies are different. They don't have any source information, so it'd make sense to entirely disable Source Link for reference assemblies.

This would impact the Ionide F# editor at minimum - when we get sourcelinked sources for a type we

  • lookup the type
  • get the assembly providing that type (often a ref assembly)
  • locate the PDB for that assembly
  • get the sourcelink information from that assembly
  • use the sourcelink information to download sources

If SourceLink is removed from ref assemblies then editors would now need to map from ref assembly to implementation assembly, which is difficult.

baronfel avatar May 03 '24 16:05 baronfel

@AndyGerlicher Just to be super clear, this only affects AssemblyInformationalVersion, not the actual assembly version.

Any project that uses any of the previous versions of Source Link packages has the git sha included in AssemblyInformationalVersion by default. Enabling Source Link by default in the SDK enabled this feature as well.

We decided not to guard by TFM since we want all targets to have good debugging and tooling experience by default.

tmat avatar May 03 '24 16:05 tmat

@baronfel Do we actually produce PDBs for reference assemblies?

tmat avatar May 03 '24 16:05 tmat

@tmat I don’t think debating the value of Source Link is the point here. Source link seems useful and we all want better debugging experiences.

The point is rather that

  • Enabling source link is a breaking change for many people’s existing tooling
  • It wasn’t required. Without enabling it, everything would have continue to work as it did with dotnet 7
  • Therefore it should have been opt-in. Or at least publicised as part of the dotnet 8 launch with info as to how to turn it off.
  • Instead, what happened was the dotnet 8 launch enabled it, breaking people’s environments, and you didn’t tell anyone about it. That’s not great.

borland avatar May 03 '24 21:05 borland

@borland I understand introducing breaking changes is not ideal. We believe in this case the benefits outweigh the need to adapt some repositories to the new behavior.

This specific change has been announced, documented and instructions to restore the previous behavior provided: https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/8.0/source-link

tmat avatar May 03 '24 21:05 tmat

I definitely agree turning it on is good. It's just the stamping of the assembly version that breaks even VS scenarios I don't think was thought through fully. I don't think it's required for the source link stuff either, it just seems like a nice to have.

@baronfel @marcpopMSFT for awareness as well. Is it possible we can get this reverted? (specifically, IncludeSourceRevisionInInformationalVersion should default to false)

AndyGerlicher avatar May 04 '24 17:05 AndyGerlicher

@AndyGerlicher Is the AssemblyInformationalVersion issue only with reference assemblies? In other words, if the attribute didn't have the SHA in reference assemblies would that resolve the caching problem?

Why isn't it feasible to set IncludeSourceRevisionInInformationalVersion to false in systems that need it?

tmat avatar May 06 '24 14:05 tmat

That's correct it's only really an issue for ref assemblies, although it would seem odd for the reference assembly version information to differ from implementation.

And yes, our workaround is to set that to false. But we shouldn't need to do that, esp. not to get stable ref assemblies. Making this change reduced the effectiveness of the VS Build Acceleration feature, further degrades the correctness of MSBuild incrementality, breaks caching, breaks customers that parse version information as a Version format (@baronfel has more info on that), and isn't required for the source link feature. It seems more like a preference and there are significant downstream consequences.

AndyGerlicher avatar May 06 '24 16:05 AndyGerlicher

Note that the feature has been enabled for projects that use Source Link for 5+ years. Surprising that none of the VS Build Accelerated projects used Source Link before.

tmat avatar May 06 '24 16:05 tmat

Disabling this is also a breaking change, to projects that rely on the version to have the SHA.

Every project that used to use Source Link PackageReference will have to set IncludeSourceRevisionInInformationalVersion to true if they want the original Source Link behavior.

tmat avatar May 06 '24 16:05 tmat

@AndyGerlicher How exactly are the reference assemblies built for caching? Could that build process switch this property off? The reference assemblies used for caching are not the same as reference assemblies published to nuget packages for general consumption, correct?

tmat avatar May 06 '24 16:05 tmat

They are the same.

In MSBuild, the implementation and ref assemblies are swapped before CoreCompile executes so that project builds can't perform an up-to-date check with just the ref assembly. The timestamp on the ref assembly will be old if it hasn't changed (the MVID is checked before copying the ref assembly). With this change, whenever there's a commit the MVID is guaranteed to be different even if it's just an empty commit.

In the "Build Acceleration" feature in Visual Studio, the project system up-to-date check watches the ref assembly to know if it needs to dispatch MSBuild or just copy around the implementation assembly without invoking MSBuild (which is significantly faster, stuff like RAR and the compiler don't need to run). This feature requires stability of the ref assembly. The only reason this feature isn't completely broken is because people likely don't commit that much locally to unrelated things enough to show it breaking in overall telemetry.

In QuickBuild (internal), we watch what file accesses happen during the build. Since MSBuild will use the ref assemblies and pass those into the compiler, we can know that the implementation assembly is not accesses (only copied). An interface-aware cache hit is then translated into a cache reply (basically the same as the VS feature). This is worse for us though since the hash or MVID of the ref assembly is guaranteed to change (unless you're building the same commit multiple times).

There's no other ref assembly choice for these features to use, the compiler only builds the two assemblies (implementation + ref).

AndyGerlicher avatar May 06 '24 17:05 AndyGerlicher