How to solve conflicting dependencies from two different packages

Hi,

I have a package A that uses a dependency B ver 1
I have another package C that uses the same dependency B but ver 2

The application code itself must use A, C but also the dependency B, although version 2 only.

Is there a solution for this? One possible solution would be to use a global asmdef for the application and reference B V2 only in it, but having a global asmdefs doesn’t work well with plugins.

Maybe a solution would be to use the manifest so that it has A, C and explicitly B too but this doesn’t work if A and/or C are not distributed through the package manager system.

2 Likes

Hey there - I’ve heard back from the team who had this to share.

"We understand the question very well: there is a conflict present between the project dependencies, and this conflict needs to be addressed by the project author.

The project has the following form:

Project → A → B (v1)
Project → C → B (v2)
Project → B (v2)

There’s only one version of a package at a time, and clearly there is a conflict if package A doesn’t work with B (v2), you need to choose between either package A or package C. Another possible solution is to embed one of those package and fix the conflict present."

Thanks for the reply. If I got the answer correctly, there isn’t really a solution, but just workaround. These workarounds are not really viable if A, B and C are packages distributed, unless of course, change the packages locally.

I would prefer to use a project-wise asmdef, but as I said this doesn’t work well with plugins. One solution would be to give an option to asmdefs to be able to automatically solve global plugins dependencies.

Hi @sebas771 ,

I’m not entirely sure about your exact situation, but basically what @UnityMaru said is exact. There can only be one version of a package in the project, so if your project needs A@(whatever), B@2 and C@(whatever), this will only work if A and C both work with B@2. If B@2 breaks A, and B@1 breaks C, there is no combination that the Package Manager could ever choose which would work.

I also have trouble understanding where asmdefs come into play here, unless you’re talking about changing A to be compatible (using versionDefines and #if) with both B@1 and B@2 - or similarly, to make C and your code compatible with B@1. Either way, it means locally altering either of A or C. Or upgrading to a version of either package after their author updated it for this kind of compatibility.

Addendum: In order to make local changes to a distributed package, you can simply embed it into your project. So in your case, you could embed package A, and change the code to be compatible with package B@2.

Also, note that if using asmdefs for project code can somehow be a solution for you, it doesn’t have to be a project-wide asmdef - you can have multiple smaller asmdefs, scoped per area of the code that “stands on its own” (assuming the code is sufficiently decoupled for that). (Not sure whether that applies to your situation or not, but I thought I’d share the tip anyway. :))

I’m a bit curious about this idea. I’m not very familiar with plugins, or rather with all sorts of things people call plugins. Can you please clarify what you mean so we can validate and forward this to the proper team internally? Are we talking about native plugins for the Editor or Runtime platforms? Or managed plugins? Or code that gets compiled into Assembly-CSharp-firstpass.dll or Assembly-CSharp-firstpass-Editor.dll?

Resume this @maximeb_unity . I have never been interested to study how standard c# usually solve assembly conflicts, but my understanding is that it is able to. A quick search on Google also shows different articles about it.

My case is that I have this set of packages

6479519--727808--upload_2020-11-1_13-22-52.png

the application uses only

6479519--727811--upload_2020-11-1_13-23-10.png

while

com.sebaslab.svelto.common@2.9.9 is referenced only by com.sebaslab.svelto.tasks@1.5.8 and shouldn’t be known outside it.

My feeling is that if I reference only the last 3 packages in my application, I shouldn’t get an assembly conflict.

Of course in my manifest I have got only:

“com.sebaslab.svelto.common”:“com.sebaslab.svelto.common@3.0.0”,
“com.sebaslab.svelto.ecs”:“com.sebaslab.svelto.ecs@3.0.0”,
“com.sebaslab.svelto.tasks”:“com.sebaslab.svelto.tasks@1.5.8”,

this maybe aided by the auto-reference flag in the assembly, as I don’t want the old svelto.common dependency to be auto referenced, but I am not sure about this. It’s all just a guess.

There are some differences between the .NET runtime and Mono in Unity. Both run code written in C# and support the same .NET platform APIs, but there are key differences in how they build that code and run it.

While you’re absolutely right that you can load two different versions a DLL side-by-side in .NET, it’s not as straight-forward as you might hope (it’s certainly not automatic), and it involves configuring your C# projects and application manifest to tell the .NET runtime to load the appropriate DLLs for the right usage.

This configuration is not possible in Unity. Unity uses its own Mono-based compilation pipeline and its own scripting pipeline to load and the run compiled code. That means many of those .csproj-based and app.config-based configurations (as described in the link above) are not possible in Unity. On the other hand, it provides different tools for defining and controlling the compilation and scripting pipelines, such as asmdefs, asmrefs, Editor/compilation settings…

Unity has an extra challenge: the Asset Database, which uniquely identifies assets by GUID, and where one would expect different versions of the same asset to have the same GUID over time. This means it’s not possible to import two versions of the same asset without the Asset Database flagging that as a conflict. The apparent “solution” of changing GUIDs with every version of your code might be appealing, but it wouldn’t work reliably for many reasons (e.g. broken references to any Unity.Object-derived type).

So while I understand that intuitively you feel you should be able to use two versions of the same assembly in Unity because it’s possible in .NET, the unfortunate reality is that this is not possible today, as far as I know. This has to do with how the Asset Pipeline, Compilation Pipeline and Scripting Pipeline work. If you wish to pursue this discussion further, you might want to ask in the Scripting forum.

2 Likes

somehow I feel this will always be a problem for package distribution

2 Likes

I don’t have the time to verify what’s going on, but lately in my package manager two Mono.Cecil packages appear. I wonder how come they don’t conflict @maximeb_unity . Maybe they simple have two different dll names

6525847--736711--upload_2020-11-15_15-32-24.png

6525847--736714--upload_2020-11-15_15-32-50.png

6525847--736717--upload_2020-11-15_15-32-59.png

1 Like