本文是《机器人SLAM导航 核心技术与实践》这本书的学习笔记。本章讨论C++代码的编译方法。
【第二章】【C++编程规范】
一、C++代码编写
以一个简单的C++工程为例,分别讲解g++
、make
和CMake
这3种编译工具的用法。先来构建这个C++工程。新建一个cpp_test
文件夹,在cpp_test
中新建3个文件,分别是:main.cpp
、foo.h
、foo.cpp
。
1.foo.h文件
#ifndef FOO_H
#define FOO_H
#include <string>
namespace foo
{
class MyPrint
{
public:
MyPrint(std::string output);
void ExcutePrint();
std::string output_;
};
}
#endif
第1、2、17行是宏定义,防止头文件的重复包含与编译;
第6行是命名空间的设置,防止出现重复的函数和变量名称;
第8~15行声明类,这里不对类内的函数进行实现,具体的实现放在.cpp文件中;
第14行是定义要打印的变量;
2.foo.cpp文件
#include "foo.h"
#include <iostream>
#include <string>
namespace foo
{
MyPrint::MyPrint(std::string output):output_(output)
{
std::cout<<"class MyPrint created a object!";
std::cout<<std::endl;
}
void MyPrint::ExcutePrint()
{
std::cout<<output_<<std::endl;
}
}
第1行是对应的头文件;
第7-11行是构造函数的具体实现,函数头部需要使用类名MyPrint
作为作用域,传入的参数output
来为成员变量output_
赋值。;
第13~16行执行打印函数的具体实现;
3.main.cpp文件
#include "foo.h"
int main(int argc,char** argv)
{
foo::MyPrint my_print("I can output string!");
my_print.ExcutePrint();
return 0;
}
第1行,包含foo.h
头文件,以便实例化类MyPrint
;
第5行,实例化类MyPrint
;
第6行,调用对象中的成员函数,执行打印操作;
二、使用g++编译代码
在linux中,采用g++编译C++代码是最直接的。编译分为4步,分别是预处理、编译、汇编和连接,编译过程如下:
先安装g++工具,打开终端,输入:sudo apt install g++
安装好g++后,就可以对cpp_test工程进行编译了,编译命令如下:
cd cpp_test
g++ foo.cpp main.cpp -o cpp_test
最后生成cpp_test文件,用下面的命令可以执行cpp_test:
./cpp_test
三、使用make编译代码
当程序非常庞大时会设计很多个*.cpp
文件和外部依赖库,逐一输入g++的命令很不方便。这时候可以使用makefile
文件来编译脚本,然后使用make
命令进行编译。
将上面的编译命令改写为makefile
的形式,在文件夹cpp_test
中创建一个新的文件makefile
。文件内容如下:
start:
g++ -o foo.o -c foo.cpp
g++ -o main.o -c main.cpp
g++ -o cpp_test foo.o main.o
clean:
rm -rf foo.o main.o
第1、5行是命令块的命名,makefile中的命令可以划分成不同的块,默认make命令是调用第一个命令块的命令。make命令后面接命令块的名称,可以调用响应块的命令。
第2-4行,分别对各个*.cpp
文件进行编译,最后将生成的目标文件*.o
连接即可到的可执行文件cpp_test
。注意:命令前面必须使用tab进行缩进。
第6行,删除编程产生的中间文件。
在终端执行make
命令进行编译,执行make clean
命令删除中间文件。执行./cpp_test
执行文件。
四、使用CMake编译代码
虽然makefile
已经大大降低了程序的编译难度,但是程序有众多依赖和关联,如果全部手动去维护这些依赖关系还是很麻烦的。CMake
可以自动处理程序之间的关系,并产生对应的makefile
文件,调用make
就可以轻松编译了。
将上述代码改写为CMake
的方式,在文件夹中创建一个CMakeLists.txt
。
cmake_minimum_required(VERSION 2.8)
project(cpp_test)
include_directories("${PROJECT_BINARY_DIR}")
add_library(foo foo.cpp)
add_executable(cpp_test main.cpp)
target_link_libraries(cpp_test foo)
第1行,声明CMake最低要求的版本;
第2行,声明CMake的工程名;
第4行,设置头文件搜索路径;
第6行,创建库文件;
第7行,创建可执行文件;
第8行,为可执行文件连接依赖库;
在终端执行cmake .
命令可以生成大量中间文件和一个Makefile
文件,继续使用make
命令编译可以得到可执行文件cpp_test
。执行./cpp_test
命令可以运行程序。
文件CMakeLists.txt的编写需要遵循CMake的语法,想要了解更多CMake语法的细节,可以访问CMake的wiki界面。