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/

示例01

 # 自定义头文件目录- 告诉编译器头文件在哪个位置
 INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include)
 
 ###方式一:直接生成目标文件-可执行文件
      #编译可执行程序
      add_executable(${PROJECT_NAME}
      CVrame.cpp
      src/util.cpp
             )
 
 # # 方式二, -生成目标文件-生成静态库  --目标文件链接静态库-可执行文件
 # add_executable(${PROJECT_NAME} CVrame.cpp )
 # #生成动态链接库
 # #库文件的输出目录
 # SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
 # ADD_LIBRARY( util SHARED ${PROJECT_SOURCE_DIR}/src/util.cpp)
 # #目标文件链接到库文件
 # target_link_libraries(${PROJECT_NAME}  util)

示例02

#寻找Opencv库 ###方式opencv一
find_package(OpenCV REQUIRED)
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " includ: ${OpenCV_INCLUDE_DIRS}")
include_directories( 
        ${OpenCV_INCLUDE_DIRS}
        ${OpenCV_INCLUDE_DIRS}/opencv2
        )
link_libraries( ${OpenCV_LIBS})

###方式opencv二
# include_directories("/usr/include/opencv2")
# include_directories("/usr/include/opencv")
# include_directories("/usr/include")
# set(MY_OPENCV_LIBS opencv_calib3d opencv_core opencv_highgui
#         opencv_imgcodecs opencv_imgproc opencv_videoio
#         )
# link_libraries(  ${MY_OPENCV_LIBS}  )

# 库文件-添加非标准的共享库搜索路径
link_directories("/usr/lib/x86_64-linux-gnu/")	

八、#参考

 CMakeLists.txt
  Get started with CMake Tools on Linux https://code.visualstudio.com/docs/cpp/cmake-linux
   C++中头文件(.h)和源文件(.cpp)都应该写些什么 https://www.cnblogs.com/fenghuan/p/4794514.html
原文地址:https://www.cnblogs.com/ytwang/p/14890288.html