Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Are Runtime Identifiers supported?
ghelyar
#1 Posted : Wednesday, August 7, 2019 11:38:43 AM(UTC)
Rank: Member

Groups: Registered
Joined: 12/19/2016(UTC)
Posts: 15
Location: United Kingdom

Thanks: 4 times
Was thanked: 2 time(s) in 2 post(s)
I have a nuget package that has some native .dlls and a .net p/invoke wrapper for them.

It uses runtime identifiers to deploy the correct native .dll e.g. in the .nupkg it has /runtimes/win-x64/native/foo_native.dll as well as others for other RIDs.

When adding this package to a project, adding <RuntimeIdentifier>win-x64</RuntimeIdentifier> to the .csproj of the application (or unit test project) causes the project to build to e.g. Debug\net472\win-x64\ with foo_native.dll in the output. Without the RID it still builds, but the native dll is missing from Debug\net472\

When running these tests from Visual Studio Test Explorer or vstest.console.exe, or dotnet vstest, the native dll is found and the tests run fine.

When running these tests from NCrunch 3.29.0.7, they fail because the native dll is missing, implying it is not building with the correct RID.

Adding <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath> to the unit test project's csproj does not help.

Are RIDs currently supported?

If not is there any workaround for this? Can additional arguments be passed to the build? The missing dll only exists in the nuget package, so it has no path in the source tree before the test project is built.
ghelyar
#2 Posted : Wednesday, August 7, 2019 12:35:15 PM(UTC)
Rank: Member

Groups: Registered
Joined: 12/19/2016(UTC)
Posts: 15
Location: United Kingdom

Thanks: 4 times
Was thanked: 2 time(s) in 2 post(s)
"Copy Referenced Assemblies To Workspace" seems to do the trick, but has obvious disadvantages. Is there a better way?

Being able to test multiple RIDs is very similar to being able to test multiple target frameworks, but if it isn't already supported then that would be a feature request.
Remco
#3 Posted : Thursday, August 8, 2019 2:09:13 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 6,976

Thanks: 931 times
Was thanked: 1257 time(s) in 1170 post(s)
Hi, thanks for sharing this issue.

To date, we have done no work to implement special handling for RIDs. I am not knowledgeable about RIDs, so I can't provide reliable guidance on any workarounds ... but from what you've described, I suspect that it might be possible to have this work by implementing some custom logic inside your tests to resolve the files across workspaces.

How are the native assemblies being solved at runtime? Are you letting the CLR handle it, or do you have custom logic used to find and resolve them?

It might be possible to use NCrunchEnvironment.GetAllAssemblyLocations() to find the DLLs inside the workspace and resolve them manually.

ghelyar
#4 Posted : Thursday, August 8, 2019 7:37:41 AM(UTC)
Rank: Member

Groups: Registered
Joined: 12/19/2016(UTC)
Posts: 15
Location: United Kingdom

Thanks: 4 times
Was thanked: 2 time(s) in 2 post(s)
When the nuget package contains a native dll in /runtimes/{RID}/native/foo.dll and the top level application or unit test project is built with that RID either by specifying in the csproj <RuntimeIdentifier>{RID}</RuntimeIdentifier> or on the command line with dotnet build -r {RID} (I think msbuild /p:RuntimeIdentifier={RID} also works) the native dll is placed in the output directory. From that point, the .net dll from the nuget package can contain P/Invoke with [DllImport("foo")] in order to import the exported native function, and consumers of the nuget package can just use the nuget package like a normal .net package, as long as they set the RID on the application or unit test project.

If building without the RID, the .net wrapper library that contains the P/Invoke will be deployed to the output directory, but the native library will not, in which case it will throw an exception: System.DllNotFoundException: Unable to load DLL 'foo'

You can also specify multiple RIDs in the csproj e.g. <RuntimeIdentifiers>win-x86;win-x64;linux-x64</RuntimeIdentifiers> and then dotnet build (or dotnet publish -r {RID}) will produce an output directory for each RID, each with the appropriate assemblies, in a similar way to <TargetFrameworks>

It may just be because NCrunch is using msbuild (I assume) rather than dotnet build, and dotnet build is probably doing something on top of what msbuild does. Passing the RuntimeIdentifier/RuntimeIdentifiers properties from the csproj to msbuild /p: may fix it, or switching to dotnet build, perhaps by an option in the NCrunch project config.
Remco
#5 Posted : Thursday, August 8, 2019 9:10:54 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 6,976

Thanks: 931 times
Was thanked: 1257 time(s) in 1170 post(s)
If I understand this, the main issue is that by default, NCrunch doesn't place these files adjacent to the referencing assembly inside the build output directory.

There are many toolsets and setups that require files to be collocated. In many cases we've adopted workarounds to force them into compliance with the files in different locations (as we can massively improve performance when it's like this), but for all the other ones, we're stuck with the 'Copy referenced assemblies to workspace' setting.

At this stage I think it's unlikely we'll immediately be able to do better than just turning on this setting. When you have this setting turned on, your build system under NCrunch functions in the same manner as a normal VS/MSBuild run would, by ensuring each built assembly has its dependencies adjacent to it... So we do less funky stuff and things tend to work better, if a bit slower.
1 user thanked Remco for this useful post.
ghelyar on 8/8/2019(UTC)
talbrecht
#6 Posted : Friday, February 10, 2023 11:01:39 AM(UTC)
Rank: Member

Groups: Registered
Joined: 5/10/2019(UTC)
Posts: 11
Location: Germany

Thanks: 6 times
Was thanked: 3 time(s) in 3 post(s)
Hi Remco.

I'm using the current version (4.16.0.4) and stumbled over the same MSBuild error yesterday. My colleague started to use single file deployment which required the RID somehow. I've added a "dotnet restore -r win-x64" as prebuild event to our project to run a restore with RID explicitly as workaround.

What's the current state regarding runtime identifier support? Do you plan to respect the RuntimeIdentifier element in the project file? E.g. by running "dotnet restore" or MSBuild with the runtime identifier internally.

Best regards,
Thomas
Remco
#7 Posted : Friday, February 10, 2023 10:55:55 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 6,976

Thanks: 931 times
Was thanked: 1257 time(s) in 1170 post(s)
Hi Thomas,

Thanks for sharing this problem. Can you confirm whether the 'Copy referenced assemblies to workspace' made any difference here?

At the moment, this is still considered to be an edge case for us, so for now the focus is simply on finding a suitable workaround. Running dotnet restore inside a pre-build event is not something I would usually recommend, and I'm interested to know why this works for you as I wouldn't expect it to resolve path copying issues. Maybe we can find a cleaner way to solve this problem with configuration or extra code in the right place.
talbrecht
#8 Posted : Monday, February 13, 2023 9:30:20 AM(UTC)
Rank: Member

Groups: Registered
Joined: 5/10/2019(UTC)
Posts: 11
Location: Germany

Thanks: 6 times
Was thanked: 3 time(s) in 3 post(s)
Hi Remco.

I confirm that 'Copy referenced assemblies to workspace' solves my issue, too.

I'm using this approach now. Using 'dotnet restore' as pre-build event was just the first working fix I've found.

Best regards,
Thomas

PS: Another solution should work, too: Use conditional build behavior like $NCrunch to fall back to old project setup without single file deployment and RID usage.
1 user thanked talbrecht for this useful post.
Remco on 2/13/2023(UTC)
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

YAF | YAF © 2003-2011, Yet Another Forum.NET
This page was generated in 0.210 seconds.
Trial NCrunch
Take NCrunch for a spin
Do your fingers a favour and supercharge your testing workflow
Free Download