当前位置:   article > 正文

Cairo库移植到安卓记录

Cairo库移植到安卓记录

前言

Android Studio引入ndk编译的so库的故事,这个东西搞了两周以后,由于自己不熟悉Java和安卓开发,踩了不少坑,其中一周时间都是花在怎么用Android Studio上的。。。AS下的新版本Koala,结果网上资料全是旧版本,很多设置完全不同,遇了问题经常不知所措,后面不得已,换成了老一点的2021 dolphin版本,也学会了看安卓官网资料,逐渐才稳定下来。

好在不是紧急项目,后面赶主要任务进度就改成每周抽一天时间去处理,这个任务最核心的在于如何将cairo库移植到安卓环境去使用,这是一个2D绘图库,awtk的画布后端也有cairo的选择,几周摸爬滚打,终于将cairo移植到了安卓上,特此记录下,算是个人进军安卓开发的一小步。

环境

OS:Windows11

Cairo: 1.18.0

Android Studio: Dolphin 2021.3.1.17

NDK: r26

确保上述环境和工具已经下好,NDK用windows或者linux的都行,不过经个人测试,linux相比windows巨慢,linux下编译系统的log输出一条时间都够windows下输出十几条了,我没用虚拟机桌面系统,用的WSL,兴许是WSL本身的性能问题?

Stage1 下载Cairo,Meson编译

cairo下载地址:https://www.cairographics.org/download/

从1.17.8开始,cairo不再使用传统的configure+makefile构建系统了,而是改用一个新的构建系统meson,它的编译语法很像python,但并不像awtk的scons那样是完全基于python, 算是类python语言。

不得不接触新的编译系统多少有些抵触,不过手册和案例看下来,逐渐感觉这个系统香了,因为cairo库有很多依赖比如pixman, glib, freetype等,meson项目上有wrap脚本,在编译的时候发现依赖缺失可以直接从网上下下来特定版本。

要是旧版本的话,不只要自己一个个下依赖去配置,还要考虑依赖树内各个节点的版本兼容的问题,苦不堪言,这个自动下载的功能实在厉害!

对于交叉编译,meson可以通过编写txt文件指定特定平台的编译,我这里目标是armv7平台,给arm的平板使用。

其实还想试试x86平台的,因为AS上arm架构机型没法模拟,无法启动,查了下是电脑架构x86不好模拟arm的原因, 之前自己试过编译,结果遇到的坑根本无法解决,然后看了点科普,才知道手机x86架构算是古早的被市场淘汰的产品,除了模拟器,现在手机平板都是arm架构,看来是没有市场价值,那估计官方也没有考虑这平台,释怀了。。。。只能找arm架构的实机了,好在公司提供了个IDO-EVB3562开发板用来装安卓映像。

不废话,交叉编译设置cross_file_build_win_host_arm.txt如下:

[constants]
android_ndk='D:\Devtools\android-ndk-r26d-win\toolchains\llvm\prebuilt\windows-x86_64\'
android_ndk_toolchain='D:\Devtools\android-ndk-r26d-win\toolchains\llvm\prebuilt\windows-x86_64\bin'

[binaries]
c = android_ndk_toolchain / 'armv7a-linux-androideabi33-clang.cmd'
cpp = android_ndk_toolchain / 'armv7a-linux-androideabi33-clang++.cmd'
ar = android_ndk_toolchain / 'llvm-ar.exe'
ld = android_ndk_toolchain / 'ld.exe'
strip = android_ndk_toolchain / 'llvm-strip.exe'

[properties]
sys_root = android_ndk / 'sysroot'
c_link_args     = ['-fuse-ld=gold']
cpp_link_args   = ['-fuse-ld=gold']

[host_machine]
system = 'android'
cpu_family = 'arm'
cpu = 'armv7a'
endian = 'little'


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

如果linux平台上则是:

[constants]
android_ndk='/mnt/d/Devtools/android-ndk-r26d-linux/toolchains/llvm/prebuilt/linux-x86_64/'
android_ndk_toolchain='/mnt/d/Devtools/android-ndk-r26d-linux/toolchains/llvm/prebuilt/linux-x86_64/bin'

[binaries]
c = android_ndk_toolchain / 'armv7a-linux-androideabi33-clang'
cpp = android_ndk_toolchain / 'armv7a-linux-androideabi33-clang++'
ar = android_ndk_toolchain / 'llvm-ar'
ld = android_ndk_toolchain / 'ld'
strip = android_ndk_toolchain / 'llvm-strip'

[properties]
sys_root = android_ndk / 'sysroot'
c_link_args     = ['-fuse-ld=gold']
cpp_link_args   = ['-fuse-ld=gold']

[host_machine]
system = 'android'
cpu_family = 'arm'
cpu = 'armv7a'
endian = 'little'

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

注意windows版我指定了后缀名,因为meson实际上是脚本,根据路径的文件名执行对应文件,给脚本提供的实际是文件路径。

以下指令启动meson的编译,--cross-file用于指定交叉编译文件

meson setup --cross-file cross_file_build_win_host_arm.txt build_win_host_arm
  • 1

等待一段时间,让meson把一切配置好,最后meson会弹出项目的各项配置总结:

cairo 1.18.0

  Surface Backends
    Image                   : YES
    Recording               : YES
    Observer                : YES
    Mime                    : YES
    Tee                     : YES
    Xlib                    : NO
    Xlib Xrender            : NO
    Quartz                  : NO
    Quartz-image            : NO
    XCB                     : NO
    Win32                   : NO
    CairoScript             : YES
    PostScript              : YES
    PDF                     : YES
    SVG                     : YES

  Font Backends
    User                    : YES
    FreeType                : YES
    Fontconfig              : YES
    Win32                   : NO
    Win32 DWrite            : NO
    Quartz                  : NO

  Functions
    PNG functions           : YES
    X11-xcb                 : NO
    XCB-shm                 : NO

  Features and Utilities
    cairo-trace:            : NO
    cairo-script-interpreter: YES
    API reference           : NO

  Subprojects
    fontconfig              : YES
    freetype2               : YES (from fontconfig)
    glib                    : NO Dependency "iconv" not found, tried builtin and system
    gperf                   : YES (from fontconfig)
    libintl                 : NO Include dir /usr/local/include does not exist.
    libpng                  : YES
    libxml2                 : YES (from fontconfig)
    pixman                  : YES

  User defined options
    Cross files             : cross_file_build_win_host_arm.txt
Found ninja-1.12.1 at D:\Devtools\Meson\ninja.EXE
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

接下来就加入meson的第二阶段:ninja编译:

ninja -C build_win_host_arm
  • 1

到了这一步开始编译就开始不风顺了,中间一定会遇到某些问题,比如头文件缺失,或者源码的哪些不规范用法在gcc上过得去,到了ndk的clang就撞error,或者丢了哪些库,不过只要不是系统性问题基本都能解决。我这里先不讲,问题放在最后的踩坑上记录。

Stage2 Cairo安卓项目

ninja编译完成后应该会有以下so库,这些库都要放到后面安卓项目的libs文件夹上,缺一不可。

除了libcpufeatures.so是在ndk内部,其他库应该都能在build_win_host_arm内找到。

libcairo.so
libcpufeatures.so
libfontconfig.so
libfreetype.so
libglib-2.0.so
libintl.so
libpcre2-8.so
libpixman-1.so
libpng16.so
libxml2.so
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Android Studio新建NativeC++项目, 后面就是各种配置了, 然而自己不懂安卓开发,在编码实现上还是一头雾水,结果网上一查,其实已经有人把cairo的移植做出来了,把源码适配了下,居然能用。Nice, 那不担心了。

省篇幅,我就直接发源码吧:https://gitee.com/tracker647/cairo-for-android

记录一些注意点:

1.CMake版本务必换成更新的3.22.1,否则不识别编译选项,一些库明明加了硬说没有。

2.adbFilter选项,由于这里用的armv7a,则只指定armv7a就行了。

根据1 2修改后的build.gradle的android部分例:

android {
    namespace 'com.example.cairotest'
    compileSdk 32

    defaultConfig {
        applicationId "com.example.cairotest"
        minSdk 24
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        ndk {
            abiFilters 'armeabi-v7a'
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.22.1'
        }
    }
    buildFeatures {
        viewBinding true
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

3.cairo官方提供了一些编码案例,我用的其中一个画星星的例子,画的时候注意看有没有cairo_scale这个函数,这是用来控制整个坐标系放缩的,比如设置了cario_scale(width, height), 后面各种api传坐标就不用加width和height了,直接传百分比就行,用的移植例子一开始没注意,画出来结果一脸懵逼。

最终效果图,桌面是cairo在ubuntu wsl平台的运行结果,平板(IDO-EVB3562开发板连了个电容屏)是安卓平台运行结果。

image-20240806205456842

ninja踩坑

tips:-v打开指令log:

ninja -C $builddir -v
  • 1

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/970470?site

推荐阅读
相关标签