C++项目的基本内容了解 Cmake构建工具



一、语言:

 C语言
C++ 标准库可以分为两部分:
标准函数 库: 这个库是由通用的、独立的、不属于任何类的函数组成的。函数库继承自 C 语言。
C++ 标准库包含了所有的 C 标准库,为了支持类型安全,做了一定的添加和修改
面向对象 类库: 这个库是类及其相关函数的集合。


二、编译器:

GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAV、Fortran。大写的GCC    
gcc & g++现在是gnu中最主要和最流行的c & c++编译器 。
g++是c++的命令,以.cpp为主,
gcc是c语言一般为.c。
其实编译器是gcc还是g++ 是按照C标准还是C++标准编译链接来确定。
根据代码的后缀名来判断调用 c编译器还是c++编译器 (g++)
对于.c文件gcc当做c语言处理,g++当做c++处理;
对于.cpp文件gcc和g++均当做c++处理
编译器对程序代码的编译主要分为下面几个过程:
a) 词法分析
b) 语法分析
c) 语义分析
d) 中间代码生成
e) 代码优化
f) 代码生成
g) 符号表管理
h) 将多个步骤组合成趟
i) 编译器构造工具


三、过程:

1.编写代码

2.编译和链接
预处理阶段--编译阶段--汇编阶段--链接阶段
编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。
链接是把目标文件、操作系统的启动代码和用到的库文件进行组织,形成最终生成可执行代码的过程

01.编译过程又可以分成两个阶段:编译和汇编
gcc编译器便是把以上的几个过程进行捆绑,使用户只使用一次命令就把编译工作完成
--> 预编译处理(.c)
--> 编译、优化程序(.s、.asm)
--> 汇编程序(.obj、.o、.a、.ko)
--> 链接程序(.exe、.elf、.axf等)
02.链接
静态链接
动态链接
3.运行是执行可执行文件
调试--运行过程中调试,运行结果调试


四、具体情况

1.切换到相应的目录
2.Linux环境下
g++
用g++ 加上文件名,注意要加上文件扩展名,这样会生成一个Linux默认生成a.out的可执行文件(Windows默认生成a.exe,)
3.直接输入 ./a.out 并回车, 即可执行由demo.cpp编译链接生成的程序(Windows环境下,则改成a.exe 运行程序)
具体示例
cd /home/test/soft/test-master
g++ -o helloworld helloworld.cpp
./helloworld.cpp


01.头文件-源文件-库文件-目标文件

 source file
head file
C++中进行代码分离 在h文件中声明Declare,而在cpp文件中定义Define
头文件是文本文件,是可供阅读的;库文件是二进制文件,不可直接阅读。
头文件在编译中使用;库文件在链接中使用。
头文件中是函数或定义的声明,及少量内联函数的使用,一般不包含非静态函数实现;库文件中包含函数的实现。
头文件是手动编写的,库文件是编译生成的


02.头文件Head file

01.头文件(.h):
写类的声明(包括类里面的成员和方法的声明)、函数原型、#define常数等,但一般来说不写出具体的实现。
在写头文件时需要注意,在开头和结尾处必须按照如下样式加上预编译语句:
#ifndef CIRCLE_H
#define CIRCLE_H

//代码写在这里

#endif

eg:mydecoder.h
#ifndef _MY_DECODER_H_
#define _MY_DECODER_H_
#include<opencv2/opencv.hpp>
class myDecoder{
private:
int width;
float * d_nrm;
private:
nv_handle;
nv_state;

public:
myDecoder();
~myDecoder();
public:
int init(int width,int height);
};

#endif


03.源文件

 02.源文件(.cpp):mydecoder.cpp
源文件主要写实现头文件中已经声明的那些函数的具体代码。
开头必须#include一下实现的头文件,以及要用到的头文件
#include "decoder.h"
##hpp 是Header Plus Plus的简写
.hpp本质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该.hpp文件即可,无需再将cpp加入到project中进行编译

源代码的编译和链接
.h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的

添加头文件目录 INCLUDE_DIRECTORIES
添加需要链接的库文件目录 LINK_DIRECTORIES
工程生成目标文件 add_executable


code

 #include <time.h>  int clock_gettime(clockid_t clk_id, struct timespec* tp);
struct timespec
{
time_t tv_sec; /* 秒*/
long tv_nsec; /* 纳秒*/
};

关于 unsigned long long 于 long long
long long 最大只有19位 ;
unsigned long long 最大有20位 ,原因牺牲了符合位来换取更大的记录
可以根据需要,获取不同要求的精确时间
CLOCK_MONOTONIC 是 monotonic time ,
而 CLOCK_REALTIME 是 wall time


五、构建系统与构建工具

cmake与make
编写-编译-链接-运行 源文件太多,一个一个编译时就会特别麻烦--
make工具,它是一个自动化编译工具,你可以使用一条命令实现完全编译。但是需要编写一个规则文件,make依据它来批处理编译,这个文件就是makefile
cmake工具,它能够输出各种各样的makefile或者project文件,从而帮助程序员减轻负担。需要编写cmakelist文件,它是cmake所依据的规则
01.GNU构建系统
构建方式-GNU构建系统(GNU Build System)主要是指通过 autoconf automake和libtool这三个工具构建出来的软件结构体系,又名 Autotools
基于源码安装软件:configure->make->make install 利用脚本和make程序在特定平台上构建软件
configure脚本是由软件开发者维护并发布给用户使用的shell脚本。这个脚本的作用是检测系统环境,
最终目的是生成Makefile和config.h。configure主要检查当前目标平台的程序、库、头文件、函数等的兼容性
make通过读取Makefile文件,开始构建软件。
make install可以将软件安装到需要安装的位置
生成configure脚本和Makefile.in等文件,开发者需要创建并维护一个configure.ac文件,configure.ac用于生成configure脚本。autoconf工具用来完成这一步
cmake
xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观

02.IDE构建工具
Visual Studio


六、Cmake介绍

cmake --version
cmake --help
Usage
cmake [options] <path-to-source>
cmake [options] <path-to-existing-build>
把支持的命令行参数分成了几个类别
/usr/bin/cmake: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux),
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0,
BuildID[sha1]=, stripped
说明: /lib64是内核级的,/usr/lib64是系统级的,/usr/local/lib64是用户级


1.安装cmake

CMake能用来编写跨平台(cross-platform)的构建规则,
通过这些规则来调用各个平台的编译器、链接器,生成各个目标(静态库,静态库,或者可执行)
,CMake 并不直接建构出最终的软件,而是产生标准的建构文档(如 Makefile 或 projects )
编译器 gcc
函数库
安装好CMake,它提供了一个可执行文件cmake或cmake.exe,
有时候还提供一个GUI版本,比如ccmake或cmake-gui,调用的还是cmake命令
Ubuntu 安装 sudo apt install cmake
development tools
use the GCC compiler,
GDB to debug,
and make to build the project


2.步骤

 原始的方式  采用 gcc hello.cpp -o hello 命令来生成可执行文件
新建 build 目录,cd 到 build 目录下,敲 cmake .. 命令,敲 make 命令生成 hello 可执行文件
mkdir build && cd build && cmake .. && make -j16
ls 一下会发现 CMake 帮我们生成了 Makefile 等等一些文件。
CMakeCache.txt
CMakeFiles
cmake_install.cmake
compile_commands.json
Makefile


3.示例项目

 01.先把opencv环境配置好  sudo apt-get install libopencv-dev 
确定头文件位置
安装的位置
/usr/include/opencv2/opencv.hpp
/usr/include/opencv/
/usr/share/opencv/
确定库函数位置
/usr/lib/x86_64-linux-gnu/
02.修改Cmake
# 错误类型 .cpp:3:22: fatal error: opencv.hpp: 没有那个文件或目录
# 头文件路径
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/include
)
include_directories("/usr/include/opencv2")
include_directories("/usr/include/opencv")
include_directories("/usr/include")
link_directories("/usr/lib/x86_64-linux-gnu/")
03.修改main函数
修改根目录
std::string root_dir = "./";
std::string config_file = root_dir + "./conf/test.ini";
04.执行过程
mkdir build && cd build && cmake .. && make -j16

#make -j16意思即make最多允许16个编译器同时执行,提高编译速度,充分利用本机计算资源项目在进行并行编译
05.查看输出:
/home/test/soft/test-master/Log/IPM


七、CMakeLists.txt内容

# 最低指定的CMake版本
cmake_minimum_required(VERSION 3.10)
# 括号里面填你的工程名
project(Test)

# 指定语言要求,以下命令为c++ 11
set(CMAKE_CXX_STANDARD 11)
set( CMAKE_CXX_COMPILER "g++" )
set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_CXX_FLAGS "-std=c++11 -march=native -O3" )

# 头文件路径
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/include
)
include_directories("/usr/include/opencv2")
include_directories("/usr/include/opencv")
include_directories("/usr/include")

# 给编译器添加库目录,指定要链接的库文件的路径
link_directories("/usr/lib/x86_64-linux-gnu/")

set(MY_OPENCV_LIBS opencv_calib3d opencv_core opencv_highgui
opencv_imgcodecs opencv_imgproc opencv_videoio
)
link_libraries(
${MY_OPENCV_LIBS}
)

# 生成可执行文件 SurrouncViewPano add_executable命令也可以用来创建导入的(IMPORTED)可执行目标:add_executable(< name> IMPORTED)
# :add_executable: 使用给定的源文件,为工程引入一个可执行文件
add_executable(Test
main.cpp
src/ini_parser.cpp
src/string_util.cpp
src/Test.cpp
src/util.cpp)

#说明
# link_libraries 要在 add_executable 之前
# target_link_libraries 要在 add_executable 之后
02命令行
001.构建
rm -rf build && mkdir build && cd build && cmake .. && make all -j8
002.执行
./build/Frame /data/video_demo.mp4 /data/frame/