paullouisageneau / libdatachannel

C/C++ WebRTC network library featuring Data Channels, Media Transport, and WebSockets
https://libdatachannel.org/
Mozilla Public License 2.0
1.72k stars 350 forks source link

Mixed up dynamic and static libjuice dependencies #1225

Open agnickolov opened 1 month ago

agnickolov commented 1 month ago

I'm using vcpkg to install libdatachannel and directing it to generate static libraries. It already has a patch to achieve that even if the library doesn't support that off the shelf. That's not my problem. The problem is that the datachannel-static.lib file as generated depends on the dynamic version of libjuice. I traced the problem to this problematic construct within CMakeLists.txt (lines 418-430):

    if(USE_SYSTEM_JUICE)
        find_package(LibJuice REQUIRED)
        target_compile_definitions(datachannel PRIVATE RTC_SYSTEM_JUICE=1)
        target_compile_definitions(datachannel-static PRIVATE RTC_SYSTEM_JUICE=1)
        target_link_libraries(datachannel PRIVATE LibJuice::LibJuice)
        target_link_libraries(datachannel-static PRIVATE LibJuice::LibJuice)
    else()
        add_subdirectory(deps/libjuice EXCLUDE_FROM_ALL)
        target_compile_definitions(datachannel PRIVATE RTC_SYSTEM_JUICE=0)
        target_compile_definitions(datachannel-static PRIVATE RTC_SYSTEM_JUICE=0)
        target_link_libraries(datachannel PRIVATE LibJuice::LibJuiceStatic)
        target_link_libraries(datachannel-static PRIVATE LibJuice::LibJuiceStatic)
    endif()

The dependencies wires seem to get crossed improperly. I believe the correct linkage should be as follows instead:

    if(USE_SYSTEM_JUICE)
        find_package(LibJuice REQUIRED)
        target_compile_definitions(datachannel PRIVATE RTC_SYSTEM_JUICE=1)
        target_compile_definitions(datachannel-static PRIVATE RTC_SYSTEM_JUICE=1)
        target_link_libraries(datachannel PRIVATE LibJuice::LibJuice)
        target_link_libraries(datachannel-static PRIVATE LibJuice::LibJuiceStatic)
    else()
        add_subdirectory(deps/libjuice EXCLUDE_FROM_ALL)
        target_compile_definitions(datachannel PRIVATE RTC_SYSTEM_JUICE=0)
        target_compile_definitions(datachannel-static PRIVATE RTC_SYSTEM_JUICE=0)
        target_link_libraries(datachannel PRIVATE LibJuice::LibJuice)
        target_link_libraries(datachannel-static PRIVATE LibJuice::LibJuiceStatic)
    endif()

The above issue results in unresolved external symbols for every function from libjuice used in libdatachannel.

4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_create referenced in function "public: __cdecl rtc::impl::IceTransport::IceTransport(struct rtc::Configuration const &,class std::function<void __cdecl(class rtc::Candidate const &)>,class std::function<void __cdecl(enum rtc::impl::Transport::State)>,class std::function<void __cdecl(enum rtc::impl::IceTransport::GatheringState)>)" (??0IceTransport@impl@rtc@@QEAA@AEBUConfiguration@2@V?$function@$$A6AXAEBVCandidate@rtc@@@Z@std@@V?$function@$$A6AXW4State@Transport@impl@rtc@@@Z@5@V?$function@$$A6AXW4GatheringState@IceTransport@impl@rtc@@@Z@5@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_destroy referenced in function "public: __cdecl rtc::impl::IceTransport::IceTransport(struct rtc::Configuration const &,class std::function<void __cdecl(class rtc::Candidate const &)>,class std::function<void __cdecl(enum rtc::impl::Transport::State)>,class std::function<void __cdecl(enum rtc::impl::IceTransport::GatheringState)>)" (??0IceTransport@impl@rtc@@QEAA@AEBUConfiguration@2@V?$function@$$A6AXAEBVCandidate@rtc@@@Z@std@@V?$function@$$A6AXW4State@Transport@impl@rtc@@@Z@5@V?$function@$$A6AXW4GatheringState@IceTransport@impl@rtc@@@Z@5@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_gather_candidates referenced in function "public: void __cdecl rtc::impl::IceTransport::gatherLocalCandidates(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::vector<struct rtc::IceServer,class std::allocator<struct rtc::IceServer> >)" (?gatherLocalCandidates@IceTransport@impl@rtc@@QEAAXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$vector@UIceServer@rtc@@V?$allocator@UIceServer@rtc@@@std@@@5@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_get_local_description referenced in function "public: class rtc::Description __cdecl rtc::impl::IceTransport::getLocalDescription(enum rtc::Description::Type)const " (?getLocalDescription@IceTransport@impl@rtc@@QEBA?AVDescription@3@W4Type@43@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_set_remote_description referenced in function "public: void __cdecl rtc::impl::IceTransport::setRemoteDescription(class rtc::Description const &)" (?setRemoteDescription@IceTransport@impl@rtc@@QEAAXAEBVDescription@3@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_add_remote_candidate referenced in function "public: bool __cdecl rtc::impl::IceTransport::addRemoteCandidate(class rtc::Candidate const &)" (?addRemoteCandidate@IceTransport@impl@rtc@@QEAA_NAEBVCandidate@3@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_add_turn_server referenced in function "private: void __cdecl rtc::impl::IceTransport::addIceServer(struct rtc::IceServer)" (?addIceServer@IceTransport@impl@rtc@@AEAAXUIceServer@3@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_send_diffserv referenced in function "private: virtual bool __cdecl rtc::impl::IceTransport::outgoing(class std::shared_ptr<struct rtc::Message>)" (?outgoing@IceTransport@impl@rtc@@EEAA_NV?$shared_ptr@UMessage@rtc@@@std@@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_get_selected_candidates referenced in function "public: bool __cdecl rtc::impl::IceTransport::getSelectedCandidatePair(class rtc::Candidate *,class rtc::Candidate *)" (?getSelectedCandidatePair@IceTransport@impl@rtc@@QEAA_NPEAVCandidate@3@0@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_get_selected_addresses referenced in function "public: class std::optional<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > __cdecl rtc::impl::IceTransport::getLocalAddress(void)const " (?getLocalAddress@IceTransport@impl@rtc@@QEBA?AV?$optional@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@std@@XZ)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_set_log_level referenced in function "public: __cdecl rtc::impl::IceTransport::IceTransport(struct rtc::Configuration const &,class std::function<void __cdecl(class rtc::Candidate const &)>,class std::function<void __cdecl(enum rtc::impl::Transport::State)>,class std::function<void __cdecl(enum rtc::impl::IceTransport::GatheringState)>)" (??0IceTransport@impl@rtc@@QEAA@AEBUConfiguration@2@V?$function@$$A6AXAEBVCandidate@rtc@@@Z@std@@V?$function@$$A6AXW4State@Transport@impl@rtc@@@Z@5@V?$function@$$A6AXW4GatheringState@IceTransport@impl@rtc@@@Z@5@@Z)
4>datachannel-static.lib(icetransport.cpp.obj) : error LNK2019: unresolved external symbol __imp_juice_set_log_handler referenced in function "public: __cdecl rtc::impl::IceTransport::IceTransport(struct rtc::Configuration const &,class std::function<void __cdecl(class rtc::Candidate const &)>,class std::function<void __cdecl(enum rtc::impl::Transport::State)>,class std::function<void __cdecl(enum rtc::impl::IceTransport::GatheringState)>)" (??0IceTransport@impl@rtc@@QEAA@AEBUConfiguration@2@V?$function@$$A6AXAEBVCandidate@rtc@@@Z@std@@V?$function@$$A6AXW4State@Transport@impl@rtc@@@Z@5@V?$function@$$A6AXW4GatheringState@IceTransport@impl@rtc@@@Z@5@@Z)
paullouisageneau commented 1 month ago

The CMakeLists is correct. USE_SYSTEM_JUICE means linking against the system (dynamic) library, irrelevant of libdatachannel being static or not. Otherwise, it links against the submodule statically. This is how it works with every other submodule.