I'm currently looking into options to port a WPF-oriented library to a PCL library so that it can be used on multiple platforms, specifically Windows Store Applications.
From what I understand, a Portable Class Library references a subset of .NET libraries which are supported on the platforms you target, and is limited to the following assemblies:
And Microsoft adds the following to that:
However, not all of these assemblies are supported on all platforms. In a Portable Class Library project, you specify the platforms you want to target, and only the supported assemblies for those platforms are referenced in your project. If you try to reference an assembly that is not supported for the platforms you have targeted, Visual Studio warns you of the incompatibility. The core assemblies (mscorlib.dll, System.dll, System.Core.dll, and System.Xml.dll) are supported on all platforms.
Now, when making a PCL library, the only reference I get is .NET Portable Subset
, and I can't add any reference to it; VS will tell me all possible references have been added already.
Now my question is quite simple: when are the actual references determined, and who determines these? Is it done by the compiler at compile time, or does the CLR do it at runtime?
when are the actual references determined,
At runtime of course, the only time when it can be discovered that your code actually runs on, say, Silverlight.
and who determines these?
The CLR. It maps the retargetable assembly reference inside your compiled assembly to the concrete assembly that's available on the machine. Retargeting is a generic capability of later CLR versions, that's for example how you can use a .NET 2.0 assembly in a .NET 4.0 program. Even though it has a reference to mscorlib version 2.0.0.0 but runs with 4.0.0.0
Much the same in a PCL library, it will target version 2.0.5.0 of mscorlib.dll, a version that does not actually exist. This fake assembly reference is produced by the reference assemblies that you compile your program with. They are stored in c:\program files (x86)\reference assemblies. The compiler doesn't know any better than that the version is real. There are many sets of the reference assemblies, called profiles, engineered to expose only the types that you can hope to use on the target machine. When you start a PCL project then you pick the targets and that automatically picks the correct profile, one collection out of the set of reference assemblies that's guaranteed to work on any of the targets you picked. The more targets you select, the less types you can use in your library code.
This retargeting can of course only be done for "known" assemblies, the ones that the CLR has pre-built knowledge on how to map. Which is why you cannot add an arbitrary framework assembly reference, there would be no hope that the CLR maps it to the correct one at runtime. And most of all, little hope that it will actually be available on the machine.