用 NDK编译Graphite2

对着背影说爱祢 提交于 2019-12-06 06:42:17

Graphite is a "smart font" system developed specifically to handle the complexities of lesser-known languages of the world.

上面这段话是从Graphite的官网(http://scripts.sil.org/cms/scripts/page.php?site_id=projects&item_id=graphite_hom)上摘的对于这个Open Source library的功能的描述。它是一个类似于Harfbuzz的一个文本shape的引擎,只不过,它在shape的过程中,会更加依赖于font文件中提供的信息。对于缅甸语的处理,Graphite引擎 + Padauk font 文件的组合方案,堪称完美。

这个library用到的API也大多在standard C++的范围之内,这就给用NDK编译这个library创造了很好的条件。

在NDK中使用STL的方法,可以看到Google官方文档(prebuilts/ndk/7/sources/cxx-stl/gnu-libstdc++/README)中的一段话:

This directory contains the headers and prebuilt binaries for the
GNU libstdc++-v3 C++ Standard Template Library implementation.

These are generated from the toolchain sources by the rebuild-all-prebuilt.sh
script under build/tools.

To use it, define APP_STL to 'gnustl_static' in your Application.mk.
See docs/CPLUSPLUS-SUPPORT.html for more details.

This implementation fully supports C++ exceptions and RTTI.
这段文字中提到的 Application.mk的含义是,需要在jni这个folder下原来的那个Android.mk文件的基础之上,添加另外的一个名为 Application.mk的文件。在我们为了编译graphite2而添加的 Application.mk文件中,实际上可以只有一句话:
APP_STL := gnustl_static

编译这种module的另外的一个麻烦之处是,我们没有办法一下子看出来,到底需要往我们的source file list中添加多少个source file。大概只能通过逐个的添加文件,直到在也不会爆出“Undefined reference to ...” 这种build error的信息为止了吧。如下的Android.mk 文件是经过反复的链接报错->添加source file这样一个过程,所得到的结果。

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

HOME := /media/hanpfei

ANDROID_SOURCE_TOP=$(HOME)/LinData/android_src/JellyBean

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.cpp \
                   JniHelper.cpp\
                   JniDebug.cpp

LOCAL_LDLIBS    := -llog

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE    := graphite2

LOCAL_SRC_FILES := graphite2-1.2.0/src/Bidi.cpp \
                   graphite2-1.2.0/src/CachedFace.cpp \
                   graphite2-1.2.0/src/call_machine.cpp \
                   graphite2-1.2.0/src/CmapCache.cpp \
                   graphite2-1.2.0/src/Code.cpp \
                   graphite2-1.2.0/src/Face.cpp \
                   graphite2-1.2.0/src/FeatureMap.cpp \
                   graphite2-1.2.0/src/FileFace.cpp \
                   graphite2-1.2.0/src/Font.cpp \
                   graphite2-1.2.0/src/GlyphCache.cpp \
                   graphite2-1.2.0/src/GlyphFace.cpp \
                   graphite2-1.2.0/src/gr_face.cpp \
                   graphite2-1.2.0/src/gr_font.cpp \
                   graphite2-1.2.0/src/gr_logging.cpp \
                   graphite2-1.2.0/src/gr_slot.cpp \
                   graphite2-1.2.0/src/json.cpp \
                   graphite2-1.2.0/src/NameTable.cpp \
                   graphite2-1.2.0/src/Pass.cpp \
                   graphite2-1.2.0/src/SegCache.cpp \
                   graphite2-1.2.0/src/SegCacheEntry.cpp \
                   graphite2-1.2.0/src/SegCacheStore.cpp \
                   graphite2-1.2.0/src/Segment.cpp \
                   graphite2-1.2.0/src/Silf.cpp \
                   graphite2-1.2.0/src/Slot.cpp \
                   graphite2-1.2.0/src/Sparse.cpp \
                   graphite2-1.2.0/src/TtfUtil.cpp \
                   graphite2-1.2.0/src/UtfCodec.cpp

LOCAL_C_INCLUDES += \
        $(LOCAL_PATH)/graphite2-1.2.0/src \
        $(LOCAL_PATH)/graphite2-1.2.0/include

include $(BUILD_SHARED_LIBRARY)

这个Android.mk文件中,另一个值得我们参考的是,在同一个mk文件中,定义对于两个library的编译的方法。个人认为,比较关键的地方在于,include $(CLEAR_VARS) 这一行。它的含义大体上是将前面定义的所有的变量都给清除掉。这样大概就可以让我们很方便的将多个Android.mk文件给合并成为一个了。

执行ndk-build,输出大概就会像下面这样:

hanpfei@ubuntu:/media/hanpfei/LinData/workspace/Graphite-jni$ ndk-build 
/home/hanpfei/Data/Tools/android-ndk-r8d/build/core/add-application.mk:128: Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 3 in ./AndroidManifest.xml    
Gdbserver      : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
Gdbsetup       : libs/armeabi/gdb.setup
Compile++ thumb  : graphite2 <= Bidi.cpp
Compile++ thumb  : graphite2 <= CachedFace.cpp
Compile++ thumb  : graphite2 <= call_machine.cpp
Compile++ thumb  : graphite2 <= CmapCache.cpp
Compile++ thumb  : graphite2 <= Code.cpp
Compile++ thumb  : graphite2 <= Face.cpp
Compile++ thumb  : graphite2 <= FeatureMap.cpp
Compile++ thumb  : graphite2 <= FileFace.cpp
Compile++ thumb  : graphite2 <= Font.cpp
Compile++ thumb  : graphite2 <= GlyphCache.cpp
Compile++ thumb  : graphite2 <= GlyphFace.cpp
Compile++ thumb  : graphite2 <= gr_face.cpp
Compile++ thumb  : graphite2 <= gr_font.cpp
Compile++ thumb  : graphite2 <= gr_logging.cpp
Compile++ thumb  : graphite2 <= gr_slot.cpp
Compile++ thumb  : graphite2 <= json.cpp
Compile++ thumb  : graphite2 <= NameTable.cpp
Compile++ thumb  : graphite2 <= Pass.cpp
Compile++ thumb  : graphite2 <= SegCache.cpp
Compile++ thumb  : graphite2 <= SegCacheEntry.cpp
Compile++ thumb  : graphite2 <= SegCacheStore.cpp
Compile++ thumb  : graphite2 <= Segment.cpp
Compile++ thumb  : graphite2 <= Silf.cpp
Compile++ thumb  : graphite2 <= Slot.cpp
Compile++ thumb  : graphite2 <= Sparse.cpp
Compile++ thumb  : graphite2 <= TtfUtil.cpp
Compile++ thumb  : graphite2 <= UtfCodec.cpp
SharedLibrary  : libgraphite2.so
Install        : libgraphite2.so => libs/armeabi/libgraphite2.so
Compile++ thumb  : hello-jni <= hello-jni.cpp
Compile++ thumb  : hello-jni <= JniHelper.cpp
Compile++ thumb  : hello-jni <= JniDebug.cpp
SharedLibrary  : libhello-jni.so
Install        : libhello-jni.so => libs/armeabi/libhello-jni.so

End


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!