QNX交叉编译CUnit+CTest

编译环境

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,执行:

$ autoscan
$ mv configure.in configure.ac
$ aclocal
$ autoheader
$ libtoolize
$ automake --add-missing
$ autoconf
$ ./configure CC="qcc" CFLAGS="-Vgcc_ntox86_64" --host=x86_64-linux-gnu –prefix /home/autotest/Desktop/cunit-qnx/install
$ make
$ make install

安装成功后在/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


本文为原创内容,遵循CC BY-ND 4.0协议,署名-禁止演绎。
转载请注明出处:https://tis.ac.cn/blog/yexin/cross_compile_cunit_and_ctest_on_qnx/

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注