1. 程式人生 > 其它 >C++_專案開發與Cmake構建工具

C++_專案開發與Cmake構建工具

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/

八、#參考

 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