如何构建一个pdfium.so

前言

项目中接入了打开pdf文件的功能,使用的是https://github.com/barteksc/PdfiumAndroid/。现在想升级一下pdfium库,旧库具体原因就不解释了,毕竟这个项目最后一个commit在6年前,当然,平常用来接入打开pdf也是没问题的。

开源库

在google一通搜索,发现pdfium库包含两套,一套在aosp中,另一套在chromium中。

构建aosp版

准备

  1. ubuntu 可以使用virtual box去装个虚拟机
  2. 200GB以上硬盘空间,清华会推荐你下载aosp-latest.tar再解压,光压缩包80G了,解压完我就把tar包删了

获取aosp源码

推荐使用清华镜像https://mirrors-i.tuna.tsinghua.edu.cn/help/AOSP/,可结合google的官方说明https://source.android.com/docs/setup?hl=zh-cn。具体指令就不介绍了,主要是repo sync费时,注意选好你想构建的build tag。

Build

使用aosp的编译比较简单,直接走aosp那一套就行,主要就是使用下列命令,不过也可以结合官方文档介绍,自行修改。

1
2
3
4
5
6
cd aosp  # 进到aosp根目录
. build/envsetup.sh # 配置构建环境,这条命令会把一系列命令加到可执行环境中
lunch armv8_eng # 配置要<product_name>-<build_variant>,我这里要的是arm64的
cd external/pdfium # go to pdfium directory
mma # build module and deps
# out/target/product/armv8/obj/SHARED_LIBRARIES/libpdfium_intermediates/libpdfium.so

构建chromium版本

编好的库,直接拿来用

pdfium-binaries
这个项目是利用github action自动构建pdfium,其提供了所有版本的so,相当方便。另外想手动构建,有些要修改的内容,也可以参考这个项目中的patch。这个项目是我构建完以后才找到的,算是白忙活,不过也算是一点知识。

说明

一开始我在网上搜了很多资料,都是讲如何构建这个版本的,所以我在aosp代码同步的时候,好顺带搞了搞这个,和aosp的mm就可以构建,这个是相当头疼啊。

  1. 官方文档简单。官方只介绍了如何Build,但是没告诉你如何build安卓用的库。
  2. 网上内容复杂、老旧,对伸手党不友好。比如 install-build-deps-android.sh,我搜的所有资料,里面都有这条命令,但是,这个文件其实已经删除了。
  3. 没有镜像。可能是我没找到,反正代码是我全程开科技同步的。

准备

  1. ubuntu。不确定mac行不行,我mac上试了一下,install-build-deps.sh提示我没有lsb-release,我就直接换ubuntu了
  2. 80GB硬盘。其实用不了,我虚拟机开了这么多。
  3. 上网要有科技,所有代码都在googlesource,建议有较好的网络。

构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:/path/to/depot_tools"

# get code
mkdir repo
cd repo
gclient config --unmanaged https://pdfium.googlesource.com/pdfium.git
echo "target_os = [ 'android' ]" >> .gclient
gclient sync
gclient runhooks


# setup build
cd pdfium
./build/install-build-deps.sh --android

gn args out

args

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
target_os="android"
target_cpu="arm64"

use_goma = false
pdf_bundle_freetype=true
pdf_is_standalone=true
is_component_build=false
pdf_enable_xfa=false
pdf_enable_v8=false
pdf_use_skia = false
use_cxx11_on_android=false

is_debug=false
is_official_build=true
chrome_pgo_phase = 0

proxy

[Boto]
proxy = example-host
proxy_port = port number

save as your_file.boto
export NO_AUTH_BOTO_CONFIG=/path/your_file.boto

config

此节内容收集自互联网,有些内容并不适用,但第一条的FPDFSDK_EXPORTS是必须的。

  1. 打开pdfium/BUILD.gn 文件,找到 config(“pdfium_common_config”),将以下配置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    config("pdfium_common_config") {
    cflags = [ ]
    ldflags = []
    include_dirs = [ "." ]
    defines = [
    "PNG_PREFIX",
    "PNG_USE_READ_MACROS",
    **"FPDFSDK_EXPORTS"**
    ]
  • 增加”-fvisibility=default”到 cflags ,将符号的可见性设置为默认值。这意味着其他组件可以引用该符号,并且符号定义可以被另一个组件中的同名定义覆盖。
  • 增加”-DNOCJK”到 cflags ,这将停止将字体嵌入到.so文件中并减小其大小。
  • 增加“FPDFSDK_EXPORTS” 到 defines — 把符号表嵌入到共享库中。
  1. 在component(“pdfium”)前追加以下配置 -L/lib/x86_64-linux-gnu/libatomic貌似可以不加,因为之前是 -latomic,结果系统死活找不到
    1
    2
    3
    4
    5
    6
    7
    8
    9
    shared_library("pdfsdk") {
    deps = [":pdfium"]
    ldflags = [ "-L/lib/x86_64-linux-gnu/libatomic" ]
    if (target_os == "android") {
    configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
    }
    }
    component("pdfium") {
    //…

build

1
ninja -C out pdfsdk

备注

  1. 指定commit同步代码:gclient sync –revision 837fe726e639f823a62ed4aa4abda45d40f3c803
  2. 同步代码时要加的参数,因为我们只想要代码 并不想要history
    repo init –depth=1 -u https://github.com/zawzaww/aosp-android.git-bandroid-8.1.0
    repo sync -f –force-sync –no-clone-bundle –no-tags -j$(nproc –all)
  3. gclient也可以加上-no-history节省同步时间

参考

pdfium-binaries
https://i.lckiss.com/?p=5897
https://github.com/bblanchon/pdfium-binaries/blob/master/patches/shared_library.patch
https://groups.google.com/g/pdfium/c/-WdW5n0KZ-8