转载

为 Android 编译 MuPDF 查看器

你需要一个 工作的 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 编译器。

如果一切正常,你应该也能够在命令中运行如下这些命令:

  • Android SDK tools: android, emulator, and adb.
  • Android NDK tools: ndk-build.
  • Oracle Java JDK 8: java, and javac.
  • Apache Ant: ant.
  • Git: git.
  • GNU Make: make, or gmake.
  • C compiler: cc, gcc, or clang.

构建

使用 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
原文  https://www.wolfcstech.com/2018/06/06/android-build-viewer/
正文到此结束
Loading...