微信号:hj-academy

介绍:关注开发者在实际应用中遇到的问题.提供最真实的干货,以技术会友,为广大的开发者提供最直接的交流平台.

使用CodeTyphon实现库文件跨越Android和iOS平台

2016-06-07 09:47 何晓杰

            有很多情况下,我们都希望将一套代码用在各个平台,以减轻工作量。除开UI和与系统密切相关的部分外,业务逻辑都是通用的。而更为底层的模块,如加解密模块,压缩模块,甚至各种工具等,我们也都希望它是跨平台的,一方面降低开发和维护成本,另一方面也保证各平台的逻辑统一。本文我们就来探讨这种实现的可能性。

 

            首先也借这个机会再次推广下 CodeTyphon,它是一个非常难能可贵的、几乎可以跨全平台的强悍工具,我也已经在 CC 上开了课程,地址是:http://www.cctalk.com/course/161021604561/,大家若有兴趣,可以前去观看或是每周三参加直播。

 

            用 CodeTyphon 来实现安卓的 so 文件编译是很轻松的事情,只需要安装后下载相关 Library 和 Toolchain,然后编译 crosselements 即可。在 Ubuntu 下尤其好用,通常情况下我们只需要编译 arm-android, mipsel-android 和 i386-android 就够了。但是要将程序编译到 iOS 上,由于需要 Mac,而 CodeTyphon 在 Mac 上也并非很给力,所以我们就需要做很多额外的工作,会比较折腾。

 

            说了这么多,先把 Mac 下的环境搭起来吧,首先下载编译 CodeTyphon ,下载地址就不贴了,随处能找得到。当前版本的 CodeTyphon 内置 3.1.1 版本的 FPC,我们需要的正是该版本的 FPC。另外,我们还需要 FPC 源码,用以编译出支持 iOS 的跨平台编译器。

 

            安装完 CodeTyphon 后,我们可以找到其内带的 FPC。为了方便起见,我们定义一些环境变量:

 


Linux 下用这个

$ export FPC=/usr/local/codetyphon/fpc/fpc64/bin/x86_64-linux/fpc

Mac 下用这个(Mac 下有个比较坑的地方,要跨 iOS 必须使用 32 位的原始编译器)

$ export FPC=/usr/local/codetyphon/fpc/fpc32/bin/i386-darwin/ppc386

$ export OUT=/usr/local/lib/fpc/3.1.1

$ export IOS_PLATFORM=/Applications/Xcode.app/Contents/Developer/Platforms

$ export TYPHON=/usr/local/codetyphon


 

            下面是完整的步骤了,一堆命令,按顺序输入就行:

 


$ svn checkout http://svn.freepascal.org/svn/fpc/trunk/Developer/FPC/3.1.1

$ cd /Developer/FPC/3.1.1

$ sudo make distclean

$ sudo make FPC=${FPC} OPT="-ap" distclean all

$ sudo make FPC=/Developer/FPC/3.1.1/compiler/ppc386 install

$ sudo make distclean

$ sudo make FPC=${FPC} CPU_TARGET="x86_64"OPT="-ap" distclean all

$ sudo make crossinstall CPU_TARGET=x86_64

$ suod mv ${OUT}/ppcrossx64 ${OUT}/ppcx64

$ sudo make distclean

$ export IOS_BASE=${IOS_PLATFORM}/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk

$ export BIN_BASE=${IOS_BASE}/usr/bin

$ sudo make FPC=${FPC} OPT="-ap"CPU_TARGET=aarch64 CROSSOPT="-FD${BIN_BASE} -XR${IOS_BASE}" all

$ sudo make FPC=/Developer/FPC/3.1.1/compiler/ppcrossarmOPT="-ap" CPU_TARGET=aarch64 CROSSOPT="-FD${BIN_BASE}-XR${IOS_BASE} -ap" install CROSSINSTALL=1  


 

            到这一步,真机的环境就已经搭建完成了,如果你还需要在模拟器调试,可以再编译 x86_64 版本的编译器:

 


$ sudo make distclean

$ export IOS_BASE=${IOS_PLATFORM}/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk

$ export BIN_BASE=${IOS_BASE}/usr/bin 

$ sudo make FPC=${FPC} OPT="-ap" CPU_TARGET=x86_64OS_TARGET=iphonesim CROSSOPT="-FD${BIN_BASE} -XR${IOS_BASE}" all

$ sudo make crossinstall CPU_TARGET=x86_64OS_TARGET=iphonesim


 

            下面就可以写一个简单的程序来进行验证:

 


library libdemo;

 

{$mode objfpc}{$H+}

 

uses

  cthreads, ctypes,math, classes, sysutils, jni2, jni_utils;

 

function hello(name: PChar): PChar; cdecl;

var

  ret: string;

begin

  ret := Format('Hello%s', [string(name)]);

  Result :=strAlloc(Length(ret));

  strcopy(Result,PChar(ret));

end;

 

function Java_com_sample_NativeLib_hello(env: PJNIEnv; obj:jobject; name: jstring): jstring; stdcall;

var

  namestr: string;

  ret: PChar;

begin

  namestr :=jstringToString(env, name);

  ret :=hello(PChar(namestr));

  Result :=stringToJstring(env, string(ret));

end;

 

exports

  hello,

 Java_com_sample_NativeLib_hello;

 

begin

 SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow,exUnderflow, exPrecision]);

end.

 



            这个程序只导出 hello 方法,并且有通用和 jni 两种形式,我们可以用简单的方式来进行编译:

 


$ fpc -Scghi demo.pas      



            这样就直接得到一个用于 linux 下的 libdemo.so (或者 mac 下的 libdemo.dylib)文件,如果要编译到 Android 平台使用,则可以添加一些参数:

 


$ fpc -Tandroid -Parm -Scghi -Fl${TYPHON}/binLibraries/android-4.4-api19-armdemo.pas


 

            这样就得到了一个可用于 Android ARM 架构的 so,如果要编译其他架构的 so,可以将 -P 后面的参数更改为 mipsel 或 i386 等。

 

            如果要跨 iOS 平台,可能就不那么顺利了,因为 iOS 平台不支持使用 dylib,会导致审核被拒,苹果只接受静态库。因此我们必须将这份代码编译成 .a,并且在 iOS 工程内进行链接。

 

            查阅了相当多的资料都表明,CodeTyphon 并不支持直接编译为静态库,但是在往常的开发经验中,我们知道只要有 .o 文件,就可以得到 .a,因此就有了下面的命令:

 


$ ${OUT}/ppcrossa64 -Tdarwin -Cn demo.pas

$ ar -q libdemo.a `grep "\.o$" link.res`

$ ranlib libdemo.a


 

            此时我们能够得到一个 libdemo.a 文件,这个文件即包含了导出的 hello函数。需要注意的是,在生成 iOS 相关的文件的时候,-T 参数应当是 darwin,在查阅 fpc 本身的命令帮助时,发现可以选填 ios,但是这一选项是无效的,只能选 darwin,另外,如果要生成模拟器用的 .a 文件,应该用 ppcx64,命令如下:



$ ${OUT}/ppcx64 -Tiphonesim -Cn demo.pas






如果要检查函数是否正常导出了,可以用以下命令:

 


$ nm libdemo.a | grep hello


 

            现在我们就可以将这个静态库链接到iOS工程内了,只需要再添加一个头文件即可完成调用,具体方法就不再赘述了。


 
沪江技术学院 更多文章 深度学习 干货 | 原来你是这样的 setTimeout GoogleDeveloperDay回顾 Docker实践 | 来自沪江、滴滴、蘑菇街架构师的交流分享 实现 APK 保护时常见的坑和解决方案
猜您喜欢 推荐书单第一季 如何引发流行:《引爆点》 头条丨百度连续三年获得亚洲专利精英奖 关于启用 HTTPS 的一些经验分享 【会议】Zabbix中国区峰会2016