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/
还需要安装cmake
、make
、automake
、autoconf
、libtool
、zip
、sqlite
等软件,具体安装方法根据 Linux 发行版本确定,这里不再赘述。
备注:ARM64 都是带 fpu 的,所以不需要区分-mfloat-abi
的设置。
2、使用 VCPKG 编译一些基础的依赖库#
下载安装 vcpkg
的命令如下:
# 下载 vcpkg git clone https://github.com/microsoft/vcpkg.git # 编译出 vcpkg 工具 cd vckpg ./bootstrap-vcpkg.sh
编译 sqlite3
、curl
、geos
等第三方库的 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
条件,对编译出的库的影响。
hdf5 编译失败可以参考 https://www.cnblogs.com/oloroso/p/14606052.html 。
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_IMPLEMENTATION
为 1
的时候才存在。这个函数本身没有定义,只是在 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理