FreeType2 交叉编译 Android

3

我成功地为arm、arm64、x86和x86_64架构编译了Freetype2库。以下是我编译它所采取的步骤。

  1. Created standalone toolchains for architectures mentioned above. make_standalone_toolchain.py \ --arch arm64 \ --api 26 \ --stl=libc++ \ --install-dir=my-arm64-toolchain
  2. Set some envirement variables

    export PATH=$PATH:`pwd`/my-toolchain/bin
    target_host=aarch64-linux-android
    export AR=$target_host-ar
    export AS=$target_host-as
    export CC=$target_host-gcc
    export CXX=$target_host-g++
    export LD=$target_host-ld
    export STRIP=$target_host-strip
    export CFLAGS="-fPIE -fPIC"
    export LDFLAGS="-pie"
    
  3. Configure freetype for compilation

./configure --host=aarch64-linux-android --prefix=/home/freetype-arm64 --without-zlib --without-harfbuzz --with-png=no

  1. 最后进行编译并安装

编译成功后,我得到了静态的freetype库。

我将库添加到我的Android Studio libs文件夹中。 以下是库的文件夹结构:

libs---freetype
    |---${ANDROID_ABI}
         |---include
             |---freetype2
                 |---freetype
                     ---|Bunch of header files
                 |---ftbuild.h
         |---lib
             |---libfreetype.a

以下是我的CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.4.1)

add_definitions("-DGLM_FORCE_SIZE_T_LENGTH -DGLM_FORCE_RADIANS")

add_subdirectory(src/main/cpp/glm)

add_library(freetype STATIC IMPORTED)
set_target_properties(freetype PROPERTIES IMPORTED_LOCATION${PROJECT_SOURCE_DIR}/libs/freetype/${ANDROID_ABI}/lib/libfreetype.a)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall")
add_library(native-lib SHARED
        src/main/cpp/native-lib.cpp
        src/main/cpp/graph.cpp
        src/main/cpp/text.cpp
        src/main/cpp/graphDataWorker.cpp
        )
target_include_directories(native-lib PRIVATE ${PROJECT_SOURCE_DIR}/libs/freetype/${ANDROID_ABI}/include/freetype2)                       

target_link_libraries(native-lib
                  android
                  freetype
                  GLESv2
                  EGL
                  glm
                  atomic
                  log
                  OpenSLES
                  )

问题在于我可以在代码中使用库,而且Android Studio没有给出任何错误提示,但是当我尝试运行应用程序时,它会给出以下错误提示:链接器命令失败,退出代码为1(使用-v查看调用)
PS:我在Android Studio文件树中也看不到freetype头文件,但可以看到其他库。
问题:我导入库的方式有误还是这是交叉编译问题?如果是后者,如何正确处理?我已经对此问题进行了大量研究,但未能找到解决方案。非常感谢您的帮助。

从你的CMakeLists.txt文件来看,库的导入似乎没有问题。链接器提示使用“-v”查看调用,也许它会告诉你是否链接了正确的库。但是你看不到freetype包含文件的事实确实很奇怪。 - brainsandwich
@brainsandwich 感谢您的评论。它说ld: ../../../../libs/freetype/arm64-v8a/lib/libfreetype.a(ftinit.o): Relocations in generic ELF (EM: 62) ../../../../libs/freetype/arm64-v8a/lib/libfreetype.a: error adding symbols: File in wrong format,而EM:62代表x86_64。也许编译过程正在使用错误的库进行链接?这是可能的吗? - Vygintas B
我认为我遇到了同样的问题。你在编译时使用STL端口吗?https://developer.android.com/ndk/guides/cpp-support.html - Andrey Semenov
1个回答

4
除非在安装FreeType2时混合了路径,否则似乎库的编译不正确,因为链接器抱怨该库是针对x86_64架构的。在Linux上,通常可以使用命令file检查库所构建的体系结构。另一种检查体系结构的方法是使用随Android NDK一起提供的objdump工具(如果我记得正确,它也是通过工具链生成的)。它的名称遵循与编译器/链接器/...工具相同的模式,$target_host-objdump
我建议使用CMake而不是autotools编译FreeType2,至少在我的情况下,我就是这样成功完成的。
以下是我编写的用于交叉编译FreeType2以供Android使用的CMake配置示例。这有点复杂,因为它是我构建几个库的项目的一部分。
我的CMake配置使用ExternalProject下载和编译Freetype。我的顶级CMakeLists.txt包含:
# CMakeLists.txt
set(DEVENV_CMAKE_ARGS
  -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
  -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
  -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}
  -DCMAKE_C_FLAGS=${CMAKE_CXX_FLAGS}
  -DCMAKE_C_FLAGS_${BUILD_TYPE}=${CMAKE_C_FLAGS_${BUILD_TYPE}}
  -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
  -DCMAKE_CXX_FLAGS_${BUILD_TYPE}=${CMAKE_CXX_FLAGS_${BUILD_TYPE}}
  -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}
  -DCMAKE_CXX_EXTENSIONS=${CMAKE_CXX_EXTENSIONS}
)
if(BUILD_SHARED_LIBS)
  list(APPEND DEVENV_CMAKE_ARGS -DBUILD_STATIC_LIBS=OFF -DLIBTYPE=SHARED)
else()
  list(APPEND DEVENV_CMAKE_ARGS -DBUILD_STATIC_LIBS=ON -DLIBTYPE=STATIC)
endif()
if(DEFINED ANDROID_TOOLCHAIN_DIR)
  get_filename_component(_toolchain_dir ${ANDROID_TOOLCHAIN_DIR} ABSOLUTE)
  list(APPEND DEVENV_CMAKE_ARGS -DANDROID_TOOLCHAIN_DIR=${_toolchain_dir})
endif()
if(DEFINED CMAKE_ANDROID_ARCH_ABI)
  list(APPEND DEVENV_CMAKE_ARGS -DCMAKE_ANDROID_ARCH_ABI=${CMAKE_ANDROID_ARCH_ABI})
endif()

if(CMAKE_TOOLCHAIN_FILE)
  get_filename_component(_toolchain_file ${CMAKE_TOOLCHAIN_FILE} ABSOLUTE)
  list(APPEND DEVENV_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${_toolchain_file})
endif()

add_subdirectory(freetype)

所以变量DEVENV_CMAKE_ARGS包含适用于交叉编译的CMake参数,反映了我的当前CMake配置。在freetype目录下,CMakeLists.txt包含:
# freetype/CMakeLists.txt
project(freetype)

include(ExternalProject)

if(NOT FREETYPE_GIT_REPOSITORY)
  set(FREETYPE_GIT_REPOSITORY "https://git.savannah.gnu.org/git/freetype/freetype2.git")
endif()

set(FREETYPE_GIT_REPOSITORY "${FREETYPE_GIT_REPOSITORY}"
  CACHE STRING "Git repository for library Freetype."
)

if(NOT FREETYPE_GIT_TAG)
  set(FREETYPE_GIT_TAG "VER-2-9")
endif()

set(FREETYPE_GIT_TAG "${FREETYPE_GIT_TAG}"
  CACHE STRING "Tag or branch of Git repository to build."
)

message(STATUS "Freetype Git repository: ${FREETYPE_GIT_REPOSITORY}")
message(STATUS "Freetype Git tag: ${FREETYPE_GIT_TAG}")

externalproject_add(freetype
  GIT_REPOSITORY "${FREETYPE_GIT_REPOSITORY}"
  GIT_TAG "${FREETYPE_GIT_TAG}"
  SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/freetype/src"
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/freetype/build"
  CMAKE_ARGS ${DEVENV_CMAKE_ARGS}
)

基本上,这个CMakeLists.txt文件使用ExternalProject在构建目录中下载和编译FreeType2。

我使用一个Android的工具链文件:

# android.cmake
set(CMAKE_SYSTEM_NAME "Android")
set(CMAKE_ANDROID_STANDALONE_TOOLCHAIN ${ANDROID_TOOLCHAIN_DIR})

如果太过复杂,那是因为这段内容来自于我参与的一个用于交叉编译安卓应用的项目。希望这能对你有所帮助。


谢谢您的答复。能告诉我该如何将您的顶级cmakelists.txt集成到我的cmakelists.txt中吗?另外,如果我的主要开发机器是Windows,这个方法还适用吗? - Vygintas B
我执行externalproject_add时出现了错误。该错误来自ExternalProject.cmake中的if语句if(NOT GIT_EXECUTABLE) message(FATAL_ERROR "error: could not find git for clone of ${name}") endif() - Vygintas B
@VygintasB 可能是因为 Git 不在您的 PATH 变量中,我将我的 CMake 配置内容复制粘贴出来是因为懒惰,但您不需要那么复杂的东西。最简单的方法是直接使用 CMake 从 FreeType 源代码生成一个构建目录,并使用工具链文件告诉 CMake 您要交叉编译 Android,就像您自己的项目一样。无论如何,它应该可以在 Windows 上工作,因为 CMake 的目的是提供一个系统无关的环境。 - piwi
谢谢你的回答。你的例子对我来说还不够,但它让我对cmake如何进行交叉编译有了很重要的见解。 - Vygintas B
@VygintasB 很高兴你找到了解决问题的方法! - piwi
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接