你需要一个 工作的 Android 开发环境,它由 Android SDK 和 Android NDK 组成。建立这一环境最简单的方式就是使用 Android Studio 下载并安装 SDK 和 NDK。确保 Android/Sdk/tools 和 Android/Sdk/ndk-bundle 目录在你的 PATH 上。
你也需要 Oracle 的 Java JDK(OpenJDK 与 Android 不兼容)。你也需要 Apache Ant 构建系统。你也需要 Git,GNU Make,和一个 C 编译器。
如果一切正常,你应该也能够在命令中运行如下这些命令:
使用 Git 下载工程(不要忘了加上 –recursive 标记):
$ git clone --recursive git://git.ghostscript.com/mupdf-android-viewer-mini.git
加上 –recursive 标记是为了让 Git 可以递归地下载 mupdf-android-viewer-mini 工程及其依赖的所有工程。MuPDF 由于牵涉到多个模块,因而采用了 Git 的 submodule 机制来管理这些模块。在 mupdf-android-viewer-mini 工程的根目录下,有一个名为 .gitmodules
描述了它依赖的子模块:
[submodule "jni"] path = jni url = ../mupdf-android-fitz.git
在下载代码时,加了 –recursive 标记,Git 在下载完 mupdf-android-viewer-mini 工程之后,就会下载 mupdf-android-fitz 工程,并把它放在 mupdf-android-viewer-mini 工程的 jni
子目录下。而在 mupdf-android-fitz 工程的根目录下,同样有一个 .gitmodules
文件,描述 mupdf-android-fitz 工程依赖的模块:
[submodule "thirdparty/jbig2dec"] path = thirdparty/jbig2dec url = ../jbig2dec.git [submodule "thirdparty/mujs"] path = thirdparty/mujs url = ../mujs.git [submodule "thirdparty/freetype"] path = thirdparty/freetype url = ../thirdparty-freetype2.git [submodule "thirdparty/harfbuzz"] path = thirdparty/harfbuzz url = ../thirdparty-harfbuzz.git [submodule "thirdparty/jpeg"] path = thirdparty/libjpeg url = ../thirdparty-libjpeg.git [submodule "thirdparty/lcms2"] path = thirdparty/lcms2 url = ../thirdparty-lcms2.git [submodule "thirdparty/openjpeg"] path = thirdparty/openjpeg url = ../thirdparty-openjpeg.git [submodule "thirdparty/zlib"] path = thirdparty/zlib url = ../thirdparty-zlib.git [submodule "thirdparty/curl"] path = thirdparty/curl url = ../thirdparty-curl.git [submodule "thirdparty/freeglut"] path = thirdparty/freeglut url = ../thirdparty-freeglut.git
Git 在下载完 mupdf-android-fitz 工程之后,还会下载这些模块,并放在 mupdf-android-fitz 工程目录的 thirdparty
目录下,即 mupdf-android-viewer-mini/jni/libmupdf
目录下。
直接使用 Git 的 –recursive 标记下载,与如下的命令序列是等价的:
$git clone git://git.ghostscript.com/mupdf-android-viewer-mini.git $cd mupdf-android-viewer-mini $git submodule update --init $cd jni $git submodule update --init $cd libmupdf $git submodule update --init
在开始构建之前,还需要在 mupdf-android-viewer-mini 工程的根目录下创建 local.properties
文件,配置 Android SDK 和 NDK 的路径:
## This file is automatically generated by Android Studio. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # # This file must *NOT* be checked into Version Control Systems, # as it contains information specific to your local configuration. # # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. #Tue Jun 05 19:57:20 CST 2018 sdk.dir=/home/hanpfei0306/data/dev_tools/Android/Sdk ndk.dir=/home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b
此外,还需要在 mupdf-android-viewer-mini/jni/libmupdf
目录下执行 make generate
命令生成必要的文件:
mupdf-android-viewer-mini/jni/libmupdf $ make generate
否则,如果直接执行 make
进行构建,将很快报出找不到某些文件的错误:
[mips64] Compile : mupdf_core <= bbox-device.c [mips64] Compile : mupdf_core <= draw-mesh.c In file included from /media/data/osprojects/mupdf-android-viewer-mini/jni/libmupdf/platform/java/mupdf_native.c:10:0: /media/data/osprojects/mupdf-android-viewer-mini/jni/libmupdf/include/mupdf/pdf.h:10:34: fatal error: mupdf/pdf/name-table.h: No such file or directory #include"mupdf/pdf/name-table.h" ^ compilation terminated. /mmedia/data/dev_tools/Android/android-ndk-r12b/build/core/build-bake[1]: *** [/media/data/osprojects/mupdf-androiid-viewer-mini/jni/build/intenary.mk:472: recirmediates/ndkBuild/release/obj/local/mips64p/objs/mupdf_java//media/data/osprojecets/mupdf-android-viewer-mini/jni/libmupdf/platform/java/mupdf_nati vfeor .o] Error 1 target '/media/data/osprojects/mupdf-android-viewer-mini/jni/build/intermediates/ndkBuild/release/obj/local/mips64/objs/mupdf_java//media/data/osprojects/mupdf-android-viewer-mini/jni/libmupdf/platform/java/mupdf_native.o' failed make[1]: *** 正在等待未完成的任务.... make[1]: Leaving directory '/media/data/osprojects/mupdf-android-viewer-mini/jni
之后就可以在 mupdf-android-viewer-mini 工程的根目录下执行如下命令来构建了:
$make
查看 mupdf-android-viewer-mini 工程的 Makefile 文件的内容:
# This is a very simple Makefile that calls 'gradlew' to do the heavy lifting. # # The tool 'adb' must be on the path, so that we can find the Android SDK. ANDROID_HOME := $(shell which adb | sed 's,/platform-tools/adb,,') default: assembleDebug release: assembleRelease install: installDebug assembleDebug: ANDROID_HOME=$(ANDROID_HOME) ./gradlew assembleDebug assembleRelease: ANDROID_HOME=$(ANDROID_HOME) ./gradlew assembleRelease installDebug: ANDROID_HOME=$(ANDROID_HOME) ./gradlew installDebug lint: ANDROID_HOME=$(ANDROID_HOME) ./gradlew lint archive: ANDROID_HOME=$(ANDROID_HOME) ./gradlew uploadArchives sync: archive rsync -av MAVEN/com/ ghostscript.com:/var/www/maven.ghostscript.com/com/ run: install adb shell am start -n com.artifex.mupdf.mini.app/.LibraryActivity clean: rm -rf .gradle build rm -rf jni/.externalNativeBuild jni/.gradle jni/build rm -rf lib/.gradle lib/build rm -rf app/.gradle app/build
执行 make
只是调用了 gradle 命令 ./gradlew assembleDebug
。
执行上面的 make
命令,在执行到为 armeabi ABI 编译动态链接库时将报错:
. . . . . . /tmp/ccrxybCM.s:4815: Error: cannot honor width suffix -- `add r4,r4,r2' /tmp/ccrxybCM.s:4824: Error: cannot honor width suffix -- `mul r2,r3' /tmp/ccrxybCM.s:4827: Error: lo register required -- `add r3,r3,#128' /tmp/ccrxybCM.s:4828: Error: cannot honor width suffix -- `asr r3,r3,#8' /tmp/ccrxybCM.s:4876: Error: cannot honor width suffix -- `mov r0,#0' /tmp/ccrxybCM.s:4937: Error: cannot honor width suffix -- `mov r4,#0' /tmp/ccrxybCM.s:5010: Error: cannot honor width suffix -- `mov r1,#1' /tmp/ccrxybCM.s:5011: Error: cannot honor width suffix -- `mov r2,#44' make[1]: *** [/media/data/osprojects/mupdf-android-viewer-mini/jni/build/intermediates/ndkBuild/release/obj/local/armeabi/objs/mupdf_core//media/data/osprojects/mupdf-android-viewer-mini/jni/libmupdf/source/fitz/draw-scale-simple.o] Error 1 make[1]: *** 正在等待未完成的任务.... make[1]: Leaving directory '/media/data/osprojects/mupdf-android-viewer-mini/jni' * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. BUILD FAILED Total time: 4 mins 5.65 secs Makefile:12: recipe for target 'assembleDebug' failed make: *** [assembleDebug] Error 1
默认情况下, ./gradlew assembleDebug
将为 ‘armeabi’,’armeabi-v7a’,’arm64-v8a’,’x86’,’x86_64’,’mips’,’mips64’ 起种 ABI 构建动态链接库,但实际上对某些 ABI 的支持完全没有必要,比如早已过时的 ‘armeabi’,以及非常小众的 ‘mips’,’mips64’。因而修改 mupdf-android-viewer-mini/jni/build.gradle
文件,配置 ndk.abiFilters
,过滤掉不需要的 ABI:
. . . . . . android { compileSdkVersion 25 buildToolsVersion '25.0.3' defaultConfig { minSdkVersion 16 targetSdkVersion 25 externalNativeBuild.ndkBuild.arguments '-j4' // Uncomment one of the following lines to limit builds to certain ABIs. ndk.abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } . . . . . .
无需编译 armeabi 的 abi 之后,mupdf-android-viewer-mini 工程顺利编译通过:
. . . . . . :lib:transformNativeLibsWithStripDebugSymbolForDebug :lib:transformNativeLibsWithSyncJniLibsForDebug :lib:bundleDebug :lib:compileDebugSources :lib:assembleDebug BUILD SUCCESSFUL Total time: 1 mins 58.883 secs
参考文档:
How to build the MuPDF viewer for Android