MSBuild task to get update FileAssemblyVersion for only projects with changes - c#

Is there any way, using msbuild or otherwise, to detect which projects have changes in the current build and update the FileAssemblyVersion attribute in AssemblyInfo.cs for those projects only?

Assuming you've set up incremental [get and] compiles, the next step would be to hook into the MSBuild sequence. Have a look in FrameworkDir\Microsoft.Common.Targets. The problem is that things just are not set up to work in this way - the fact that there are _TimestampBeforeCompile and _TimeStampAfterCompile steps which just show that you cant determine a priori if something is going to compile. While you could theoretically hook in before [the language specific] CoreCompile [e.g., in Microsoft.CSharp.targets], the problem would be that you need to have the same Inputs as it does in order to determine if its going to happen, which would mean lots of cut and pasting and keeping in sync with system files. The other thing to be wary of is noted in the comment at the top of the _ComputeNonExistentFileProperty target.
So, outside of doing some very deep modifications to the sequence (e.g., hooking in a 'post build' bit which forces a second compile if a custom _TimeStampAfterCompile of yours detects that a compilation took place, I'd say there's no easy, recommended or supported way.
Having said that, the AssemblyFileVersion (you refer to FileAssemblyVersion, which doesnt exist :P) is easy to modify after the compile as its just a resource - you'll find tools for that. But I assume you're really talking about doing both it and the AssemblyVersion, which cant be tweaked after the fact in the same way.

Related

How do I make the WasmEmitSymbolMap and/or WasmNativeStrip properties take effect?

I want to be able to interpret an Edge performance profiler report for my Blazor WebAssembly app. To do this, I need to avoid the issue described in this question whereby all functions are renamed to names like "wasm-function[12345]". This answer aims to explain a means of doing this by setting the properties WasmEmitSymbolMap and/or WasmNativeStrip. However, it does not provide sufficient detail on how to get these properties to actually take effect. For me, they do not make any difference. The Edge performance profiler continues to name the functions according to the "wasm-function[12345]" pattern no matter what I try, and I cannot find the file "dotnet.js.symbols" - that supposedly ought to be created somewhere, since I specified WasmEmitSymbolMap - at all.
What I have tried
I tried adding these lines within a PropertyGroup in the "client" project's csproj file:
<WasmEmitSymbolMap>true</WasmEmitSymbolMap>
<WasmNativeStrip>false</WasmNativeStrip>
I tried adding those same lines within a PropertyGroup in the "server" project's csproj file, too, because the answer doesn't say which file they belong in.
Because the answer warns that one of the two properties "can only be used in AOT compiled mode", I added the following line alongside the aforementioned ones in both csproj files:
<RunAOTCompilation>true</RunAOTCompilation>
I also tried adding the following line in both files:
<RunAOTCompilationAfterBuild>true</RunAOTCompilationAfterBuild>
At various times I tried force-refreshing (shift+F5) the page in my application, just in case something was out of date.
None of the steps 1, 2, 3 or 5 made a difference. As to step 4, I do not know whether this change would have fixed the problem or not, because it made the build take such a long time that I eventually gave up and cancelled it.
The answer is I should have had more patience with RunAOTCompilationAfterBuild. It does do the job. Weirdly the second time I tried it, it didn't take as long and didn't appear to go through all the same steps as it had done the first time, so some stuff must have been cached or something. This is despite the fact I had cleaned the solution in the meantime.
So the answer is: put all this stuff in your csproj (the Client project csproj, I think, but it doesn't matter if it's in both):
<PropertyGroup>
...
<RunAOTCompilation>true</RunAOTCompilation>
<RunAOTCompilationAfterBuild>true</RunAOTCompilationAfterBuild>
<WasmEmitSymbolMap>true</WasmEmitSymbolMap>
<WasmNativeStrip>false</WasmNativeStrip>
...
</PropertyGroup>
and be aware that it will take a really long time to compile. like 10-15 minutes or maybe more, and for a lot of that time it will be sitting there not printing any output - it just sits there for several minutes with a message that mentions something called "emscripten".
Because it takes such a long time to compile, you won't want to do this routinely for your debug builds. Only when you specifically want to investigate a performance problem.
Additional relevant discussion here: https://github.com/dotnet/aspnetcore/issues/26850

Can a Roslyn Source Generator discover the IDE's spacing/etc preferences?

I'm writing a Roslyn source generator, and as a matter of principle I'd like to make sure the generated source (which is now visible, debuggable, etc) adheres at least somewhat to the user's configuration of tabs vs spaces, brace locations, etc. I don't plan on supporting everything, but the obvious ones: sure.
So; I'm implementing ISourceGenerator and ISyntaxReceiver, which means I have access to the GeneratorInitializationContext, GeneratorExecutionContext and SyntaxNode APIs. However, I cannot find any way to get these IDE settings from here. Is this possible?
This might not even be possible because of the reality that I'm talking about IDE settings and there isn't always an IDE - for example, the user could just be running dotnet build at the command line.
(or perhaps alternatively; is it possible to trigger a "format document" equivalent on the generated code before handing it back to the caller?)
As observed by the conversation, there's no good way to do this (or at least not as of this writing). A generator could try to use the values from an .editorconfig to know the formatting settings if you want to piece it together, but you'd have to write some of that yourself at this point. My suggestion would be until we build in support for this, just don't worry about it, and feel free to direct user complaints to this or the bug.
No matter what, the debugging problem makes things tricky: the file open in the IDE needs to match the file that was produced during the build, since the debugger expects that to line up. The .editorconfig at least means both sides can see the same value.

Output a Roslyn MSBuildWorkspace to different folder

When executing
mSBuildWorkspace.TryApplyChanges(solution);
Visual Studio changes the solution in place. This means that if I want to output to a different location, I need to first copy the whole solution to the requested target and only then work on it. This is error prone as the solution might have relative path links to dependencies, which can break when moving the solution.
So is there a way to tell MSBuildWorkspace to output the changes to a different folder than the source?
There's no built-in support for this.
Option #1: Instead of instead of calling TryApplyChanges you could call Solution.GetChanges to figure out what changed compared to what was originally loaded, and then call the various methods to get the changed documents and apply the edit yourself. This means you're on the hook to actually apply the edits -- source file edits are easy (just write the updated text) but if you care about more complicated things like project changes (adding/removing references) you don't really have a way to leverage MSBuildWorkspace's support for those sorts of things.
Option #2: Roslyn's open source, so you'd have to modify MSBuildWorkspace yourself to allow such a redirection, which would let you potentially try to reuse some of the more complicated logic around project manipulation. Or you can just copy/paste the implementation of the applying, and then use Solution.GetChanges and the reused code.

How to handle your code that later versions of the framework include?

I have to work with an old version of Mono in Unity projects. I find myself recreating some classes and extension methods that exist in later versions of .NET. Should I be marking these with an attribute that will make it easy to take them out at a later point, just wait for the inevitable errors, and delete the duplicate code, or take some other approach I'm not familiar with yet? If the attribute route is the way to go, is there already an appropriate attribute created for this kind of thing?
Here's what I'd like:
[PresentInDotNET(3.5)]
I fill in the version and get alerted when the framework is at that level or higher.
Split them off to a separate assembly, and change the set of assemblies that make up the final delivery based on the .NET version. You need to rebuild your main assembly to refer to the correct assemblies (depending on whether Foo is in MySystem or System), but as long as you keep namespaces identical, that's all. If you are not even interested in keeping compatibility with older versions, you can simply delete classes from this assembly as they become available.
Alternatively, if the classes/extension methods you are recreating are not interesting (in the sense that you gain nothing by having .NET supply them for you), simply put them in their separate namespace and accept that you are duplicating code already present in newer versions. It doesn't matter a whole lot which assembly gets the job done, after all, as long as it happens.
Whatever you do, try to avoid going the route of #ifdefs, runtime discovery, and other conditional code, as this is much harder to maintain.
How about adding "// TODO" comments for places like this? Visual Studio will display these in the Task window and you can get at them pretty easily.

How to use an altered Roslyn in Visual Studio

C# isn't enough for me, so I've taken advantage of the newly-open sourced Roslyn to extend it, say by modifying it to use French quotes.
But I don't want to build my newly-French-quoted files on the command line! I want Intellisense! I want a nice UI! In short, I want to get Visual Studio to use my Roslyn, not Microsoft's.
Can I do this yet? If so, how?
Quoted straight from this link in your question:
ADVANCED USAGE
It is also possible to update your copy of Visual Studio to use your
own built version of Roslyn (for example, to see how the IDE reacts to
your changes), but it’s slightly complicated:
First of all, you’ll need to use the release fork, not the master
fork. This is because the compiler code is constantly changing in
reaction to feedback, and that includes changes to the APIs that are
used by the non-open IDE bits in the Roslyn preview in order to access
compiler information (until the APIs get locked down as we get closer
to completion). When these APIs change, the ability to communicate
between the two is lost. The release fork, however, accurately
reflects the state of the code at the time that the Roslyn preview was
snapped, and so is safe to use as a baseline for this sort of thing.
(You can see the fork on the Roslyn CodePlex site by choosing “Source
Code” and then opening the “Browsing changes in” dropdown – it’s
called “releases\build-preview.”)
To switch to this fork in Git, you will need to execute the following
two commands from an appropriate Git prompt in your enlistment:
Git fetch
Git checkout – track origin/releases/build-preview
Your git repository will now have the contents of the
releases/build-preview branch. Once you’ve done this, you can switch
back and forth between the branches using Git checkout master and git
checkout releases/build-preview. (Details on Git usage are beyond the
scope of this blog; see
http://www.git-scm.com/book/en/Git-Branching-Remote-Branches for more
information on branching in Git.)
Second, you’ll need to disable Visual Studio’s strong-name assembly
checking for the relevant assemblies first. There’s a script to help
with that, which you can find checked into the source code at
Src/Tools/Microsoft.CodeAnalysis.Toolset.Open/Scripts/Prepare.bat.
With all of that done, make your changes. Then, after building, ensure
that CompilerPackage is set as the startup project, and then
F5/Ctrl+F5 to launch a VS instance containing the changes.
Please note that we will never accept pull requests for the release
fork – we need to keep it pristine and accurately reflecting the state
of the code relative to the Roslyn preview bits. Anything you actually
want considered for submission would need to be ported to a fork
created from the master first.
Interesting times ahead. Though I have a certain amount of trepidation about finding myself in a company where they use an entirely customised compiler to do awful, awful things. The gun to shoot yourself in the foot with has just been upgraded...

Categories