Windows环境下编译Assimp库生成Android可用的.a/.so文件

前言

在做项目过程中需要使用Assimp这个3D模型读取库来读取obj格式的模型,因为项目是基于Android平台,采用NDK开发,所以就打算编译Assimp库并生成.so文件。本文使用Assimp-v.5.0.0.rc1(https://github.com/assimp/assimp/releases/tag/v.5.0.0.rc1),此版本已经支持导入blendshape。

步骤

  1. 下载Android Studio(主要是利用其带的SDK以及CMAKE)
  2. 下载并安装Python,注意安装过程中需要勾选添加到环境变量,我安装的是Python3.5,可通过命令行键入python检查Python是否已经配置好
  3. 下载NDK, 本文使用r14b 64位 (https://github.com/assimp/assimp/wiki/Android-compilation-on-Windows-%28Quick-overview%29)
  4. 下载并解压Assimp-v.5.0.0.rc1
    Windows环境下编译Assimp库生成Android可用的.a/.so文件_第1张图片
  5. 在NDK目录下的build/tools下,通过以下命令生成编译时所需要的交叉编译ToolChain,注意:
    a) –arch 参数指定不同的架构:arm64-v8a对应arm64,armeabi-v7a对应arm等等
    b) 这里要指定使用哪种stl,本文使用gnustl,如果不指定的话,会报一些中的函数的错误。“xx”is not a member of ‘std’ 等等。后续在使用编译出来的Assimp库时,Application.mk中要配置同样的C库。
    c) –api 选择了9。
    在这里插入图片描述
  6. 将生成的android-toolchain-24-llvm-armeabi_v7a整个文件夹复制到Assimp-v.5.0.0.rc1的同级目录下。
  7. 在Assimp-v.5.0.0.rc1的同级目录下,新建一个build_assimp.bat,用于编译生成.so文件,文件内容如下;
1.	@echo off  
2.	cls  
3.	  
4.	REM *NOTE* Change these based on   
5.	SET ASSIMP_DIR=assimp-v.5.0.0.rc1  
6.	SET OUTPUT_DIR=aassimp-build-armeabi-v7a  
7.	SET ANDROID_PATH=C:/Users/chenchengju/AppData/Local/Android/Sdk  
8.	SET NDK_PATH=G:/software/android-ndk-r16b  
9.	SET NDK_TOOLCHAIN=%~dp0android-toolchain-24-llvm-armeabi-v7a  
10.	SET CMAKE_TOOLCHAIN=%NDK_PATH%/build/cmake/android.toolchain.cmake  
11.	SET CMAKE_PATH=%ANDROID_PATH%/cmake/3.6.4111459  
12.	  
13.	REM *NOTE* Careful if you don't want rm -rf, I use it for testing purposes.  
14.	  
15.	mkdir %OUTPUT_DIR%  
16.	  
17.	REM pushd doesn't seem to work ):<  
18.	cd %OUTPUT_DIR%  
19.	  
20.	if not defined ORIGPATH set ORIGPATH=%PATH%  
21.	SET PATH=%CMAKE_PATH%\bin;%ANDROID_PATH%\tools;%ANDROID_PATH%\platform-tools;%ORIGPATH%  
22.	  
23.	cmake ^  
24.	      -GNinja ^  
25.	      -DCMAKE_TOOLCHAIN_FILE=%CMAKE_TOOLCHAIN% ^  
26.	      -DASSIMP_ANDROID_JNIIOSYSTEM=ON ^  
27.	      -DANDROID_NDK=%NDK_PATH% ^  
28.	      -DCMAKE_MAKE_PROGRAM=%CMAKE_PATH%\bin\ninja.exe ^  
29.	      -DCMAKE_BUILD_TYPE=Release ^  
30.	      -DANDROID_ABI="armeabi-v7a" ^  
31.	      -DANDROID_NATIVE_API_LEVEL=9 ^  
32.	      -DANDROID_FORCE_ARM_BUILD=TRUE ^  
33.	      -DCMAKE_INSTALL_PREFIX=install ^  
34.	      -DANDROID_STL=gnustl_static ^  
35.	      -DCMAKE_CXX_FLAGS=-Wno-c++11-narrowing ^  
36.	      -DANDROID_TOOLCHAIN=clang ^  
37.	  
38.	      -DASSIMP_BUILD_TESTS=OFF ^  
39.	  
40.	      ../%ASSIMP_DIR%  
41.	  
42.	cmake --build .  
43.	  
44.	cd ..  
45.	  
46.	pause 

注意一下情况:
1 ASSIMP_DIR是第4步解压的Assimp库所在的文件夹
2 OUTPUT_DIR是保存编译生成文件的文件夹
3 ANDROID_PATH跟NDK_PATH需要修改为自己机器上的路径
4 NDK_TOOLCHAIN是保存工具链的文件夹
5 下面的-DANDROID_ABI和-DANDROID_NATIVE_API_LEVEL参数需要改成所需的值。
6 DANDROID_STL=gnustl_static ^ ,需要与之前生成工具链选择的c库一致。
7 然后双击运行.bat文件,如果没有报错,就能在< OUTPUT_DIR>/code/下找到libassimp.so文件,想要生成其他架构下的.so文件,只需修改生成toolchain和.bat文件参数(-DANDROID_ABI=“armeabi-v7a” ^ ),再执行即可。
8 如果想生成静态库.a,需要打开assimp/CMakeList.txt,将BUILD_SHARED_LIBS关掉,并增加下面三行,然后重复上面步骤。
Windows环境下编译Assimp库生成Android可用的.a/.so文件_第2张图片

去符号

使用ndk 下面的 工具 使用以下命令去符号

/data/Android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin$ ./arm-linux-androideabi-strip -g --strip-debug --strip-unneeded /data/work/assimp_4/libassimp.a

一些错误的记录:

  • Windows环境下编译Assimp库生成Android可用的.a/.so文件_第3张图片
    **解决方法:**去assimp/code/CMakeList.txt中将IrrXML相关的代码注释掉,然后Assimp支持很多格式,但是在实际使用中,除非本身就是一个3D模型查看器或者转换器,否则最终可能就固定使用那么2,3个格式。显然编译时把其他的格式编进去是无用且浪费的,徒增库的大小,并且一些模型的导入用到了IrrXML相关的代码,比如上图中ColladaParser。剔除不需要的模型格式的方法是:将对应的导入的代码注释掉,并且添加一个宏。
    Windows环境下编译Assimp库生成Android可用的.a/.so文件_第4张图片
  • 有些std::xxx在assimp自己的文件中有定义,会发生冲突,这种情况根据报错进行对应的修改。
  • atof not find,头文件没包含,include一下

Assimp定制化:

assimp功能强大,可以加载和导出多种3D模型,附加多种效果优化功能,但在需求中有很多功能使用不到,所以可以在编译时直接剔除已达到减小静态库的目的,需要注意的是:除了需要在编译时通过宏控制编译之外还需要直接在code/CMakeLists.txt文件中将相应的源码注释掉。

  1. 在编译时只保留obj模块,其余模块都不需要编译,可以直接通过cmake-gui工具直接取消对应模块的勾选来达到排除对应模块编译的效果。
  2. 因为我们只使用assimp的模型加载功能,所以在assimp项目code/CMakeLists.txt文件中将*Exporter.cpp源码【如:AssxmlExporter.cpp】列表注释以达到将该源码剔除编译列表的目的。
  3. 根据assimp项目code/PostStepRegistry.cpp文件,查看使用到的每个process的作用,决定哪些process是可以去掉的,若要去掉对应的process,可在项目根目录下的CMakeLists.txt文件中定义对应的宏,如:
    add_definitions(-DASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS),然后在code/CMakeLists.txt文件中将该宏中对应的源码从列表中注释掉。同理可将如下process也一起去除:
  • ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
  • ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
  • ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
  • ASSIMP_BUILD_NO_DEBONE_PROCESS
  • ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
  • ASSIMP_BUILD_NO_FLIPUVS_PROCESS
  • ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS
  • SSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
  • ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS
  • ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS
  • ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS
  • ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS

结语

assimp库是有内存泄漏的!!!
assimp库是有内存泄漏的!!!
assimp库是有内存泄漏的!!!
重要的事情说三遍。
谢谢!

你可能感兴趣的:(Rendering)