CMake:无法链接使用共享zlib包装器库

时间:2018-04-16 17:38:00

标签: c++ cmake zlib libzip

在我的情况下,我有两个CMake项目(如果重要的话,使用MSYS Makefiles构建):

  1. 一个是使用Zlib和Libzip为库用户提供压缩功能的共享库,让我们称之为 mylib
  2. 另一个是使用 mylib 做一些拉链的东西的应用程序。它不必担心Zlib,Libzip或其他任何东西。我们称之为 app
  3. 我在下面创建了一个简单的示例,演示了我遇到的奇怪问题。简单地说, app 在运行 make 时拒绝链接,但仅当某些Libzip代码在 mylib 中保留未注释时(编译和链接正常,无论如何)。

    Zlib和Libzip源代码位于C:/ Dev / Libs。

    LIB /的CMakeLists.txt

    cmake_minimum_required(VERSION 3.7)
    
    # Set project
    project(mylib)
    set(LIBS_DIR "C:/Dev/Libs")
    
    # Add mylib sources
    include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src")
    file(GLOB_RECURSE SRCS "src/*.cpp")
    add_library(mylib SHARED ${SRCS})
    
    # Add Zlib
    set(ZLIB_ROOT "${LIBS_DIR}/zlib-1.2.11")
    include_directories(${ZLIB_ROOT})
    target_include_directories(mylib PUBLIC ${ZLIB_ROOT})
    file(GLOB ZLIB_SRCS "${ZLIB_ROOT}/*.c")
    add_library(zlib STATIC ${ZLIB_SRCS})
    
    # Add Libzip
    set(LIBZIP_ROOT "${LIBS_DIR}/libzip-1.1.3")
    include_directories("${LIBZIP_ROOT}/lib")
    target_include_directories(mylib PUBLIC "${LIBZIP_ROOT}/lib")
    file(GLOB LIBZIP_SRCS "${LIBZIP_ROOT}/lib/*.c")
    add_library(libzip STATIC ${LIBZIP_SRCS})
    
    set(LIBS_LINK    zlib libzip)
    set(LIBS_INSTALL zlib libzip)
    set(LIBS_EXPORT  zlib libzip)
    target_link_libraries(mylib PUBLIC ${LIBS_LINK})
    
    # https://rix0r.nl/blog/2015/08/13/cmake-guide/
    # Define headers for this library. PUBLIC headers are used for
    # compiling the library, and will be added to consumers' build
    # paths.
    target_include_directories(mylib PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
        $<INSTALL_INTERFACE:include>
        PRIVATE src)
    
    # 'make install' to the correct locations (provided by GNUInstallDirs).
    include(GNUInstallDirs)
    install(TARGETS mylib ${LIBS_INSTALL} EXPORT mylibConfig
            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
            RUNTIME DESTINATION ${CMAKE_CURRENT_BINARY_DIR})  # This is for Windows
    install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
    
    # This makes the project importable from the install directory
    # Put config file in per-project dir (name MUST match), can also
    # just go into 'cmake'.
    install(EXPORT mylibConfig DESTINATION share/mylib/cmake)
    
    # This makes the project importable from the build directory
    export(TARGETS mylib ${LIBS_EXPORT} FILE mylibConfig.cmake)
    

    LIB / SRC / lib.hpp

    #pragma once
    
    namespace lib
    {
        int func();
    }
    

    LIB / SRC / lib.cpp

    #include "lib.hpp"
    
    #define ZIP_STATIC
    #include "zip.h"
    
    int lib::func()
    {
        zip_source_t *src;
        zip_error_t error;
        src = zip_source_buffer_create(0, 1, 0, &error);
    
        return 10;
    }
    

    应用程序/的CMakeLists.txt

    cmake_minimum_required(VERSION 3.7)
    
    project(app)
    
    # Add app sources
    file(GLOB_RECURSE SRCS "src/*.cpp")
    add_executable(app ${SRCS})
    
    # Add mylib
    set(mylib_DIR "${CMAKE_CURRENT_BINARY_DIR}/../lib")
    find_package(mylib REQUIRED)
    configure_file("${mylib_DIR}/libmylib.dll" "libmylib.dll" COPYONLY)
    target_link_libraries(app mylib)
    

    应用程序/ SRC / app.hpp

    #pragma once
    #include <lib.hpp>
    

    应用程序/ SRC / app.cpp

    #include <iostream>
    #include "app.hpp"
    
    int main()
    {
        std::cout << lib::func() << std::endl;
        return 0;
    }
    

    构建 mylib

    的输出
    $ make
    [ 13%] Built target zlib
    [ 98%] Built target libzip
    Scanning dependencies of target mylib
    [ 99%] Building CXX object CMakeFiles/mylib.dir/src/lib.cpp.obj
    [100%] Linking CXX shared library libmylib.dll
    [100%] Built target mylib
    

    构建 app

    的输出
    $ make
    Scanning dependencies of target app
    [ 50%] Building CXX object CMakeFiles/app.dir/src/app.cpp.obj
    [100%] Linking CXX executable app.exe
    CMakeFiles/app.dir/objects.a(app.cpp.obj):app.cpp:(.text+0x17): undefined reference to `lib::func()'
    collect2.exe: error: ld returned 1 exit status
    make[2]: *** [app.exe] Error 1
    make[1]: *** [CMakeFiles/app.dir/all] Error 2
    make: *** [all] Error 2
    

    如果我在 lib / src / lib.cpp 中评论src = zip_source_buffer_create(0, 1, 0, &error);,请重建然后重建 app

    $ make
    -- Configuring done
    -- Generating done
    -- Build files have been written to: C:/Dev/Builds/cmaketest/app
    [ 50%] Linking CXX executable app.exe
    [100%] Built target app
    
    $ ./app
    10
    

    产生预期结果。

    问题必须出在 app 的CMakeLists中,因为 mylib 构建正常而没有任何链接错误。或者我在 mylib 中错误地添加了zlib / libzip?我需要静态链接到它们,我无法使用find_package

    谢谢!

1 个答案:

答案 0 :(得分:0)

在复制.dll.a文件后也能正常工作:

configure_file("${mylib_DIR}/libmylib.dll.a" "libmylib.dll.a" COPYONLY)

并使用以下内容为 lib 中的所有方法添加前缀:

__declspec(dllexport)