C/C++编译、测试须知、须会,CMake、Boost等
以下内容为本人实习期间学习笔记!!参考了网上的许多教程,共享大家,欢迎交流。
动态库和静态库(共享库)
不同点:代码被载入的时刻不同
静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大,程序运行时不再需要静态库
动态库的代码编译时不会链接到目标代码中,运行时才被载入,程序运行时还需要动态库存在
库的编译:无论是静态库还是动态库,都是.o
文件创建的。
静态库:
1、先通过gcc编译成.o
文件
gcc -o hello.o -c hello.c
2、生成静态库.a文件
ar cqs libHello.a hello.o
3、链接
gcc main.c libHello.a -o Out1
动态库:
动态库的名字一般是libxxx.so
,动态函数库在编译的时候并没有编译进代码中,生成的可执行文件比较小,动态函数库的升级比较方便。
创建动态库的方法一般采用C语言编译器的-G
或者-shared
选项,或者直接使用工具ld
创建。
-shared
:该选项指定生成动态链接库,不使用该标志外部程序无法连接,相当于一个可执行文件
-fpic
:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的,所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,二不能达到真正代码段共享的目的。
-L
:表示要连接的库在当前目录中
-ltest
:编译器查找动态链接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
1、生成中间目标文件.o
g++ -fpic -c test.cpp
2、根据中间文件创建动态库文件.so
g++ -shared -o libtest.so test.o
3、调用动态库
g++ -o Tout main.cpp ./libtest.so
gcc编译,如果是c++文件,直接将gcc改成g++
1、gcc -c test.c
---->生成.o目标代码
2、gcc -o test test.c
---->生成bin可执行文件
3、gcc test.c
---->生成a.out可执行文件
常用参数:
1、-E
;指示编译器仅对输入文件进行预处理,使用该选项时预处理器的输出被送到标准输出,而不是存储在文件里。
2、-S
;指示编译器为c代码产生汇编语言文件后停止编译,汇编文件的缺省扩展名是.s
3、-c
;仅把源代码编译为目标代码。缺省时GCC建立的目标代码文件有一个.o的拓展名
4、-o
(小写);编译选项为将产生的可执行文件指定文件名
5、-O
(大写);对源代码进行基本优化,主要进行跳转和延迟退栈两种优化
-O0:不做优化;-O1:默认优化;-O2:除了完成-O1的优化之外,还进行一些额外的调整工作,如指令调整;-O3:包括循环展开和其他一些与处理特性相关的优化工作。
6、-l
和-L
;指定程序要链接的库,-l参数紧接着就是库名。
如数学库,它的库名为m
,它的库文件名是libm.so
如果要用一个第三方提供的库,要先把这个.so文件拷贝到/usr/lib里,编译时加上参数,-l库名。
如果要用库里的函数,还需要与该库配套的头文件。
放在/lib
和/usr/lib
和/usr/local/lib
里的库直接用-l
参数就能链接,如果没有在这三个目录里,需要用-L
如常用的X11
的库,它放在/usr/X11R6/lib
目录下,编译时要用-L/usr/X11R6/lib -lX11
7、-Wall
;打印出gcc提供的警告信息
-w
;关闭所有警告信息;-v
;列出所有编译步骤
交叉编译:
交叉编译通俗地讲就是在一中平台上编译出能运行在体系结构不同的另一种平台上。
交叉编译用到的编译器叫交叉编译器,做本地编译的叫本地编译器。
使用方法跟本地的gcc差不多,但有一点特殊的是,必须用-L和-l指定编译器用系统的库和头文件。
cmake简单语法规则:
[官方文档]:[https://cmake.org/cmake/help/cmake2.4docs.html]
[中文对照]:[http://www.cnblogs.com/52php/p/5684588.html]
1、变量使用${}
方式取值,在IF控制语句中直接使用变量名。
2、指令(参数1 参数2)参数使用括弧括起,参数之间使用空格或分好分开。
3、指令大小写无关,参数和变量大小写相关。
外部编译:
1、需要为任何子目录建立一个CMakeLists.txt
2、ADD_SUBDIRECTORY
指令:ADD_SUBSIRECTORY(source_dir [binary_dir][EXCLUDE_FROM_ALL])
,用于向当前工程添加存放源文件的子目录,并可有指定中间二进制和目标二进制存放的位置。
3、通过SET
命令重新定义编译输出。
EXECUTABLE_OUTPUT_PATH
指定最终的目标二进制的位置。
LIBRARY_OUTPUT_PATH
指定最终共享库目录。
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
在外部编译中PROJECT_BINARY_DIR
指的是外部编译所在目录。
PROJECT(project_name)
:指定项目的名称
CMAKE_MINIMUM_REQUIRED(VERSION 3.13)
:限定CMake的最低版本要求
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
:将当前目录中的源文件名称赋值给变量
AUX_SOURCE_DIRECTORY(<dir> <variable>)
ADD_EXECUTABLE(main ${DIR_SRCS})
:指示需要编译的源文件和要生成的可执行文件名
ADD_SUBDIRECTORY(src)
:添加一个子目录
TARGET_LINK_LIBRARIES(main Test)
:指明可执行文件main
需要连接一个名为Test
的链接库
ADD_LIBRARY(Test ${DIR_TEST1_SRCS})
:将该目录中的源文件编译为共享库
查找并使用其他程序库
FindlibNAME.cmake
:NAME是函数库名称,如查找头文件db_cxx.h
和链接库libdb_cxx.so
命名为:Findlibdb_cxx.cmake
PROJECT(main)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
SET(CMAKE_SOURCE_DIR .)
SET(CMAKE_MODULE_PATH ${CMAKE_ROOT}/Modules ${CMAKE_SOURCE_DIR}/cmake/modules)
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
ADD_EXECUTABLE(main ${DIR_SRCS})
FIND_PACKAGE( libdb_cxx REQUIRED)
MARK_AS_ADVANCED(
LIBDB_CXX_INCLUDE_DIR
LIBDB_CXX_LIBRARIES)
IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
#如果LIBDB_CXX_INCLUDE_DIR和LIBDB_CXX_LIBRARIES都被赋值MESSAGE(STATUS "Found libdb libraries")INCLUDE_DIRECTORIES(${LIBDB_CXX_INCLUDE_DIR})MESSAGE( ${LIBDB_CXX_LIBRARIES} )TARGET_LINK_LIBRARIES(main ${LIBDB_CXX_LIBRARIES}18 )
ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
FIND_PACKAGE
:查找库文件,命令执行后,CMake会到变量CMAKE_MODULE_PATH
指示
的目录中查找文件Findlibdb_cxx.cmake
并执行。
debug版本和release版本:
debug
版本的项目生成的可执行文件需要有调试信息并且不需要进行优化
release
版本的不需要调试信息但需要优化
在gcc/g++中通过编译时的参数来决定,优化成都调到最高需要设置参数-O3
,最低-O0
不做优化
添加调试信息-g -ggdb
CMake中变量CMAKE_BUILD_TYPE
取值:Debug、Release、RelWithDebInfo、MinSizeRel
=Debug时,CMake使用变量CMAKE_CXX_FLAGS_DEBUG
和CMAKE_C_FLAGS_DEBUG
中的字符串生成Makefile
=Release时,使用变量CMAKE_CXX_FLAGS_RELEASE
和CMAKE_C_FLAGS_RELEASE
OPTION
:提供用户可以选择的选项
OPTION(OPTION_VAR "注释"[初始值])
,初始值选项为ON
或OFF
,未提供则为OFF
通过OPTION(OPTION_VAR "" OFF)
设置,则IF(OPTION_VAR)
为FALSE
IF语法:常用的是字符串比较
1、看字符串是否定义过:
IF(DEFINED STR_VAR)/IF(NOT DEFINED STR_VAR)
ELSE()
ENDIF()
2、字符串比较
IF(${STR_VAR} STREQUAL "ON")
ELSE()
ENDIF()
cmake使用流程:
CMakeLists.txt----->cmake----->Makefile----->make
cmake [options] <path-to-source>
boost test工具
1、
宏BOOST_AUTO_TEST_SUITE
表示测试套件的开始
宏BOOST_AUTO_TEST_SUITE_END
表示测试套件的结束
各个测试放在两个宏之间
2、
BOOST_AUTO_TEST_CASE
定义单元测试
eg:
BOOST_AUTO_TEST_SUITE(stringtest)BOOST_AUTO_TEST_CASE(test1){mystring s;BOOST_CHECK(s.size()==0);
}BOOST_AUTO_TEST_SUIT_END()
3、单元测试的基本思想是使用Boost提供的宏来测试各个类特性。
BOOST_CHECK
和BOOST_REQUIRE_EQUAL
是Boost提供的预定义宏,用于验证代码输出
4、Boost的一整套的测试工具,基本上可以说是用于验证表达式的宏;
主要有3个类别:BOOST_WARN、BOOST_CHECK、BOOST_REQUIRE
;
BOOST_CHECK
和BOOST_REQUIRE
之间的区别:前者即使断言失败,测试仍会进行,后者则认为是很严重的错误,当BOOST_REQUIRE
失败时,代码不会继续执行。
5、检查函数和类方法,最简单的方法是创建一个新测试
BOOST_AUTO_TEST(functionTest1){BOOST_REQUIRE(myfunc1(99,'A',6.2)==12);myClass o1("hello world!\n");BOOST_REQUIRE(o1.memoryNeeded()<16);
}
6、浮点数比较
需要包含头文件:
#include<boost/test/floating_point_comparsion.hpp>
用到的宏:
BOOST_WARN_CLOSE_FRACTION
BOOST_CHECK_CLOSE_FRACTION
BOOST_REQUIRE_CLOSE_FRACTION
用法:
BOOST_CHECK_CLOSE_FRACTION(left-value,right-value,tolerance-limit)
;
tolerance-limit
:精度要求,公差要求
BOOST_CHECK_CLOSE_FRACTION
宏的左值和右值必须是同一种类型。
eg:
#define BOOST_TEST_MODULE floatingTest
#include<boost/test/included/unit_test.hpp>
#include<boost/test/floating_point_comparison.hpp>
#include<cmath>BOOST_AUTO_TEST_SUITE(test)BOOST_AUTO_TEST_CASE(test){float f1=123.43;float result=sqrt(f1);BOOST_CHECK_CLOSE_FRACTION(f1,result*result,0.0001);
}BOOST_AUTO_TEST_SUITE_END()
7、在一个文件中包含多个测试套件
可以在一个文件中包含多个测试套件,每个测试套件必须有一对宏。
在运行回归测试时,用预定义的--log_level=test_suite
选项生成的输出很详细。
8、框架测试
代码入口点必须是名为:init_unit_test_suite
的例程
#define BOOST_TEST_MODULE MasterTestSuite
#include<boost/test/included/unit_test.hpp>
using boost::unit_test;test_suite*
init_unit_test_suite(int argc,char* argv[]){test_suite* ts1=BOOST_TEST_SUITE("test_suite1");ts1->add(BOOST_TEST_CASE(&test_case1));ts1->add(BOOST_TEST_CASE(&test_case2));test_suite* ts2=BOOST_TEST_SUITE("test_suite2");ts2->add(BOOST_TEST_CASE(&test_case3));ts2->add(BOOST_TEST_CASE(&test_case4));framework::master_test_suite().add(ts1);framework::master_test_suite().add(ts2);return 0;
}
测试套件通过:BOOST_TEST_SUITE
宏创建,通过add
方法把所有的测试套件添加到主测试套件中。
单元测试通过:BOOST_TEST_CASE
宏创建,通过add
方法添加到测试套件中。
不建议把单元测试直接加到主测试套件中。
主测试套件:master_test_suite
方法属于:boost::unit_test_framework
命名空间的一部分,它在内部实现了一个单实例对象。
使用BOOST_TEST_CASE
宏创建的单元测试以函数指针作为输入参数。
9、装备
测试装备(test fixture
)是指在执行测试之前设置一个环境,在测试完成时清除它。
宏:BOOST_FIXTURE_TEST_CASE(testname,F)
使用全局装备:BOOST_GLOBAL_FIXTURE(<Fixture Name>)
http2:超文本传输协议2.0
还不是很完善。。会持续完善的。。。
C/C++编译、测试须知、须会,CMake、Boost等相关推荐
- cmake编译安装完成后 执行cmake --version报错 bash: /usr/bin/cmake: 没有那个文件或目录
cmake编译安装完成后 执行cmake --version报错 bash: /usr/bin/cmake: 没有那个文件或目录 cmake 没有那个目录 - 未完代码 - 博客园 因为直接使用cma ...
- 第7课第2节_Binder系统_c++实现_编译测试
设置执行环境: .setenv lunch 23(.full_tiny4412-eng)进入到代码所在目录执行mmm . 七. Binder系统之服务的c++实现 1. 编写代码 参考文件: fram ...
- python面试技巧和注意事项_Python 程序员面试须知须会的5个问题
原标题:Python 程序员面试须知须会的5个问题 作为一个程序员,可能或多或少经历过一些技术面试,有些是编程语言本身的问题,有些是跟工程相关的问题.今天我们来总结关于Python程序员面试的时候经常 ...
- 在Ubuntu上安装NTL库以及编译测试
文章目录 介绍: 步骤: 0. 下载前的准备 1. 下载GMP并解压 2. 下载NTL并解压 3. 对GMP进行编译 4. 对NTL进行编译 编译测试: 关于wsl下载和文件权限: 参考资料: 介绍: ...
- Jenkins搭建.NET自动编译测试并实现半增量部署
@hzl201 2020-04-13 09:26 字数 18724 阅读 3353 Jenkins搭建.NET自动编译测试并实现半增量部署 运维 jenkins 前言 以前写前端项目打包部署,都是手动 ...
- xSense MTI C++ SDK编译测试
测试环境 操作系统:ubuntu 18.04.5 LTS 64位.RK3399PRO-Linux 传感器型号:MTi-3.MTi-630 下载 在MTi知识库中下载MT软件套装,根据系统版本为下载的是 ...
- CMake Error at cmake/boost.cmake:76 (MESSAGE)
在源码安装mysql5.7系列时,出现如下错误: 错误现象: CMake Error at cmake/boost.cmake:76 (MESSAGE): You can download it wi ...
- CMake使用宏编译测试
首先代码中定义了使用宏的模块: 在任何位置都可以使用宏 #ifndef UNIT_TESTif(m_stop) {break;}std::cout << "thread is g ...
- 树梅派编译opencv并且编译测试流程
个人实测可行流程: 网上的资料太多了,整理大家的经验终于编译成功--- 1编译流程:参考https://www.cnblogs.com/lykyl/p/8545844.html https://blo ...
最新文章
- 让Everest 0.6支持Intel 82852/82855 GM/GME显卡图形登录
- 网站建设注重用户体验尤为重要
- git-fork下来的项目(拷贝到本地 根据原来的库更新)
- 中国楼市场的真相————写在厦门楼市崩盘之后
- stm32之USB应用实例(官方例程资料下载使用)
- boost::math模块具有输出和输入方面的非有限环回的简要基本测试
- 【数位DP】CF 54C,509C,431D,628D,855E,1245F,95D
- 三次握手和四次挥手图解_TCP三次握手和四次挥手详解
- python怎么读数据库_Python如何读写SQLite数据库
- Android自动化测试(UiAutomator)简要介绍 - 萧瑟一笑的专栏 - 博客频道 - CSDN.NET...
- MATLAB 2020b版本发布,下载试用版并上手使用记录。
- 开源阅读书源_阅读——开源阅读软件
- 伺服速度控制模式接线图_伺服驱动器控制模式的接线及其注意事项
- Class 学习 (Es6阮一峰)
- 三星s8清除html查看器,三星Galaxy S8/S8+双清教程_怎么清理数据缓存和恢复出厂设置...
- JAVA Swing添加表格
- 【web自动化测试Robotframework开发手册—特殊元素】
- php 生日还剩多少天,请教PHP中计算离生日还剩下多少天问题?
- android 获取屏幕旋转方向,android获取手机屏幕尺寸和旋转方向
- python基础-BytesIO,StringIO
热门文章
- 一文教你用java实现出租车计价器设计(附下载源码)
- 孙叫兽进阶之路之源代码配置管理过程(图文教程)
- 计算机dos通讯,PC双机通信DOS
- android 重新启动应用程序,通过单击应用程序图标打开Android应用程序时重新启动...
- php-5.2.6安装,php5.2.6安装openssl.o扩展,make时报错?
- margin赋值为负值的几种效果(负值像素,负值百分数)
- Python操作Redis(转)
- 深入理解redis数据类型
- scrapy架构解析
- PHP中__get()和__set()的用法实例详