2016-08-10 102 views
-1

我試圖創建一個項目,這將創建一個可執行MyExec.exe,這將依賴於另一個庫Niftilib,其本身取決於的zlibVS2015如何將靜態庫鏈接到其他庫和可執行文件?

我做什麼,我用cmake並創造了superbuild,使用ExternalProject_Add下載和編譯zlib的

ExternalProject_Add(Zlib 
    SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/zlib" 
    BINARY_DIR "${PROJECT_BINARY_DIR}/deps/zlib-build" 
    INSTALL_DIR "${PROJECT_BINARY_DIR}/deps/zlib-install" 
    GIT_REPOSITORY "${git_protocol}://github.com/madler/zlib.git" 
    GIT_TAG "50893291621658f355bc5b4d450a8d06a563053d" 
    CMAKE_ARGS 
     -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> 
     -DINSTALL_BIN_DIR=<INSTALL_DIR>/bin 
     -DINSTALL_INC_DIR=<INSTALL_DIR>/include 
     -DINSTALL_LIB_DIR=<INSTALL_DIR>/lib 
     -DINSTALL_MAN_DIR=<INSTALL_DIR>/share/man 
     -DINSTALL_PKGCONFIG_DIR=<INSTALL_DIR>/share/pkgconfig) 

我也做了同樣的Nifticlib

ExternalProject_Add(Nifticlib 
    SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib" 
    BINARY_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib-build" 
    INSTALL_DIR "${PROJECT_BINARY_DIR}/deps/nifticlib-install" 
    GIT_REPOSITORY "${git_protocol}://gitlab.com/slckr/nifticlib.git" 
    GIT_TAG "9f427b39eb6a16822c6ed34454f87eb751b23220" 
    CMAKE_ARGS 
     -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> 
     -DZLIB_INCLUDE_DIR=${ZLIB_INC_DIR} 
     -DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibd.lib 
    DEPENDS Zlib) 

然後我做了同樣的MyExec

ExternalProject_Add(MyExec 
    SOURCE_DIR "${PROJECT_BINARY_DIR}/MyExec" 
    BINARY_DIR "${PROJECT_BINARY_DIR}/MyExec-build" 
    INSTALL_DIR "${PROJECT_BINARY_DIR}/MyExec-install" 
    GIT_REPOSITORY "${git_protocol}://gitlab.com/slckr/MyExec.git" 
    GIT_TAG "8514aacf5422f1111602e24ea73b229556293b8c" 
    CMAKE_ARGS 
     -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> 
     -DBOOST_INC_DIR=${Boost_INCLUDE_DIRS} 
     -DBOOST_LIB_DIR=${Boost_LIBRARY_DIRS} 
     -DZLIB_INC_DIR=${ZLIB_INC_DIR} 
     -DZLIB_LIB_DIR=${ZLIB_LIB_DIR} 
     -DNIFTI_INC_DIR=${NIFTI_INC_DIR} 
     -DNIFTI_LIB_DIR=${NIFTI_LIB_DIR} 
    DEPENDS Nifticlib) 

在我MyExec項目CMakeLists,我有這樣的:

cmake_minimum_required(VERSION 3.6) 

project(MyExec) 

include_directories(${BOOST_INC_DIR} ${ZLIB_INC_DIR} ${NIFTI_INC_DIR}) 
link_directories(${BOOST_LIB_DIR} ${ZLIB_LIB_DIR} ${NIFTI_LIB_DIR}) 

add_subdirectory(DataStructure) 
add_subdirectory(FileHandler) 
add_subdirectory(Parser) 

add_executable(${PROJECT_NAME} MyExec.cc) 
target_link_libraries(${PROJECT_NAME} zlibd znz nifticdf niftiio DataStructure FileHandler Parser) 

install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) 

我的目標是能夠無需所有需要的庫文件(除升壓)分發MyExec.exe。我希望將nifticlib庫嵌入到我的exec中。

如果我這樣編譯,它不起作用,因爲它說zlibd.dll丟失。我發現我必須將可執行文件鏈接到zlibstaticd而不是zlibd。

但我的問題是,我也應該改變 - DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibd.lib到 - DZLIB_LIBRARY_DEBUG=${ZLIB_LIB_DIR}/zlibstaticd.lib在Nifticlib項目?

或者它只在可執行項目中起作用嗎?爲什麼nifticlib要求我提供zlib庫的路徑,如果它是作爲靜態庫構建的並且不執行任何鏈接?

謝謝。

編輯:如果我不zlib的鏈接到我的可執行文件,我得到這些錯誤:

5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzdopen referenced in function znzdopen 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzread referenced in function znzread 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzwrite referenced in function znzwrite 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzputs referenced in function znzputs 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzgets referenced in function znzgets 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzputc referenced in function znzputc 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzgetc referenced in function znzgetc 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzflush referenced in function znzflush 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzeof referenced in function znzeof 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzclose referenced in function Xznzclose 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzopen referenced in function znzopen 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gzseek referenced in function znzseek 
5>znz.lib(znzlib.obj) : error LNK2019: unresolved external symbol gztell referenced in function znztell 

ZNZ是nifticlib的一部分。它是使用zlib庫的部分。

編輯2:,使其更簡單,我的問題是它的連接發生像鏈接1或鏈接2(明知nifticlib依賴於zlib的,無論是編譯爲靜態庫):

Linking 1       Linking 2 
--------------   --------------  --------------- 
| zlib |   | zlib |  | nifticlib | 
--------------   --------------  --------------- 
     |       \     /
--------------     \    /
| nifticlib |     \    /
--------------      \   /
     |       ------------------- 
--------------     | MyExec.exe | 
| MyExec.exe |     ------------------- 
-------------- 
+0

如果我理解正確,_Niftilib_取決於_zlib_並且您想要將您的應用程序與_Niftilib_鏈接。不,在執行中並不重要。項目,但它在_Niftilib_ lib中很重要。以及。但是,在VS中,我不使用CMake,當您創建一個靜態鏈接(依賴於另一個靜態鏈接)時,可以通過Configuration Properties - > Librarian - > General - > Additional Dependencies將其鏈接(在Niftilib項目中的zlib)。所以我認爲,是的,你應該改變它,並可能跳過執行。項目。希望這有助於;-) – Dom

+0

我想如果我在exec中跳過它,MyExec項目不會編譯。它在鏈接步驟失敗,因爲它無法找到符號。我的問題是,如果我編譯依賴於zlib的niftilib,zlib符號是否會包含在niftilib.lib中?我是否也需要將它鏈接到MyExec?謝謝。 – whiteShadow

+0

您是否嘗試在exec中跳過它?如果你不直接從exec調用zlib函數,它應該只在niftlib中鏈接,不應該在exec中設置,我想是這樣......不幸的是我不確定......: - /試一試。 – Dom

回答

1

的通常的方式是鏈接只在生成可執行二進制文件時完成。這包括例如正常的可執行文件,但也包括動態庫(.dll,.so)。鏈接不是爲靜態庫(.lib,.a)完成的。

這意味着如果你建立一個「nifticlib」靜態庫,它不需要鏈接到「zlib」。

您應該明確地將依賴關係從動態更改爲靜態,因爲CMake會將靜態庫的依賴關係攜帶到最終的二進制文件。在這種情況下,它應該沒有問題,因爲你沒有指定一個真正的CMake依賴項,只是庫的一些變量。

注意:在Visual Studio中,您可以非常容易地將靜態庫「鏈接」到彼此中。它所做的只是將所有函數串聯到一個.lib文件中。不過,CMake並沒有使用這個特性,而是在靜態庫目標上執行「TARGET_LINK_LIBRARIES」時,像上面提到的那樣依賴於它。

+0

好的,謝謝。所以它更像鏈接2.它現在很有意義。我檢查了nifticlib以及它爲什麼向我要求zlibd.lib,但我認爲這是因爲nifticlib正在編譯一些單元測試(可執行文件),所以它也需要將它們鏈接到zlib。所以即使我不使用這些可執行文件,它們也會被編譯。 – whiteShadow

+0

@whiteShadow Ups ...對不起,我沒有意識到,鏈接是關於動態庫。這個答案必須是正確的。 – Dom

+0

@Dom沒有它是關於靜態庫 – whiteShadow

相關問題