CMake指令入門 ——以構建OpenCV項目為例

CMake指令入門 ——以構建OpenCV項目為例

轉自:https://blog.csdn.net/sandalphon4869/article/details/100589747

一、安裝

sudo apt-get install cmake

安裝好后,輸入

cmake -version

如果出現了cmake的版本顯示,那么說明安裝成功

二、cmake編譯

cmake的作用就是將在IDE編譯器中的編譯功能拿出來,可以在終端上完成。類似于vim和文本編輯器。

cmake的編譯方式:

  • 內部構建(in-source-build)

  • 外部構建(out-of-source-build)

兩者的區別僅僅是前者將生成的編譯文件和源代碼、CMakeLists.txt 混雜在一起,后者就只是創建了一個文件夾 build 存儲生成的編譯文件,更好刪除編譯生成的文件而已(直接刪文件夾)。

三、語法

1. 基本語法

  • 指令是大小寫無關的,參數和變量是大小寫相關的。但推薦你全部使用大寫指令。

  • 變量使用 ${}方式取值,但是在 IF 控制語句中是直接使用變量名。如:${SRC_LIST}

  • 指令(參數 1 參數 2…) 參數使用括弧括起,參數之間使用空格或分號分開。

    如:ADD_EXECUTABLE(hello main.c func.c) 或者 ADD_EXECUTABLE(hello main.c;func.c)

  • 注釋:# comment

2. 指令

搞清當前目錄的意思:

  • CMakeLists.txt 中的 . 表示當前目錄是CMakeLists.txt文件所在的目錄,而非執行時終端的當前目錄。

  • cmake . 這條終端命令是執行時終端的當前目錄。

(1) PROJECT()

PROJECT(projectname [CXX] [C] [Java])

總結:定義工程名稱,并可指定工程支持的語言。

  • 定義工程名稱:如 PROJECT(HELLO) ,那么工程的名稱就是 HELLO

  • 支持的語言列表:支持的語言列表是可以忽略的, 默認情況表示支持所有語言。
    如指定C++:PROJECT(HELLO CXX)

  • 這個指令隱式的定義了四個 cmake 變量:

    • <projectname>_BINARY_DIR 以及 <projectname>_SOURCE_DIR(格式,并非實際的變量)。對于這個工程就是 HELLO_BINARY_DIRHELLO_SOURCE_DIR (之后就可以直接使用了這兩個變量),使用 <projectname>_BINARY_DIR 這個是無效的。
      PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 變量。
    • 他們的值分別跟 HELLO_BINARY_DIRHELLO_SOURCE_DIR 一致。區別是這兩個會自動根據工程名字的變化而變化。
    • 建議以后直接使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR,即使修改了工程名稱,也不會影響這兩個變量。如:從HELLO該為WORLD,那么前者就得寫成WORLD_BINARY_DIRWORLD_SOURCE_DIR,但后者還是 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR

(2) CMAKE_MINIMUM_REQUIRED()

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

cmake最低版本

(3) SET()

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

作用:定義變量的值

比如:

  • 如果有多個源文件,也可以定義成:SET(SRC_LIST main.c t1.c t2.c)

  • 可以用 "" 來處理包含空格的文件名:SET(SRC_LIST "hello world.cpp")(建議使用方式)

  • 使用c++11特性:set(CMAKE_CXX_FLAGS "${CAMKE_CXX_FLAGS} -std=c++11"),防止出現因為c++11才有的編譯錯誤,比如 error: ‘to_string’ is not a member of ‘std’

  • 設置編譯模式 Build Type,要加引號,不加可能報錯。

    • Debug模式:set(CMAKE_BUILD_TYPE "Debug")
    • Release模式:set(CMAKE_BUILD_TYPE "Release"),更快。

(4) MESSAGE()

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display")

作用:在cmake編譯過程中向終端輸出用戶定義的信息。

三種信息類型:

  • SEND_ERROR:產生錯誤,生成過程被跳過

  • STATUS:輸出前綴為 -- 的信息。

  • FATAL_ERROR:立即終止所有 cmake 過程

輸出內容:"hello ${<variant name>}"

比如:

PROJECT(HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "The value of HELLO_SOURCE_DIR is${HELLO_SOURCE_DIR}" )
ADD_EXECUTABLE(hello ${SRC_LIST})

輸出:

...
The value of HELLO_SOURCE_DIR is/home/song/code
...

ps:引號的作用是保留空格

  • "hello world ${HELLO_SOURCE_DIR}":輸出為 hello world /home

  • hello world ${HELLO_SOURCE_DIR}:輸出為 helloworld/home

(5) AUX_SOURCE_DIRECTORY()

①基本含義

AUX_SOURCE_DIRECTORY(dir VARIABLE)

作用是發現一個目錄 dir 下所有的源代碼文件并將列表存儲在一個變量中,這個指令臨時被用來自動構建源文件列表。因為目前 cmake 還不能自動發現新添加的源文件。 (本目錄為CMakeLists.txt所在的目錄)

比如:

AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(main ${SRC_LIST})

將本目錄下的源代碼文件添加到SRC_LIST變量中,再將這些文件編譯成生成文件。

②子目錄

注意:如果本目錄下有子目錄,是不會將子目錄下的源代碼文件添加進去的,得手動打出來。比如:

# 本目錄下的子目錄subDir
AUX_SOURCE_DIRECTORY(./subDir SRC_LIST)

③可添加多個

這兩個一起添加進入 SRL_LIST,并不是后者覆蓋前者。

AUX_SOURCE_DIRECTORY(./src/text SRC_LIST)
AUX_SOURCE_DIRECTORY(./src/serial SRC_LIST)

(6) ADD_SUBDIRECTORY

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

這個指令用于向當前工程添加存放源文件的子目錄,并可以指定中間二進制和目標二進制存放的位置。

EXCLUDE_FROM_ALL參數的含義:將這個目錄從編譯過程中排除,比如,工程 的 example,可能就需要工程構建完成后,再進入 example 目錄單獨進行構建(當然,你 也可以通過定義依賴來解決此類問題)。

比如:

將 src 子目錄加入工程,并指定編譯輸出(包含編譯中間結果)路徑為bin 目錄。

(7) FIND_PACKAGE()

FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] 
[[REQUIRED|COMPONENTS] [componets...]])

參數:

REQUIRED 參數:如果使用了這個參數,說明這 個鏈接庫是必備庫,如果找不到這個鏈接庫,則工程不能編譯。

功能:只找一個名為 name 的包(后面都是修飾條件),所以如果要找多個包,要分多個FIND_PACKAGE() 寫。

比如:

  • OpenCV3:

    find_package(OpenCV REQUIRED)
    
  • ROS:

    find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)
    

(8) INCLUDE_DIRECTORIES()

include_directories()

功能:鏈接頭文件

描述:可以將要鏈接的頭文件都寫在括號里,不用分成多個 INCLUDE_DIRECTORIES()寫。

比如:

  • OpenCV3:${OpenCV_INCLUDE_DIRS}
  • ROS:${catkin_INCLUDE_DIRS}
include_directories(${OpenCV_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

(9) ADD_EXECUTABLE()

ADD_EXECUTABLE(hello ${SRC_LIST})

生成可執行文件。

  • 相關的源文件是SRC_LIST 中 定義的源文件列表, 你也可以直接寫成ADD_EXECUTABLE(hello main.c ti.c)

  • 可以寫成 ADD_EXECUTABLE(hello main) cmake 會自動的在本目錄查找 main.c 或者 main.cpp等,當然,最好不要偷這個懶,以免這個目錄確實存在一個 main.c 和一個 main.cpp

  • hello是最終要執行的可執行文件:./hello

(10) TARGET_LINK_LIBRARIES()

TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2...)

功能:這個必須寫ADD_EXECUTABLE() 之后,為生成文件target添加庫。

比如:

  • OpenCV3:${OpenCV_LIBS}
  • ROS:${catkin_LIBRARIES}

3. 總結

添加文件的方式

  • 手動添加:set()

    SET(SRC_LIST "main.cpp forest.hpp")
    ADD_EXECUTABLE(main ${SRC_LIST})
    
  • 自動添加:AUX_SOURCE_DIRECTORY()

    AUX_SOURCE_DIRECTORY(. SRC_LIST)
    ADD_EXECUTABLE(main ${SRC_LIST})
    

四、構建OpenCV項目

項目結構

為了使整個項目更加條理,我們的文件夾采用如下組織方式:

bin
build
src
CMakeLists.txt

其中bin目錄用于放編譯生成的可執行文件,build目錄用于cmake構建項目,src用于放源代碼。

OpenCV源文件

下面是我們寫的一個OpenCV示例代碼:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>using namespace std;
using namespace cv;int main(int argc, char** argv)
{if (argc != 2){cout << "Usage: opencv_test <image path>" << endl;return -1;}char *imgName = argv[1];Mat image;image = imread(imgName, 1);if (!image.data){cout << "No image data" << endl;return -1;}Mat gray_img;cvtColor(image, gray_img, CV_BGR2GRAY);imwrite("images/result.jpg", gray_img);return 0;
}

這是一個很簡單的例子:讀取圖片然后轉化成灰度圖。

編寫CMakeLists.txt

CMake文件的文件名CMakeLists.txt有嚴格的大小寫要求,注意不要寫錯。

# project name
PROJECT(HELLO)# using C++11
set(CMAKE_CXX_FLAGS "${CAMKE_CXX_FLAGS} -std=c++11 ")# cmake version
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)# find OpenCV
FIND_PACKAGE(OpenCV REQUIRED)# show the message of OpenCV
message(STATUS "OpenCV library status:")
message(STATUS "    version: 	${OpenCV_VERSION}")
message(STATUS "    headers: 	${OpenCV_INCLUDE_DIRS}")
message(STATUS "    libraries: 	${OpenCV_LIBS}")# link headers
INCLUDE_DIRECTORIES({OpenCV_INCLUDE_DIRS})# 添加源代碼文件到SRC_LIST變量中
AUX_SOURCE_DIRECTORY(. SRC_LIST)# 生成可執行文件
ADD_EXECUTABLE(hello ${SRC_LIST})# after ADD_EXECUTABLE,為生成文件target添加庫
TARGET_LINK_LIBRARIES(hello ${OpenCV_LIBS})

PROJECT指令的語法是:

PROJECT(projectname [CXX] [C] [Java])

你可以用這個指令定義工程名稱,并可指定工程支持的語言,支持的語言列表是可以忽略的,這個指令隱式的定義了兩個cmake變量: <projectname>_BINARY_DIR 以及<projectname>_SOURCE_DIR。前者指構建路徑,后者指工程路徑,即 CMakeLists.txt 所在的路徑。

同時cmake系統也幫助我們預定義了 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 變量,他們的值分別跟 opencv_test_BINARY_DIRopencv_test_SOURCE_DIR 一致。

為了統一起見,建議以后直接使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR,即使修改了工程名稱,也不會影響這兩個變量。如果使用了<projectname>_SOURCE_DIR,修改工程名稱后,需要同時修改這些變量。

接下來是設置cmake要求的最低版本號:

cmake_minimum_required(VERSION 3.5)

SET指令的語法是:

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

現階段,你只需要了解SET指令可以用來顯式的定義變量即可。這里我們將變量CMAKE_RUNTIME_OUTPUT_DIRECTORY定義為${opencv_test_SOURCE_DIR}/bin也就是工程路徑下的bin目錄。

下面介紹一個很重要的指令:find_package 這個指令以被用來在系統中自動查找配置構建工程所需的程序庫。在linux和unix類系統下這個命令尤其有用。CMake自帶的模塊文件里有大半是對各種常見開源庫的 find_package 支持,支持庫的種類非常多。

當它找到OpenCV程序庫之后,就會幫助我們預定義幾個變量,OpenCV_FOUNDOpenCV_INCLUDE_DIRSOpenCV_LIBRARY_DIRSOpenCV_LIBRARIES,它們分別指是否找到OpenCV,OpenCV的頭文件目錄,OpenCV的庫文件目錄,OpenCV的所有庫文件列表。接著我們就可以使用這些變量來配置了:

include_directories(${OpenCV_INCLUDE_DIRS})

上面這個指令用來設置包含的頭文件的路徑。

link_directories(${OpenCV_LIBRARY_DIRS})

上面這個指令用來設置庫文件的路徑。

target_link_libraries(opencv_test ${OpenCV_LIBS})

上面這個指令用來設置需要的庫文件,它的語法是:

TARGET_LINK_LIBRARIES(target library1<debug | optimized> library2...)

其中的target就是前面設置生成的目標文件(可執行文件):

add_executable(opencv_test src/opencv_test.cpp)

這個命令很好理解,首先是可執行文件的名字,然后是源碼的名字。因此,這個命令一定要在TARGET_LINK_LIBRARIES之前使用。

現在我們的CMakeLists.txt就介紹完了。

構建項目并運行

mkdir build && cd build
cmake ..
make
# 至此構建完成,下面運行
./opencv_test

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/532566.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/532566.shtml
英文地址,請注明出處:http://en.pswp.cn/news/532566.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CVE-2017-7529Nginx越界讀取緩存漏洞POC

漏洞影響 低危&#xff0c;造成信息泄露&#xff0c;暴露真實ip等 實驗內容 漏洞原理 通過查看patch確定問題是由于對http header中range域處理不當造成&#xff0c;焦點在ngx_http_range_parse 函數中的循環&#xff1a; HTTP頭部range域的內容大約為Range: bytes4096-81…

Linux命令行性能監控工具大全

Linux命令行性能監控工具大全 作者&#xff1a;Arnold Lu 原文&#xff1a;https://www.cnblogs.com/arnoldlu/p/9462221.html 關鍵詞&#xff1a;top、perf、sar、ksar、mpstat、uptime、vmstat、pidstat、time、cpustat、munin、htop、glances、atop、nmon、pcp-gui、collect…

Weblogic12c T3 協議安全漏洞分析【CVE-2020-14645 CVE-2020-2883 CVE-2020-14645】

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 關注公眾號&#xff1a;b1gpig信息安全&#xff0c;文章推送不錯過 ## 前言 WebLogic是美國Oracle公司出品的一個application server,確切的說是一個基于JAV…

Getshell總結

按方式分類&#xff1a; 0x01注入getshell&#xff1a; 0x02 上傳 getwebshell 0x03 RCE getshell 0x04 包含getwebshell 0x05 漏洞組合拳getshell 0x06 系統層getcmdshell 0x07 釣魚 getcmdshell 0x08 cms后臺getshell 0x09 紅隊shell競爭分析 0x01注入getshell&#xff1a;…

編寫可靠bash腳本的一些技巧

編寫可靠bash腳本的一些技巧 原作者&#xff1a;騰訊技術工程 原文鏈接&#xff1a;https://zhuanlan.zhihu.com/p/123989641 寫過很多 bash 腳本的人都知道&#xff0c;bash 的坑不是一般的多。 其實 bash 本身并不是一個很嚴謹的語言&#xff0c;但是很多時候也不得不用。以下…

python 到 poc

0x01 特殊函數 0x02 模塊 0x03 小工具開發記錄 特殊函數 # -*- coding:utf-8 -*- #內容見POC.demo; POC.demo2 ;def add(x,y):axyprint(a)add(3,5) print(------------引入lambad版本&#xff1a;) add lambda x,y : xy print(add(3,5)) #lambda函數,在lambda函數后面直接…

protobuf版本常見問題

protobuf版本常見問題 許多軟件都依賴 google 的 protobuf&#xff0c;我們很有可能在安裝多個軟件時重復安裝了多個版本的 protobuf&#xff0c;它們之間很可能出現沖突并導致在后續的工作中出現版本不匹配之類的錯誤。本文將討論筆者在使用 protobuf 中遇到的一些問題&#…

CMake常用命令整理

CMake常用命令整理 轉自&#xff1a;https://zhuanlan.zhihu.com/p/315768216 CMake 是什么我就不用再多說什么了&#xff0c;相信大家都有接觸才會看一篇文章。對于不太熟悉的開發人員可以把這篇文章當個查找手冊。 1.CMake語法 1.1 指定cmake的最小版本 cmake_minimum_r…

CVE-2021-41773 CVE-2021-42013 Apache HTTPd最新RCE漏洞復現 目錄穿越漏洞

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; CVE-2021-41773漏洞描述&#xff1a; Apache HTTPd是Apache基金會開源的一款流行的HTTP服務器。2021年10月8日Apache HTTPd官方發布安全更新&#xff0c;披…

SSRF,以weblogic為案例

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 復習一下ssrf的原理及危害&#xff0c;并且以weblog的ssrf漏洞為案例 漏洞原理 SSRF(Server-side Request Forge, 服務端請求偽造) 通常用于控制web進而…

C++11 右值引用、移動語義、完美轉發、萬能引用

C11 右值引用、移動語義、完美轉發、引用折疊、萬能引用 轉自&#xff1a;http://c.biancheng.net/ C中的左值和右值 右值引用可以從字面意思上理解&#xff0c;指的是以引用傳遞&#xff08;而非值傳遞&#xff09;的方式使用 C 右值。關于 C 引用&#xff0c;已經在《C引用…

C++11 std::function, std::bind, std::ref, std::cref

C11 std::function, std::bind, std::ref, std::cref 轉自&#xff1a;http://www.jellythink.com/ std::function 看看這段代碼 先來看看下面這兩行代碼&#xff1a; std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::function<void(Ev…

Java安全(一) : java類 | 反射

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 1.java基礎 Java平臺共分為三個主要版本Java SE&#xff08;Java Platform, Standard Edition&#xff0c;Java平臺標準版&#xff09;、Java EE&#xff0…

LeetCode-287 尋找重復數 二分法

LeetCode-287 尋找重復數 二分法 287. 尋找重復數 給定一個包含 n 1 個整數的數組 nums &#xff0c;其數字都在 1 到 n 之間&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一個重復的整數。 假設 nums 只有 一個重復的整數 &#xff0c;找出 這個重復的數 。…

對某公司一次弱口令到存儲型xss挖掘

轉自我的奇安信攻防社區文章:https://forum.butian.net/share/885 免責聲明: 滲透過程為授權測試,所有漏洞均以提交相關平臺,博客目的只為分享挖掘思路和知識傳播** 涉及知識: xss注入及xss注入繞過 挖掘過程: 某次針對某目標信息搜集無意發現某工程公司的項目招標平臺 …

C++11新特性選講 語言部分 侯捷

C11新特性選講 語言部分 侯捷 本課程分為兩個部分&#xff1a;語言的部分和標準庫的部分。只談新特性&#xff0c;并且是選講。 本文為語言部分筆記。 語言 Variadic Templatesmove semanticsautoRange-based for loopInitializer listLambdas… 標準庫 type_traitsunodered…

java安全(二):JDBC|sql注入|預編譯

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 1 JDBC基礎 JDBC(Java Database Connectivity)是Java提供對數據庫進行連接、操作的標準API。Java自身并不會去實現對數據庫的連接、查詢、更新等操作而是通…

java安全(三)RMI

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 1.RMI 是什么 RMI(Remote Method Invocation)即Java遠程方法調用&#xff0c;RMI用于構建分布式應用程序&#xff0c;RMI實現了Java程序之間跨JVM的遠程通信…

LeetCode-726 原子的數量 遞歸

LeetCode-726 原子的數量 遞歸 題目鏈接&#xff1a;LeetCode-726 原子的數量 給你一個字符串化學式 formula &#xff0c;返回 每種原子的數量 。 原子總是以一個大寫字母開始&#xff0c;接著跟隨 0 個或任意個小寫字母&#xff0c;表示原子的名字。 如果數量大于 1&#xf…

java安全(四) JNDI

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 1.JNDI JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目錄接口。通過調用JNDI的API應用程序可以定位資源和其他程序對象。JNDI是Java…