Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting PCL, Mvvmcross, Nuget and Xamarin Studio to play "nice" on Mac

Looking at the MvvmCross.PortableSupport.3.0.1.nuspec I noticed the there is the following line:

<file src="_._" target="lib\portable-win+net45+MonoAndroid16+MonoTouch40+sl40+wp71\_._" />.

I understand that nuget is creating a list of supported frameworks from that list (win+...+sl40+wp71) and that the project to which this library is added must support one of those frameworks. Basically it enumerates the project types to which this can be added.

Now if I try to install this package into a portable project having Profile49 this will work on Windows since Profile49 on Windows is net45+wp80.

However on the Mac the Profile49 is net45+wp80+MonoAndroid10+MonoTouch10.

This means that a nuget package with the supported frameworks win+net45+MonoAndroid16+MonoTouch40+sl40+wp71 cannot be installed on a project of Profile49 on Mac since there are frameworks having a lower version (MonoTouch10 and MonoAndroid10).

  • Could the string portable-win+net45+MonoAndroid+MonoTouch+sl40+wp71 be used on the mvvmcross side instead? Any reason for the specific versions?

  • Why do the profiles shipped with Xamarin (e.g. /Library/Frameworks/Mono.framework/External/xbuild-frameworks/.NETPortable/v4.5/Profile/Profile49) include MonoTouch10 and MonoAndroid10?

Thank you for your insights.

like image 229
revau.lt Avatar asked Jul 15 '13 11:07

revau.lt


2 Answers

Update: If you are using the Alpha channel of Xamarin Studio there is no longer a need to copy PCLs from Windows. You can use v4.0, Profile158, this also works out of the box with Async.

Update: I added instructions on how to get async to work in PCL in this article: Xamarin Studio Mac, Portable class library, Async and Android, so go there after this article if you want to work with async in your PCL.

A sort of working solution to the problem I had to get Mvvm+PCL+Xamarin Studio on Mac to work. See below for the details.

The steps below make things work for Android and PCL projects. For iOS projects Xamarin Studio on Mac is communicating a TargetFramework of MonoTouch,Version=v1.0 to Nuget. Since the mvvm packages contain +MonoTouch40 Nuget refuses to install the packages on the project. A workaround is to add

  <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>

to the .csproj, add the packages with Nuget and set TargetFrameworkVersion back to v1.0.

I have verified the behaviour in Visual Studio. There a project with TargetFramework MonoTouch,Version=v4.0 is reported to the Nuget plugin. This is why the same packages work on Visual Studio an not on Xamarin Studio Mac. I guess this should be corrected to be consistent.

Steps

Xamarin Studio

  1. Make sure to use the Beta or Alpha channel in Xamarin Studio under Mac
  2. Install the Nuget package manager: Xamarin Studio / Add-In Manager

Install .NETPortable into Mono.Framework

  1. Copy the .NETPortable (C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETPortable) folder from a Windows PC to your Mac
  2. Place it under /Library/Frameworks/Mono.framework/External/xbuild-frameworks/.NETPortable/ (Make sure not to overwrite an already existing folder, in case this gets shipped with Xamarin Studio!!!) (see here also)

Patch Nuget

A patched fork can be found here: https://nuget.codeplex.com/SourceControl/network/forks/takoyakich/nuget/latest, take the 2.7 branch. If you want to patch yourself:

git clone https://git01.codeplex.com/nuget
cd nuget
git checkout -b 2.7 origin/2.7 

patch -p1 < {patch file saved from below}

cd src/Core
xbuild

cp bin/Debug/NuGet.Core.dll  ~/Library/Application\ Support/XamarinStudio-4.0/LocalInstall/Addins/MonoDevelop.PackageManagement.0.6/NuGet.Core.dll

Restart Xamarin Studio if you kept it open.

Test it!

  1. Open Xamarin Studio
  2. Create a new portable library
  3. On the project, go to options, Build/General you should see a dialog letting you choose the Target Frameworks (e.g. .net45+wp8 corresponds to Profile49)
  4. Goto references, Manage Nuget packages, Add Mvvmcross
  5. Follow one of @slodge 's excellent n+1 mvvmcross tutorial videos from here ...

Patch to Nuget.Core.dll:



    diff --git a/src/Core/NETPortable/NetPortableProfileTable.cs b/src/Core/NETPortable/NetPortableProfileTable.cs
    index 6f6a9ff..edc710c 100644
    --- a/src/Core/NETPortable/NetPortableProfileTable.cs
    +++ b/src/Core/NETPortable/NetPortableProfileTable.cs
    @@ -49,16 +49,12 @@ namespace NuGet
             private static NetPortableProfileCollection BuildPortableProfileCollection()
             {
                 var profileCollection = new NetPortableProfileCollection();
    -            string portableRootDirectory =
    -                    Path.Combine(
    -                        Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86, Environment.SpecialFolderOption.DoNotVerify),
    -                        @"Reference Assemblies\Microsoft\Framework\.NETPortable");
    -
    +            string portableRootDirectory = GetPortableRootDirectory ();
                 if (Directory.Exists(portableRootDirectory))
                 {
                     foreach (string versionDir in Directory.EnumerateDirectories(portableRootDirectory, "v*", SearchOption.TopDirectoryOnly))
                     {
    -                    string profileFilesPath = versionDir + @"\Profile\";
    +                    string profileFilesPath = Path.Combine(versionDir,"Profile");
                         profileCollection.AddRange(LoadProfilesFromFramework(profileFilesPath));
                     }
                 }
    @@ -66,6 +62,22 @@ namespace NuGet
                 return profileCollection;
             }

    +        private static string GetPortableRootDirectory()                                                                                                                                                                                                                                                                                               
    +        {                                                                                                                                                                                                                                                                                                                                              
    +            if (IsMonoOnMac ()) {                                                                                                                                                                                                                                                                                                                      
    +                return "/Library/Frameworks/Mono.framework/External/xbuild-frameworks/.NETPortable";                                                                                                                                                                                                                                                   
    +            }                                                                                                                                                                                                                                                                                                                                          
    +            return Path.Combine(                                                                                                                                                                                                                                                                                                                       
    +                Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86, Environment.SpecialFolderOption.DoNotVerify),                                                                                                                                                                                                                     
    +                @"Reference Assemblies\Microsoft\Framework\.NETPortable");                                                                                                                                                                                                                                                                             
    +        }                                                                                                                                                                                                                                                                                                                                              
    +                                                                                                                                                                                                                                                                                                                                                       
    +        static bool IsMonoOnMac ()                                                                                                                                                                                                                                                                                                                     
    +        {                                                                                                                                                                                                                                                                                                                                              
    +            // Environment.OSVersion.Platform returns UNIX, didn't find a better way :-(                                                                                                                                                                                                                                                               
    +            return File.Exists ("/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder");                                                                                                                                                                                                                                                      
    +        }       
    +
             private static IEnumerable<NetPortableProfile> LoadProfilesFromFramework(string profileFilesPath)
             {
                 if (Directory.Exists(profileFilesPath))

like image 180
revau.lt Avatar answered Nov 10 '22 07:11

revau.lt


As of February 2014, the steps above are not needed. Using Xamarin Studio 4.3.2, Alpha channel, and nuget addin via adding mrward's addin repository first and then installing nuget addin, I was able to switch the target to p49 and add the HotTuna pack directly to a new PCL project.

like image 39
Alexy Avatar answered Nov 10 '22 05:11

Alexy