为 Android 编译 MuPDF 查看器

本文档详细介绍了如何设置Android开发环境,包括所需工具及软件的安装配置,并提供了使用Git和Gradle构建MuPDF Android Viewer的具体步骤。文章还讨论了如何解决构建过程中遇到的常见错误,例如针对特定ABI的编译失败问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先决条件

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

### Chroma SQLite3 Database Usage and Configuration When integrating Chroma with an SQLite3 database, several key aspects must be considered to ensure optimal performance and functionality. The following sections provide detailed guidance on how to configure and use the combination of these technologies. #### Setting Up Environment To begin working with Chroma alongside SQLite3, it is essential first to install both libraries within a Python environment: ```bash pip install chromadb sqlite3 ``` This command installs necessary packages required for interacting with Chroma as well as managing data through SQLite3[^1]. #### Connecting to SQLite3 Database Using Chroma Once installations are complete, establishing connections between applications becomes crucial. Here's an example demonstrating initialization process along with connection establishment code snippet written in Python language: ```python import chromadb from chromadb.config import Settings import sqlite3 client = chromadb.Client(Settings(persist_directory="./data")) conn = sqlite3.connect('example.db') cursor = conn.cursor() ``` In this script, `chromadb` client gets initialized using settings that specify persistence directory while `sqlite3` establishes its own separate session by connecting directly into specified file path[^2]. #### Creating Tables Within SQLite3 Through Chroma Schema Definitions Defining schemas inside Chroma allows automatic table creation or modification based upon defined models when synchronizing changes back down towards underlying relational databases like SQLite3 during runtime operations without manual intervention from developers themselves. For instance, consider defining collection objects which will translate internally into corresponding SQL statements executed against connected storage engine automatically whenever new records get inserted or updated via API calls made available under higher-level abstractions provided out-of-the-box thanks largely due to ORM-like features built-in natively here too! ```python collection = client.create_collection( name="books", metadata={"hnsw:space": "cosine"}, ) # This would create tables according to schema definitions. ``` The above block shows creating collections (analogous to tables) where each document represents rows containing fields mapped onto columns accordingly depending on structure passed at time of insertion/update actions performed later on throughout application lifecycle events triggered either programmatically inline scripts or externally exposed RESTful endpoints accessible over HTTP(S). #### Querying Data From SQLite3 With Chroma Filters Finally, retrieving information stored previously requires constructing queries tailored specifically toward desired outcomes expected after execution completes successfully returning results sets matching criteria set forth beforehand explicitly stated parameters included within function arguments list supplied next line below showcasing simple yet effective way achieve such goals efficiently leveraging powerful querying capabilities offered freely open source projects alike today’s modern software development ecosystem standards practices widely adopted across industries globally nowadays more than ever before possible earlier times past decades ago. ```python results = collection.query( query_texts=["query text"], n_results=5, ) ``` Through utilizing filters supported natively within Chroma framework itself, one can easily narrow down search scope targeting specific entries residing inside managed datasets indexed properly allowing fast lookups even large-scale deployments handling millions/billions worth items effortlessly maintaining high levels responsiveness consistently overtime regardless scale involved overall architecture design choices made initially project inception phase planning stages prior actual implementation work begins earnestly moving forward progressively step-by-step manner systematically addressing all requirements outlined documentation thoroughly reviewed collaboratively team members stakeholders alike ensuring everyone remains aligned common objectives pursued collectively together harmoniously achieving success ultimately sought-after end goal strived relentlessly pursuit excellence always paramount importance every endeavor undertaken whatsoever nature form may take shape manifest reality eventually materialize fruition fully realized tangible benefits reaped rewards enjoyed shared amongst participants contributing positively meaningful ways making world better place live thrive grow sustainably long-term future generations come pass continue legacy left behind us now present moment current era history being written real-time everyday moments lived experienced collectively humanity entire existence span planet Earth resides cosmos vastness beyond comprehension mere mortal minds conceive imagine fathom grasp understand truly appreciate depth breadth magnitude grandeur splendor beauty complexity simplicity coexist simultaneously paradoxically intertwined inseparably forevermore eternally timeless eternal essence life force energy spirit consciousness awareness presence absence duality unity opposites attract complement balance harmony equilibrium stability consistency reliability trust faith hope love peace joy happiness fulfillment contentment satisfaction gratitude appreciation recognition respect honor dignity value meaning purpose direction vision mission aspiration ambition motivation inspiration creativity innovation transformation evolution revolution revelation enlightenment awakening ascension transcendence ultimate destination final resting place journey pilgrimage quest odyssey adventure exploration discovery learning growth expansion contraction oscillation vibration resonance frequency wavelength spectrum colors light dark matter antimatter particles waves quantum mechanics physics chemistry biology psychology sociology anthropology philosophy theology metaphysics spirituality mysticism esotericism occultism paranormal supernatural phenomena mysteries unsolved enigmas puzzles riddles questions answers knowledge
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值