引子
最近些年车机研发相当火热,而车内通信大多都绕不开vsomeip,这个框架官方对Linux、QNX等系统支持的比较好,但是如果想用NDK去交叉编译它就会踩很多坑,这里就分享一下本人用NDK编译vsomeip3.3.8时的流程,其他版本的vsomeip应该也是大同小异,欢迎有能力的大佬改良我的操作~
环境准备
作者用的是Ubuntu的容器,在docker内首先要下载要用的包:
apt-get update &&
apt-get install zip git curl &&
apt-get install gcc g++ vim less file python3 python3-pip &&
pip3 install --break-system-packages cpplint &&
apt-get install graphviz doxygen asciidoc source-highlight
当然还要下载vsomeip和ndk,安卓交叉编译用到的Boost库以及cmake:
https://github.com/android/ndk/wiki/Unsupported-Downloads
https://github.com/moritz-wundke/Boost-for-Android.git
https://github.com/COVESA/vsomeip
https://github.com/Kitware/CMake/releases/tag/v3.22.1
这里需要注意:要根据Boost for Android库中Readme里Boost版本对NDK的支持性选择下载
eg:作者选择了NDK r25c版本和VSOMEIP3.3.8
再设置几个后面要用到的环境变量:
export ANDROID_NDK=/path/to/your/ndk/root
export CMAKEPATH=/path/to/cmake/bin
这里ndk路径要指向NDK解压后的根目录,eg:~/ndk/ndk-r25c
cmake路径指向其内部的bin目录,eg:~/cmake/cmake-3.22.1/bin
下一步就是根据ndk版本下对应的boost库,这里直接进之前下载的Boost-for-Android自动搞:
cd Boost-for-Android && ./build-android.sh $ANDROID_NDK --boost=1.76.0
这里作者选择了Boost 1.76.0版本,其实1.76.0以上的boost版本都支持了r25c。
魔改vsomeip3
由于vsomeip对安卓的支持性并不好,所以在编译前要自己手动魔改一下:
- 现在的安卓ndk已经没有utils/Log.h了 我们去find一下可以发现只有android/log.h,因此我们要修改vsomeip-3.3.8/implementation/logger/src/message.cpp:
#include<android/log.h> //update from <utils/Log.h>
//update five long **ALOG** define lines to:
#define ALOGE(LOG_TAG, ...) (__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__))
#define ALOGW(LOG_TAG, ...) (__android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__))
#define ALOGI(LOG_TAG, ...) (__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__))
#define ALOGD(LOG_TAG, ...) (__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__))
#define ALOGV(LOG_TAG, ...) (__android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__))
以及vsomeip-3.3.8/implementation/tracing/src/connector_impl.cpp:
#include<android/log.h> //update from <utils/Log.h>
//update that long **ALOG** define lines to:
#define ALOGI(LOG_TAG, ...) (__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__))
还有vsomeip-3.3.8/implementation/utility/include/utility.hpp这里可能会在编译时抛出VSOMEIP_BASE_PATH未定义的问题,我们可以在vsomeip的CMakeLists里面加上
target_comepile_definitions(vsomeip3 PRIVATE -DVSOMEIP_BASE_PATH=\"/path/you/want/run/someip\")
- 我们继续在CMakeLists里面给安卓交叉编译做一些支持:
首先找到这一行,我们需要针对安卓做一些针对性的初始化内容而且不要影响到其他OS的:
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
这一行的上下加完如下:
/* add */ set(OS_LIBS ${SystemD_LIBRARIES})
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
/* add */
if (${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(OS "ANDROID")
set(DL_LIBRARY "")
set(EXPORTSYMBOLS "")
set(NO_DEPRECATED "")
set(OPTIMIZE "")
set(OS_CXX_FLAGS "-DWITHOUT_SYSTEMD")
find_library(ANDROID_LOG_LIB log)
set(OS_LIBS ${ANDROID_LOG_LIB})
endif(${CMAKE_SYSTEM_NAME} MATCHES "Android")
同理在我们增加内容的后面几行在OS为FreeBSD的配置里也这么加上:
/* add */ set(OS_LIBS ${ANDROID_LOG_LIB})
endif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
再继续往下找到文档中 # Directories 块,找到if(MSVC)这一句,修改它的else模块为安卓提供支持:
else()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OS_CXX_FLAGS} -g ${OPTIMIZE} -std=c++14 ${NO_DEPRECATED} ${EXPORTSYMBOLS}")
if (${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(USE_RT "")
else()
set(USE_RT "rt")
endif()
endif()
这里我们将安卓单独拎出来,安卓编译并不依赖librt,ndk也没有它,如果加上它会在LINKING时报错
最后,我们要将我们前面替换的这一句**set(OS_LIBS ${SystemD_LIBRARIES})**为每个编出来的so都进行修改:
具体操作为在CMakeLists中找到# Configuration library , # Base library , # Service Discovery library
, # E2E library , # Compatibility library 这五个部分,找到target_link_libraries这一句,将target_link_libraries(… ${SystemD_LIBRARIES}) 改为 target_link_libraries(… ${OS_LIBS})
3. 现在我们要到Boost库里面去,作者这里用aarch64架构,因此操作流程如下:
cd ~/Boost-for-Android/build/out/arm64-v8a/lib
mv libboost_filesystem-clang-mt-a64-1_76.a libboost_filesystem.a
mv libboost_system-clang-mt-a64-1_76.a libboost_system.a
mv libboost_thread-clang-mt-a64-1_76.a libboost_thread.a
这里改名的原因是cmake对这个库的支持并不好,这样的后缀名它找不到,会在编译时报错。同理的,如果后面你自己的程序需要用到其他库文件,也要都改名。
编译vsomeip3
现在进入vsomeip根目录,然后:
mkdir build && cd build
$CMAKEPATH/cmake .. -DBoost_INCLUDE_DIR=${HOME}/Boost-for-Android/build/out/arm64-v8a/include/boost-1_76 \
-DBoost_LIBRARY_DIR=${HOME}/Boost-for-Android/build/out/arm64-v8a/lib \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI="arm64-v8a" \
-DANDROID_NDK=$ANDROID_NDK \
-DANDROID_NATIVE_API_LEVEL=33 \
-DANDROID_PLATFORM=android-33 \
-DANDROID_STL=c++_shared \
-DCMAKE_BUILD_TYPE=${BUILDTYPE} \
-DBOOST_ROOT=${HOME}/Boost-for-Android/build/out/arm64-v8a \
-DCMAKE_VERBOSE_MAKEFILE=ON
make -j4
make install
到这里你就应该能够成功编译出vsomeip3了,如果有任何问题可以留言给作者,或者如果有大佬有更好的操作也可以一起讨论~
参考资料
https://www.cnblogs.com/BruceWayne09/p/16716973.html
https://github.com/nkh-lab/vsomeip/blob/ndk/CMakeLists.txt