C/C++编译、测试须知、须会,CMake、Boost等

46 篇文章 2 订阅

以下内容为本人实习期间学习笔记!!参考了网上的许多教程,共享大家,欢迎交流。

动态库和静态库(共享库)

不同点:代码被载入的时刻不同

静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大,程序运行时不再需要静态库

动态库的代码编译时不会链接到目标代码中,运行时才被载入,程序运行时还需要动态库存在

库的编译:无论是静态库还是动态库,都是.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_DEBUGCMAKE_C_FLAGS_DEBUG中的字符串生成Makefile

=Release时,使用变量CMAKE_CXX_FLAGS_RELEASECMAKE_C_FLAGS_RELEASE

OPTION:提供用户可以选择的选项
OPTION(OPTION_VAR "注释"[初始值]),初始值选项为ONOFF,未提供则为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_CHECKBOOST_REQUIRE_EQUAL 是Boost提供的预定义宏,用于验证代码输出

4、Boost的一整套的测试工具,基本上可以说是用于验证表达式的宏;
主要有3个类别:BOOST_WARN、BOOST_CHECK、BOOST_REQUIRE
BOOST_CHECKBOOST_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

还不是很完善。。会持续完善的。。。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值