2016-04-23 80 views
1

如何鏈接到我的項目中包含的外部庫?CMake - 如何鏈接到我已經與我的項目打包的外部庫?

這裏是我的項目是如何設置:

我有一個名爲app文件夾,這是我在那裏坐的main.cpp。

C:\Raph\src\App 

main.cpp 

我也有一個名爲「ExternalLibrary」文件夾,這正是我所捆綁的Qt庫,我需要在我的項目中使用:

C:\Raph\src\ExternalLibrary\Platform\Windows\Qt5.6\VS2013_64bit 

它包含3個文件夾:

**bin** 
    moc.exe 
    rcc.exe 
    uic.exe 
    ...... 
    bunch of Qt dll files 

**include** 
    bunch of Qt header files 

**lib** 
    bunch of Qt lib files 

我需要安裝的CMake做三件事情:

  1. 動態鏈接到我已經打包在「ExternalLibrary」中的Qt庫。

  2. 每當我在項目中添加Qt類或資源時,自動執行moc.exe,uic.exe,rcc.exe。我也不需要任何 生成的moc_myClassname.cpp顯示在項目中。

  3. 我希望所有的Qt dll最終都放在可執行文件所在的bin文件夾中。例如:

    C:\拉斐\建立\拉斐\的Windows \ 64 \調試\ BIN

    Raph.exe +所有必要的Qt的Dll

+1

過寬:幾個不相關的問題。總之:1.谷歌'find_package + QT'。 2. *自動*顯示新的源文件不是CMake的一項功能。通常每次添加/刪除源時都需要修改'CMakeLists.txt'。 3.只需創建將文件複製到目標目錄的規則。嘗試專注於單個問題並在提問前進行基本搜索。 – Tsyvarev

回答

0

(1)你可以找到Qt庫採用以下方式:

find_package(Qt5Core [...] 5.6 REQUIRED) 
add_executable(someExe file1.cpp) 
target_link_libraries(someExe Qt5::Core) 

請注意,您應該保留Qt的原始目錄結構,也包含Qt cmake腳本,例如lib/cmake/Qt5/Qt5Config.cmake

如果你想有一個特定的目錄將包括Qt的搜索時,你可以做(​​您搜索的Qt前):

set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "./your/path") 

例如,這可以是你提供的目錄。

(2)您可以使用cmake的automoc功能。只需添加

set(CMAKE_AUTOMOC ON) 
set(CMAKE_INCLUDE_CURRENT_DIR ON) 

在您的cmake腳本的開頭。 CMake也支持AUTOUICAUTORCC。我還沒有嘗試過,但可能的工作類似。 (3)您可以將自定義目標添加到您的項目中,以複製dll。當你建立這個目標時,所有的dll都會被複制。您可以從Qt查找腳本定義的目標(例如Qt5::Core)獲取dll的路徑。

get_target_property(LOC_R Qt5::Core LOCATION_RELEASE) 
get_target_property(LOC_D Qt5::Core LOCATION_DEBUG) 

但是,您還應該掃描這些目標的依賴性(他們依賴的其他dll)。你可以寫,掃描爲correspondig的dll目標的整個列表,並將它們添加到列表中選擇宏,讓我們把這些RELEASE_DLLSDEBUG_DLLS

macro(copydlls RELEASE_DLLS DEBUG_DLLS MODULELIST) 
    foreach(ELEMENT ${${MODULELIST}}) 
     get_target_property(LOC_R ${ELEMENT} LOCATION_RELEASE) 
     get_target_property(LOC_D ${ELEMENT} LOCATION_DEBUG) 
     list(APPEND ${RELEASE_DLLS} ${LOC_R}) 
     list(APPEND ${DEBUG_DLLS} ${LOC_D}) 


     get_target_property(DEPENDENCIES_RELEASE ${ELEMENT} IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE) 
     foreach(DEPENDENCY ${DEPENDENCIES_RELEASE}) 
      if(TARGET ${DEPENDENCY}) 
       get_target_property(LOC_R ${DEPENDENCY} LOCATION_RELEASE) 
       if(${LOC_R} MATCHES ".dll$") 
        list(APPEND ${RELEASE_DLLS} ${LOC_R}) 
       endif() 
      endif() 
     endforeach()  

     get_target_property(DEPENDENCIES_DEBUG ${ELEMENT} IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG) 
     foreach(DEPENDENCY ${DEPENDENCIES_DEBUG}) 
      if(TARGET ${DEPENDENCY}) 
       get_target_property(LOC_D ${DEPENDENCY} LOCATION_DEBUG) 
       if(${LOC_D} MATCHES ".dll$") 
        list(APPEND ${DEBUG_DLLS} ${LOC_D}) 
       endif()   
      endif() 
     endforeach()  

     get_target_property(DEPENDENCIES_RELEASE ${ELEMENT} IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE) 
     foreach(DEPENDENCY ${DEPENDENCIES_RELEASE}) 
      if(TARGET ${DEPENDENCY}) 
       get_target_property(LOC_R ${DEPENDENCY} LOCATION_RELEASE) 
       if(${LOC_R} MATCHES ".dll$") 
        list(APPEND ${RELEASE_DLLS} ${LOC_R}) 
       endif() 
      endif() 
     endforeach()  

     get_target_property(DEPENDENCIES_DEBUG ${ELEMENT} IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG) 
     foreach(DEPENDENCY ${DEPENDENCIES_DEBUG}) 
      if(TARGET ${DEPENDENCY}) 
       get_target_property(LOC_D ${DEPENDENCY} LOCATION_DEBUG) 
       if(${LOC_D} MATCHES ".dll$") 
        list(APPEND ${DEBUG_DLLS} ${LOC_D}) 
       endif() 
      endif() 
     endforeach() 

    endforeach() 
endmacro() 

然後,你可以得到所有的Qt的dll文件列表中,由調用這個宏有:

IF(MSVC) 
    set(QT_MODULES "Qt5::Core" "Qt5::Gui" "Qt5::Widgets") 
    set(RELEASE_DLLS) 
    set(DEBUG_DLLS) 
    copydlls(RELEASE_DLLS DEBUG_DLLS QT_MODULES)  
ENDIF(MSVC) 

當你檢索到的信息,您可以創建自定義目標下列方式。假設您的列表中有您的所有dll路徑RELEASE_DLLSDEBUG_DLLS,並且您的可執行文件名稱爲TARGETS中的列表。然後,你可以做這樣的事情:

if(MSVC) 

    set(COPY_COMMAND_RELEASE "-E copy_if_different ") 
    set(COPY_COMMAND_DEBUG "-E copy_if_different ") 

    list(REMOVE_DUPLICATES RELEASE_DLLS) 
    list(REMOVE_DUPLICATES DEBUG_DLLS) 

    foreach(DLL ${RELEASE_DLLS}) 
     string(CONCAT COPY_COMMAND_RELEASE "${COPY_COMMAND_RELEASE} \"${DLL}\" ") 
    endforeach() 
    foreach(DLL ${DEBUG_DLLS}) 
     string(CONCAT COPY_COMMAND_DEBUG "${COPY_COMMAND_DEBUG} \"${DLL}\" ") 
    endforeach() 

    string(CONCAT COPY_COMMAND_RELEASE ${COPY_COMMAND_RELEASE} "\"${CMAKE_CURRENT_BINARY_DIR}/Release\" ") 
    string(CONCAT COPY_COMMAND_DEBUG ${COPY_COMMAND_DEBUG} "\"${CMAKE_CURRENT_BINARY_DIR}/Debug\" ") 

    add_custom_target(COPY_DLLS) 

    foreach(EXECUTABLE ${TARGETS}) 
     add_custom_command(TARGET COPY_DLLS PRE_BUILD COMMAND ${CMAKE_COMMAND} ${COPY_COMMAND_RELEASE} COMMENT "Copying dlls to executable directory...") 
     add_custom_command(TARGET COPY_DLLS PRE_BUILD COMMAND ${CMAKE_COMMAND} ${COPY_COMMAND_DEBUG} COMMENT "Copying dlls to executable directory...") 
    endforeach() 

endif() 

如果你想要這個目標每隔您的其他目標之一是建立執行時間,你可以這樣做:

foreach(EXECUTABLE ${TARGETS}) 
    add_dependencies(${EXECUTABLE} COPY_DLLS) 
endforeach() 

不要foget你還必須將它添加到複製DLL目標從pluginsplatforms目錄複製到你的可執行文件夾,例如:

add_custom_command(TARGET COPY_DLLS PRE_BUILD 
    COMMAND ${CMAKE_COMMAND} -E copy_directory ${PATH_QT_ROOT}/plugins/platforms ${CMAKE_CURRENT_BINARY_DIR}/Debug/platforms 
    COMMAND ${CMAKE_COMMAND} -E copy_directory ${PATH_QT_ROOT}/plugins/platforms ${CMAKE_CURRENT_BINARY_DIR}/Release/platforms 
    COMMENT "Copying Qt platforms to executable directory...") 
相關問題