Create (not PCL) Monotouch or .net dll from one .csproj

Code reuse in .NET and Monotouch has been covered in many ways, but most of the techniques involve concurrent sets of projects / solutions.

I would like this question to clarify whether it is possible to build using the same csproj file either .NET or a MonoTouch version of the same assembly based on the platform and configuration chosen.

Let's assume the following:

  • The collector runs Windows.
  • Visual Studio and MSBuild are available.
  • This method is not needed for MonoDevelop, as MonoDevelop does not currently support XBuild / MSBuild for MonoTouch.
  • MonoTouch binaries are available from actual MonoTouch installation.
  • Only the library needs to be created, not the complete application. This library:
    • Doesn't contain .xib or plists.
    • Uses platform specific code to be conditionally compiled.
    • Does the reference assembly have specific assemblies (required) and they should be processed by the .csproj file.

Question . Given these assumptions, could the library be

  • Compiled for Windows .NET or
  • Compiled for direct reference with MonoTouch app solution after copying binary to Mac.

based on the current platform and Visual Studio configuration?

Current research

  • The fact that portable libraries compiled on Windows can be used by MonoTouch solutions gives some hope that this is possible.
  • Using <NoStdLib>true</NoStdLib>

    in .csproj when building for MonoTouch along with different ones HintPath

    for System, System.Core, System.Xml, etc. seems to be necessary.
  • Not sure how to reference the correct version of mscorlib when building for MonoTouch.
+3


source to share


2 answers


It turns out that this is indeed possible with MSBuild. The key points if you are starting with a C # project built for Windows.NET that you want to compile for iOS as well are the following. Note: this does not work with MonoDevelop. It only works with Visual Studio. This is because MonoDevelop does not currently use a full MSBuild compliant build system for MonoTouch.

  • Create a new solution and project framework for iOS called iOS. This is used to compile a project for MonoTouch. You can name it whatever you want, but use the name consistently from now on.
  • For iOS platform, set NoStdLib to true to avoid automatic reference to mscorlib.dll. Also provide the path to the directory that contains local copies of the MonoTouch libraries copied from your Mac installation of MonoTouch:

    <PropertyGroup Condition="'$(Platform'=='iOS'">
      <NoStdLib>true</NoStdLib>
      <iOSLibs>c:\MonoTouch\</iOSLibs>
    </PropertyGroup>`
    
          

  • Add links to local copies of all listed MonoTouch assemblies from the folder:

    <ItemGroup Condition="'$(Platform'=='iOS'">
      <Reference Include="mscorlib">
        <HintPath>$(iOSLibs)\mscorlib.dll</HintPath>
      </Reference>    
      <Reference Include="System">
        <HintPath>$(iOSLibs)\System.dll</HintPath>
      </Reference>    
      <Reference Include="System.Core">
        <HintPath>$(iOSLibs)\System.Core.dll</HintPath>
      </Reference>    
      <Reference Include="System.Xml"> 
        <HintPath>$(iOSLibs)\System.Xml.dll</HintPath>
      </Reference>
      <Reference Include="System.Xml.Linq"> 
        <HintPath>$(iOSLibs)\System.Xml.Linq.dll</HintPath>
      </Reference>
      <Reference Include="monotouch">
        <HintPath>$(iOSLibs)\monotouch.dll</HintPath>
      </Reference>    
    </ItemGroup>
    
          

  • Visual Studio automatically adds an element group that references all .NET assemblies. Since we instructed Visual Studio / MSBuild to get them from the iOSLibs folder when building for iOS, we must conditionally disable the default build. This stops VS from complaining about duplicate assembly references. Modify the first line ItemGroup

    and add the condition as follows. (Note: the list of assemblies will differ depending on what your project is referring to.)

    <ItemGroup Condition=" '$(Platform)' != 'iOS' ">
      <Reference Include="System" />
      <Reference Include="System.Core" />
      <Reference Include="System.Drawing" />
      <Reference Include="System.Windows.Forms" />
      <Reference Include="System.Xml.Linq" />
      <Reference Include="System.Data.DataSetExtensions" />
      <Reference Include="Microsoft.CSharp" />
      <Reference Include="System.Data" />
      <Reference Include="System.Xml" />
    </ItemGroup>
    
          

You are now ready to go. Once you've done this for all projects in your solution, you can select iOS from the Solution dropdown and create binary compatible MonoTouch assemblies like magic without using portable class classes! (This does not mean that PCLs are not useful, they certainly are, but the method shown here is much more generally applicable.)



A more detailed knowledge of MSBuild and its significant power will help you simplify even further, for example:

  • Moving most of the above into a generic MSBuild file that you can reference all of your project files to eliminate duplication.
  • Defining compiler constants with <DefineConstants>...</DefineConstants>

    so your code can do things differently based on the current solution and configuration.
+3


source


Technically, it should be possible to rewrite the generated assembly for the target platform using tools like https://github.com/jbevain/cecil , but I don't know, I think it's worth the (huge) effort. Disassembly and rebuilding is another (expensive) option.

If you are asking a question about retargeting a build provided by a third party and this is your only plan, make sure you are not breaking any of the licensing terms.



Now, if you can remove some of your assumptions and use a different build system (like rake or make), you can also achieve PCL-free code sharing at the buildfile level.

Hope it helps.

+1


source







All Articles