GDAL(Geospatial Data Abstraction Library)(https://www.gdal.org/)是一个在X/MIT许可协议下的开源栅格空间数据转换库。GDAL功能很强大,支持很多数据格式,使用方便,是GIS开发的不二之选。GDAL库支持多种操作系统,当然也包括Android,然而其官方的Android编译指南,确实写的不明不白,搞不清咋回事,可能是太旧了吧。于是乎我就在Linux下(Windows下的NDK工具貌似不太好用)摸索的一下GDAL的编译,方法记录如下。
1.创建独立工具链
创建一个独立的NDK工具链,具体参考
按照需要创建工具链,比如我创建了arm和arm64架构两个,建议带上-lstdc++选项 。
把bin目录加入PATH
2.configure
进入GDAL源码目录,构建arm架构的库,执行下面的configure代码,--prefix指定了要安装的路径,安装实际情况修改。同时还可以指定需要哪些模块,不需要哪些模块。
如果构建arm64架构,下面的代码开头的CFLAGS="-mthumb" CXXFLAGS="-mthumb"要去掉,host部分改成--host=aarch64-linux-android即可。
CFLAGS="-mthumb" CXXFLAGS="-mthumb" LIBS="-lstdc++" ./configure --prefix=/home/zouleid/gdal/android --with-threads --with-ogr --host=arm-linux-androideabi --without-geos --with-libz=internal --with-png=internal --with-libtiff=internal --with-geotiff=internal --with-jpeg=internal --with-sqlite3=yes -without-libtool -with-oci=no --with-xerces=no --with-expat=no --with-libkml=no --without-jpeg12 --without-bsb --without-grib --without-openfilegdb --without--filegdb --without-pam --without-pdf --without-sentinel2 --without-ctg --without-kmlsuperoverlay --without-wcs --without-vdv --without-dgn --without-dwg
如果configure提示出错,可能是NDK工具链没有加入到环境变量。
configure成功后,可以看到详细的模块信息。
3.make
直接make,开始编译。编译过程中经常会出问题,跟进去解决一下即可,一般不难。
不过有个经验,使用新的GDAL版本,编译出错的可能性较小。比如我用2.3版的源码编译没有出过错误,2.2版的需要改一些源码兼容性错误,1系列的源码就更费劲了。
常见错误:‘to_string’ was not declared in this scope
这个错误其实很简单,打开报错文件的源代码就可以发现。NDK用的是gcc 4.9版本,好像没有to_string函数,源码虽然对to_string进行了处理,但是添加的宏(见下图红框)没处理gcc 4.9,所以,把这个宏处理一下就好。
常见错误:apps目录下代码编译错误
这个报错完全不用管,这是GDAL库构建完成后,构建可执行工具时出错了。这些可执行工具不需要,也没法在Android上使用,编译错误也就不用管了,反正我要的GDAL库已经有了。如果make到这个阶段,就可以当成是构建完成了。
4.创建动态链接库so
构建完成了,先检查一下文件
经过刚才的构建,生成了一个静态库libgdal.a,如果你只需要静态库,到这里就算可以了。可我需要动态库so文件,咋办?
这里我们可以修改一下下 GUNmakefile文件:
打开GUNmakefile文件,找到下面的部分
force-lib:
$(AR) r $(GDAL_LIB) $(GDAL_OBJ)
$(RANLIB) $(GDAL_LIB)
$(LD_SHARED) $(GDAL_SLIB_SONAME) $(GDAL_OBJ) $(GDAL_LIBS) $(LDFLAGS) $(LIBS) \
-o $(GDAL_SLIB)
将其修改为:
force-lib:
$(AR) r $(GDAL_LIB) $(GDAL_OBJ)
$(RANLIB) $(GDAL_LIB)
# $(LD_SHARED) $(GDAL_SLIB_SONAME) $(GDAL_OBJ) $(GDAL_LIBS) $(LDFLAGS) $(LIBS) \
# -o $(GDAL_SLIB)
arm-linux-androideabi-g++ \
--sysroot=/home/public/Android/android-ndk-r14b/platforms/android-22/arch-arm/ \
-Wl,--no-undefined -Wl,-z,noexecstack -shared -Wl,-soname,libgdal222.so -o libgdal222.so \
$(GDAL_OBJ) \
-L/home/public/Android/android-ndk-r14b/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a \
-L/home/public/Android/android-ndk-r14b/platforms/android-22/arch-arm/usr/lib \
-lgnustl_shared -llog -lz -lm -ldl -lc -lgcc
上面其实是用g++生成了一个名为libgdal222.so的动态链接库文件。上面的代码不要直接抄,要自己改。上面的代码设置了sysroot路径和另外两个路径,以及生成动态链接库的名字,这些都要根据需要修改。
然后,“make force-lib”即可。
如果构建arm64架构,对应的修改编译器、路径就好了。
我构建出来的arm架构的libgdal222.so有21M大,如果不需要调试,可以strip一下,就只剩15M了。
xxx@xxx-PC:~/gdal/gdal-2.3.1$ ls -l libgdal222.so
-rwxr-xr-x 1 xxx xxx 22053740 8月 10 20:26 libgdal222.so
xxx@xxx-PC:~/gdal/gdal-2.3.1$ cp libgdal222.so libgdal222.bak.so
xxx@xxx-PC:~/gdal/gdal-2.3.1$ arm-linux-androideabi-strip libgdal222.so
xxx@xxx-PC:~/gdal/gdal-2.3.1$ ls -l libgdal222.so
-rwxr-xr-x 1 xxx xxx 16715060 8月 10 20:27 libgdal222.so
注意:这样编译出来的动态链接库so需要libgnustl_shared.so,这个文件在NDK里有,按照你要的架构拷贝出来(其实上面修改makefile的时候已经出现过它的路径了)。
5.make install
make完了make install,构建出来的结果就被安装在了构建时--prefix指定的路径中。
不用多说了吧,如果自己生成的so没进去,就自己拷贝进去。
6.其他说明
其他的事情以后再补充吧。