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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

cmake简明使用指南

發布時間:2025/4/16 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 cmake简明使用指南 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

cmake簡明使用指南

Last update 2018/8/8

先執行cmake生成makefile,然后看看里面的內容,(至少在ubuntu16.04上的cmake3.5.1上),有如下內容提供:

# Help Target help:@echo "The following are some of the valid targets for this Makefile:"@echo "... all (the default if no target is provided)"@echo "... clean"@echo "... depend"@echo "... edit_cache"@echo "... rebuild_cache"@echo "... net_demo"@echo "... src/net_demo.o"@echo "... src/net_demo.i"@echo "... src/net_demo.s" .PHONY : help

其中net_demo是我自己的build target,可以忽略。可以看到,提供了edit_cache選項,則通過make edit_cache可以交互式的修改一些變量,挺好的。

why this manual?

必須用cmake
很多開源項目如KDE、VTK、OpenCV、Caffe等,都使用cmake來構建。要玩轉這些項目,就需要掌握cmake。而且趨勢是cmake會更加流行。

實際情況往往是,系統預裝的opencv不夠用,嘗試編譯opencv的時候遇到cmake各種問題,被折騰的死去活來,于是決定好好學一下cmake。

cmake資料不夠好
cmake經歷了多個版本發展,現在(2017.05.05)它的官方文檔比原來有了很多進步。

現有的

小白視角
從一個cmake小白的角度來總結cmake的用法。

環境說明

cmake提供命令行方式,以及圖形界面方式(包括cmake-GUI和ccmake)。這里僅使用cmake命令行方式,因為更簡單直接。

使用ubuntu16.04, cmake3.5版。其他系統和cmake版本問題也都不大,因為本文盡量做到具備較好的通用性。

先確保安裝了gcc,g++和cmake

hello world

最簡單的cmake項目,不使用IDE(如CLion),也不考慮什么編碼風格的,就是干,簡單粗暴!

代碼

編輯兩個文件:main.cc和CMakeLists.txt。它們放在你的項目目錄,比如~/work/hello-cmake

main.cc

#include <iostream> using namespace std;int main(){cout << "Hello World!" << endl;return 0; }

CMakeLists.txt

cmake_minimum_required (VERSION 2.8) project(hello-world) add_executable(hello main.cc)

運行

開終端,運行這些命令:

cd ~/work/hello-cmake #進入你的cmake項目目錄 cmake . #執行cmake make #執行make

windows下的做法

可以用Visual Studio來編譯
假設C++代碼和CMakeLists.txt文件內容相同。那么打開cmd執行如下命令,或者把如下命令保存到一個文件(例如build.bat)中再執行這個文件:

# 在源碼相同目錄下構建 cmake -G "Visual Studio 14" #生成.sln文件 cmake --build . #調用native build tool。在windows上,相當于是打開.sln然后手動點擊構建。

或者在專門的文件夾里面編譯:

#當然,把編譯出來的東西單獨放到一個目錄也是OK的 mkdir build cd build cmake -G "Visual Studio 14" .. cmake --build . cd ..

以及,可以指定用Release模式,x64架構:

BUILD_DIR=build rm -rf $BUILD_DIR mkdir -p $BUILD_DIR cd $BUILD_DIRcmake \-G "Visual Studio 14 Win64" \..cmake --build . --config Release # 在windows上,必須在build的時候指定編譯類型,而不是cmake的階段

或者用Unix的構建工具套件,這里使用的是tdmgcc64。安裝之后把mingw32-make.exe復制一份為make.exe再執行

mkdir buildUnix cd buildUnix cmake -G "Unix Makefiles" .. make cd ..

必要的解釋

cmake命令會在提供的路徑(上例為".")下,找到CMakeLists.txt并執行它。執行成功后生成makefile(或其他類似的,目前階段就認為是makefile好了);執行make,會根據makefile內容去執行。

至于cmake和make執行了哪些操作,需要了解cmake的語法,以及makefile的編寫規則。有了cmake,其實可以忽略makefile,不妨認為makefile就是寫給編譯器gcc看的。

更便利的運行方式

通常cmake運行后產生若干文件,和源碼目錄混雜在一起并不是一個好的選擇。通常新建一個build目錄,在build目錄執行cmake。

個人傾向于建一個腳本,每次用cmake構建時,參數比較多,用這個腳本比較方便:

compile.sh

#!/bin/bashset -x #把本行后的腳本執行內容,打印到屏幕。用于調試 set -e #本行后,如果某行執行結果返回值不是true,那么終止LOG="log.build" touch $LOG rm $LOGexec &> >(tee -a "$LOG") #將屏幕輸出內容,同時寫入log文件:便于后續查找echo "Logging to $LOG"BUILD_ROOT=build if [ -d $BUILD_ROOT ]; thenrm -rf $BUILD_ROOT fi mkdir -p $BUILD_ROOT cd $BUILD_ROOT echo "building root folder is $BUILD_ROOT"echo "Now do cmake"cmake ..echo "Now do make"make -j8echo "Done"

執行構建腳本:

chmod +x compile.sh ./compile.sh cd build ./hello

cmake使用原理

自頂向下看,cmake執行的是給定路徑下的CMakeLists.txt,比如"."表示當前路徑,".."表示當前目錄的父目錄。

CMakeLists.txt中指定項目的輸入和輸出:
輸出:產生的可執行文件(或者庫文件?)
輸入:產生輸出所依賴的源文件(以及庫文件?)

CMakeLists.txt中通過cmake的語法編寫相應代碼語句,這些語句被cmake解釋執行。進而產生makefile,用make去執行就完成編譯。

cmake語法并不很復雜,往往翻看下cmake的官方手冊就能知道某個變量、命令、標準的各種細節了。

cmake官方文檔

遇到cmake指令看不懂,直接看文檔,基本上解決問題。

在線文檔

https://cmake.org/cmake/help/latest/

自行構建離線文檔

實在是忍受不了查看文檔時刷一個個網頁一直出不來結果的情況。自己動手豐衣足食。如果你網絡比較好,可以跳過這一節。

查看哪些apt包是cmake的文檔:

aptitude search cmake

結果顯示cmake-doc提供了文檔,cmake-data則是另一種形式的文檔。

安裝cmake及其文檔:

sudo apt install cmake cmake-doc cmake-data #安裝cmake文檔 dpkg -L cmake-doc #查看cmake-doc包安裝位置

發現是在/usr/share/doc/cmake-data目錄,它的馬甲目錄(鏈接)是/usr/share/doc/cmake-doc,那就開啟來好了:

cd /usr/share/doc/cmake-data/html python -m SimpleHTTPServer 4002 #用python開一個本地http服務器

瀏覽器訪問http://localhost:4002查看文檔。

“另一種形式的文檔”呢?在/usr/share/cmake-3.5/Help目錄,是.rst格式文檔,要用sphinx編譯:

sudo pip install sphinx #先確保裝了pip cd /usr/share/cmake-3.5/Help sudo sphinx-quickstart #按照提示來,唯一需要注意的是autogen選擇y。這一步生成makefile cd _build sudo make html #編譯生成html cd html python -m SimpleHTTPServer 4003

可以把上述開啟文檔的http服務器命令用tmux開啟。

查詢某個命令:http://10.10.10.53:4003/command/
查詢某個變量:http://10.10.10.53:4003/variable/
查詢某個手冊:http://10.10.10.53:4003/manual/
查詢某個模塊:http://10.10.10.53:4003/module/
查詢發行日志:http://10.10.10.53:4003/release/
查詢 policy :http://10.10.10.53:4003/policy/ 包含了各種cmake規范

find_package()的用法

先吐個槽

本來,直接查看手冊中find_package()一節即可。

鑒于現有一些博客對于find_package()這條命令介紹不夠好,比如這篇內容陳舊、不全面;比如這篇純粹是官方文檔翻譯,而官方文檔不夠突出重點,所以再羅嗦一小節的內容。

平時用cmake,遇到問題最多就是這個find_package()命令的使用導致的。最常見于尋找opencv包的情況。

這里噴一下opencv:要想用opencv各種特性,就要自行把opencv_contrib編譯進去。編譯時候還會出現各種3rdparty的包從github上無法下載要手動解決的問題,不方便。

find_package()是如何工作的

find_package():

先從CMAKE_MODULE_PATH變量表示的路徑下去找Find<name>.cmake文件;

如果失敗,則在CMAKE安裝目錄/share/cmake-x.y/Modules目錄下查找Find<name>.cmake文件

如果上一步失敗,則查找<Name>Config.cmake或者<lower-case-name>-config.cmake文件。按8大順序查找你想要的包,如果前一個里面找到了就不去后面的找,還可以通過變量關閉某個查找順序項

比如現在要找opencv的包。那么它的查找順序是(都是在尋找<Name>Config.cmake或者<lower-case-name>-config.cmake):

  • 在CMAKE_PREFIX_PATH變量所表示的路徑下尋找。
    換言之,CMAKE_PREFIX_PATH有最高的查找優先級。
    在find_package()參數列表中填寫NO_CMAKE_PATH則跳過該查找項。

  • 在cmake特有的環境變量中查找。包括:
  • <package>_DIR CMAKE_PREFIX_PATH CMAKE_FRAMEWORK_PATH CMAKE_APPBUNDLE_PATH

    對于OpenCV,就是OpenCV_DIR了。
    在find_package()參數列表中填寫NO_CMAKE_ENVIRONMENT_PATH跳過該查找項。

  • find_package()的HINTS參數指定

  • 系統環境變量PATH里尋找。
    在find_package()參數列表中填寫NO_SYSTEM_ENVIRONMENT_PATH跳過該查找項。

  • 搜索在CMake GUI中最新配置過的工程的構建樹。在find_package()參數列表中填寫NO_CMAKE_BUILDS_PATH跳過該查找項。

  • 搜索存儲在CMake用戶包注冊表(User Package Registry)中的路徑。
    在find_package()參數列表中填寫NO_CMAKE_PACKAGE_REGISTRY或者設定CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY變量值為TRUE跳過該查找項。(似乎Linux下沒啥用!)
    (update@2018-07-31 00:47:33 今天被這個User Package Registry坑慘了!具體實例和解決方法看SO上的一個問答:how-to-avoid-cmake-to-read-in-its-system-cache-home-cmake。簡單說,Caffe的cmake腳本中有一句export Caffe,這會向User Package Registry寫東西,在ubuntu下的表現就是在~/.cmake/package/Caffe路徑下寫入一個文件,文件名字是一個hash值,文件內容是cmake編譯的caffe的路徑。一旦有多個版本的caffe存在并且都用了cmake編譯,而如果前面1~5的設置路徑有錯誤,那么就加載這個~/.cmake/package/Caffe/xxx文件中的路徑。很坑!)

  • 搜索在當前系統的平臺文件中定義的cmake變量:
  • CMAKE_SYSTEM_PREFIX_PATH CMAKE_SYSTEM_FRAMEWORK_PATH CMAKE_SYSTEM_APPBUNDLE_PATH

    在find_package()參數列表中填寫NO_CMAKE_SYSTEM_PATH選項跳過這些路徑。
    注意 這里測試發現,CMAKE_SYSTEM_PREFIX_PATH是/usr/local;/usr;/;/usr;/usr/local,如果前面的查找順序項都失敗或者被關閉了,那么在這一查找項上,會在/usr/local這樣的路徑下,查找opencv開頭的目錄,比如/usr/local/opencv-git-master會被找到;而假如我把opencv的路徑換成不以opencv開頭,比如/usr/local/what-opencv則不能找到opencv。

  • find_package()參數列表中用PATHS指定搜索路徑。這些路徑一般是硬編碼的參考路徑。。。。(太長而且個人覺得沒啥用,想看的去找手冊好了)
  • 寫了這么多查找順序,其實就記住一個好了,先設定定CMAKE_PREFIX_PATH變量,再用find_package()去找包,保證萬事大吉:

    list(APPEND CMAKE_PREFIX_PATH "/opt/opencv-git-master") #引號里是我的opencv安裝路徑 find_package(OpenCV)

    成功查找到包后,產生這些變量嗎?
    按照cmake手冊的說法,find_package()執行后會產生幾個變量:

    _FOUND
    _INCLUDE_DIRS 或者 _INCLUDES
    _LIBRARIES 或者 _LIBS
    _DEFINITIONS

    但嘗試找opencv的包時,無論是apt裝的opencv還是自行編譯的opencv,都是一樣:并非這幾個變量都有值:

    CMAKE_MODULE_PATH is:
    -- Found OpenCV: /usr/local/opencv-git-master (found version "3.2.0")
    OpenCV_FOUND is : 1
    OpenCV_INCLUDE_DIRS is : /usr/local/opencv-git-master/include;/usr/local/opencv-git-master/include/opencv
    OpenCV_INCLUDES is :
    OpenCV_LIBRARIES is opencv_calib3d;opencv_core;opencv_features2d;opencv_flann;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_shape;opencv_stitching;opencv_superres;opencv_video;opencv_videoio;opencv_videostab;opencv_aruco;opencv_bgsegm;opencv_bioinspired;opencv_ccalib;opencv_datasets;opencv_dnn;opencv_dnn_modern;opencv_dpm;opencv_face;opencv_freetype;opencv_fuzzy;opencv_hdf;opencv_line_descriptor;opencv_optflow;opencv_phase_unwrapping;opencv_plot;opencv_reg;opencv_rgbd;opencv_saliency;opencv_stereo;opencv_structured_light;opencv_surface_matching;opencv_text;opencv_tracking;opencv_xfeatures2d;opencv_ximgproc;opencv_xobjdetect;opencv_xphoto
    OpenCV_LIBS is : opencv_calib3d;opencv_core;opencv_features2d;opencv_flann;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_shape;opencv_stitching;opencv_superres;opencv_video;opencv_videoio;opencv_videostab;opencv_aruco;opencv_bgsegm;opencv_bioinspired;opencv_ccalib;opencv_datasets;opencv_dnn;opencv_dnn_modern;opencv_dpm;opencv_face;opencv_freetype;opencv_fuzzy;opencv_hdf;opencv_line_descriptor;opencv_optflow;opencv_phase_unwrapping;opencv_plot;opencv_reg;opencv_rgbd;opencv_saliency;opencv_stereo;opencv_structured_light;opencv_surface_matching;opencv_text;opencv_tracking;opencv_xfeatures2d;opencv_ximgproc;opencv_xobjdetect;opencv_xphoto
    OpenCV_DEFINITIONS is :
    ```

    引用第三方庫

    比如讀取jpeg圖像,并轉化到Lab空間以及灰度圖像。使用到opencv庫,利用find_package()進行查找。代碼如下:

    main.cc

    #include <iostream> #include <opencv2/opencv.hpp>using cv::Mat; using cv::imread; using cv::imshow; using cv::waitKey; using cv::cvtColor; using cv::COLOR_BGR2Lab; using cv::COLOR_BGR2GRAY;int main(){// Load imageMat srcImage = imread("cat.jpg", -1);Mat dstImage;imshow("RGB Space", srcImage);// Convert to other color spacecvtColor(srcImage, dstImage, COLOR_BGR2Lab);imshow("Lab Space", dstImage);cvtColor(srcImage, dstImage, COLOR_BGR2GRAY);imshow("Gray Scale", dstImage);waitKey();return 0; }

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.2)project(hello-cmake)list(APPEND CMAKE_PREFIX_PATH "/usr/share/OpenCV") # apt裝的opencv #list(APPEND CMAKE_PREFIX_PATH "/usr/local/opencv-git-master") #自行編譯的opencv message("CMAKE_MODULE_PATH is: ${CMAKE_MODULE_PATH}") find_package(OpenCV#NO_CMAKE_PATH#NO_CMAKE_ENVIRONMENT_PATH#NO_SYSTEM_ENVIRONMENT_PATH#NO_CMAKE_PACKAGE_REGISTRY#NO_CMAKE_SYSTEM_PATH) message("OpenCV_FOUND is : ${OpenCV_FOUND}") message("OpenCV_INCLUDE_DIRS is : ${OpenCV_INCLUDE_DIRS}") message("OpenCV_INCLUDES is : ${OpenCV_INCLUDES}") message("OpenCV_LIBRARIES is ${OpenCV_LIBRARIES}") message("OpenCV_LIBS is : ${OpenCV_LIBS}") message("OpenCV_DEFINITIONS is : ${OpenCV_DEFINITIONS}")add_executable(hello main.cc)target_link_libraries(hello ${OpenCV_LIBS})

    build.sh

    #!/bin/bashset -x set -eLOG="log.build" touch $LOG rm $LOGexec &> >(tee -a "$LOG")echo "Logging to $LOG"BUILD_ROOT=build if [ -d $BUILD_ROOT ]; thenrm -rf $BUILD_ROOT fimkdir -p $BUILD_ROOT cd $BUILD_ROOTecho "building root folder is $BUILD_ROOT"echo "Now do cmake" cmake ..make -j8echo "Done"

    編寫自己的庫

    利用add_library()生成庫文件。

    main.cc

    #include <iostream> using namespace std;void smile(){cout << "Nice smile" << endl; }

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.2)message("BUILD_SHARED_LIBS is ${BUILD_SHARED_LIBS}") #set(BUILD_SHARED_LIBS ON) # 設定BUILD_SHARED_LIBS來表示add_library構建共享庫(shared)還是靜態庫(static) message("BUILD_SHARED_LIBS is ${BUILD_SHARED_LIBS}")add_library(smile STATIC main.cc) #不過,add_library()顯示地設定SHARED和STATIC,更直觀

    build.sh
    其實每次我的build.sh都是一樣的:)

    #!/bin/bashset -x set -eLOG="log.build" touch $LOG rm $LOGexec &> >(tee -a "$LOG")echo "Logging to $LOG"BUILD_ROOT=build if [ -d $BUILD_ROOT ]; thenrm -rf $BUILD_ROOT fimkdir -p $BUILD_ROOT cd $BUILD_ROOTecho "building root folder is $BUILD_ROOT"echo "Now do cmake" cmake ..make -j8echo "Done"

    現在,自己的庫寫好了,怎么用呢?一種方法是make install,另一種方法是提供配置文件,比如mylibrary-config.cmake這種,后者需要配合.cmake.in文件進行生成,可以參考官方wiki:https://cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file

    ===================
    2018年8月16日 20點46分
    這里插播一個實際遇到的情況,挺有意思,領教了CMAKE_CXX_COMPILER變量的厲害(采坑)
    小伙伴的ubuntu上要編譯Caffe,官方源碼下載后用CMake構建,到95%左右,convert_mnist_siamse_data.o這里會報錯,說DSO Missing,具體指向的是libcstdc++.
    開始時百思不得其解,因為查看g++和cmake,以及protobuf什么的,都是apt裝的或者系統自帶的,為啥缺庫呢。
    后來有人指出是鏈接階段沒有鏈接libstdc++.so.6。但是為啥要明確鏈接它?
    我的Debug方法:利用message( )函數(相當于C/C++里的printf( ))暴力輸出各種鏈接庫的名字,還是不能發現問題,逐步溯源到CMake的輸出,發現CMAKE_CXX_COMPILER這個變量的取值出了問題。

    CMAKE_CXX_COMPILER
    CXX這個環境變量被設定了,設定的值為/usr/bin/gcc-5
    CMake會讀取這個$CXX 然后設定CMAKE_CXX_COMPILER為這個值,也就是用gcc-5替代了g++
    所以后續編譯的話都缺少stdc++這個庫
    在終端里,unset CXX,或者把你的bashrc/zshrc里面的export CXX=/usr/bin/gcc-5注釋掉并退出重新進入shell,就可以正常使用CMAKE_CXX_COMPILER這一變量來編譯Caffe了。

    cmake變量

    這篇寫的還可以:https://chaopei.github.io/blog/2018/10/cmake-variable.html

    這篇更詳細一些:https://riptutorial.com/zh-CN/cmake/example/11821/變量和全局變量緩存

    如果希望cmake -Dvar=value的方式,臨時設定變量的值,則必須用set(VAR "some value" CACHE STRING "ignore this" [FORCE])的方式

    轉載于:https://www.cnblogs.com/zjutzz/p/6815342.html

    總結

    以上是生活随笔為你收集整理的cmake简明使用指南的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 成人欧美一区二区三区黑人免费 | 免费观看视频在线观看 | 国产三级按摩推拿按摩 | 三级在线观看网站 | 日韩欧美一二区 | 污漫网站| 永久免费在线视频 | 国产精品69久久 | 涩涩国产 | 久久久久99精品国产片 | 亚洲精品国产欧美在线观看 | 精品日韩一区二区三区 | 欧美一区二区福利 | 插我一区二区在线观看 | 99re这里只有精品首页 | 婷婷天堂网 | 国产亚洲精品久久久久久无几年桃 | 777精品| 日韩污视频在线观看 | 深夜精品视频 | 欧美精品激情视频 | 99re8在线精品视频免费播放 | 午夜黄色网 | 国产爆乳无码一区二区麻豆 | 精品午夜福利视频 | 麻豆一区二区三区四区 | 97精品国产97久久久久久免费 | 婷婷中文字幕在线 | 高清三区 | 波多野结衣中文字幕一区 | 中文字幕不卡在线观看 | 日韩成人片 | 国产一区二区三区久久 | 欧美骚少妇 | 一个人看的www片免费高清中文 | 全部毛片永久免费看 | 午夜偷拍视频 | 精品午夜一区二区 | 最全aⅴ番号库 | 久久av喷吹av高潮av萌白 | 国产性按摩| 欧美在线视频一区二区 | 亚洲视频中文 | 在线视频啪 | 片黄在线观看 | 欧美性爱精品在线 | 黑人番号 | 久久涩视频 | 精品久久人妻av中文字幕 | 成人三级视频 | 国产aaa视频 | 精品黑人一区二区三区国语馆 | 制服.丝袜.亚洲.中文.综合懂色 | 亚洲日本va中文字幕 | 国产精品美女久久久久图片 | 我爱52av| 亚洲看片 | 黄色一级片在线播放 | 国产精品毛片av | 国产精品福利一区 | 国外成人性视频免费 | 亚洲精品中文字幕 | 九七在线视频 | 动漫玉足吸乳羞免费网站玉足 | 色翁荡息又大又硬又粗又爽 | 国产综合激情 | 国产成人免费在线 | 人人爱爱人人 | 日韩免费看片 | 国产精品美女毛片真酒店 | 欧美福利视频一区二区 | 性色视频 | 中文字幕一区二区三区日韩精品 | av一区在线播放 | 亚洲国产精品欧美久久 | 久久久96 | 91香蕉一区二区三区在线观看 | 国产视频精品免费 | 最近日本中文字幕 | 日本美女性高潮 | 亚州色图欧美色图| 亚洲乱码国产乱码精品精大量 | 亚洲精品乱码久久久久久自慰 | 国产思思| 欧美另类视频 | 欧美精品久久久久久久久 | 国产毛片3 | 国产三级中文字幕 | 日韩精品人妻一区 | 国产精品一区二区三区不卡 | 成人在线免费观看网站 | 日韩黄色在线播放 | 精品国产乱码久久久久久婷婷 | 岛国av毛片| av一区二区免费 | 久久日本视频 | 免费看欧美成人a片无码 | 国产女同91疯狂高潮互磨 | 女人裸体免费网站 |