Search code examples
c++cmakezlibconan

CMake build error: undefined reference to 'deflateEnd'


I'm trying to use zlib in my project. The CMakeLists.txt is as follows:

cmake_minimum_required(VERSION 3.5)

project(cmake-demo LANGUAGES CXX)
# The version number.
set(CMDemo_VERSION_MAJOR 0)
set(CMDemo_VERSION_MINOR 1)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(${PROJECT_SOURCE_DIR}/build/conan_paths.cmake)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/build)
find_package(uwebsockets)

#ZLIB
if(ZLIB_FOUND)
  set(INC_DIRS ${INC_DIRS} ${ZLIB_INCLUDE_DIRS})
  set(LINK_LIBS ${LINK_LIBS} ${ZLIB_LIBS})
endif()

# Global approach
if(uwebsockets_FOUND)
  set(INC_DIRS ${INC_DIRS} ${uwebsockets_INCLUDE_DIRS})
  set(LINK_LIBS ${LINK_LIBS} ${uwebsockets_LIBS})
endif()

#libuv
if(libuv_FOUND)
  set(INC_DIRS ${INC_DIRS} ${libuv_INCLUDE_DIRS})
  set(LINK_LIBS ${LINK_LIBS} ${libuv_LIBS})
endif()

#usockets
if(usockets_FOUND)
  set(INC_DIRS ${INC_DIRS} ${usockets_INCLUDE_DIRS})
  set(LINK_LIBS ${LINK_LIBS} ${usockets_LIBS})
endif()

include_directories(${INC_DIRS})

add_executable(${PROJECT_NAME} main.cpp)
message("libs=${LINK_LIBS}")
target_link_libraries(${PROJECT_NAME} ${LINK_LIBS})

#output of message("${LINK_LIBS}")
C:/ProgramData/Miniconda3/Library/lib/z.lib;C:/Users/Sunway/.conan/data/libuv/1.41.0/_/_/package/9965605309592d7e617ec929633249a2031e4263/lib/libuv_a.a;C:/Users/Sunway/.conan/data/usockets/0.7.1/_/_/package/a24f5291464b4270092bce2e738cbf9f3cd53bb7/lib/libuSockets.a

I'm sure that ${LINK_LIBS} is correct, but it still doesn't work:

CMakeFiles/cmake-demo.dir/main.cpp.obj: In function `ZN3uWS15DeflationStreamD1Ev':
C:/Users/Sunway/.conan/data/uwebsockets/19.2.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/uWebSockets/PerMessageDeflate.h:186: undefined reference to `deflateEnd'

os: Windows10 x64

IDE: QtCreator4.14.2

compiler: MinGW 32-bit


Solution

  • The thing is, that you have to set the path to the library file as the target_link_libraries argument.

    According to the documentation, if you want to link the library, each argument of target_link_libraries can be:

    • A library target name
    • A full path to a library file (e.g. /usr/lib/foo.so)
    • A plain library name (e.g. foo)

    In your case I suggest you to add the complete path to the library.

    I don't have all the code of your project, so I suggest you consider this minimal example:

    add_executable(test main.cpp)
    
    SET (ZLIB_ROOT "/tmp/zlib")
    SET (ZLIB_INCLUDE_DIR "/tmp/zlib/include/")
    SET (ZLIB_LIBRARY "/tmp/zlib/lib/libz.so.1.2.11")
    
    FIND_PACKAGE (ZLIB REQUIRED)
    MESSAGE (" zlib version major is " ${ZLIB_VERSION_MAJOR})
    MESSAGE (" zlib version minor is " ${ZLIB_VERSION_MINOR})
    MESSAGE (" zlib include is " ${ZLIB_INCLUDE_DIR})
    MESSAGE (" zlib libraries are " ${ZLIB_LIBRARIES})
    
    target_link_libraries(test ${ZLIB_LIBRARIES})
    

    After downloading the latest zlib release and installing it in /tmp, everything works as expected.


    Update: as @uilianries mentioned, since you are using conan, you have cmake_find_package generator that defines variables with all the necessary paths. So you don't need to set the paths in CMakeLists.txt manually.