C++編譯的基本知識

1 C++編譯的基本知識

對於源代碼包,咱們只有編譯才能在系統上運行。ios

在一個 C++ 工程中,並非全部代碼都會編譯成可執行文件。只有帶有 main 函數的文件纔會生成可執行程序。而另外一些代碼,咱們只想把它們打包成一個東西,供其餘程序調用。這個東西叫作庫。 一個庫每每是許多算法、程序的集合,咱們會在以後的練習中,接觸到許多庫。例如,OpenCV 庫提供了許多計算機視覺相關的算法,而 Eigen 庫提供了矩陣代數的計算。 Linux下的編譯器有gcc、g++,隨着源文件的增長,直接用gcc/g++命令的方式顯得效率低下,人們開始用Makefile來進行編譯。然而隨着工程體量的增大,Makefile也不能知足需求,因而便出現了Cmake工具。CMake是對make工具的生成器,是更高層的工具,它簡化了編譯構建過程,可以管理大型項目,具備良好的擴展性。對於ROS這樣大致量的平臺來講,就採用的是CMake,而且ROS對CMake進行了擴展,因而便有了Catkin編譯系統。c++

2 使用g++

咱們用編譯器 g++ (g++ 是一個 C++ 編譯器)把.cpp文件編譯成一個可執行文件 。算法

g++ helloSLAM.cpp

剛纔這條編譯命令把 helloSLAM.cpp 這個文本文件編譯成了一個可執行程序。咱們檢查當前目錄,會發現多了一個 a.out 文件,並且它具備執行權限(終端裏顏色不一樣)。咱們輸入./a.out 便可運行此程序編輯器

3 使用 cmake

3.1 cmake簡介

單個C++文件能夠用g++來編譯成一個可執行文件。可是一個大工程使用 cmake 來管理源代碼 。函數

理論上說,任意一個 C++ 程序均可以用 g++ 來編譯。但當程序規模愈來愈大時,一個工程可能有許多個文件夾和裏邊的源文件,這時輸入的編譯命令將愈來愈長。一般一個小型 c++ 項目含有十幾個類,各種間還存在着複雜的依賴關係。 可能原文件中其中一部分要編譯成可執行文件,另外一部分編譯成庫文件。 若是僅靠 g++ 命令,咱們須要輸入大量的編譯指令,整個編譯過程會變得異常繁瑣。工具

3.2 cmake使用介紹,與生成可執行文件

在一個 cmake 工程中,咱們會用 cmake 命令生成一個 makefle 文件,而後,用 make命令 ,根據這個 makefle 文件的內容,編譯整個工程。 cmake 過程處理了工程文件之間的關係,而 make 過程實際調用了 g++ 來編譯程序 。ui

cmake的操做對象其實是CMakeLists.txt 文件,所以須要開發者先編寫一個CMakeLists.txt 文件CMakeLists.txt 文件告訴 cmake 咱們要對這個目錄下的文件作什麼事情。CMakeLists.txt 文件內容須要遵照 cmake 的語法。spa

好比:code

# 聲明要求的 cmake 最低版本
cmake_minimum_required( VERSION 2.8 )

# 聲明一個 cmake 工程
project( HelloSLAM )
# 添加一個可執行程序
# 語法: add_executable( 自定義程序名 源代碼文件 )
add_executable( helloSLAM helloSLAM.cpp )

演示了最基本的工程:指定一個工程名和一個可執行程序(這也是如何使用cmake生成可執行文件的示例)。對象

過程:

在當前目錄下 ,首先用cmake對該工程進行分析,再用make指令對工程進行編譯。

第一步

cmake .

注意加這個.說明要編譯的源文件以及CMakeLists.txt 文件應當都在打當前目錄下。

第二步:

make

cmake 會輸出一些編譯器等信息,而後在當前目錄下生成一些中間文件,其中最重要的就是 MakeFile。MakeFile 是一個自動化編譯的腳本,能夠將它理解成一系統自動生成的編譯指令。

效果:

cmake 過程處理了工程文件之間的關係,而 make 過程實際調用了 g++ 來編譯程序。雖然這個過程當中多了調用cmake 和 make 的步驟,但咱們對項目的編譯管理工做,從輸入一串 g++ 命令,變成了維護若干個比較直觀的 CMakeLists.txt 文件,這將明顯下降維護整個工程的難度。好比,當我想新增一個可執行文件時,只需在 CMakeLists.txt 中添加一行「add_executable」命令便可,然後續的步驟都是不變的。 cmake 會幫咱們解決代碼的依賴關係,無需咱們輸入一大串 g++ 命令。

刪除中間文件:

如今這個過程當中,惟一讓咱們不滿的是, cmake 生成的中間文件還留在咱們代碼文件當中。當咱們想要發佈代碼時,並不但願把這些中間文件一同發佈出去。這時咱們還需把它們一個個刪除,這十分的不便。一種更好的作法是讓這些中間文件都放在一箇中間目錄中,在編譯成功後,把這個中間目錄刪除便可。因此,更常見的編譯 cmake 工程的作法就是這樣 :

mkdir build
cd build
cmake ..
make

咱們新建了一箇中間文件夾「build」,而後進入 build 文件夾,經過 cmake .. 命令,對上一層文件夾,也就是代碼所在的文件夾進行編譯。這樣, cmake 產生的中間文件就會生成在 build 文件夾中,與源代碼分開。當咱們發佈源代碼時,只要把 build 文件夾刪掉便可。 下次編譯的時候再像這樣新建。

3.3 cmake生成庫文件

只有帶有 main 函數的文件纔會生成可執行程序。而另外一些代碼,咱們只想把它們打包成一個東西,供其餘程序調用。這個東西叫作庫。

一個庫每每是許多算法、程序的集合(由不含main函數的源文件編譯而成),咱們會在以後的練習中,接觸到許多庫。例如,OpenCV 庫提供了許多計算機視覺相關的算法,而 Eigen 庫提供了矩陣代數的計算。

3.3.1 使用cmake 生成庫

好比對於一個libHelloSLAM.cpp 文件 。這個庫提供了一個 printHello 函數,調用此函數將輸出一個信息。可是它沒有 main函數,這意味着這個庫中沒有可執行文件。

//這是一個庫文件
#include <iostream>
using namespace std;
void printHello()
{
cout<<"Hello SLAM"<<endl;
}

這個庫提供了一個 printHello 函數,調用此函數將輸出一個信息。可是它沒有 main函數,這意味着這個庫中沒有可執行文件。爲了libHelloSLAM.cpp編譯成庫文件,咱們在 CMakeLists.txt 里加一句:

add_library( hello libHelloSLAM.cpp )

這條命令告訴 cmake,我想把這個文件編譯成一個叫作「hello」的庫。以後即可以使用 cmake 和make編譯整個工程:

cd build
cmake ..
make

這時,在 build 文件夾中會生成一個 libhello.a 文件,這就是咱們獲得的庫(靜態庫),以.a 做爲後綴名。


在 Linux 中,庫文件分紅靜態庫和共享庫兩種。靜態庫以.a 做爲後綴名,共享庫以.so結尾。全部庫都是一些函數打包後的集合,差異在於靜態庫每次被調用都會生成一個副本,而共享庫則只有一個副本,更省空間。若是咱們想生成共享庫而不是靜態庫,只需用:

add_library( hello_shared SHARED libHelloSLAM.cpp )

就能夠編譯成一個共享庫。此時獲得的文件是 libhello_shared.so 了。

3.3.2 使用庫文件

庫文件是一個壓縮包,裏頭帶有編譯好的二進制函數。不過,僅有.a 或.so 庫文件的話,咱們並不知道它裏頭的函數究竟是什麼,調用的形式又是什麼樣的。爲了讓別人(或者本身)使用這個庫,咱們須要提供一個頭文件,說明這些庫裏都有些什麼。所以,對於庫的使用者, 只要拿到了頭文件和庫文件,就能夠調用這個庫了

編寫一個庫文件對應的頭文件:

libHelloSLAM.h

#ifndef LIBHELLOSLAM_H_
#define LIBHELLOSLAM_H_
void printHello();// 對庫文件中的函數進行聲明,以讓別人知道庫文件裏有什麼
#endif

這樣,根據這個文件和咱們剛纔編譯獲得的庫文件,就可使用這個函數了。下面我
們寫一個可執行程序,調用這個簡單的函數void printHello()

useHello.cpp

#include "libHelloSLAM.h"
int main( int argc, char** argv )
{
printHello();
return 0;
}

而後,在 CMakeLists.txt 中添加一個可執行程序的生成命令,連接到剛纔咱們使用的庫上:

add_executable( useHello useHello.cpp ) //編譯剛編寫的可執行文件
target_link_libraries( useHello hello_shared )//將共享庫連接到某個頭文件

經過這兩句話, useHello 程序就能順利使用 hello_shared 庫中的代碼了。

對於他人提供的庫,咱們也可用一樣的方式對它們進行調用,整合到本身的程序中。

3.4 小結

  1. 首先,程序代碼由頭文件和源文件組成;
  2. 帶有 main 函數的源文件編譯成可執行程序,其餘的編譯成庫文件。
  3. 若是可執行程序想調用庫文件中的函數,它須要參考該庫提供的頭文件,以明白調用
    的格式。同時,要把可執行程序連接到庫文件上。 (可是根據描述是不須要編譯頭文件的)

使用g++或者cmake本質是使用文本開發環境,即便用文本編輯器編輯代碼,再對編輯好的代碼進行編譯等生成文件。除此以外,還可使用集成開發環境。

相關文章
相關標籤/搜索