• Linux 下交叉编译 ARM64-linux 版本 GDAL-3.2.0


    Linux 下交叉编译 ARM64-linux 版本 GDAL-3.2.0

    1、下载安装编译环境

    这里的主机环境是 linux x86_64 ,具体哪个版本不重要,安装相关工具的时候使用对应版本的命令即可(可参考:GEOS/GDAL 交叉编译ARM64-linux版本)。

    我这里下载的是 gcc-arm-8.3 版本的交叉编译工具链,命令如下:

    # 1、下载安装编译器
    axel https://developer.arm.com/-/media/Files/downloads/gnu-a/8.3-2019.03/binrel/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu.tar.xz?revision=2e88a73f-d233-4f96-b1f4-d8b36e9bb0b9&la=en&hash=167687FADA00B73D20EED2A67D0939A197504ACD
    # 解压到 /opt 目录下
    tar -xJvf gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu.tar.xz -C /opt/
    

    还需要安装cmakemakeautomakeautoconflibtoolzipsqlite等软件,具体安装方法根据 Linux 发行版本确定,这里不再赘述。

    备注:ARM64 都是带 fpu 的,所以不需要区分-mfloat-abi的设置。

    2、使用 VCPKG 编译一些基础的依赖库

    下载安装 vcpkg 的命令如下:

    # 下载 vcpkg
    git clone https://github.com/microsoft/vcpkg.git
    # 编译出 vcpkg 工具
    cd vckpg
    ./bootstrap-vcpkg.sh
    

    编译 sqlite3curlgeos 等第三方库的 ARM64-linux 版本:

    # 导入 gcc-arm 工具链的路径到 PATH
    export PATH=${PATH}:/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin
    # 下载和编译第三方库
    ./vcpkg install sqlite3:arm64-linux    # 当前版本 3.33.0
    ./vcpkg install zstd:arm64-linux       # 当前版本 1.4.5
    ./vcpkg install liblzma:arm64-linux    # 当前版本 5.2.5
    ./vcpkg install tiff:arm64-linux       # 当前版本 4.1.0
    ./vcpkg install curl:arm64-linux       # 当前版本 7.73.0
    # ./vcpkg install hdf5:arm64-linux
    ./vcpkg install libwebp:arm64-linux    # 当前版本 1.1.0
    ./vcpkg install openjpeg:arm64-linux   # 当前版本 2.3.1
    ./vcpkg install geos:arm64-linux       # 当前版本 3.8.1
    

    libgeos 3.8与之前的版本略有差异,也可以选择自己编译。自己编译要注意是否使用 -DGEOS_INLINE=1 条件,对编译出的库的影响。

    3、交叉编译 PROJ-7.2.0

    之所以不使用 vcpkg 来编译 proj4 库,是因为当前 vcpkg 内的版本比较低,就自己编译了。

    编译过程命令记录如下:

    # 下载源码包
    axel https://github.com/OSGeo/PROJ/releases/download/7.2.0/proj-7.2.0.tar.gz
    # 解压并进入目录
    tar -xzf proj-7.2.0.tar.gz && cd proj-7.2.0
    
    # 使用 cmake 命令生成 Makefile
    # CMAKE_INCLUDE_PATH、CMAKE_LIBRARY_PATH 指向上一步编译第三方库的输出目录
    PATH=${PATH}:/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin 
    cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc 
    -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ 
    -DCMAKE_FIND_ROOT_PATH=/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu 
    -DCMAKE_INCLUDE_PATH=/home/test/code/vcpkg/installed/arm64-linux/include 
    -DCMAKE_LIBRARY_PATH=/home/test/code/vcpkg/installed/arm64-linux/lib 
    -DCMAKE_C_FLAGS=-fPIC -DCMAKE_CXX_FLAGS=-fPIC 
    -DCMAKE_CXX_STANDARD=11 -DCMAKE_INSTALL_PREFIX="./output" 
    -DPROJ_TESTS=OFF -DBUILD_GMOCK=OFF 
    -DBUILD_LIBPROJ_SHARED=OFF -Dgtest_force_shared_crt=OFF 
    -DBUILD_PROJSYNC=OFF -DBUILD_PROJINFO=OFF -DBUILD_CCT=OFF 
    -DBUILD_CS2CS=OFF -DBUILD_GEOD=OFF -DBUILD_GIE=OFF -DBUILD_PROJ=OFF
    # 上面一堆 -DBUILD_XXX=OFF 关闭相应的构建,是因为前面编译的第三方库都是静态库
    # 这里要用的话某些库的依赖(比如libcurl依赖的openssl)需要手动修改 CMakeLists.txt 去引入
    # 所以干脆不要了,编译 proj 本来也只是给编译 gdal 使用的。
    
    # 编译并输出编译结果到 output 目录
    make && make install
    

    编译之后,可以拷贝到 vcpkg 的安装目录下,后面编译 GDAL 的时候,方便第三方库路径的指定。

    CMAKE 编译工具链指定

    上面使用了直接指定 CMAKE_CXX_COMPILER 等相关变量的方式,需要指定的变量比较多。

    推荐通过创建一个 gcc_arm_toolchain.cmake 文件,然后使用 -DCMAKE_TOOLCHAIN_FILE=gcc_arm_toolchain.cmake 选项的方式来指定编译器等相关设置。

    gcc_arm_toolchain.cmake 文件内容

    # 指定目标系统
    SET(CMAKE_SYSTEM_NAME Linux)
    
    # 指定编译器
    SET(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
    SET(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
    
    # 指定搜索的根路径
    SET(CMAKE_FIND_ROOT_PATH /opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu)
    SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # 使用本机程序
    SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)  # 仅使用 FIND_ROOT 下的库
    SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)  # 仅使用 FIND_ROOT 下的头文件
    

    4、交叉编译 GDAL-3.2.0

    先下载并解压源代码

    axel https://github.com/OSGeo/gdal/releases/download/v3.2.0/gdal-3.2.0.tar.gz
    tar -xzf gdal-3.2.0.tar.gz
    

    然后参考 linux下编译GDAL3.x > configure 完成,输出 geos 等为 no 修改 configure 文件。

    大概修改如下:

    • 搜索 CURL_SETTING= 找到 CURL 库检查这一段的结尾,添加

      CURL_SETTING=yes
      CURL_INC=
      CURL_LIB="-lcurl -lssl -lcrypt $LIBS"

    • 回到第一行,搜索 checking for sqlite3_open

      找到后将上面一行 LIBS="" 注释掉

      (因为会出有很多个,只修改这一个即可)

    • 搜索 LIBLZMA_SETTING= 修改等于号后面部分

      LIBLZMA_SETTING="yes"

    • 搜索 HAVE_OPENJPEG=no 找到 OPENJPEG 库检查这一段的结尾,添加

      HAVE_OPENJPEG="yes"
      OPENJPEG_LIBS="-lopenjp2 ${LIBS}"
      OPT_GDAL_FORMATS="openjpeg $OPT_GDAL_FORMATS"

    • 搜索 HAVE_GEOS= 找到 GEOS 库检查这一段的结尾,添加

      HAVE_GEOS="yes"
      HAVE_GEOS_RESULT="yes"
      GEOS_LIBS="-lgeos -lgeos_c ${LIBS}"

    然后执行 configure 脚本,生成 Makefile 文件。

    # 注意这里的环境变量设置
    PATH=${PATH}:/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin 
    CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ 
    CFLAGS=-I/home/test/code/vcpkg/installed/arm64-linux/include 
    CXXFLAGS=-I/home/test/code/vcpkg/installed/arm64-linux/include 
    LDFLAGS=-L/home/test/code/vcpkg/installed/arm64-linux/lib 
    LIBS="-lpthread -dl"  LT_SYS_LIBRAR_PATH=./lib 
    ./configure --prefix=/home/test/code/gdal_output --host=aarch64-linux 
    --with-sqlite3=/home/test/code/vcpkg/installed/arm64-linux  
    --with-rename-internal-libtiff-symbols=yes 
    --with-rename-internal-shapelib-symbols=yes 
    -with-curl=/home/test/code/vcpkg/installed/arm64-linux 
    -with-proj=/home/test/code/vcpkg/installed/arm64-linux 
    -with-proj-extra-lib-for-test="-lcurl -ltiff -lssl -lcrypto -ljpeg -llzma -lz" 
    --with-zstd=/home/test/code/vcpkg/installed/arm64-linux 
    --with-geotiff=internal 
    --with-jpeg=/home/test/code/vcpkg/installed/arm64-linux 
    --with-openjpeg=yes --with-liblzma=yes 
    -with-webp=/home/test/code/vcpkg/installed/arm64-linux 
    -with-geos=/home/test/code/vcpkg/installed/arm64-linux
    

    最后进行编译

    PATH=${PATH}:/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin make
    

    4、遇到的错误及解决办法

    基本上都可以按照 linux下编译GDAL3.x(集成Proj和Geos等) 里面对错误的解决办法进行解决。

    这里修改后的 LIBS 变量内容如下:

    OTHER_LIB_PATH="/home/test/code/vcpkg/installed/arm64-linux/lib"
    LIBS	=	${OTHER_LIB_PATH}/libwebp.a 
    			${OTHER_LIB_PATH}/libwebpdecoder.a 
    			 ${OTHER_LIB_PATH}/libwebpdemux.a 
    			 ${OTHER_LIB_PATH}/libwebpmux.a 
    			 ${OTHER_LIB_PATH}/libopenjp2.a 
    			 ${OTHER_LIB_PATH}/libturbojpeg.a 
    			 ${OTHER_LIB_PATH}/libzstd.a 
    			 ${OTHER_LIB_PATH}/libproj.a 
    			 ${OTHER_LIB_PATH}/libcurl.a 
    			 ${OTHER_LIB_PATH}/libtiff.a 
    			 ${OTHER_LIB_PATH}/libssl.a 
    			 ${OTHER_LIB_PATH}/libcrypto.a 
    			 ${OTHER_LIB_PATH}/libjpeg.a 
    			 ${OTHER_LIB_PATH}/libszip.a 
    			 ${OTHER_LIB_PATH}/libsqlite3.a 
    			 ${OTHER_LIB_PATH}/libgeos_c.a 
    			 ${OTHER_LIB_PATH}/libgeos.a 
    			 ${OTHER_LIB_PATH}/liblzma.a 
    			 ${OTHER_LIB_PATH}/libz.a 
    			$(KAK_LIBS) $(DWG_LIBS) $(CURL_LIB) 
    			$(MRSID_LIBS) $(MRSID_LIDAR_LIBS) $(ECW_LIBS) $(INGRES_LIB) 
    			$(PCIDSK_LIB) $(RASDAMAN_LIB) $(SOSI_LIB) 
    			$(OPENCL_LIB) $(JVM_LIB) $(LIBICONV) $(FGDB_LIB) $(LIBXML2_LIB) $(MONGODB_LIB) 
    			$(MONGOCXXV3_LIBS) $(JNI_LIB) $(HDFS_LIB) 
    			-lpthread -lm -lrt -ldl 
    

    找不到 png_riffle_palette_neon 等相关定义的问题

    报错的内容如下:

    /bin/sh /home/test/code/gdal-3.2.0/gdal/libtool --mode=link --silent aarch64-linux-gnu-g++ -L/home/test/code/vcpkg/installed/arm64-linux/lib gdalinfo_bin.lo  /home/test/code/gdal-3.2.0/gdal/libgdal.la  -o gdalinfo
    /opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/8.3.0/../../../../aarch64-linux-gnu/bin/ld: /home/test/code/gdal-3.2.0/gdal/.libs/libgdal.so: undefined reference to `png_riffle_palette_neon'
    /opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/8.3.0/../../../../aarch64-linux-gnu/bin/ld: /home/test/code/gdal-3.2.0/gdal/.libs/libgdal.so: undefined reference to `png_do_expand_palette_rgb8_neon'
    /opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/8.3.0/../../../../aarch64-linux-gnu/bin/ld: /home/test/code/gdal-3.2.0/gdal/.libs/libgdal.so: undefined reference to `png_init_filter_functions_neon'
    /opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/8.3.0/../../../../aarch64-linux-gnu/bin/ld: /home/test/code/gdal-3.2.0/gdal/.libs/libgdal.so: undefined reference to `png_do_expand_palette_rgba8_neon'
    

    查看编译好的 .libs/libgdal.so 的导出函数

    objdump -T .libs/libgdal.so|grep png_
    0000000000000000      D  *UND*	0000000000000000              png_riffle_palette_neon
    0000000000000000      D  *UND*	0000000000000000              png_do_expand_palette_rgb8_neon
    0000000000000000      D  *UND*	0000000000000000              png_init_filter_functions_neon
    0000000000000000      D  *UND*	0000000000000000              png_do_expand_palette_rgba8_neon
    000000000168d064 g    DF .text	000000000000005c  Base        png_push_restore_buffer
    000000000168b9ec g    DF .text	0000000000000068  Base        png_malloc_base
    ....
    

    果然这里几个函数没有定义,找到这几个函数所在的文件

    grep png_riffle_palette_neon -R frmts/png/libpng/*  
    frmts/png/libpng/pngpriv.h:                      png_riffle_palette_neon,
    frmts/png/libpng/pngrtran.c:               png_riffle_palette_neon(png_ptr);
    

    查看 frmts/png/libpng/pngpriv.h 文件,找到这个函数的声明,可知这是一个内部函数,并且只有在 PNG_ARM_NEON_IMPLEMENTATION1 的时候才存在。这个函数本身没有定义,只是在 pngrtran.c 文件里面调用了一次。

    // frmts/png/libpng/pngpriv.h
    2120 #if PNG_ARM_NEON_IMPLEMENTATION == 1
    2121 PNG_INTERNAL_FUNCTION(void,
    2122                       png_riffle_palette_neon,
    2123                       (png_structrp),
    2124                       PNG_EMPTY);
    
    // frmts/png/libpng/pngrtran.c
    4774 #ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
    4775          if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
    4776          {
    4777             if (png_ptr->riffled_palette == NULL)
    4778             {
    4779                /* Initialize the accelerated palette expansion. */
    4780                png_ptr->riffled_palette =
    4781                    (png_bytep)png_malloc(png_ptr, 256 * 4);
    4782                png_riffle_palette_neon(png_ptr);
    4783             }
    4784          }
    4785 #endif
    

    通过查看相关的宏定义可知,只有在 PNG_ARM_NEON_IMPLEMENTATION 定义了,且值为 1 的时候,这些函数才会被调用。找到frmts/png/libpng/pngpriv.h 文件中对 PNG_ARM_NEON_IMPLEMENTATION 的定义相关语句,可以知道在没有设置 PNG_ARM_NEON_OPT 宏的时候,会去根据进行相关设置。

    所以这里的解决办法也很简单,直接在这里顶上加上一行 #define PNG_ARM_NEON_OPT 0 即可。

    #ifndef PNG_ARM_NEON_OPT
       /* ARM NEON optimizations are being controlled by the compiler settings,
        * typically the target FPU.  If the FPU has been set to NEON (-mfpu=neon
        * with GCC) then the compiler will define __ARM_NEON__ and we can rely
        * unconditionally on NEON instructions not crashing, otherwise we must
        * disable use of NEON instructions.
        *
        * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
        * can only be turned on automatically if that is supported too.  If
        * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
        * to compile with an appropriate #error if ALIGNED_MEMORY has been turned
        * off.
        *
        * Note that gcc-4.9 defines __ARM_NEON instead of the deprecated
        * __ARM_NEON__, so we check both variants.
        *
        * To disable ARM_NEON optimizations entirely, and skip compiling the
        * associated assembler code, pass --enable-arm-neon=no to configure
        * or put -DPNG_ARM_NEON_OPT=0 in CPPFLAGS.
        */
    #  if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && 
       defined(PNG_ALIGNED_MEMORY_SUPPORTED)
    #     define PNG_ARM_NEON_OPT 2
    #  else
    #     define PNG_ARM_NEON_OPT 0
    #  endif
    #endif
    
  • 相关阅读:
    获取mysql数据库中的表信息
    Django Rest Framework --- 分页器组件
    Django Rest Framework --- 频率组件
    Django Rest Framework --- 权限组件
    Django Rest Framework --- 认证组件
    Django Rest Framework --- 视图组件
    序列化组件
    restful规范,cbv源码执行流程,drf之APIView及Respons源码分析
    前后台分离式开发(文件的上传下载),cookie(存放在前台),session(存放在后台)
    ajax,分页器
  • 原文地址:https://www.cnblogs.com/oloroso/p/13995309.html
Copyright © 2020-2023  润新知