Does NCrunch support property functions? I am trying to use that msbuild feature (like explained here http://blogs.msdn.com/b/visualstudio/archive/2010/04/02/msbuild-property-functions.aspx) and nothing works.
I noticed that one of my calculated properties get copied to environment variables of ncrunch build process, but could not get any other value copied. Is this possible?
Thank you
Remco NCrunch Developer
#7202
10 Apr 2015 21:27 UTC
Hi,
NCrunch sits on top of MSBuild, so in theory it should be able to handle almost all features of MSBuild. There have been some very niche features in MSBuild that it cannot handle - but this is due to the limitations of the MSBuild API itself, which doesn't seem to be 100% aligned with normal MSBuild function.
Sorry but the link you provided to the example didn't work for me. Can you show me the code you're having trouble with?
NCrunch sits on top of MSBuild, so in theory it should be able to handle almost all features of MSBuild. There have been some very niche features in MSBuild that it cannot handle - but this is due to the limitations of the MSBuild API itself, which doesn't seem to be 100% aligned with normal MSBuild function.
Sorry but the link you provided to the example didn't work for me. Can you show me the code you're having trouble with?
For example:
<OriginalProjectDir Condition="'$(NCrunch)' != '1'">$(MSBuildProjectDirectory)</OriginalProjectDir>
<OriginalProjectDir Condition="'$(NCrunch)' == '1'">$(NCrunchOriginalProjectDir)</OriginalProjectDir>
<BASEDIR Condition="'$(BASEDIR)' == ''">$(OriginalProjectDir.Substring(0, $(OriginalProjectDir.ToUpper().IndexOf(`\SomeDirInPath`))))</BASEDIR>
<OriginalProjectDir Condition="'$(NCrunch)' != '1'">$(MSBuildProjectDirectory)</OriginalProjectDir>
<OriginalProjectDir Condition="'$(NCrunch)' == '1'">$(NCrunchOriginalProjectDir)</OriginalProjectDir>
<BASEDIR Condition="'$(BASEDIR)' == ''">$(OriginalProjectDir.Substring(0, $(OriginalProjectDir.ToUpper().IndexOf(`\SomeDirInPath`))))</BASEDIR>
Remco NCrunch Developer
#7204
11 Apr 2015 05:38 UTC
Thanks for the code sample. This code has a few problems with it, though a couple of these aren't very obvious as they are specific to how NCrunch utilises MSBuild.
The first issue is that when NCrunch first tries to load your project, it performs an 'analysis build' that involves loading the project file into memory and executing a number of build targets. This analysis build does not specify the $(NCrunchOriginalProjectDir) property - as the project hasn't yet been relocated to a workspace and this property therefore doesn't really make sense yet. It does, however, specify $(NCrunch) == '1', which can cause this code to fail with the missing string/length issue during project load.
The second issue is that when NCrunch loads the project XML into the build runner in preparation for performing the actual build inside the workspace, MSBuild performs an evaluation step over the properties before $(NCrunchOriginalProjectDir) has been defined. This causes the same error case as above, although it happens later in the process (just before a build is started).
The third potential issue is more related to the assumptions this code makes about the structure of the workspace NCrunch has constructed to hold this project. If this workspace doesn't have 'SomeDirInPath' in its path, then things will go wrong. This may be perfectly OK if you have the project set up to use dependencies that exist further up the solution structure and NCrunch's relative path emulation successfully builds the workspace in the way your code is expecting it to be, but I would check this carefully as without upwards relative dependencies being specified from the project, NCrunch assumes that directories above the project's directory aren't important.
Anyway, try the following alternative code:
<BASEDIR Condition="'$(BASEDIR)' == '' AND '$(NCrunchOriginalProjectDir)' == ''">$(MSBuildProjectDirectory.Substring(0, $(MSBuildProjectDirectory.ToUpper().IndexOf(`\SOMEDIRINPATH`))))</BASEDIR>
<BASEDIR Condition="'$(BASEDIR)' == '' AND '$(NCrunchOriginalProjectDir)' != ''">$(NCrunchOriginalProjectDir.Substring(0, $(NCrunchOriginalProjectDir.ToUpper().IndexOf(`\SOMEDIRINPATH`))))</BASEDIR>
The first issue is that when NCrunch first tries to load your project, it performs an 'analysis build' that involves loading the project file into memory and executing a number of build targets. This analysis build does not specify the $(NCrunchOriginalProjectDir) property - as the project hasn't yet been relocated to a workspace and this property therefore doesn't really make sense yet. It does, however, specify $(NCrunch) == '1', which can cause this code to fail with the missing string/length issue during project load.
The second issue is that when NCrunch loads the project XML into the build runner in preparation for performing the actual build inside the workspace, MSBuild performs an evaluation step over the properties before $(NCrunchOriginalProjectDir) has been defined. This causes the same error case as above, although it happens later in the process (just before a build is started).
The third potential issue is more related to the assumptions this code makes about the structure of the workspace NCrunch has constructed to hold this project. If this workspace doesn't have 'SomeDirInPath' in its path, then things will go wrong. This may be perfectly OK if you have the project set up to use dependencies that exist further up the solution structure and NCrunch's relative path emulation successfully builds the workspace in the way your code is expecting it to be, but I would check this carefully as without upwards relative dependencies being specified from the project, NCrunch assumes that directories above the project's directory aren't important.
Anyway, try the following alternative code:
<BASEDIR Condition="'$(BASEDIR)' == '' AND '$(NCrunchOriginalProjectDir)' == ''">$(MSBuildProjectDirectory.Substring(0, $(MSBuildProjectDirectory.ToUpper().IndexOf(`\SOMEDIRINPATH`))))</BASEDIR>
<BASEDIR Condition="'$(BASEDIR)' == '' AND '$(NCrunchOriginalProjectDir)' != ''">$(NCrunchOriginalProjectDir.Substring(0, $(NCrunchOriginalProjectDir.ToUpper().IndexOf(`\SOMEDIRINPATH`))))</BASEDIR>
Thank you very much for explaining.
Was swamped with other stuff, so I could not get it working yet. You were right, I need to handle the fact that ncrunch does not copy whole tree nicely, but what was something like d:\a\b\c\d\e.csproj can become d:\ncrunchdir\c\d\e.csproj, but even with calculating for that it did not work, how it finally started working is by adding in the condition that IndexOf returns >= 0. It is still mystery to me why is that condition needed, as all csproj files are under the same tree, but it works now. Thank you again for explaining.
Was swamped with other stuff, so I could not get it working yet. You were right, I need to handle the fact that ncrunch does not copy whole tree nicely, but what was something like d:\a\b\c\d\e.csproj can become d:\ncrunchdir\c\d\e.csproj, but even with calculating for that it did not work, how it finally started working is by adding in the condition that IndexOf returns >= 0. It is still mystery to me why is that condition needed, as all csproj files are under the same tree, but it works now. Thank you again for explaining.
Edited 15 Apr 2015 20:02 UTC
Post a reply
Log in to reply.