编译LibPDFium.so:三、编译最新稳定版本的PDFium
网上流传的旧版本编译方法(GYP),编译出来的pdfium没有高亮标注等功能。所以需要探索新版本的编译方法。
一、window 编译。
之前提过 vs_pdfium ,完全可以在windows平台使用VS编译 Pdfium 并运行测试。不过产物(静态库)竟然达到了上百兆,着实吓退了一波。
通过调整编译参数,比如打开代码优化O2,开启多线程编译/MP,取消生成debug信息等,上面的项目可以在数分钟内编译成45MB左右的静态库。
参考 pdfium-binaries ,如果编译成dll的话产物很小的,所以尝试编译成dll动态库,结果只有5.4
兆字节,再次充满信心!
主要是周围模块编译成静态库,最后fpdfsdk
模块链接这些模块,生成动态库。代码生成方式仍然是MD。
下面将过程从头“录制”一遍:
1. 获取代码。
gclient config --unmanaged https://android.googlesource.com/platform/external/pdfium
gclient sync
第一句生成一个.gclient文件,第二句正式开始拉取。关于代理设置,不同代理协议做法不同,有的直接就可以联网拉取代码,有的则须额外配置git proxy,参见系列第一篇。
使用 gclient sync 主要是将配套的依赖库也下载下来。可以修改DEPS
跳过v8、skia等暂时不需要的模块。若反复出现Still working on:
不用慌,后台仍在下载,可以通过查看临时文件夹的大小估算下载速度。(任务管理器中没有显示相应的流量访问)
若依循官方指引,运气好的话可以继续下去,不过运气不好,卡在了 gn args out/release
上面,先是让安装Windows 10 SDK version 10.0.19041.0,装完了又报错说找不到 user32.lib。
所以参考 vs_pdfium 手动搭建vs项目。
2. 编译稳定分支
PDFium仓库有两个:https://android.googlesource.com/platform/external/pdfium 和 https://pdfium.googlesource.com/pdfium.git
我下载下来的是安卓的仓库。切到最新的稳定分支,android11-mainline-release
。
然后目标是用VS编译出 fpdfsdk.dll。检查各模块的 BUILD.gn 得知编译范围,项目工程我直接复用 vs_pdfium 的,需要将新的源代码文件添加到工程中去。VS 并不擅长做这个,仅仅一两百个文件拖进去,就会卡住一会儿。
所以一部分文件我选择手工拖拽添加,另外一些则通过直接修改工程文件 (*.vcxproj
和*.vcxproj.filters
) 加入。
其中 fpdfsdk 模块会编译成最后的动态库,其 c++预定义中的 static 须改为 COMPONENT_BUILD;FPDF_IMPLEMENTATION;FPDFSDK_EXPORTS;
。
最好先从小的第三方模块开始编译,比如zlib。
第三方模块中,一些模块需要应用patch修改,比如 freetype。在根目录进入bash,应用指令为patch -p0 < third_party/freetype/0000-include.patch
。
另一个模块 libjpeg_turbo 则有部分的汇编代码,需用 nasm.exe 编译。参考项目Libjpeg-turbo-VS,在VS中可以很方便地书写自定义编译指令。
nasm.exe -fwin$(PlatformArchitecture) -DWIN$(PlatformArchitecture) -D__x86_64__ %(FullPath) -i$(SolutionDir)pdfium_lib\pdfium\third_party\libjpeg_turbo\simd\x86_64 -i$(SolutionDir)pdfium_lib\pdfium\third_party\libjpeg_turbo\simd\nasm -o$(Platform)\$(Configuration)\%(Filename).obj
编译成功后,得到 5.39MB 的 fpdfsdk.dll,测试项目链接上它的导入库 fpdfsdk.lib,最后成功编译运行。
二、为安卓交叉编译 PDFium.so
1. 使用 bash 与 ndk 路线。
编译 libjpeg_turbo 时,windows 平台的数个 *.asm 换成了一个 .S 文件,clang工具链可以直接编译这样的汇编代码,无需额外下载 yasm。
当然也可以和旧版一样使用 libjpeg,不过libjpeg的部分代码需要修改。
JNI层的FPDFDest_GetPageIndex
换成了FPDFDest_GetDestPageIndex
。
与旧版相比,性能不升反降。简单测试下,接连渲染 Gpu Pro 1.pdf 的前十页,发现性能有轻微下降。经查,是内存管理模块 thirdparty/base 引起的。
2. 使用 cmake 编译。
大同小异,已更新开源仓库(包含最新的Pdfium源码)。与上文一样进行了性能测试,额外测试了代码优化选项对性能以及体积的影响:
- 无优化 : 夸张地用了4秒多才渲染完前十页。大小 10MB。
- -Os : 700ms 左右。大小 6.15MB。
- -O3 : 与上文一致。大小 6.49MB.