簡體   English   中英

CMake - 如何鏈接到我用項目打包的外部庫?

[英]CMake - How Can I link to an external library that I have packed with my project?

我如何鏈接到我用我的項目打包的外部庫?

以下是我的項目設置方式:

我有一個名為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 Dlls

(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)。 您可以編寫一個宏來掃描對應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)

檢索到該信息后,您可以通過以下方式創建自定義目標。 假設您將列表RELEASE_DLLSDEBUG_DLLS中的所有dll路徑以及您的可執行文件名稱作為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()

不要忘了你還必須將platforms目錄從plugins復制到可執行文件夾,例如將其添加到copy dll目標:

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...")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM