1. 背景

软件定义汽车,智能网联汽车作为未来汽车发展的主流方向。

SOME/IP 是一个汽车的中间件解决方案,可用于控制消息。从一开始,它的设计就是为了完美地适应不同尺寸和不同操作系统的设备。这包括小型设备,如相机、AUTOSAR设备,以及头部单元或远程信息处理设备。同时还确保了SOME/IP支持信息娱乐域以及车内其他域的功能,从而使SOME/IP可以用于多数替换场景以及更传统的CAN场景,在智能网联汽车,面向服务开发SOA架构思想环境下,SOME/IP扮演着非常重要的角色–通信。

参考文章:

01-基于SOA架构someip 开发-Linux开发环境搭建

2. 针对QNX 环境

2.1 Boost版本:

采用1.55.0版本

https://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.gz

2.1.1 boost配置

Cmake配置:

SET(Boost_FOUND TRUE)##source dirSET(Boost_DIR /workspace/someip/toolchains/boost_1_55_0)##compile output include and lib dirSET(Boost_INCLUDE_DIR ${Boost_DIR}/build/qnx/include)SET(Boost_LIBRARY_DIR ${Boost_DIR}/build/qnx/lib)SET(BOOST_LIBRARYDIR ${Boost_DIR}/build/qnx/lib)

2.2 更换vsomeip工程

更换后的工程下载链接:

https://github.com/lixiaolia/vsomeip-qnx.git

镜像:

https://hub.yzuu.cf/lixiaolia/vsomeip-qnx.git

2.2.1 修改点 //patch

CMakeLists.txt

diff --git a/CMakeLists.txt b/CMakeLists.txtindex 262f813..62d31e0 100644--- a/CMakeLists.txt+++ b/CMakeLists.txt@@ -85,6 +85,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") endif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")if (${CMAKE_SYSTEM_NAME} MATCHES "QNX")+message("compile ${PROJECT_NAME} for QNX.") set(OS "QNX") set(DL_LIBRARY "") set(EXPORTSYMBOLS "-Wl,-export-dynamic -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exportmap.gcc")@@ -186,7 +187,7 @@ else() endif()if (${CMAKE_SYSTEM_NAME} MATCHES "QNX")- set(VSOMEIP_BOOST_HELPER implementation/helper/1.70)+ set(VSOMEIP_BOOST_HELPER implementation/helper/1.55) else() message( STATUS "Using boost version: ${VSOMEIP_BOOST_VERSION}" ) if (${VSOMEIP_BOOST_VERSION} GREATER 107400)

2.3 修改capicxx-core-runtime

2.3.1 修改CMakeLists.txt

IF(MSVC)message("using MSVC Compiler")add_definitions(-DCOMMONAPI_INTERNAL_COMPILATION -DCOMMONAPI_DLL_COMPILATION)add_compile_options(/EHsc /wd4996)ELSE ()##M:TIM 2023# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -Werror -DCOMMONAPI_INTERNAL_COMPILATION -fvisibility=hidden")set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -Werror -DCOMMONAPI_INTERNAL_COMPILATION -fvisibility=hidden")ENDIF(MSVC)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCOMMONAPI_LOGLEVEL=COMMONAPI_LOGLEVEL_${MAX_LOG_LEVEL}")##M:TIM 2023 if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")FIND_PACKAGE(PkgConfig)pkg_check_modules(DLT "automotive-dlt >= 2.11")IF(DLT_FOUND)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_DLT")ENDIF(DLT_FOUND)endif()

2.3.1 修改CallInfo.cpp

#include #include #include  //ADD:TIM 2023

2.3.1 修改Runtime.hpp

#include #include #include #include #include //ADD:TIM 2023

2.4 修改capicxx-someip-runtime

所有修改打了个patch:

diff --git a/CMakeLists.txt b/CMakeLists.txtindex ad72647..e853043 100644--- a/CMakeLists.txt+++ b/CMakeLists.txt@@ -29,6 +29,10 @@ message(STATUS "USE_CONSOLE is set to value: ${USE_CONSOLE}") SET(DEFAULT_SEND_TIMEOUT "5000" CACHE STRING "default send timeout") message(STATUS "DEFAULT_SEND_TIMEOUT is set to value: ${DEFAULT_SEND_TIMEOUT} ms") +if (${CMAKE_SYSTEM_NAME} MATCHES "QNX")+message("compile ${PROJECT_NAME} for QNX.")+endif (${CMAKE_SYSTEM_NAME} MATCHES "QNX")+ IF(USE_FILE) add_definitions(-DUSE_FILE) ENDIF(USE_FILE)@@ -66,7 +70,8 @@ include_directories( ${Boost_INCLUDE_DIR} ) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4503") link_directories(${Boost_LIBRARY_DIR}) else()-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -DCOMMONAPI_INTERNAL_COMPILATION -D_GLIBCXX_USE_NANOSLEEP -DBOOST_LOG_DYN_LINK -pthread -fvisibility=hidden")+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -DCOMMONAPI_INTERNAL_COMPILATION -D_GLIBCXX_USE_NANOSLEEP -DBOOST_LOG_DYN_LINK -pthread -fvisibility=hidden")+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -DCOMMONAPI_INTERNAL_COMPILATION -D_GLIBCXX_USE_NANOSLEEP -DBOOST_LOG_DYN_LINK -pthread -fvisibility=hidden") endif()SET(MAX_LOG_LEVEL "DEBUG" CACHE STRING "maximum log level")diff --git a/include/CommonAPI/SomeIP/ClientId.hpp b/include/CommonAPI/SomeIP/ClientId.hppindex 5d74984..751cda6 100644--- a/include/CommonAPI/SomeIP/ClientId.hpp+++ b/include/CommonAPI/SomeIP/ClientId.hpp@@ -38,8 +38,8 @@ public: COMMONAPI_EXPORT size_t hashCode();COMMONAPI_EXPORT client_id_t getClientId();-COMMONAPI_EXPORT uid_t getUid() const;-COMMONAPI_EXPORT gid_t getGid() const;+COMMONAPI_EXPORT CommonAPI::uid_t getUid() const;+COMMONAPI_EXPORT CommonAPI::gid_t getGid() const;protected: client_id_t client_id_;diff --git a/include/CommonAPI/SomeIP/StringEncoder.hpp b/include/CommonAPI/SomeIP/StringEncoder.hppindex b250638..62c32fd 100644--- a/include/CommonAPI/SomeIP/StringEncoder.hpp+++ b/include/CommonAPI/SomeIP/StringEncoder.hpp@@ -14,7 +14,7 @@ #include  #include  -#if defined(_WIN32) || defined(ANDROID)+#if defined(_WIN32) || defined(ANDROID) || defined(__QNX__) #if !defined(LITTLE_ENDIAN) #define LITTLE_ENDIAN 1234 #endifdiff --git a/include/CommonAPI/SomeIP/Watch.hpp b/include/CommonAPI/SomeIP/Watch.hppindex 1ba7201..313c499 100644--- a/include/CommonAPI/SomeIP/Watch.hpp+++ b/include/CommonAPI/SomeIP/Watch.hpp@@ -59,7 +59,7 @@ class Watch : public CommonAPI::Watch { void processQueueEntry(std::shared_ptr _queueEntry);private:-#ifdef _WIN32+#if defined(WIN32) || defined(__QNX__) int pipeFileDescriptors_[2]; #else int eventFd_;@@ -73,10 +73,13 @@ private: std::mutex dependentDispatchSourcesMutex_;std::weak_ptr connection_;-+#if defined(WIN32) || defined(__QNX__)+const int pipeValue_;+#endif #ifdef _WIN32 HANDLE wsaEvent_;-const int pipeValue_;+#elif defined(__QNX__)+//do nothings #else const std::uint64_t eventFdValue_; diff --git a/src/CommonAPI/SomeIP/ClientId.cpp b/src/CommonAPI/SomeIP/ClientId.cppindex e116bb4..15f9ea8 100644--- a/src/CommonAPI/SomeIP/ClientId.cpp+++ b/src/CommonAPI/SomeIP/ClientId.cpp@@ -52,11 +52,11 @@ client_id_t ClientId::getClientId() { return client_id_; } -uid_t ClientId::getUid() const {+CommonAPI::uid_t ClientId::getUid() const { return uid_; } -gid_t ClientId::getGid() const {+CommonAPI::gid_t ClientId::getGid() const { return gid_; } diff --git a/src/CommonAPI/SomeIP/Watch.cpp b/src/CommonAPI/SomeIP/Watch.cppindex 09c5a06..82b2b93 100644--- a/src/CommonAPI/SomeIP/Watch.cpp+++ b/src/CommonAPI/SomeIP/Watch.cpp@@ -5,14 +5,17 @@#include  +#include +#include  #include  #include #ifdef _WIN32 #include  #include +#elif defined(__QNX__)+//do nothings #else-#include  #include  #endif @@ -30,6 +33,8 @@ namespace SomeIP { Watch::Watch(const std::shared_ptr& _connection) : #ifdef _WIN32 pipeValue_(4)+#elif defined(__QNX__)+pipeValue_(4) #else eventFd_(0), eventFdValue_(1)@@ -159,6 +164,18 @@ Watch::Watch(const std::shared_ptr& _connection) : WSACleanup(); } pollFileDescriptor_.fd = pipeFileDescriptors_[0];+#elif defined(__QNX__)+if(pipe(pipeFileDescriptors_) == -1) {+std::perror(__func__);+}+for (auto fd : pipeFileDescriptors_) {+int flags = fcntl(fd, F_GETFL);+flags |= O_NONBLOCK;+if (fcntl(fd, F_SETFL, flags) == -1) {+std::perror(__func__);+}++} #else eventFd_ = eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE); if (eventFd_ == -1) {@@ -184,6 +201,9 @@ Watch::~Watch() { // cleanup closesocket(pipeFileDescriptors_[0]); WSACleanup();+#elif defined(__QNX__)+close(pipeFileDescriptors_[0]);+close(pipeFileDescriptors_[1]); #else close(eventFd_); #endif@@ -242,6 +262,10 @@ void Watch::pushQueue(std::shared_ptr _queueEntry) { printf("send failed with error: %d\n", error); } }+#elif defined(__QNX__)+if(write(pipeFileDescriptors_[1], &pipeValue_, sizeof(pipeValue_)) == -1) {+std::perror(__func__);+} #else while (write(eventFd_, &eventFdValue_, sizeof(eventFdValue_)) == -1) { if (errno != EAGAIN && errno != EINTR) {@@ -270,6 +294,11 @@ void Watch::popQueue() { else { printf("recv failed with error: %d\n", WSAGetLastError()); }+#elif defined(__QNX__)+int readValue = 0;+if(read(pipeFileDescriptors_[0], &readValue, sizeof(readValue)) == -1) {+std::perror(__func__);+} #else std::uint64_t readValue(0); while (read(eventFd_, &readValue, sizeof(readValue)) == -1) {

3. 编译脚本

#!/bin/bash##----------------------------------------------------------#author: TIM#email : 1352430027@qq.com#description: SOA someip build script # ---------------------------------------------------------#Warm reminder :Abort operation with Ctrl+C# ---------------------------------------------------------ROOT_DIR=$(pwd)# qnx tools dirQNX_TOOLS_PATH=/workspace/tools/prebuilt_QNX700export QNX_CONFIGURATION=$QNX_TOOLS_PATH/.qnxexport QNX_TARGET=$QNX_TOOLS_PATH/target/qnx7export QNX_HOST=$QNX_TOOLS_PATH/host/linux/x86_64export QNX_ARCH=aarch64leexport MAKEFLAGS=-I$QNX_TOOLS_PATH/target/qnx7/usr/includeexport MAKELDFLAGS=-L$QNX_TOOLS_PATH/target/qnx7/usr/lib,-L$QNX_PREBUILT/target/qnx7/aarch64le/libexport PATH=$QNX_HOST/usr/bin:/pkg/hwtools/bin/:$PATH#use aarch64-unknown-nto-qnx7.0.0QNX_TOOLCHAINS_CC64=$QNX_TOOLS_PATH/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.0.0-gccQNX_TOOLCHAINS_CXX64=$QNX_TOOLS_PATH/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.0.0-g++# prefix configPREFIX_DIR=${ROOT_DIR}/build/qnxPREFIX_INSTALL_DIR=${PREFIX_DIR}/installHOST_TOOL_DIR=${ROOT_DIR}/host_toolsTHIRD_PARTY_DIR=${ROOT_DIR}/thirdpartyBOOST_ARCHIVE_PATH=${ROOT_DIR}/toolchains/archive/boost_1_55_0.tar.gzBOOST_DIR=${ROOT_DIR}/toolchains/boost_1_55_0DLT_ARCHIVE_PATH=${ROOT_DIR}/toolchains/archive/dlt-daemon-2.18.8.tar.gzDLT_DIR=${ROOT_DIR}/toolchains/dlt-daemon-2.18.8echo -e "Project dir: $ROOT_DIR"if [ -d ${PREFIX_INSTALL_DIR} ];thenrm -rf $PREFIX_INSTALL_DIRmkdir -p $PREFIX_INSTALL_DIRelsemkdir -p $PREFIX_INSTALL_DIRfiif [ ! -d ${ROOT_DIR}/host_tools ];thenmkdir host_toolsfi#### BOOST ####if [ ! -d ${BOOST_DIR} ];thenecho -e "dir ${BOOST_DIR} is not exist. now do it."##tar -xzf ${BOOST_ARCHIVE_PATH} -C ${ROOT_DIR}/toolchains/ cd ${BOOST_DIR}/mkdir -p build/qnx#patch for boost-1.55.0patch -p1  start to build for QNX."echo "---------------------------"cmake -B $PREFIX_DIR \-DCMAKE_INSTALL_PREFIX=$PREFIX_INSTALL_DIR \-DCMAKE_TOOLCHAIN_FILE=$ROOT_DIR/cmake/qnx.toolchain.cmake \-DDLT_LIBRARIES=${DLT_DIR}/build/qnx/install/lib/libdlt.so \-DCMAKE_HOST_LINUX=OFF \-DCMAKE_HOST_WIN32=OFFcmake --build $PREFIX_DIR --target install

4. 其他

4.1 thirdparty 目录

├── archive
├── capicxx-core-runtime
├── capicxx-someip-runtime
├── CMakeLists.txt
└── vsomeip

CMakeLists.txt:

if (${CMAKE_SYSTEM_NAME} MATCHES "QNX")message("cmake build for QNX")SET(USE_INSTALLED_COMMONAPI OFF CACHE BOOL "Use installed commonapi OFF")SET(USE_INSTALLED_DBUS OFF CACHE BOOL "Use installed commonapi OFF")SET(ENABLE_SIGNAL_HANDLING 1 CACHE BOOL "Use installed commonapi 1")SET(DIAGNOSIS_ADDRESS 0x10 CACHE INT "Diagnosis address 0x10")add_subdirectory(capicxx-core-runtime)add_subdirectory(vsomeip)add_subdirectory(capicxx-someip-runtime)endif()

4.2 根目录

├── build
├── build_all_qnx.sh
├── build_all_x86.sh
├── cfg
├── cmake
├── CMakeLists.txt
├── doc
├── examples
├── host_tools
├── thirdparty
├── toolchains

CMakeLists.txt:

#config projects#project(SOA_SOMEIP)cmake_minimum_required(VERSION 3.1.3)option(CMAKE_HOST_LINUX "build tartget host is Linux" ON)option(CMAKE_LINK_PTHREAD_LIB "build tartget link phread lib" OFF)#set(CMAKE_CXX_STANDARD 11)#incldueinclude(${CMAKE_SOURCE_DIR}/cmake/func.define.cmake)add_subdirectory(thirdparty)add_subdirectory(examples)

4.3 :qnx.toolchain.cmake

SET(CMAKE_SYSTEM_NAME QNX)SET(QNX_TOOLS_PATH /workspace/tools/prebuilt_QNX700)SET(CMAKE_CXX_COMPILER ${QNX_TOOLS_PATH}/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.0.0-g++)SET(CMAKE_C_COMPILER ${QNX_TOOLS_PATH}/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.0.0-gcc)IF(NOT DEFINED ENV{QNX_TARGET})MESSAGE(FATAL_ERROR "Environment \"QNX_TARGET\" not defined")ENDIF()IF(NOT DEFINED ENV{QNX_HOST})MESSAGE(FATAL_ERROR "Environment \"QNX_HOST\" not defined")ENDIF()IF(NOT DEFINED ENV{QNX_ARCH})MESSAGE(FATAL_ERROR "Environment \"QNX_ARCH\" not defined, should one of x86, x86_64, aarch64le")ENDIF()SET(QNX_HOST $ENV{QNX_HOST})SET(QNX_TARGET $ENV{QNX_TARGET})SET(QNX_ARCH $ENV{QNX_ARCH})#SET(QCC_TARGET gcc_nto${QNX_ARCH}_gpp)#SET(CMAKE_C_COMPILER ${QNX_HOST}/usr/bin/qcc)#set(CMAKE_C_COMPILER_TARGET ${QCC_TARGET})SET(CMAKE_C_FLAGS_DEBUG "-g")SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")SET(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")#SET(CMAKE_CXX_COMPILER ${QNX_HOST}/usr/bin/qcc)#set(CMAKE_CXX_COMPILER_TARGET ${QCC_TARGET})SET(CMAKE_CXX_FLAGS_DEBUG "-g")SET(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")SET(Boost_FOUND TRUE)SET(Boost_DIR /workspace/someip/toolchains/boost_1_55_0)SET(Boost_INCLUDE_DIR ${Boost_DIR}/build/qnx/include)SET(Boost_LIBRARY_DIR ${Boost_DIR}/build/qnx/lib)SET(BOOST_LIBRARYDIR ${Boost_DIR}/build/qnx/lib)ADD_DEFINITIONS( -D__QNX__ )ADD_DEFINITIONS( -D__QNXNTO__ )ADD_DEFINITIONS( -D_QNX_SOURCE )ADD_DEFINITIONS( -D__USE_ISOC99 )ADD_DEFINITIONS( -D_GLIBCXX_USE_C99 )

5. 结果

5.1 编译结果:

.├── CMakeCache.txt├── CMakeDoxyfile.in├── CMakeDoxygenDefaults.cmake├── CMakeFiles│ ├── 3.20.0│ ├── cmake.check_cache│ ├── CMakeDirectoryInformation.cmake│ ├── CMakeOutput.log│ ├── CMakeRuleHashes.txt│ ├── CMakeTmp│ ├── Makefile2│ ├── Makefile.cmake│ ├── progress.marks│ └── TargetDirectories.txt├── cmake_install.cmake├── examples│ ├── CMakeFiles│ ├── cmake_install.cmake│ ├── HelloWorldSomeIPClient│ ├── HelloWorldSomeIPService│ └── Makefile├── install│ ├── bin│ ├── etc│ ├── include│ └── lib├── install_manifest.txt├── Makefile└── thirdparty├── capicxx-core-runtime├── capicxx-dbus-runtime├── capicxx-someip-runtime├── CMakeFiles├── cmake_install.cmake├── Makefile└── vsomeip

5.2 QNX 环境运行