从单个.csproj构建(非PCL)Monotouch或.net dll

时间:2013-02-07 19:27:24

标签: .net msbuild xamarin.ios reusability mono.cecil

跨.NET和Monotouch的代码重用已经以多种方式解决,但大多数技术涉及并行的项目/解决方案集。

我想要这个问题来澄清是否有可能使用单个csproj文件构建 .NET或相同程序集的MonoTouch版本,基于所选平台和配置。

假设如下:

  1. 构建计算机运行Windows。
  2. Visual Studio和MSBuild可用。
  3. 该方法不需要在MonoDevelop上工作,因为MonoDevelop目前没有为MonoTouch启用XBuild / MSBuild。
  4. 可以使用有效的MonoTouch安装中的MonoTouch二进制文件。
  5. 只需要构建一个库,而不是一个完整的应用程序。这个库:
    1. 不包含任何.xib或plist。
    2. 是否使用特定于平台的代码,这些代码将有条件地编译。
    3. 是否引用特定于平台的程序集(必要),并且这些程序集需要由.csproj文件处理。
  6. 问题:鉴于这些假设,图书馆可以

    1. 针对Windows .NET编译或
    2. 二进制复制到Mac后,编译为通过MonoTouch应用解决方案直接引用。
    3. 基于当前的Visual Studio平台和配置?

      当前研究

      1. MonoTouch解决方案可以使用在Windows上编译的可移植库这一事实,这有可能带来一些希望。
      2. 在为MonoTouch构建时,在.csproj中使用<NoStdLib>true</NoStdLib>,以及System,System.Core,System.Xml等的不同HintPath似乎是必要的。
      3. 不确定如何在构建MonoTouch时引用正确版本的mscorlib。

2 个答案:

答案 0 :(得分:3)

事实证明,MSBuild实际上很可能。 关键点,假设您开始使用为Windows .NET创建的C#项目,您也想为iOS编译,如下所示。 注意:这不适用于MonoDevelop。它仅适用于Visual Studio。这是因为MonoDevelop目前不使用完整的MSBuild兼容的MonoTouch构建系统。

  1. 为iOS创建一个名为iOS的新解决方案和项目平台。这用于编译MonoTouch的项目。您可以将此任何名称命名,但在后面的内容中使用该名称。
  2. 对于iOS平台,将NoStdLib设置为true以避免自动引用mscorlib.dll。还要设置一个目录的路径,该目录包含从Mac上的MonoTouch安装中复制的MonoTouch dll的本地副本:

    <PropertyGroup Condition="'$(Platform'=='iOS'">
      <NoStdLib>true</NoStdLib>
      <iOSLibs>c:\MonoTouch\</iOSLibs>
    </PropertyGroup>`
    
  3. 从文件夹中添加对所有引用的MonoTouch程序集的本地副本的引用:

    <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>
    
  4. Visual Studio会自动添加引用所有.NET程序集的ItemGroup。由于我们已经指示Visual Studio / MSBuild在构建iOS时从iOSLibs文件夹中获取这些内容,因此我们应该有条件地禁用默认程序集。这阻止了VS抱怨重复的程序集引用。更改ItemGroup的第一行并添加条件,如下所示。 (注意:程序集列表将根据项目当前引用的内容而有所不同。)

    <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>
    
  5. 现在你准备好了。为解决方案中的所有项目完成此操作后,您可以从解决方案下拉列表中选择iOS,并构建MonoTouch二进制兼容程序集,如magic,,无需使用可移植类库! (这并不意味着PCL没用,它们肯定是,但这里显示的技术更普遍适用。)

    更详细的MSBuild知识及其相当大的功能将帮助您进一步简化,例如:

    1. 将上述大部分内容移动到一个可以从所有项目文件中引用的公共MSBuild文件中,以消除重复。
    2. 使用<DefineConstants>...</DefineConstants>定义编译器常量,以允许代码根据当前解决方案和配置以不同方式执行操作。

答案 1 :(得分:1)

从技术上讲,应该可以使用https://github.com/jbevain/cecil之类的工具重写生成的程序集以定位不同的平台,但我认为这不值得付出(巨大的)努力。拆解和重建是另一种(昂贵的)选择。

如果您的问题是关于重新定位第三方提供的程序集,并且这是您唯一的计划,请确保您没有违反任何许可条款。

现在,如果您可以删除一些假设,并使用不同的构建系统(如rake或make),您还可以在构建文件级别实现不使用PCL的代码共享。

希望它有所帮助。