日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Cmakelist知识总结

發(fā)布時(shí)間:2023/12/31 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cmakelist知识总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Cmakelist知識總結(jié)

文章目錄

  • Cmakelist知識總結(jié)
    • 程序編譯鏈接過程簡介
    • Cmakelist簡介
    • Cmakelist寫法
    • cmakelist實(shí)例解析

程序編譯鏈接過程簡介

一個完整的 C++ 語言項(xiàng)目可能包含多個 .cpp 源文件,項(xiàng)目的運(yùn)行需要經(jīng)過“編譯”和“鏈接”兩個過程:

  • 編譯 :由編譯器逐個對源文件做詞法分析、語法分析、語義分析等操作,最終生成多個目標(biāo)文件。每個目標(biāo)文件都是二進(jìn)制文件,但由于它們會相互調(diào)用對方的函數(shù)或變量,還可能會調(diào)用某些鏈接庫文件中的函數(shù)或變量,編譯器無法跨文件找到它們確切的存儲地址,所以這些目標(biāo)文件無法單獨(dú)執(zhí)行。
  • 鏈接:對于各個目標(biāo)文件中缺失的函數(shù)和變量的存儲地址(后續(xù)簡稱“缺失的地址”),由鏈接器負(fù)責(zé)修復(fù),并最終將所有的目標(biāo)文件和鏈接庫組織成一個可執(zhí)行文件。

我們在開發(fā)過程中也經(jīng)常會面臨庫文件和目標(biāo)文件的概念,因此在做工程文件時(shí),經(jīng)常需要了解什么是庫文件?什么是目標(biāo)文件?什么是依賴項(xiàng)?

  • 庫文件包含幾種類型:(1)資源類型的,就是存放的東西,供外部調(diào)用的沒有函數(shù),只有變量或類的實(shí)體;(2)有簡單的函數(shù)供外部調(diào)用的文件;(3)也是用的比較多的,就是包含一個完整的模塊,緊提供一個外部調(diào)用的接口,當(dāng)外部調(diào)用該接口就開始運(yùn)行這個模塊,外部幾乎就處于休眠狀態(tài);
    (1)靜態(tài)庫
    靜態(tài)庫就是一些目標(biāo)文件的集合,windows下以.lib結(jié)尾,linux下以.a結(jié)尾。靜態(tài)庫在程序鏈接的時(shí)候使用,鏈接器會將程序中使用到函數(shù)的代碼從庫文件中拷貝到應(yīng)用程序中。一旦鏈接完成,在執(zhí)行程序的時(shí)候就不需要靜態(tài)庫了。由于每個使用靜態(tài)庫的應(yīng)用程序都需要拷貝所用函數(shù)的代碼,所以靜態(tài)鏈接的文件會比較大。

(2)動態(tài)庫
動態(tài)庫,windows下叫DLL,linux下叫共享庫以.so結(jié)尾. (so ==share object) 在程序的鏈接時(shí)候并不像靜態(tài)庫那樣在拷貝使用函數(shù)的代碼,而只是作些標(biāo)記。然后在程序開始啟動運(yùn)行的時(shí)候,動態(tài)地加載所需模塊。所以,應(yīng)用程序在運(yùn)行的時(shí)候仍然需要共享庫的支持。 共享庫鏈接出來的文件比靜態(tài)庫要小得多。動態(tài)庫的好處是,不同的應(yīng)用程序如果調(diào)用相同的庫,那么在內(nèi)存里只需要有一份該共享庫的實(shí)例。

  • 目標(biāo)文件就是編譯過程中產(chǎn)生的,鏈接起來生成可執(zhí)行文件的。
  • 依賴項(xiàng)就是設(shè)定項(xiàng)目所依賴的項(xiàng)目,以決定具體生成解決方案時(shí)項(xiàng)目編譯的順序(一般一個解決方案會有很多項(xiàng)目組成)。 通常來說,依賴項(xiàng)取決于這個項(xiàng)目引用的組件和項(xiàng)目,系統(tǒng)可以自己決定。

我們明確了上述的具體定義后,可以介紹一個工程文件從源文件到可執(zhí)行文件的編譯流程;具體編譯流程如下:

① 預(yù)處理過程
預(yù)處理相當(dāng)于根據(jù)預(yù)處理指令組裝新的C/C++程序。經(jīng)過預(yù)處理,會產(chǎn)生一個沒有宏定義,沒有條件編譯指令,沒有特殊符號的輸出文件,這個文件的含義同原本的文件無異,只是內(nèi)容上有所不同。
讀取C/C++源程序,對其中的偽指令(以#開頭的指令)進(jìn)行處理,內(nèi)容如下:

  • 將所有的“#define”刪除,并且展開所有的宏定義;
  • 處理所有的條件編譯指令,如:“#if”、“#ifdef”、“#elif”、“#else”、“endif”等。這些偽指令的引入使得程序員可以通過定義不同的宏來決定編譯程序?qū)δ男┐a進(jìn)行處理。預(yù)編譯程序?qū)⒏鶕?jù)有關(guān)的文件,將那些不必要的代碼過濾掉;
  • 處理“#include”預(yù)編譯指令,將被包含的文件插入到該預(yù)編譯指令的位置(注意:這個過程可能是遞歸進(jìn)行的,也就是說被包含的文件可能還包含其他文件);
  • 刪除所有的注釋;
  • 添加行號和文件名標(biāo)識,以便于編譯時(shí)編譯器產(chǎn)生調(diào)試用的行號信息及用于編譯時(shí)產(chǎn)生的編譯錯誤或警告時(shí)能夠顯示行號;
  • 保留所有的#pragma編譯器指令。
  • ② 編譯過程

    將預(yù)處理完的文件進(jìn)行一系列詞法分析、語法分析、語義分析及優(yōu)化后,產(chǎn)生相應(yīng)的匯編代碼文件。

    ③ 匯編過程

    將編譯完的匯編代碼文件翻譯成機(jī)器指令,并生成可重定位目標(biāo)程序的.o文件,該文件為二進(jìn)制文件,字節(jié)編碼是機(jī)器指令。

    匯編器是將匯編代碼轉(zhuǎn)變成機(jī)器可以執(zhí)行的指令,每一個匯編語句幾乎都對應(yīng)一條機(jī)器指令。所以匯編器的匯編過程相對于編譯器來講比較簡單,它沒有復(fù)雜的語法,也沒有語義,也不需要做指令優(yōu)化,只是根據(jù)匯編指令和機(jī)器指令的對照表一一翻譯即可。

    ④ 鏈接(build)過程

    通過鏈接器將一個個目標(biāo)文件(或許還會有庫文件)鏈接在一起生成一個完整的可執(zhí)行程序。由匯編程序生成的目標(biāo)文件并不能立即就被執(zhí)行,其中可能還有許多沒有解決的問題。

    例如,某個源文件中的函數(shù)可能引用了另一個源文件中定義的某個符號(如變量或者函數(shù)調(diào)用等);在程序中可能調(diào)用了某個庫文件中的函數(shù),等等。所有的這些問題,都需要經(jīng)鏈接程序的處理方能得以解決。

    鏈接程序的主要工作就是將有關(guān)的目標(biāo)文件彼此相連接,也就是將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來,使得所有的這些目標(biāo)文件成為一個能夠被操作系統(tǒng)裝入執(zhí)行的統(tǒng)一整體。

    Cmakelist簡介

    cmake 是一個跨平臺、開源的構(gòu)建系統(tǒng)。它是一個集軟件構(gòu)建、測試、打包于一身的軟件。它使用與平臺和編譯器獨(dú)立的配置文件來對軟件編譯過程進(jìn)行控制。
    要了解CMakelist.txt文件,首先我們先了解一下Makefile。Makefile 可以簡單的認(rèn)為是一個工程文件的編譯規(guī)則,描述了整個工程的編譯和鏈接等規(guī)則。其中包含了那些文件需要編譯,那些文件不需要編譯,那些文件需要先編譯,那些文件需要后編譯,那些文件需要重建等等。編譯整個工程需要涉及到的,在 Makefile 中都可以進(jìn)行描述。換句話說,Makefile 可以使得我們的項(xiàng)目工程的編譯變得自動化,不需要每次都手動輸入一堆源文件和參數(shù)。

    Cmake的所有語句都寫在一個CMakeLists.txt的文件中,CMakeLists.txt文件確定后,直接使用Cmake命令進(jìn)行運(yùn)行,但是這個命令要指向CMakeLists.txt所在的目錄,Cmake之后就會產(chǎn)生我們想要的makefile文件,然后再直接make就可以編譯出可執(zhí)行程序或者動態(tài)庫。所以基本步驟就只有兩步:(1)cmake生成MakeLists.txt文件;(2)make執(zhí)行編譯工作。

    Cmakelist寫法

    一個cmakelist文件主要包含以下的內(nèi)容:
    (1)聲明 cmake 最低版本
    cmake_minimun_required(VERSION 2.8)
    (2)聲明 cmake 工程名字
    project( HelloSLAM )
    加上上述指令,它會引入兩個變量 demo_BINARY_DIR 和 demo_SOURCE_DIR,同時(shí),cmake 自動定義了兩個等價(jià)的變量 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR。

    PROJECT_SOURCE_DIR: 工程的根目錄
    PROJECT_BINARY_DIR: 運(yùn)行 cmake 命令的目錄,通常是 ${PROJECT_SOURCE_DIR}/build
    PROJECT_NAME: 返回通過 project 命令定義的項(xiàng)目名稱
    CMAKE_CURRENT_SOURCE_DIR: 當(dāng)前處理的 CMakeLists.txt 所在的路徑
    CMAKE_CURRENT_BINARY_DIR: target 編譯目錄
    CMAKE_CURRENT_LIST_DIR: CMakeLists.txt 的完整路徑
    CMAKE_CURRENT_LIST_LINE: 當(dāng)前所在的行
    CMAKE_MODULE_PATH: 定義自己的 cmake 模塊所在的路徑,SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令來調(diào)用自己的模塊
    EXECUTABLE_OUTPUT_PATH: 重新定義目標(biāo)二進(jìn)制可執(zhí)行文件的存放位置
    LIBRARY_OUTPUT_PATH: 重新定義目標(biāo)鏈接庫文件的存放位置

    (3)設(shè)置 cmake 編譯模式
    set( CMAKE_BUILD_TYPE “Debug” )
    (¥)添加c++11標(biāo)準(zhǔn)支持
    set(CMAKE_CXX_FLAGS “-std=c++11 -O3”)
    參數(shù)CMAKE_CXX_FLAGS含義是: set compiler for c++ language而后面的-O3(是字母opq的o,大寫的歐)是用來調(diào)節(jié)編譯時(shí)的優(yōu)化程度的,最高為-O3,最低為-O0(即不做優(yōu)化)-Ox這個參數(shù)只有在CMake -DCMAKE_BUILD_TYPE=Release時(shí)有效,因?yàn)閐ebug 版的項(xiàng)目生成的可執(zhí)行文件需要有調(diào)試信息并且不需要進(jìn)行優(yōu)化,而 release 版的不需要調(diào)試信息但需要優(yōu)化。
    (5)添加變量
    set( Sophus_INCLUDE_DIR ${PROJECT_SOURCE_DIR} )
    (6)添加依賴
    一般添加依賴項(xiàng)都需要解決三個問題:去哪里找頭文件(.h等) 對應(yīng)于GCC的參數(shù) -I;去哪里找?guī)煳募?.so/.lib/.ddl等) 對應(yīng)于GCC的參數(shù) -L;需要鏈接的庫文件名稱 對應(yīng)于GCC的參數(shù) -l。
    find_package的作用就是去尋找該庫的頭文件位置、庫文件位置以及庫文件名稱,并將其設(shè)為變量,返回提供給CMakeLists.txt其他部分使用。

    find_package( Sophus REQUIRED ) find_package( Pangolin ) find_package( OpenCV REQUIRED )

    (7)添加頭文件

    include_directories( “/usr/include/eigen3” ) include_directories( ${Pangolin_INCLUDE_DIRS} ) include_directories( ${Sophus_INCLUDE_DIRS} )

    (8)設(shè)置鏈接庫搜索目錄
    link_directories(${CMAKE_CURRENT_SOURCE_DIR}/libs)
    (9)添加一個可執(zhí)行程序
    add_executable( helloSLAM helloSLAM.cpp )
    或者

    aux_source_directory(. SRC_LIST) # 搜索當(dāng)前目錄下的所有.cpp文件 add_library(helloSLAM ${SRC_LIST})

    或者

    file(GLOB SRC_LIST "*.cpp") file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp") add_library(helloSLAM ${SRC_LIST} ${SRC_PROTOCOL_LIST})

    其中,GLOB命令將所有匹配globbing-expressions(可選,假如不寫,毛都匹配不到)的文件挑選出來,默認(rèn)以字典順序排序。
    (10)構(gòu)建靜態(tài)庫
    add_library( hello_static STATIC libHelloSLAM.cpp )
    (11)構(gòu)建靜動態(tài)庫或者共享庫
    add_library( hello_shared SHARED libHelloSLAM.cpp )
    (12)庫文件鏈接到可執(zhí)行程序上

    target_link_libraries( useHello hello_shared ) target_link_libraries( imageBasics ${OpenCV_LIBS} ) target_link_libraries( joinMap ${OpenCV_LIBS} ${PCL_LIBRARIES} )

    或者
    link_libraries(libface.a)


    link_libraries用在add_executable之前,target_link_libraries用在add_executable之后。
    link_libraries用來鏈接靜態(tài)庫,target_link_libraries用來鏈接導(dǎo)入庫,即按照header file + .lib + .dll方式隱式調(diào)用動態(tài)庫的.lib庫。


    (13)指定安裝地址
    cmake -DCMAKE_INSTALL_PREFIX=/usr/local

    (14)Debug和Release版本
    CMAKE_BUILD_TYPE 指定基于make的產(chǎn)生器的構(gòu)建類型(Release,Debug)

    SET(CMAKE_CXX_FLAGS_DEBUG"ENVCXXFLAGS?O0?Wall?g?ggdb") SET(CMAKE_CXX_FLAGS_RELEASE"ENVCXXFLAGS?O0?Wall?g?ggdb")

    debug 版的項(xiàng)目生成的可執(zhí)行文件需要有調(diào)試信息并且不需要進(jìn)行優(yōu)化,、
    release 版的不需要調(diào)試信息但需要優(yōu)化。這些特性在 gcc/g++ 中是通過編譯時(shí)的參數(shù)來決定的,如果將優(yōu)化程度調(diào)到最高需要設(shè)置參數(shù)-O3,最低是 -O0 即不做優(yōu)化;添加調(diào)試信息的參數(shù)是 -g -ggdb ,如果不添加這個參數(shù),調(diào)試信息就不會被包含在生成的二進(jìn)制文件中。
    (15)調(diào)試信息
    打印信息,類似于 echo/printf ,主要用于查cmake文件的語法錯誤。
    message(“mysql_use_test_sources : ${mysql_use_test_sources}”)

    cmakelist實(shí)例解析

    CmakeLists.txt的重要組成部分:拆分成以下幾部分進(jìn)行講解。

    1、表明Cmake所需要的最低版本:僅針對本項(xiàng)目
    cmake_minimum_required(VERSION2.9 FATAL_ERROR)

    2、定義需要的特殊變量(optional)(關(guān)于set的用法我目前沒有細(xì)看,有心的同學(xué)自己鉆研)

    SET(sampleName MyApp)
    如上面的例子:set(project_name cloud_viewer_PointXYZ)

    3、查找我們構(gòu)建工程所需要的package,這一步極其重要。
    find_package(PCL 1.8.0 REQUIRED) #主要依賴的package
    # //如果PCL被找到的話,那么將會生成幾個包含package信息的Cmake環(huán)境變量,下面幾個相關(guān)的變量就會被設(shè)置
    PCL_FOUND:PCL找到后就設(shè)置為1,否則未設(shè)置
    PCL_INCLUDE_DIRS:設(shè)置PCL頭文件和依賴項(xiàng)頭文件的安裝路徑
    PCL_LIBRARIES:設(shè)置已構(gòu)建和已安裝PCL庫的文件名
    PCL_LIBRARY_DIRS:設(shè)置PCL庫和第三方依賴的路徑
    PCL_VERSION:找到的PCL版本
    PCL_COMPONENTS:列出所有的可用部分
    PCL_DEFINITIONS:列出所有需要的預(yù)處理器定義和編譯器標(biāo)志
    # 這些變量將會在后面的cmakescript中用到。
    # 這些環(huán)境變量描述了package的外部頭文件位置(include路徑),
    # 依賴的庫文件的位置(lib),以及源程序的位置。
    # 例如上面命令執(zhí)行找到PCL后,將會創(chuàng)建環(huán)境變量PCL_INCLUDE_DIRS,其中包含指定PCL庫頭文件.h的查找路徑;
    # 創(chuàng)建環(huán)境變量PCL_LIBRARY_DIRS,其中包含指定PCL庫的.lib文件的所在目錄的路徑.
    # //REQUIRED表示如果沒有找到,cmake會停止處理,并報(bào)告一個錯誤.

    # 如果所要構(gòu)建的project還依賴于其它的package,例如python那么可以采用命令:find_package(PCL 1.8.0 REQUIRED COMPONENTS python),# 此時(shí)python將作為PCLpackage的組成成分,它所對應(yīng)的頭文件include路徑和lib庫文件路徑都將被# 一起包含在PCL的對應(yīng)環(huán)境變量PCL_INCLUDE_DIRS和PCL_LIBRARY_DIRS中,方便后面使用。# 同樣的,例如:find_package(PCL 1.8.0 REQUIRED COMPONENTS common io)//找到PCL1.8.0及以上的版本//REQUIRED表示找不到,cmake失敗//COMPONENTS表示對PCL模塊的要求 # 要求一個模塊:find_package(PCL 1.3 REQUIRED COMPONENTS io) # 要求多個模塊:find_package(PCL 1.3 REQUIRED COMPONENTS io common) # 要求所有模塊:find_package(PCL 1.3 REQUIRED)

    4、指定構(gòu)建project所需要的資源【 根據(jù)find_package結(jié)果進(jìn)行 】
    include_directories(${PCL_INCLUDE_DIRS})
    # 包含頭文件的位置。當(dāng)編譯一個需要第三方庫的項(xiàng)目時(shí),為了讓 cmake知道你在項(xiàng)目里包含的外部頭文件, 需使用include_directories()在–
    # --我們的PCL_INCLUDE_DIRS宏(完全包含了我們所需要的頭文件.h)中查找,讓cmake查找到它可能包含的頭文件。
    link_directories(${PCL_LIBRARY_DIRS})
    # 添加鏈接器的lib庫文件路徑,當(dāng)編譯一個需要第三方庫的項(xiàng)目時(shí),去哪找?guī)煳募?.so/.dll/.lib/.dylib/…)
    # 使用 link_directories,讓cmake在PCL_LIBRARY_DIRS宏中查找它可能包含的lib文件
    add_definitions(${PCL_DEFINITIONS})
    # 使用add_definitions 讓cmake在PCL_DEFINITIONS中找出它可能包含的預(yù)處理器定義和編譯器標(biāo)志

    # 除此之外也可以手動添加特殊路徑如:【對應(yīng)的頭文件與庫文件均需要添加】include_directories("G:/Matlab/extern/include")include_directories("C:/Program Files/MobileRobots/Aria/include")link_directories("G:/Matlab/extern/lib/win32/microsoft")link_directories("C:/Program Files/MobileRobots/Aria/lib")

    5、從指定源文件構(gòu)建可執(zhí)行文件
    add_executable (project_name cloud_viewer_PointXYZ.cpp)
    # 告訴cmake我們嘗試生成一個可執(zhí)行文件,從一個單一的源文件cloud_viewer_PointXYZ.cpp生成一個名字是project_name的可執(zhí)行文件。–
    –CMake會注意生成的后綴名suffix (.exe on Windows platform and blank on UNIX) and the permissions。
    # 該命令將從源文件cloud_viewer_PointXYZ.cpp構(gòu)建可執(zhí)行程序project_name.exe.
    # 如果從多個源文件構(gòu)建可執(zhí)行程序則可以表示成:
    add_executable (project_namemain.cpp test1.cpp test2.cpp)
    或者
    add_executable (project_namemain.cpp part.h grab.h interface.h test.cpp test.h)

    6、為project構(gòu)建library
    add_library(${project_name} ${${project_name}_src})#默認(rèn)創(chuàng)建共享library

    7、指定可執(zhí)行文件需要連接的庫 設(shè)置要鏈接的庫文件的名稱
    target_link_libraries (project_name ${PCL_LIBRARIES})#前一個參數(shù)為可執(zhí)行文件的名字
    target_link_libraries (project_name ${PCL_LIBRARIES} libeng.lib libmx.lib libmex.lib libmat.lib Aria.lib winmm.libwsock32.lib)
    # 我們生成的可執(zhí)行文件調(diào)用 PCL 函數(shù). 到現(xiàn)在, 我們只包含了PCL頭文件,所以編譯器知道我們調(diào)用的方法。–
    # --我們也需要讓連接器知道我們鏈接所依賴的庫文件。PCL通過使用PCL_LIBRARIES變量尋找相關(guān)庫文件,target_link_libraries()宏對可執(zhí)行文件與變量進(jìn)行鏈接。

    TARGET_LINK_LIBRARIES(${project_name}${MRPT_LIBS} # This is filled byFIND_PACKAGE(MRPT ...)"" # Optional extra libs... )

    總結(jié)

    以上是生活随笔為你收集整理的Cmakelist知识总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。