1. 程式人生 > 其它 >windows使用cmake開發C++注意事項記錄

windows使用cmake開發C++注意事項記錄

一,庫引用

如引用OpenCV,最快捷的方式是在官網下載如opencv-3.4.10-vc14_vc15.exe的exe程式,執行後即可獲得編譯後的opencv。

在CMakeLists.txt中配置opencv的標頭檔案目錄和lib檔案即include_directories和target_link_libraries即可完成引用。

include_directories和target_link_libraries可都使用絕對路徑,避免出錯。用OpenCV_DIR,${OpenCV_LIBRARIES} ,${OpenCV_INCLUDE_DIRS}等來配置可能會出錯。

其他庫的引用同樣,只需在include_directories

target_link_libraries命令中分別配置庫的絕對路徑即可。

二,多個包相互依賴

比如下圖目錄結構:

base包和sock包都是作為共享庫,sock依賴base,dcm包依賴base和sock。

1)在根目錄的CMakeLists.txt中配置

ADD_SUBDIRECTORY(src/package/base)
ADD_SUBDIRECTORY(src/package/sock)
ADD_SUBDIRECTORY(src/package/dcm)

理解:ADD_SUBDIRECTORY相當於將子目錄CMakeLists.txt中的指令碼匯入到根目錄的CMakeLists.txt,在根目錄的build資料夾下執行cmake ..

的時候,cmake的source物件是根目錄的CMakeLists.txt。

此時無論是在子目錄的CMakeLists.txt中還是Findxxx.cmake檔案中引用全域性變數CMAKE_SOURCE_DIR,其值都是根目錄的路徑。而PROJECT_SOURCE_DIR所指的是所在的CMakeLists.txt的路徑。

2)配置Findxxx.cmake檔案的路徑,在執行find_package時cmake會去CMAKE_MODULE_PATH中的路徑中尋找包的cmake檔案

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)

3)編寫Findxxx.cmake

該檔案最基本的作用時定義包xxx的標頭檔案目錄變數和lib檔案路徑變數,最簡單如下

message("==================start find base package=================")
if(NOT DEFINED base_DIR)
	message("not define package dir ")
else()
	message("package dir is ${base_DIR} ")
endif()

message("cmake src dir is ${CMAKE_SOURCE_DIR} ")

set(base_LIB_DIR "${CMAKE_SOURCE_DIR}/install/lib")
set(base_INC_DIR "${base_DIR}/include")

if((NOT EXISTS "${base_INC_DIR}") OR (NOT EXISTS "${base_LIB_DIR}"))
	message("this module include or lib path not exsit")
endif()

FIND_LIBRARY(base_LIBS NAMES base PATHS "${base_LIB_DIR}")
if(base_LIBS)
	set(base_FOUND TRUE)
	set(base_INCLUDE_DIRS ${base_INC_DIR})
	set(base_LIBRARIES ${base_LIBS})
	# mark_as_advanced(base_FOUND base_INCLUDE_DIRS base_LIBRARIES)
else()
	message("can not found lib")
endif()

上面時base包的cmake檔案,在dcm包的CMakeLists.txt中就可以使用下面命令來引用base包

find_package(base)

include_directories(${base_INCLUDE_DIRS})

target_link_libraries(${PROJECT_NAME}_lib PUBLIC
${base_LIBRARIES}

}

4)配置lib和exe安裝目錄,在根目錄CMakeLists.txt中設定CMAKE_INSTALL_PREFIX包含的路徑

set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install)

5)在子專案的CMakeLists.txt配置targets的安裝路徑,如下

INSTALL(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION lib
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

因為根目錄CMakeLists.txt配置了CMAKE_INSTALL_PREFIX,這裡的資料夾lib是在CMAKE_INSTALL_PREFIX目錄下的,所以該子專案的targets會被安裝到MedicalApp/install/lib目錄下。

TARGETS 可指定多個。

三,共享庫匯出

base和sock作為共享庫供dcm包使用,在base和sock的標頭檔案中,對於所有匯出函式,在函式前加_declspec(dllexport),如下:

對於所有匯出類,在類名前加上

#ifdef OS_WIN
_declspec(dllexport)
#endif

如下:

以上對類和函式的新增都是在標頭檔案中,原始檔中不需要新增

四,包編譯

由於sock依賴base,dcm依賴base和sock,所以在用vs2019編譯及安裝時,順序依次是base,sock,dcm

1)在vs2019中,選擇"檢視"->"終端",執行如下

cd build

cmake ..

2)在MedicalApp\build\src\package\base目錄下開啟base.sln,選擇"INSTALL"右鍵"生成",結束後會生成base.dll和base.lib,並且已經拷貝到MedicalApp\install\lib目錄下

3)接下來對sock包和dcm包依次執行上面步驟,最終在MedicalApp\install\lib目錄下,如下圖:

其中opencv_world3410d.dll是手動拷貝過來的,exe執行時需要