本文的對應代碼可在此處下載
http://download.csdn.net/detail/gh_home/9633641
cmake 命令與visual studio的對應
cmake | visual studio |
---|---|
PROJECT(name) | 解決方案名稱 name |
ADD_EXECUTABLE(name ${SRC_LIST}) | 工程名稱 生成exe名稱 name |
設置cmake的編譯器
- 首先使用 cmake -help獲取cmake支持的編譯器
- 運行 cmake -G “Visual Studio 12 2013 Win64” 設定好
外部構建
如果cpp文件和CmakeLists.txt文件在同一文件夾下,在此文件夾下運行
cmake .
這樣所有cmake產生的編譯文件都在此文件夾下,和我們的源文件混在一起,爲了避免這種情況,我們需要在CmakeList文件夾下新建一個build文件夾,進入此文件夾,運行
cmake ..
這樣,所有編譯產生的文件都會在build文件夾下了
正規的源代碼目錄
- 所有的源代碼文件放入src文件夾
- 生成的目標文件exe 放入bin文件夾
- 對於工程項目的接口及說明文件放入doc文件夾
- 對於項目所調用的外部lib文件放入lib文件夾
- 對於項目的功能性描述放入README.md
- 對於項目的exe的示例調用寫一個.bat或者.sh文件放出來
- 寫明CopyRight文件
- 對於項目的構建,文件結構,調用關係放在CmakeLists.txt中,以方便之後調用
- 附加: 其實還可以建立一個文件夾爲build用於存放編譯工程產生的中間文件,但是這個文件夾在發佈的時候是要刪除的
關於生成的visual studio項目結構
- 首先要配置管理器,要求這三個項目都生成
- 在我們的executable工程即OPENCV_CMAKE_EXE工程上右鍵,選擇設爲啓動項目,這樣ctr+F5就可以運行我們生成的exe了
- 以上三個項目的作用:我們可以通過點擊解決方案OPENCV_CMAKE,查看項目依賴項,會發現:
- 所有的項目都會依賴於ZERO_CHECK這個項目
- ALL_BUILD會依賴所有的項目,這是爲了我們在每一個execuable後都會生成一個項目,有時候我們更改了某幾個項目,但是又不方便每次都記住是哪些項目發生了更改,這樣我們就可以直接通過生成ALL_BUILD來更新所有的更改項目以及與更改有關的(附加依賴)的項目
將源碼文件放在src文件夾編譯怎麼做?
首先,所有要編譯的文件夾下都需要有一個CMakeLists.txt,因此我們這裏會寫兩個CMakeLists.txt,一個用於CMake的工程,這個相當於所有cmake編譯的入口,這個CMakeLists的標誌就在於其會出現
PROJECT(NAME)
之後,主CMakeLists會調用各個子文件夾的CMakeLists,這些CMakeLists是怎麼關聯起來的呢?我認爲是通過以主CMakeLists的相對路徑通過ADD_SUBDIRECTORY命令來關聯
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
其中source_dir 爲存放你要加入的CMakeLists的所在文件夾,binary_dir是可選的,這裏指定source_dir 中的CMakeLists 編譯輸出(包含編譯中間結果)路徑爲binary_dir。如果不進行 binary_dir目錄的指定,那麼編譯結果(包括中間結果)都將存放在build/source_dir 目錄(這個目錄跟原有的 source_dir 目錄對應),指定 binary_dir目錄後,相當於在編譯時將 source_dir 重命名爲 binary_dir,所有的中間結果和目標二進制都將存放在 binary_dir目錄。
以上是主CMakeLists中該寫的內容,那麼在source_dir 中用於編譯源代碼的CMakeLists該怎麼寫呢?事實上我們需要將source_dir 中的源代碼編譯成一個lib以便主CMakeLists的PROJECT調用。使用以下命令編譯lib
SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
這樣,我們就會在source_dir 中得到一個名爲libhello.so的文件,如果我們想指定這個文件的生成位置,可以使用以下命令
SET(LIBRARY_OUTPUT_PATH <路徑>)來指定一個新的位置
如果我們想要使用靜態庫,調用
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
將源文件編譯爲靜態庫是不夠的,因爲生成的文件可能與動態庫文件重名,所以要不更改生成靜態庫的名字爲hello_static,或者使用下述命令
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES,其基本語法是:
SET_TARGET_PROPERTIES(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
這個函數就是設置一些固有的property,其中還包括改變生成.so的版本號
我們如何調用src下編譯好的lib來生成exe
1. 鏈接頭文件
src文件夾下的.cpp文件和.h文件之間互相關聯也是通過相對路徑的,如果.cpp和.h都在src文件夾下,在.cpp中使用
#include"hello.h"
在cmake中是可以編譯通過的,意味着在搜尋hello.h時,.cpp所在文件夾是默認的搜索路徑
但是如果.h文件在另外一個文件夾,我們就需要增加尋找頭文件的路徑了,通過以下命令
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
其中[AFTER|BEFORE]缺省,意味着後面添加的路徑追加在已有路徑之前還是之後。
使用示例
INCLUDE_DIRECTORIES(/usr/include/hello)
當然,如果頭文件距離我們的源文件相對路徑不遠,我們也可以通過以下方式,上面那種方式很適合絕對路徑,就是調用一個類似於OPENCV的庫的時候
#include "include/hello.h"
2. 鏈接庫文件
之前我們編譯生成了libhello.so,現在我們要把這個庫鏈入exe文件,我們使用TARGET_LINK_LIBRARIES
TARGET_LINK_LIBRARIES(target library1
<debug | optimized> library2
...)
鏈接動態庫
TARGET_LINK_LIBRARIES(main libhello.so)
鏈接靜態庫
TARGET_LINK_LIBRARIES(main libhello.a)
這裏的目標文件main爲一個可執行文件
下面是一個使用cmake編譯帶有opencv庫的示例
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
PROJECT(OPENCV_CMAKE)
SET(SRC_LIST main.cpp)
set (OpenCV_DIR D:/OpenCV/opencv2410/opencv/build) #這一句設置了OPENCV的目錄地址
FIND_PACKAGE(OpenCV REQUIRED)
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
ADD_EXECUTABLE(OPENCV_CMAKE_EXE ${SRC_LIST})
TARGET_LINK_LIBRARIES(OPENCV_CMAKE_EXE ${OpenCV_LIBS})
main.cpp
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
cv::Mat image = imread("test.jpg");
imshow("GH_HOME", image);
cv::waitKey();
}
編譯結果如下
-- OpenCV ARCH: x64
-- OpenCV RUNTIME: vc12
-- OpenCV STATIC: OFF
-- Found OpenCV 2.4.10 in D:/OpenCV/opencv2410/opencv/build/x64/vc12/lib
-- You might need to add D:\OpenCV\opencv2410\opencv\build\x64\vc12\bin to your PATH to be able to run your applications.
-- Configuring done
-- Generating done
-- Build files have been written to: D:/MyDesign/code/CMake/OpenCVTemp/BUILD
這樣的話直接運行生成的exe會出現確實OpenCV相關的DLL文件,所以設置上可以補充兩點:
1. 在系統的環境變量Path中添加OpenCV的DLL所在目錄
2. 在項目的屬性-調試-環境 中添加OpenCV的DLL所在目錄