自动化测试

前言

自动化测试需要使用到makefile,但是较大工程的makefile编写复杂,学习简洁的cmake语法,自动生成工程的Makefile文件

(一)Makefile与cmake基础

1.1 Makefile基础

Makefile能够将一个工程自动化编译,提高软件开发、多案例仿真效率;

程序的编译和链接:

编译:将源文件转换成机器可以理解的二进制文件。编译共分为3步:

​ ①对源文件进行预处理,处理一些#定义的命令或语句(如宏、#include、#ifdef等),生成*.i文件;

​ ②进行编译,进行词法分析、语法分析、语义分析等,生成*.s文件;

​ ③汇编,将对应的汇编指令翻译成机器指令,生成可重定位的二进制目标文件*.o(windows系统下.obj)

链接: 将有关的目标文件(linux的.o,win的.obj)彼此相连接,转变成可执行文件(linux的.out,win的.exe)。随后,代码可以和可执行文件分离。例如,可以将可执行文件单独放到服务器运行。(需要测试)

因此一个源文件需要机器运行时,需要经过上述的几个步骤,如果源文件太多,一个一个编译太麻烦,于是这里设计了make工具,根据一个Makefile规则文件,以告诉make命令需要如何去编译和链接程序批量处理编译工作。

其他概念

1、编译 (complie):把cpp代码翻译成机器语言,保存到目标文件中。CPP->OBJ。

2、编译单元(Translation Unit) 是指一个.cpp文件以及这所include的所有.h文件,.h文件里面的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件

3、目标文件(Obj File):编译后生成的文件,以机器码的形式包含了编译单元里所有的函数和数据、导出符号表、未解决符号表、地址重定向表等。重点:包括了可重定位文件(.o、.obj文件)和库文件(.a 、.so文件)

4、编译器(Compiler):将一种语言(通常为高级语言)翻译为另一种语言(通常为低级语言)的程序

5、静态链接库(.a) 多个目标文件的集合

6、动态链接库(.so): 另一个可执行文件及其它的目标文件结合,动态链接库在程序执行时才被调用

7、链接(link):链接程序的主要工作就是将有关的目标文件(库文件、.o文件)彼此相连接,最后转成可执行文件。理解:主要是对各个函数数据进行定位,定向地址,同时对各个未解决符号找定义

注: 具体如何链接的,静态链接库和动态链接库的作用到底是什么,我不清楚

8、GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAV、Fortran、Pascal、Object-C等语言。

9、gcc是GCC中的GUN C Compiler(C 编译器)

10、g++ 是GCC中的GUN C++ Compiler(C++编译器)

1.2 cmake基础

对于一个大工程,编写和维护Makefile仍然过于复杂,特别是当多个人员共同完成一个跨平台工程时(linux和win下的编译工具和文件格式不同),除了编码工作外,还需要负担额外的代码编译、跨平台编译维护工作,于是希望能够有一套新的工具能够简化研究人员的日常工作软件(cmake菜谱CMake Cookbook中文版),会自动检测可用编译器,根据你的配置文件自动寻找外部依赖库,能够在不同的平台上配置、构建、测试和部署项目。

优点:
1、开源代码,使用类BSD许可发布。
2、跨平台,并可以生成native编译配置文件,在linux/Unix平台,生成makefile,在苹果平台可以生成Xcode,在windows平台,可以生成MSVC的工程文件。
3、能够管理大型项目。
4、简化编译构建过程和编译过程。cmake的工具链:cmake+make。
5、高效率,因为cmake在工具链中没有libtool。
6、可扩展,可以为cmake编写特定功能的模块,扩展cmake功能。

缺点:
1、cmake只是看起来比较简单,使用并不简单;
2、每个项目使用一个CMakeLists.txt(每个目录一个),使用的是cmake语法。
3、cmake跟已有体系配合不是特别的理想,比如pkgconfig。

虽然cmake入门容易,但是深入很难学。目前已经学习的cmake知识足够完成当前项目的自动化测试目标。

(二)基础语法学习

cmake使用教程(一)-起步 - 掘金 (juejin.cn)

2.1 cmake起步

一个最基本的CMakeLists.txt文件最少需要包含以下三行:

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
add_executable(Tutorial tutorial.cxx)

其中命令解释如下:

  1. CMake需要一个最低版本的检查CMAKE_MINIMUM_REQUIRED
    CMake中只有系统指令是不区分大小写的,但是变量和字符串是区分大小写的;
    VERSION必须大写,换言之预定义宏是不可以随意写的;

    可使用cmake --version查看系统cmake版本信息

  2. 之后需要建一个工程名,project(工程名)

  3. 构建目标文件即可,add_executable(可执行程序,源文件1,源文件2, …)

示例:

创建一个tutorial.cpp文件,用来计算两个数字的和;编写一个CMakeLists.txt文件,包括上述三行代码。这样就完成了一个最简单的cmake程序。用cmake来编译这段代码,进入命令行执行内部构建命令

cmake .

输出log信息:

-- The C compiler identification is AppleClang 9.0.0.9000039
-- The CXX compiler identification is AppleClang 9.0.0.9000039
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/saka/Desktop/Tutorial/Step1

同时生成了三个文件CMakeCache.txtMakefilecmake_install.cmake和一个文件夹CmakeFiles,然后执行

make

即可生成可执行程序Tutorial

2.1 添加库

首先介绍cmake内声明变量的语法:set(KEY VALUE)

set(KEY VALUE)接受两个参数,用来声明变量。在camke语法中使用KEY并不能直接取到VALUE,必须使用${KEY}这种写法来取到VALUE

CMake中也可以使用set()来设置一些cmake内置变量(能否直接使用set进行cmake中某些条件的设置或者更改?):如

set(PROJECT_NAME Tutorial) #设置工程名称
project(${PROJECT_NAME})

set(CMAKE_CXX_STANDARD 11) #设置c++11版本
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 设置指定的C++编译器版本是必须的,如果不设置,或者为OFF,则指定版本不可用时,会使用上一版本。

set(CMAKE_CXX_STANDARD_EXTENSIONS OFF)#不知道是什么意思,可能是编码错误?相近的有CMAKE_CXX_EXTENSIONS,告诉CMake,只启用 ISO C++ 标准的编译器标志,而不使用特定编译器的扩展。将代码改成CMAKE_CXX_EXTENSIONS,编译正常

参考1:CMake 变量 - 简书 (jianshu.com)

参考2:CMake语法—内置变量 - kaizenly - 博客园 (cnblogs.com)

参考3:CMake教程](三)CMake 配置指定C++11编译的标准_cliy的博客-CSDN博客_cmake 指定c++11

例如声明库的路径,并将该路径添加进编译器搜索头文件的路径之下:

set(CMAKE_PREFIX_PATH /nfs/home/user/systemc-2.3.0a) #将systemc库的路径设置为变量
include_directories(${CMAKE_PREFIX_PATH}/include)           #获取该变量的值并设为头文件搜索路径

在一个工程中,有时会使用自己建立的库或者一些第三方标准库文件(如systemc标准库),此时需要在CMakeLists.txt文件中添加库。

  1. 需要告知编译器搜索头文件的路径,使用命令include_directories(dir)设置;
  2. 设定查找库的路径(动态库或者静态库),使用命令find_library();
  3. 指定要链接的库文件的路径,使用命令link_directories();
  4. 设置c++标准;设置源文件,使用命令aux_source_directory();
  5. 使用源文件生成可执行文件,使用命令add_executable();
  6. 将找到的库链接到可执行文件上;

具体文件内容如下:

cmake_minimum_required(Version 3.24)
project(Tutorial)

set(CMAKE_PREFIX_PATH /nfs/home/user/systemc-2.3.0a) #将systemc库的路径设置路径列表,能不能用普通变量代替?测试后发现可以
include_directories(${CMAKE_PREFIX_PATH}/include)           #获取该变量的值并设为头文件搜索路径
find_library(systemc systemc ${CMAKE_PREFIX_PATH}/lib-linux64)
link_directories(${CMAKE_PREFIX_PATH}/lib-linux64)


set(CMAKE_CXX_STANDARD 11) #设置c++11版本
set(CMAKE_CXX_STANDARD_REQUIRED ON)# 设置指定的C++编译器版本是必须的
set(CMAKE_CXX_EXTENSIONS OFF)#只启用 ISO C++ 标准的编译器标志,而不使用特定编译器的扩展

aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} systemc)

项目文件结构如下

.
|--CMakeLists.txt.txt
|--tutorial.cpp
|--param.h
|--test_case.cpp
|--sc_main.cpp
		

2.3 多级文件cmake

在2.2中CMakeLists.txt的基础上,添加工程内源文件的路径和头文件路径

例如下列项目文件结构

.
|--CMakeCache.txt
|--top
|  |--complete_systemc.h
|--test
|  |--test_case1.cpp
|  |--test_case2.cpp
|  |--test_case.h
|--add_module
|  |--add.h
|  |--add.cpp
|--minus
|  |--minus.cpp
|  |--minus.h
|--param.h
|--sc_main.cpp

设置CMakeLists.txt如下

cmake_minimum_required(Version 3.24)
project(Tutorial)

set(CMAKE_PREFIX_PATH /nfs/home/user/systemc-2.3.0a) 
include_directories(${CMAKE_PREFIX_PATH}/include ./top ./test ./add_module ./minus)         
find_library(systemc systemc ${CMAKE_PREFIX_PATH}/lib-linux64)
link_directories(${CMAKE_PREFIX_PATH}/lib-linux64)

set(CMAKE_CXX_STANDARD 11) #设置c++11版本
set(CMAKE_CXX_STANDARD_REQUIRED ON)# 设置指定的C++编译器版本是必须的
set(CMAKE_CXX_EXTENSIONS OFF)#只启用 ISO C++ 标准的编译器标志,而不使用特定编译器的扩展

aux_source_directory(. SRC_LIST)
aux_source_directory(./top SRC_LIST1)
aux_source_directory(./test SRC_LIST2)
aux_source_directory(./add_module SRC_LIST3)
aux_source_directory(./minus SRC_LIST4)
add_executable(${PROJECT_NAME} ${SRC_LIST} ${SRC_LIST1} ${SRC_LIST2} ${SRC_LIST3} ${SRC_LIST4})
target_link_libraries(${PROJECT_NAME} systemc)

2.4命令解析

2.4.1 include_directories(dir)

include_directories ([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
将指定目录添加到编译器的头文件搜索路径之下,指定的目录被解释成当前源码路径的相对路径。这些目录被添加到当前 CMakeLists 文件的目录属性 INCLUDE_DIRECTORIES 中。

默认情况下,include_directories命令会将目录添加到列表最后,可以通过命令设置CMAKE_INCLUDE_DIRECTORIES_BEFORE变量为ON来改变它默认行为,将目录添加到列表前面。也可以在每次调用include_directories命令时使用AFTERBEFORE选项来指定是添加到列表的前面或者后面。如果使用SYSTEM选项,会把指定目录当成系统的搜索目录。该命令作用范围只在当前的CMakeLists.txt。

2.4.2 find_library()

该命令用于查找库(动态库或者静态库),当构建依赖于第三方库/系统库,可以使用该命令来查找并使用库(Cmake中有另外一个命令find_package,能获取库的更多信息,具体可以参考Cmake命令之find_package介绍

find_library (<VAR> name [path1 path2 ...])

几个基本参数的解析

  • <var>用于存储该命令执行的结果,也就是找到的库的全路径(包含库名):
     1. <var>可以是普通变量(需要指定NO_CACHE选项),也可以是缓存条目(意味着会存放在CMakeCache.txt中,不删除该文件或者用set重新设置该变量,其存储的值不会再刷新);
     2. 当库能被找到,<var>会被存放正常的库路径,当库未被找到,<var>中存放的值为"<var>-NOTFOUND"。只要<var>中的值不是"<var>-NOTFOUND",那么即使多次调用find_library<var>也不会再刷新;
  • name用于指定待查找的库名称,库名称可以使用全称,例如libmymath.a(优先会当成全名搜索);也可以不带前缀(例如前缀lib)和后缀(例如Linux中的.so.aMac中的.dylib等),直接使用mymath
  • path用于指定库的查找的路径;

Cmake命令之find_library介绍 - 简书 (jianshu.com)

2.4 link_directories()

该指令的作用主要是指定要链接的库文件的路径,经过测试,如果使用库文件但不指定链接库文件的路径的话,make会出错。

2.5 aux_source_directory()

aux_source_directory(<dir> <variable>)

在目录中查找源文件,收集指定目录中所有源文件的名称,并将列表存储在提供的变量中。 该命令旨在供使用显式模板实例化的项目使用。 模板实例化文件可以存储在Templates子目录中,并使用此命令自动收集,以避免手动列出所有实例化。

2.6 add_executable()

使用指定的源文件来生成目标可执行文件。这里的目标可执行文件分为三类:普通可执行目标文件导入可执行目标文件别名可执行目标文件。分别对应三种命令格式。

add_executable (<name> [WIN32] [MACOSX_BUNDLE]
      [EXCLUDE_FROM_ALL]
      [source1] [source2 ...])
add_executable (<name> IMPORTED [GLOBAL])
add_executable (<name> ALIAS <target>)

Cmake命令之add_executable介绍 - 简书 (jianshu.com)

2.7 target_link_libraries()

将找到的库链接到可执行文件上,target_link_libraries需要放在add_executable之后,官方推荐使用这个接口,而不推荐使用link_libraries,link_libraries需要放到add_executable之前。

2.8 add_subdirectory()

add_subdirectory (source_dir [binary_dir] [EXCLUDE_FROM_ALL`])
添加一个子目录并构建该子目录。

命令解析

  • source_dir
    必选参数。该参数指定一个子目录,子目录下应该包含CMakeLists.txt文件和代码文件。子目录可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前目录的一个相对路径。
  • binary_dir
    可选参数。该参数指定一个目录,用于存放输出文件。可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前输出目录的一个相对路径。如果该参数没有指定,则默认的输出目录使用source_dir
  • EXCLUDE_FROM_ALL
    可选参数。当指定了该参数,则子目录下的目标不会被父目录下的目标文件包含进去,父目录的CMakeLists.txt不会构建子目录的目标文件,必须在子目录下显式去构建。例外情况:当父目录的目标依赖于子目录的目标,则子目录的目标仍然会被构建出来以满足依赖关系(例如使用了target_link_libraries)

Cmake命令之add_subdirectory介绍 - 简书 (jianshu.com)

(三)扩展语法学习

3.1 如何将cmake出来的大量文件放在一个子文件夹

单独建立了一个文件夹用于存放cmake和make等的文件

cmake和make成功,但是编译时工程内部功能读取文件时报错

(四)shell脚本

利用shell脚本,实现多个测试项的自动化测试

首先编写shell脚本,例如编写一个文件名为run.sh脚本:

关键信息包括:

# shell脚本的单行注释使用:#

#测试案例1

可执行文件名 > 输出log保存路径/输出log保存文件名 >> EOF 

input信息1

input信息2

...

EOF

#测试案例2

可执行文件名 > 输出log保存路径/输出log保存文件名 >> EOF 

input信息1

input信息2

...

EOF

例如:

Tutorial > ./log/Tutorial_test1_output.log >> EOF
1
10
yes
EOF
Tutorial > ./log/Tutorial_test2_output.log >> EOF
2
10
no
EOF

其中部分知识点解释如下:

shell标本编写完成之后,使用命令bash run.sh即可开始自动仿真测试

(五)总结

为了在仿真过程中实现自动化测试编译,提高仿真效率,使用makefile方法完成编译,具体过程如下:

1、建立makefile

由于makefile语法复杂,对新手不太友好,难以在较短时间内实现基于第三方标准库的具有多级目录的工程Makefile文件编写,经过调研,学习使用cmake方法自动生成Makefile

2、生成可执行文件

根据cmake生成的Makefile,使用make,生成可执行文件,即可在终端实现仿真工程的编译

3、自动化测试

编写shell脚本,例如编写一个文件名为run.sh脚本,使用命令bash run.sh即可开始自动仿真测试

4、存在问题

目前cmake、make、bash 都是在工程根目录下完成的,如何将cmake放置在一个单独的文件夹内,提高代码的整洁性,需要进一步探索

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值