难点:osgEarth使用了大量opengl函数,需要转换成opengles函数。
工具CMake3.12 osgEarth2.9。
编译器ninja ndk:android-ndk-r19c 交叉编译工具链:android-ndk-r19c/build/cmake/android.toolchain.cmake 第三方依赖库3rdpartyAndroid.zip(适用于armeabi v5和v7)。
准备工作
1、解决gles库的问题
在android iphone等平台上使用的都是gles,而不是opengl。
osgEarth2.9默认是不支持android的,但是是支持iphone的,在支持iPhone的基础上进行修改,使其支持android。并且osg是支持android的,也可以参照其设置方式。
修改osgearth2.9\CMakeLists.txt,添加:
SET(OSGEARTH_USE_GLES FALSE)
#hankern20211106 add android support
IF(ANDROID)
SET(OSGEARTH_USE_GLES TRUE)
# Map the OPENGL_PROFILE to OSG_GL*_AVAILABLE settings
SET(OPENGL_PROFILE "GLES2" CACHE STRING "OpenGL Profile to use, choose from GL1, GL2, GL3, GLES1, GLES2, GLES3")
ELSE()
# Map the OPENGL_PROFILE to OSG_GL*_AVAILABLE settings
SET(OPENGL_PROFILE "GL2" CACHE STRING "OpenGL Profile to use, choose from GL1, GL2, GL3, GLES1, GLES2, GLES3")
ENDIF()
IF ((OPENGL_PROFILE STREQUAL "GL1") OR (OPENGL_PROFILE STREQUAL "GL2"))
OPTION(OSG_GL1_AVAILABLE "Set to OFF to disable use of OpenGL 1.x functions library." ON )
ELSE()
OPTION(OSG_GL1_AVAILABLE "Set to OFF to disable use of OpenGL 1.x functions library." OFF )
ENDIF()
IF ((OPENGL_PROFILE STREQUAL "GL2"))
OPTION(OSG_GL2_AVAILABLE "Set to OFF to disable use of OpenGL 2.x functions library." ON )
ELSE()
OPTION(OSG_GL2_AVAILABLE "Set to OFF to disable use of OpenGL 2.x functions library." OFF )
ENDIF()
IF ((OPENGL_PROFILE STREQUAL "GL3") OR (OPENGL_PROFILE STREQUAL "GLCORE"))
OPTION(OSG_GL3_AVAILABLE "Set to OFF to disable use of OpenGL 3.x functions library." ON )
if(APPLE)
add_definitions(-DGL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED)
endif()
ELSE()
OPTION(OSG_GL3_AVAILABLE "Set to OFF to disable use of OpenGL 3.x functions library." OFF )
ENDIF()
IF ((OPENGL_PROFILE STREQUAL "GLES1"))
OPTION(OSG_GLES1_AVAILABLE "Set to OFF to disable use of OpenGL ES 1.x functions library." ON )
ELSE()
OPTION(OSG_GLES1_AVAILABLE "Set to OFF to disable use of OpenGL ES 1.x functions library." OFF )
ENDIF()
IF ((OPENGL_PROFILE STREQUAL "GLES2"))
OPTION(OSG_GLES2_AVAILABLE "Set to OFF to disable use of OpenGL ES 2.x functions library." ON )
ELSEIF ((OPENGL_PROFILE STREQUAL "GLES3"))
OPTION(OSG_GLES3_AVAILABLE "Set to OFF to disable use of OpenGL ES 3.x functions library." ON )
ELSEIF ((OPENGL_PROFILE STREQUAL "GLES2+GLES3"))
OPTION(OSG_GLES2_AVAILABLE "Set to OFF to disable use of OpenGL ES 2.x functions library." ON )
OPTION(OSG_GLES3_AVAILABLE "Set to OFF to disable use of OpenGL ES 3.x functions library." ON )
ELSE()
OPTION(OSG_GLES2_AVAILABLE "Set to OFF to disable use of OpenGL ES 2.x functions library." OFF )
OPTION(OSG_GLES3_AVAILABLE "Set to OFF to disable use of OpenGL ES 3.x functions library." OFF )
ENDIF()
修改osgearth2.9\CMakeModules\FindOpenGLES.cmake,添加:
ELSEIF (ANDROID) #hankern20211105 add android support
IF(OSG_GLES1_AVAILABLE)
FIND_PATH(OPENGL_INCLUDE_DIR GLES/gl.h
PATHS
${ANDROID_SYSROOT}/usr/include)
FIND_LIBRARY(OPENGL_LIBRARIES GLESv1_CM
PATHS
${ANDROID_SYSROOT}/usr/lib)
ELSEIF(OSG_GLES2_AVAILABLE)
FIND_PATH(OPENGL_INCLUDE_DIR GLES2/gl2.h
PATHS
${ANDROID_SYSROOT}/usr/include)
FIND_LIBRARY(OPENGL_LIBRARIES GLESv2
PATHS
${ANDROID_SYSROOT}/usr/lib)
ELSEIF(OSG_GLES3_AVAILABLE)
FIND_PATH(OPENGL_INCLUDE_DIR GLES3/gl3.h
PATHS
${ANDROID_SYSROOT}/usr/include)
FIND_LIBRARY(OPENGL_LIBRARIES GLESv3
PATHS
${ANDROID_SYSROOT}/usr/lib)
ENDIF()
2、解决库引用顺序的问题
windows库的顺序是从左至右,android库的顺序是从右至左
修改src/osgEarth/CMakeLists.txt(改完这个,其它库的顺序不用改,也都能成功生成,原因探寻中)
if(NOT NRL_STATIC_LIBRARIES)
#hankern20211107
if(ANDROID)
LINK_WITH_VARIABLES(${LIB_NAME} OSGMANIPULATOR_LIBRARY ZLIB_LIBRARY GDAL_LIBRARY CURL_LIBRARY OPENTHREADS_LIBRARY OSGSHADOW_LIBRARY OSGGA_LIBRARY OSGTEXT_LIBRARY OSGVIEWER_LIBRARY OSGFX_LIBRARY OSGDB_LIBRARY OSGTERRAIN_LIBRARY OSGSIM_LIBRARY OSGUTIL_LIBRARY OSG_LIBRARY)
ELSE()
LINK_WITH_VARIABLES(${LIB_NAME} OSG_LIBRARY OSGUTIL_LIBRARY OSGSIM_LIBRARY OSGTERRAIN_LIBRARY OSGDB_LIBRARY OSGFX_LIBRARY OSGVIEWER_LIBRARY OSGTEXT_LIBRARY OSGGA_LIBRARY OSGSHADOW_LIBRARY OPENTHREADS_LIBRARY CURL_LIBRARY GDAL_LIBRARY ZLIB_LIBRARY OSGMANIPULATOR_LIBRARY)
ENDIF()
else(NOT NRL_STATIC_LIBRARIES)
LINK_WITH_VARIABLES(${LIB_NAME} OSG_LIBRARY OSGUTIL_LIBRARY OSGSIM_LIBRARY OSGTERRAIN_LIBRARY OSGDB_LIBRARY OSGFX_LIBRARY OSGVIEWER_LIBRARY OSGTEXT_LIBRARY OSGGA_LIBRARY OSGSHADOW_LIBRARY OPENTHREADS_LIBRARY CURL_LIBRARY GDAL_LIBRARY ZLIB_LIBRARY OSGMANIPULATOR_LIBRARY SSL_EAY_RELEASE LIB_EAY_RELEASE TIFF_LIBRARY PROJ4_LIBRARY PNG_LIBRARY JPEG_LIBRARY)
endif(NOT NRL_STATIC_LIBRARIES)
3、解决生成tests的问题
交叉编译的exe程序是运行不起来的,所以就不要生成tests的测试程序了
修改src/CMakeLists.txt
#hankern20211108
IF((NOT OSGEARTH_BUILD_PLATFORM_IPHONE AND NOT OSGEARTH_BUILD_PLATFORM_IPHONE_SIMULATOR) AND (NOT ANDROID))
ADD_SUBDIRECTORY( tests )
ENDIF()
在做以上操作前,不要启动cmake,也不要执行configure操作
启动CMake后先做如下操作:
ANDROID_PLATFORM设置为android-28
ANDROID_NDK设置为D:\android-ndk-r19c
ANDROID_ABI设置为arm64-v8a(以上变量一定要在cmake的configure前设置,如果不是需要删除缓存,重新设置后再configure,因为先configure后会缓存一些变量,后面是无法修改的)
主要是影响CMAKE_LINKER交叉编译工具的选择,以上步骤会使用D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-ld.exe之类的工具,不设置会使用D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/bin/arm-linux-androideabi-ld.exe之类的工具。
然后configure,再设置其它内容
INSTALL_TO_OSG_DIR设置为true
OPENGL_egl_LIBRARY设置为D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/aarch64-linux-android/28/libGLESv2.so
OSGEARTH_BUILD_PLATFORM_IPHONE设置为true
OPENGL_INCLUDE_DIR设置为D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/include
OPENGL_LIBRARIES设置为D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/aarch64-linux-android/28/libGLESv3.so (因为osg编译时使用的v3版本,所以这里需要使用v3)
CURL_INCLUDE_DIR设置为E:\Projects\QT5.12\osg_earth_src\osg\osg3.6\3rdparty\curl\include
CURL_IS_STATIC设置为true
CURL_LIBRARY、CURL_LIBRARY_DEBUG设置为E:/Projects/QT5.12/osg_earth_src/osg/osg3.6/3rdparty/build/curl/obj/local/armeabi-v7a/libcurl.a
E:/Projects/QT5.12/osg_earth_src/osg/osg3.6/3rdparty/build/curl/obj/local/armeabi/libcurl.a(上面的版本链接通不过)
GDAL_DIR设置为E:\Projects\QT5.12\osg_earth_src\osg\osg3.6\3rdparty\gdal
GDAL_INCLUDE_DIR设置为E:\Projects\QT5.12\osg_earth_src\osg\osg3.6\3rdparty\gdal\include
GDAL_LIBRARY设置为E:/Projects/QT5.12/osg_earth_src/osg/osg3.6/3rdparty/build/gdal/obj/local/armeabi-v7a/libgdal.a
E:\Projects\QT5.12\osg_earth_android_build\3rdpartyAndroid\gdal\obj\local\armeabi-v8a\lib(该库需要重新编译C++学习(三四六)cygwin 交叉编译 gdal_hankern的专栏-CSDN博客)
E:/Projects/QT5.12/osg_earth_src/osg/osg3.6/3rdparty/build/gdal/obj/local/armeabi/libgdal.a(上面的版本链接通不过)
OPENTHREADS_LIBRARY、OPENTHREADS_LIBRARY_DEBUG、OSGDB_LIBRARY、OSGDB_LIBRARY_DEBUG、OSGFX_LIBRARY、OSGFX_LIBRARY_DEBUG、OSGGA_LIBRARY、OSGGA_LIBRARY_DEBUG、、OSGMANIPULATOR_LIBRARY、OSGMANIPULATOR_LIBRARY_DEBUG、OSGSHADOW_LIBRARY、OSGSHADOW_LIBRARY_DEBUG、OSGTERRAIN_LIBRARY、OSGTERRAIN_LIBRARY_DEBUG、OSGTEXT_LIBRARY、OSGTEXT_LIBRARY_DEBUG
、OSGUTIL_LIBRARY、OSGUTIL_LIBRARY_DEBUG、OSGVIEWER_LIBRARY、OSGVIEWER_LIBRARY_DEBUG、OSGWIDGET_LIBRARY、OSGWIDGET_LIBRARY_DEBUG、OSG_LIBRARY、OSG_LIBRARY_DEBUG
设置为D:\OSG_OSGEARTH_Android\lib64目录下对应的*.a和*d.a
OSG_INCLUDE_DIR、OSG_GEN_INCLUDE_DIR设置为D:\OSG_OSGEARTH_Android\include
OSG_LIBRARY、OSG_LIBRARY_DEBUG设置为D:\OSG_OSGEARTH_Android\lib64
OSG_GEN_INCLUDE_DIR设置为D:\OSG_OSGEARTH_Android\include
CMAKE_INSTALL_PREFIX设置为D:\OSG_OSGEARTH_Android
OSGEARTH_INSTALL_SHADERS设置为TRUE
DYNAMIC_OSGEARTH设置为true,生成动态库,设置为false生成静态库
CMAKE_BUILD_TYPE,设置编译类型,一般包含Debug, Release, RelWithDebInfo, MinSizeRel几种,貌似不能同时编译不同类型,比如Debug|Release,因此只能手工选择多次编译
执行ninja.exe -f build.ninja
执行ninja.exe install安装程序
清除命令为ninja.exe -t clean
构建某一个模块(osg)ninja.exe -f build.ninja osg
问题1:
CMAKE_LINKER自动识别为D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/bin/arm-linux-androideabi-ld.exe,需不需要改为:
D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-ld.exe,后面的是构建osg时用的工具。
解答1:注意在CMAKE启动后,configure前设置ANDROID_PLATFORM、ANDROID_NDK、ANDROID_ABI。
问题2:E:/Projects/QT5.12/osg_earth_src/osgearth/osgearth2.9/src/osgEarth/ThreadingUtils.cpp:44:10: error: use of undeclared identifier 'gettid'
解答2:
unsigned osgEarth::Threading::getCurrentThreadId()
{
/* OpenThreads::Thread* t = OpenThreads::Thread::CurrentThread();
return t ? t->getThreadId() : 0u;*/
#ifdef _WIN32
return (unsigned)::GetCurrentThreadId();
#elif __APPLE__
return ::syscall(SYS_thread_selfid);
#elif __ANDROID__
return gettid();
#elif __LINUX__
return (unsigned)::syscall(SYS_gettid);
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
long tid;
syscall(SYS_thr_self, &tid);
return (unsigned)tid;
#else
/* :XXX: this truncates to 32 bits, but better than nothing */
return (unsigned)pthread_self();
#endif
}
openthread中没有gettid,只有getThreadId,因此做如下修改:
unsigned osgEarth::Threading::getCurrentThreadId()
{
/* OpenThreads::Thread* t = OpenThreads::Thread::CurrentThread();
return t ? t->getThreadId() : 0u;*/
#ifdef _WIN32
return (unsigned)::GetCurrentThreadId();
#elif __APPLE__
return ::syscall(SYS_thread_selfid);
#elif __ANDROID__
//return gettid();
OpenThreads::Thread* t = OpenThreads::Thread::CurrentThread(); //hankern: use getThreadId,there is no getid function in openthread
return t ? t->getThreadId() : 0u;
#elif __LINUX__
return (unsigned)::syscall(SYS_gettid);
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
long tid;
syscall(SYS_thr_self, &tid);
return (unsigned)tid;
#else
/* :XXX: this truncates to 32 bits, but better than nothing */
return (unsigned)pthread_self();
#endif
}
问题3:error adding symbols: File in wrong format
FAILED: lib/libosgEarthd.so
cmd.exe /C "cd . && D:\android-ndk-r19c\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android28 --gcc-toolchain=D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=D:/android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -stdlib=libc++ -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libosgEarthd.so -o lib\libosgEarthd.so @CMakeFiles\osgEarth.rsp && cd ."
E:/Projects/QT5.12/osg_earth_src/osg/osg3.6/3rdparty/build/curl/obj/local/armeabi/libcurl.a: error adding symbols: File in wrong format
解答3:
可能是一个32位,一个64位;也可能是架构不同,一个是v8,一个不是(armeabi或armeabi-v7a),需要重新编译android版的curl
效果图: