Search code examples
c++cmakelinkerapache-zookeeper

error in linking zookeeper-client-c: unresolved symbols


so i have a simple module in C++ which uses some of the zookeeper-client-c API, particularly the functions:

zoo_exists, zoo_create, zoo_get_children, zoo_get, zookeeper_init, zookeeper_close

and values: ZOO_EXPIRED_SESSION_STATE, ZOO_SESSION_EVENT, ZOO_CONNECTED_STATE, ZOO_CREATED_EVENT, ZOO_DELETED_EVENT, ZOO_CHANGED_EVENT, ZOO_CHILD_EVENT, ZOO_EPHEMERAL, ZOO_OPEN_ACL_UNSAFE

When I build my project I get:

[build] DSE.lib(ZkManager.obj) : error LNK2019: unresolved external symbol __imp_zoo_create referenced in function "private: void __cdecl ZkManager::createNode(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool)" (?createNode@ZkManager@@AEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkManager.obj) : error LNK2019: unresolved external symbol __imp_zoo_exists referenced in function "private: void __cdecl ZkManager::createNode(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool)" (?createNode@ZkManager@@AEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkManager.obj) : error LNK2019: unresolved external symbol __imp_zoo_get referenced in function "private: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl ZkManager::getData(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?getData@ZkManager@@AEAA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV23@@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkManager.obj) : error LNK2019: unresolved external symbol __imp_zoo_get_children referenced in function "private: class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > __cdecl ZkManager::getChildren(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?getChildren@ZkManager@@AEAA?AV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkManager.obj) : error LNK2019: unresolved external symbol __imp_ZOO_OPEN_ACL_UNSAFE referenced in function "private: void __cdecl ZkManager::createNode(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool)" (?createNode@ZkManager@@AEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkManager.obj) : error LNK2019: unresolved external symbol __imp_ZOO_EPHEMERAL referenced in function "private: void __cdecl ZkManager::createNode(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool)" (?createNode@ZkManager@@AEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_zookeeper_init referenced in function "public: __cdecl ZkSync::ZkSync(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0ZkSync@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_zookeeper_close referenced in function "public: virtual __cdecl ZkSync::~ZkSync(void)" (??1ZkSync@@UEAA@XZ) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_ZOO_EXPIRED_SESSION_STATE referenced in function "public: static void __cdecl ZkSync::watcher(struct _zhandle *,int,int,char const *,void *)" (?watcher@ZkSync@@SAXPEAU_zhandle@@HHPEBDPEAX@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_ZOO_CONNECTED_STATE referenced in function "public: static void __cdecl ZkSync::watcher(struct _zhandle *,int,int,char const *,void *)" (?watcher@ZkSync@@SAXPEAU_zhandle@@HHPEBDPEAX@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_ZOO_CREATED_EVENT referenced in function "public: static void __cdecl ZkSync::watcher(struct _zhandle *,int,int,char const *,void *)" (?watcher@ZkSync@@SAXPEAU_zhandle@@HHPEBDPEAX@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_ZOO_DELETED_EVENT referenced in function "public: static void __cdecl ZkSync::watcher(struct _zhandle *,int,int,char const *,void *)" (?watcher@ZkSync@@SAXPEAU_zhandle@@HHPEBDPEAX@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_ZOO_CHANGED_EVENT referenced in function "public: static void __cdecl ZkSync::watcher(struct _zhandle *,int,int,char const *,void *)" (?watcher@ZkSync@@SAXPEAU_zhandle@@HHPEBDPEAX@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_ZOO_CHILD_EVENT referenced in function "public: static void __cdecl ZkSync::watcher(struct _zhandle *,int,int,char const *,void *)" (?watcher@ZkSync@@SAXPEAU_zhandle@@HHPEBDPEAX@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] DSE.lib(ZkSync.obj) : error LNK2019: unresolved external symbol __imp_ZOO_SESSION_EVENT referenced in function "public: static void __cdecl ZkSync::watcher(struct _zhandle *,int,int,char const *,void *)" (?watcher@ZkSync@@SAXPEAU_zhandle@@HHPEBDPEAX@Z) [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] C:\Users\YOSSI\CLionProjects\DSE\build\Release\DSEApp.exe : fatal error LNK1120: 15 unresolved externals [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[proc] The command: "C:\Program Files\CMake\bin\cmake.EXE" --build c:/Users/YOSSI/CLionProjects/DSE/build --config Release --target ALL_BUILD -j 6 -- exited with code: 1
[driver] Build completed: 00:01:02.133
[build] Build finished with exit code 1

I built my zookepeer following steps:

  1. downloaded zookeeper 3.9.2 tar.
  2. running: mvn clean install -DskipTests
  3. in zookeeper-client-c folder created build folder and ran: cmake .. -DWANT_SYNCAPI=ON
  4. ran cmake --build . --config Release

in C:\ZooKeeperC-Release\apache-zookeeper-3.9.2\zookeeper-client\zookeeper-client-c\Release path I have:

    cli.exe
    hashtable.lib
    zookeeper.lib

cmakelists (a little bit messy):

cmake_minimum_required(VERSION 3.12)
project(DSE)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(MSVC)
  set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
endif()

if(MSVC)
  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /VERBOSE:LIB")
endif()

# Set the path to ASIO
set(ASIO_INCLUDE_DIR "C:/asio-1.30.2/include")

# Include ASIO
include_directories(${ASIO_INCLUDE_DIR})

# Add definitions for standalone ASIO and Crow
add_definitions(-DASIO_STANDALONE)
add_definitions(-DCROW_DISABLE_STATIC_DIR)
add_definitions(-DCROW_DISABLE_COMPRESSION)
add_definitions(-DCROW_USE_ASIO)
add_definitions(-DTHREADED)
add_definitions(-DWIN32)

# If you're on Windows, you might need this
if(WIN32)
    add_definitions(-D_WIN32_WINNT=0x0601)
endif()

# Set ASIO include directory for Crow
set(CROW_ASIO_INCLUDE_DIR ${ASIO_INCLUDE_DIR})

# Find Crow
find_package(Crow CONFIG REQUIRED)

# Set gRPC_DIR
set(gRPC_DIR "C:/grpc/lib/cmake/grpc")
set(Protobuf_DIR "C:/grpc/cmake")
set(absl_DIR "C:/grpc/lib/cmake/absl")
set(utf8_range_DIR "C:/grpc/lib/cmake/utf8_range")
set(jsoncpp_DIR "C:/jsoncpp/lib/cmake/jsoncpp")

find_package(absl CONFIG REQUIRED)
find_package(Protobuf CONFIG REQUIRED)
find_package(gRPC CONFIG REQUIRED)

# Find gRPC and Protocol Buffers
find_package(gRPC CONFIG REQUIRED)
find_package(Protobuf CONFIG REQUIRED)

# Find JsonCpp
find_package(jsoncpp CONFIG REQUIRED)

# Set the path to ZooKeeper
set(ZOOKEEPER_INCLUDE_DIR "C:/ZooKeeperC-Release/apache-zookeeper-3.9.2/zookeeper-client/zookeeper-client-c/include")
set(ZOOKEEPER_GENERATED_INCLUDE_DIR "C:/ZooKeeperC-Release/apache-zookeeper-3.9.2/zookeeper-client/zookeeper-client-c/generated")
set(ZOOKEEPER_LIB_DIR "C:/ZooKeeperC-Release/apache-zookeeper-3.9.2/zookeeper-client/zookeeper-client-c/Release")

# Include ZooKeeper
include_directories(${ZOOKEEPER_INCLUDE_DIR})
include_directories(${ZOOKEEPER_GENERATED_INCLUDE_DIR})

# Find the ZooKeeper library
find_library(ZOOKEEPER_LIB NAMES zookeeper PATHS ${ZOOKEEPER_LIB_DIR})

# Define the DSE library
add_library(DSE
    app/Server.cpp
    app/controllers/VoteController.cpp
    app/controllers/VotesMap.cpp
    app/models/CommandElections.cpp
    app/models/ControllerMessage.cpp
    app/models/Vote.cpp
    app/models/VotesCount.cpp
    app/models/VotesCountKey.cpp
    app/paxos/AcceptAndAccepted.cpp
    app/paxos/PrepareAndPromise.cpp
    app/paxos/SessionsMap.cpp
    app/utils/ReadStates.cpp
    app/utils/ReadVoters.cpp
    gRPCObjects/interceptors/ClientInterceptor.cpp
    gRPCObjects/interceptors/ServerInterceptor.cpp
    gRPCObjects/paxos/FuturePaxosGreetingClient.cpp
    gRPCObjects/paxos/GreetingPaxosClient.cpp
    gRPCObjects/paxos/GreetingPaxosServer.cpp
    gRPCObjects/GreetingClient.cpp
    gRPCObjects/GreetingServer.cpp
    gRPCObjects/FutureRemoteGreetingClient.cpp
    protos/Paxos.grpc.pb.cc
    protos/Paxos.pb.cc
    protos/Vote.grpc.pb.cc
    protos/Vote.pb.cc
    zk/ZkConnector.cpp
    zk/ZkManager.cpp
    zk/ZkSync.cpp
)

# Include directories
target_include_directories(DSE PUBLIC 
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/app
    ${CMAKE_CURRENT_SOURCE_DIR}/gRPCObjects
    ${CMAKE_CURRENT_SOURCE_DIR}/protos
    ${CMAKE_CURRENT_SOURCE_DIR}/app/models
    ${CMAKE_CURRENT_SOURCE_DIR}/app/controllers
    ${CMAKE_CURRENT_SOURCE_DIR}/app/paxos
    ${CMAKE_CURRENT_SOURCE_DIR}/app/utils
    ${CMAKE_CURRENT_SOURCE_DIR}/zk
    "C:/grpc/include"
    "C:/jsoncpp/include"
    ${ASIO_INCLUDE_DIR}
    ${ZOOKEEPER_INCLUDE_DIR}
    ${ZOOKEEPER_GENERATED_INCLUDE_DIR}
)

# Option for threaded/non-threaded version
option(USE_THREADED "Use threaded version of ZooKeeper" ON)

# Set compile definitions based on USE_THREADED option
if(USE_THREADED)
    target_compile_definitions(DSE PUBLIC THREADED)
endif()

# Link libraries
target_link_libraries(DSE PUBLIC
    gRPC::grpc++
    protobuf::libprotobuf
    jsoncpp_lib
    absl::base
    absl::strings
    Crow::Crow
    ${ZOOKEEPER_LIB}
)

target_compile_definitions(DSE PUBLIC
    WIN32
    THREADED
    ASIO_STANDALONE
    CROW_USE_ASIO
)

# Add executable
add_executable(DSEApp app/main.cpp)
target_link_libraries(DSEApp PRIVATE DSE)

# If on Windows, add these definitions
if(WIN32)
    target_compile_definitions(DSE PUBLIC
        _WIN32_WINNT=0x0601
        WIN32_LEAN_AND_MEAN
        NOMINMAX
    )
endif()

Documentation has a very different building instructions, but I didn't managed them to work on Windows even through MSYS2:

enter image description here

but in my case I don't see either zookeper_mt.lib or zookeeper_st.lib, but just zookeeper.lib, might it be that it is the static version without the functions and values I mentioned ?

Those functions in the zookeeper.h are under #ifdef THREADED which should be defined for the syncapi building option.

It is written that:

The package includes two shared libraries: zookeeper_st and zookeeper_mt. The former only provides the asynchronous APIs and callbacks for integrating into the application's event loop. The only reason this library exists is to support the platforms were a pthread library is not available or is unstable (i.e. FreeBSD 4.x). In all other cases, application developers should link with zookeeper_mt, as it includes support for both Sync and Async API.

Does this mean that if I'm on windows and dont have pthread library, it will always compile the st version and the error I see is due to the fact that those functions are just didnt compile because of my OS ?

P.S: I tried to check that by changing zoo_create which is the function from the threaded API to zoo_acreate from the #ifndef THREADED and it isn't recognized as a symbol same way.

P.S: adding #define USE_STATIC_LIB

adding the define changed the output, now it looks like:

[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol create_hashtable referenced in function create_zk_hashtable [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol hashtable_insert referenced in function activateWatcher [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol hashtable_search referenced in function activateWatcher [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol hashtable_remove referenced in function add_for_event [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol hashtable_count referenced in function collectWatchers [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol hashtable_destroy referenced in function destroy_zk_hashtable [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol hashtable_iterator referenced in function collectWatchers [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol hashtable_iterator_advance referenced in function collectWatchers [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] zookeeper.lib(zk_hashtable.obj) : error LNK2019: unresolved external symbol hashtable_iterator_remove referenced in function destroy_zk_hashtable [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[build] C:\Users\YOSSI\CLionProjects\DSE\build\Release\DSEApp.exe : fatal error LNK1120: 9 unresolved externals [C:\Users\YOSSI\CLionProjects\DSE\build\DSEApp.vcxproj]
[driver] Build completed: 00:00:34.058
[build] Build finished with exit code 1

P.S 3: looks like that solved part of the problem, as now more deep dependencies aren't recognized, as the sources of zookeeper that were built have the following structure layout:

C:\ZooKeeperC-Release\apache-zookeeper-3.9.2\zookeeper-client\zookeeper-client-c\src>tree /f
Folder PATH listing
Volume serial number is AE6B-2066
C:.
│   addrvec.c
│   addrvec.h
│   cli.c
│   load_gen.c
│   mt_adaptor.c
│   recordio.c
│   st_adaptor.c
│   winport.c
│   winport.h
│   zk_adaptor.h
│   zk_hashtable.c
│   zk_hashtable.h
│   zk_log.c
│   zk_sasl.c
│   zk_sasl.h
│   zookeeper.c
│
└───hashtable
        hashtable.c
        hashtable.h
        hashtable_itr.c
        hashtable_itr.h
        hashtable_private.h
        LICENSE.txt


Solution

  • cmake_minimum_required(VERSION 3.12)
    project(DSE)
    
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    if(MSVC)
      set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
    endif()
    
    if(MSVC)
      set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /VERBOSE:LIB")
    endif()
    

    These lines are improper. Firstly, they must set the cmake variable before project. Secondly, the canonical way is setting a value to the cmake variable CMAKE_MSVC_RUNTIME_LIBRARY since cmake 3.15.

    Try to move project(DSE) after set(CMAKE_*. Or better, if your cmake is 3.15 newer:

    cmake_minimum_required(VERSION 3.15)
    project(DSE)
    
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    if(MSVC)
      set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$<CONFIG:Debug>:Debug>DLL)
    endif()
    
    if(MSVC)
      set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /VERBOSE:LIB")
    endif()
    
    project(DSE)
    
    # The rest part of CMakeLists.txt goes here