编译环境
host主机:Ubuntu 20.04
交叉编译器:qnx710工具链
交叉编译器qcc(QNX)编译CUnit源码
下载CUnit源码
官方网址下载源码包,下载得到CUnit-2.1-3.tar.bz2。
解压源码包
输入命令$ tar -jxvf CUnit-2.1-3.tar.bz2
解压,得到CUnit-2.1-3文件夹。
修改代码,注释#include <stdlib.h>
用vscode打开CUnit-2.1-3文件夹,将所有的#include <stdlib.h>
替换为/*#include <stdlib.h>*/
,注意需要使用C的注释风格,不能使用//。该头文件包含会导致编译失败,但是发现注释掉了依旧能够编译通过,因此判断注释掉应该是不影响使用的。
配置编译工具链环境
输入命令$ source /home/autotest/qnx710/qnxsdp-env.sh
,将编译工具链配置到环境变量中。
编译安装
打开终端,进入CUnit-2.1-3,执行:
1 | autoscan |
安装成功后在/home/autotest/Desktop/cunit-qnx/install下有对应的安装文件。
CMake的编译构建
QNX环境:qnx7.1.0
目的:编译cmake构建工具是为了在qnx下使用ctest。
在编译整个cmake之前,我也考虑过cmake是否支持只对其中的部分功能进行构建,比如只构建一个ctest,或许可以从option中指定,但是经查看没有对应的option可以指定。然后再考虑只对ctest那部分的CMakelists.txt进行构建,发现也是走不通的。
于是就只能编译整个cmake了。
我下载的是最新版本的cmake源码,版本号是3.21.1。
解压cmake源码。大致浏览cmake的cmakelists.txt,可以看到里面是有对QNX的支持的。
最终的cmake设置都写在qnx.cmake中了。该文件是纯手写的。。qnx.cmake如下:
set(QNX_HOST /home/autotest/qnx710/host/linux/x86_64)
set(CMAKE_SYSTEM_NAME QNX)
set(arch gcc_ntox86_64)
set(ntoarch x86_64)
set(QNX_PROCESSOR x86_64)
set(CMAKE_C_COMPILER ${QNX_HOST}/usr/bin/qcc)
set(CMAKE_C_COMPILER_TARGET ${arch})
set(CMAKE_CXX_COMPILER ${QNX_HOST}/usr/bin/q++)
set(CMAKE_CXX_COMPILER_TARGET ${arch})
set(CMAKE_ASM_COMPILER qcc -V${arch})
set(CMAKE_ASM_DEFINE_FLAG "-Wa,--defsym,")
set(CMAKE_RANLIB ${QNX_HOST}/usr/bin/nto${ntoarch}-ranlib
CACHE PATH "QNX ranlib Program" FORCE)
set(CMAKE_AR ${QNX_HOST}/usr/bin/nto${ntoarch}-ar
CACHE PATH "QNX ar Program" FORCE)
set(CMAKE_LINKER ${QNX_HOST}/usr/bin/nto${ntoarch}-ld
CACHE PATH "QNX ld Program" FORCE)
add_definitions(-D_XOPEN_SOURCE=700)
最重要的就是在最后一句add_definitions(-D_XOPEN_SOURCE=700)
,这句话的作用我个人理解是自动去找7.0.0版本以上的qnx所需要的库和头文件。
最后执行build.sh就可以编译安装整个cmake项目了。build.sh如下:
#!/bin/bash
set -e
TOP_PATH=$(cd "$(dirname "$0")"; pwd)
BUILD_JOBS=$(($(grep -c ^processor /proc/cpuinfo) - 1))
echo BUILD_JOBS = ${BUILD_JOBS}
source /home/autotest/qnx710/qnxsdp-env.sh
if test -d install
then
rm -rf install
fi
mkdir install
mkdir -p build
cd build
cmake ../cmake-3.21.1 -DCMAKE_TOOLCHAIN_FILE=${TOP_PATH}/qnx.cmake -DCMAKE_INSTALL_PREFIX=${TOP_PATH}/install
make -j${BUILD_JOBS}
make install
cd ..
cmake源代码文件、qnx.cmake和build.sh都在同一路径下,./build.sh后会在当前路径下创建build文件夹,build文件夹内存放所有的构建产物。install下存放安装的文件。
最终在qnx上使用ctest时,可以将整个install拷贝到qnx目录下。避免拷贝单个ctest,因为这有可能会导致ctest的功能不全。
将install通过scp拷贝到qnx下,然后执行$your_path/ctest -h
可以看到ctest在qnx上成功运行了。
CUnit的编译构建,安装
目的:编译cunit库是为了ctest能够链接。
CUnit的具体的编译安装可以查看上面。这个具体说一下遇到的问题和解决方法。
问题描述
一开始我选择把qcc构建出来的cunit安装到/usr下,然后ctest会从系统中找cunit的库以及头文件。但这样会造成对原有系统的破坏,原有系统是Ubuntu的,可是却安装了qcc编译的cunit,在本机上无法使用。
解决方法
现在已经有解决办法了,能够不破坏原来的系统环境,只给需要的变量赋值,就能够让ctest找到cunit的库以及头文件。
首先,为了避免破坏原有系统的环境,在安装的时候选择安装在本地目录下。如果configure时已经制定了–prefix,那么还可以在make install
的时候重写一下安装路径。make install DESTDIR=/home/autotest/Desktop/cunit-ins/install
可以对安装路径进行重写,然后CUnit就会安装在/home/autotest/Desktop/cunit-ins/install/usr/local下。(我也不知道为啥多了usr/local这个路径,不过没关系,成功安装在自己的install路径下就ok)。之后测试项目想要使用cunit的时候,只需要在CMakeLists.txt的include(CTest)和include(CUnit)之前,指定CUNIT_LIBRARY和CUNIT_INCLUDE_DIR即可。
#设置libcunit.so的具体路径
set(CUNIT_LIBRARY /home/autotest/Desktop/cunit-ins/install/usr/local/lib/libcunit.so)
#设置CUnit头文件路径
set(CUNIT_INCLUDE_DIR /home/autotest/Desktop/cunit-ins/install/usr/local/include)
PS. 在这里插一嘴,export环境变量INCLUDE_PATH和LIBRARY_PATH都不行。只能手动指定CUNIT_LIBRARY和CUNIT_INCLUDE_DIR。
测试项目的编译构建
现在ctest和cunit都已经准备好了,原有的使用ctest编写的测试代码准备编译并运行。
需要在原有的测试项目中添加上述所说的CUNIT_LIBRARY和CUNIT_INCLUDE_DIR,同时可能还需要将cunit的头文件手动包含进去(include_directory())。否则可能会报错:找不到<CUnit/CUnit.h>。其他地方维持原样即可。
测试项目遵循cmake规范,可以直接使用上面的cmake编译构建的qnx.cmake和build.sh进行编译构建,这样就省事多了。
到时候直接把开发那边提供的库和头文件手动包含进去,就可以进行测试了。
测试程序的运行
测试程序编译好后,准备拷贝到qnx上运行。测试用例的运行需要ctest(启动器)、libcunit.so.1(用于运行时链接),还有就是测试程序。但是有个坑导致了无法使用ctest启动测试程序。
坑点1:ctest运行测试用例时要求可执行程序的绝对路径和编译时的保持一致
在Ubuntu上编译时,测试程序生成在/home/autotest/Desktop/test/build下,那么在其他平台上运行时要求也是同样的路径,否则执行ctest时会报错:No test were found!!!。查看了ctest -h
没有发现能否设置相对路径,因此目前此坑还没有找到解决方法,只能保持运行平台和编译平台的相对路径一致。
但是qnx只允许用户在指定的目录下(/data)进行mkdir操作,因此无法在qnx上新建一个/home目录。于是考虑在编译平台Ubuntu上创建一个和qnx下运行路径一致的目录,于是在ubuntu上sudo mkdir /data/home/test
,因此执行build.sh时也只能以sudo
执行。于是遇到了坑点2。
优雅的解决——待研究
似乎有一个优雅的解决办法,具体可以查看问答,正确使用add_test()函数应该可以做到。
坑点2:qnx710装在了autotest用户下,导致其他用户无法使用
sudo是以管理员用户执行,但是qnx710安装在了autotest下,导致了license与autotest用户绑定,其他用户包括管理员用户无法使用。所以在编译平台Ubuntu上创建一个和qnx下运行路径一致的目录这条路暂时阻塞,需要管理员用户安装qnx710才可以继续进行。
那只能考虑不用ctest拉起测试程序。单独执行测试程序发现也是可以行得通的,./test -h
可以得到一个简单的使用:
-j junit format results
-r FILENAME result file for automated run
-s PATTERN run only tests in suite matching pattern
-t PATTERN run only test matching pattern
比如:./test -s “basic”,那么就会运行basic测试套件的所有用例,./test -s “basic” -t “test”,就只会运行CU_Test(basic,test)这个测试用例。
解决方法
已经有了解决方法:将/data/路径设置为能够被autotest用户所访问。
$ chown -hR autotest:autotest /data/
但是在运行测试程序时,因为测试程序运行时需要动态链接libcunit.so.1,于是我遇到了坑点3。
坑点3:qnx下无法将库拷贝到/usr/lib下,且默认不会从当前路径查找库文件
我将libcunit.so.1拷贝到测试程序同路径下,再次运行测试程序,发现还是无法load library libcunit.so.1,于是考虑将libcunit.so.1拷贝到/usr/lib下。但是qnx做了保护,无法将文件拷贝至/usr/lib下。
那就只能从环境变量下手了,追加链接库路径的环境变量。
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/home/yxtest
记得要写绝对路径。
使用ctest执行测试用例时,需要:
$ export LD_PRELOAD=/data/home/yxtest/libcunit.so.1
$ ./ctest --output-on-failure