Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Update MSBuildEvaluationContext to use IntrinsicFunctions from Microsoft.Build.dll #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

hwthomas
Copy link
Collaborator

This fixes Issue 75

The existing code for IntrinsicFunctions (in main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild) is a local implementation of the functions in Microsoft.Build, but is now very much out-of-date, and many of the functions which are used to evaluate newer project properties are not implemented.

It is referenced preferentially during the property evaluations (rather than the Microsoft.Build.dll referenced in the csproj file), and this causes the property evaluations to fail. Updating the code so that the Dictionary cachedIntrinsicFunctions is created dynamically at runtime from the current Microsoft.Build.dll fixes the problem, and all project properties now evaluate correctly.

@hwthomas
Copy link
Collaborator Author

I've not managed to retain the readonly on the cachedIntrinsicFunctions Dictionary, since I couldn't then initialise it during the InitEngineProperties function (called when the class is initialised). I'm not really convinced of the need for the readonly attribute, as the Dictionary is used only in the one function ResolveMember. @lytico any thoughts?

@lytico
Copy link
Member

lytico commented Jun 27, 2022

a recent version of IntrinsicFunctions would be here: https://github.com/dotnet/msbuild/blob/main/src/Build/Evaluation/IntrinsicFunctions.cs

what you are doing is link a call of type IntrinsicFunctions to msbuild-functions
so, if that solves some problems, maybe with the original idea of IntrinsicFunctions is something wrong

@hwthomas
Copy link
Collaborator Author

Looking at the history of the MonoDevelop InstrinsicFunctions (https://github.com/dotdevelop/dotdevelop/commits/main/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/IntrinsicFunctions.cs) they were re-imported from MSBuild with a commit on Sep 22 2017 and remained unchanged until an extra function String::Copy was added (IntrinsicFunctions.Extensions.cs) at the same time that the cachedIntrinsicFunctions Dictionary was added on Sep 18 2019 - just before Microsoft stopped supporting MonoDevelop. As far as I can tell, this Copy function is not called anywhere in the MonoDevelop code, and as it hasn't found its way into the dotnet/msbuild IntrinsicFunctions either, I've left it out of the (minimal) code for IntrinsicFunctions in the PR (by deleting IntrinsicFunctions.Extensions.cs).

I've added a block comment to the header of the IntrinsicFunctions.cs file to describe all this, in case any changes are needed sometime.

The only other approach to caching at runtime would be to re-import the current dotnet/msbuild/IntrinsicFunctions you referenced, and try and keep these up-to-date, though this doesn't seem a good 'future-proof' way.

The vs16.10, vs16.11, and vs17.0 branches are all the same, based on the commit on 17 Dec 2020, but there have been some recent changes for the vs17.1 vs17.2 and main branches. Hope this clarifies the PR a bit.

@lytico
Copy link
Member

lytico commented Jun 28, 2022

As far as I can tell, this Copy function is not called anywhere in the MonoDevelop code

i remember something like:
MD parses the csproj file (and all nestend build-files) & then calls (over Reflection) the commands in this "IntrinsicFunction"
so you cannot tell by code-search if some method is called.
Not sure if i remember right ....

@hwthomas
Copy link
Collaborator Author

Yes, you remember correctly (I spent a lot of time and debugging to get to the same understanding!). But in MSBuildEvaluationContext.cs, around line 1034, there is the code

	MemberInfo[] ResolveMember (Type type, string memberName, bool isStatic, MemberTypes memberTypes)
	{
		if (type == typeof (string)) {
			if (memberName == "new" || memberName == "Copy") {
				type = typeof (IntrinsicFunctions);
				memberName = "Copy";
			}
          ...  

so this function is detected specifically. I need to have a think about what the implications are in this case, so perhaps including "Copy" as an IntrinsicFunction in the local code is necessary? However, it will fail to get found in the cachedIntrinsicFunctions.TryGetValue' call a few lines later if the dynamically loaded IntrinsicFunctions` are used, so there will still be a problem! More thought needed!

@lytico
Copy link
Member

lytico commented Jun 28, 2022

https://github.com/dotnet/msbuild/blob/main/src/Build/Evaluation/IntrinsicFunctions.cs
in comment, it says:

    /// The Intrinsic class provides static methods that can be accessed from MSBuild's
    /// property functions using $([MSBuild]::Function(x,y))

so, lets look to the documentation:

https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions?view=vs-2022

@hwthomas
Copy link
Collaborator Author

So, new and Copy are not included in this list, as I read it, and a purely local implementation of those functions should be OK? The functionality probably doesn't even need to go through the MSBuildEValuationContext route now.

@hwthomas
Copy link
Collaborator Author

As far as I can see, Copy was introduced to handle dotnet/msbuild#4615 and dotnet/msbuild#1155 . @lytico are you familiar with these? I don't yet understand them fully.

@lytico
Copy link
Member

lytico commented Jun 28, 2022

i guess it's a performance workaround:

However, AFAIK the implementation of String.Copy creates a copy of the string data, which is unnecessary overhead

and dotnet/msbuild/issues/4615 has a performance label

@hwthomas
Copy link
Collaborator Author

I've added another commit to this PR which removes the special case of String.Copy in MSBuildEvaluationContext. It is no longer included as one of the Microsoft.Build.IntrinsicFunctions, so the code in ResolveMember reverts to that prior to (369681d). The test added to IntrinsicFunctionsTests is not affected by this reversion.

@hwthomas
Copy link
Collaborator Author

hwthomas commented Aug 3, 2022

Although this PR is necessary in order to progress to handling netcoreapp projects correctly, it is not yet ready to be merged, since further issues (such as #79) then become apparent (and need solving!)

@hwthomas
Copy link
Collaborator Author

hwthomas commented Sep 4, 2022

I've just updated the fix_Issue_75 branch to completely remove the local implementation of IntrinsicFunctions (see commit a51afa1 above) and squashed the previous commits to make life easier.

@lytico Further to my last comment, I think this PR could be merged now, as I don't think the remaining net5ff bugs can be tackled unless a project's properties are first evaluated correctly.

However, might it be useful to create a dev or testing branch in addition to the main one, so that other developers could try out (and help to debug) the latest code more easily?

 and update MSBuildEvaluationContext.cs accordingly

    IntrinsicFunctions are now loaded at runtime from the current version
    of Microsoft.Build.dll, as identified by the active runtime.

    The old IntrinsicFunctions test is no longer meaningful and has been removed

    This fixes Issue dotdevelop#75 so that all project properties are now evaluated correctly.
@gluckez
Copy link
Collaborator

gluckez commented Sep 4, 2022

@hwthomas +1 for the dev or testing branch, this is a convential way of working in most companies anyway and it would allow us to create pre-release builds next to release builds, should we ever set that up in the pipelines.

  Incorporate changes in PR#81 from @gluckez to fix conflicts
@hwthomas hwthomas mentioned this pull request Nov 23, 2022
@hwthomas
Copy link
Collaborator Author

Merged as part of PR #96

@hwthomas hwthomas closed this Jan 16, 2023
@hwthomas hwthomas deleted the fix_Issue_75 branch February 24, 2023 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants