C++学习(三三七)Qt5.12+osgEarth2.9 for Android

难点: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

效果图:

 

C++学习(三三七)Qt5.12+osgEarth2.9 for Android_第1张图片

你可能感兴趣的:(C++学习,android,c++)