c++unresolved-externalname-manglinglibtorrent

Why is my C++ symbol name different from the libtorrent library I'm linking to and does this cause linking to fail?


I'm trying to link a simple C++ program to libtorrent:

#include <libtorrent/add_torrent_params.hpp>
#include <libtorrent/magnet_uri.hpp>

int main(int argc, char const* argv[])
{
    lt::add_torrent_params atp = lt::parse_magnet_uri(argv[1]);
}

I invoke cl.exe on the command line and it tells me that I have unresolved external symbols:

>cl /EHsc /Fefoo.exe /I<snip>\vcpkg\installed\x86-windows\include main.cpp torrent-rasterbar.lib /link /LIBPATH:<snip>\vcpkg\installed\x86-windows\lib
Microsoft (R) C/C++ Optimizing Compiler Version 19.34.31937 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
Microsoft (R) Incremental Linker Version 14.34.31937.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:foo.exe
/LIBPATH:C:\Users\rages\code\vcpkg\installed\x86-windows\lib
main.obj
torrent-rasterbar.lib
main.obj : error LNK2019: unresolved external symbol "public: __thiscall libtorrent::add_torrent_params::~add_torrent_params(void)" (??1add_torrent_params@libtorrent@@QAE@XZ) referenced in function _main
main.obj : error LNK2019: unresolved external symbol "struct libtorrent::add_torrent_params __cdecl libtorrent::parse_magnet_uri(class boost::basic_string_view<char,struct std::char_traits<char> >)" (?parse_magnet_uri@libtorrent@@YA?AUadd_torrent_params@1@V?$basic_string_view@DU?$char_traits@D@std@@@boost@@@Z) referenced in function _main
foo.exe : fatal error LNK1120: 2 unresolved externals

Running dumpbin /exports on torrent-rasterbar.lib and looking for the add_torrent_params symbol shows me this:

??1add_torrent_params@v2@libtorrent@@QAE@XZ (public: __thiscall libtorrent::v2::add_torrent_params::~add_torrent_params(void))

This is very different from what the compiler is complaining about. I suspect this is what's causing the linker to fail, but I'm not quite sure what I need to do differently to make it work. How do I get my compiler and the library to agree on the symbol names?


Solution

  • This was caused by a missing define. The libtorrent build page is very clear about this:

    A common mistake when building and linking against libtorrent is to build with one set of configuration options (#defines) and link against it using a different set of configuration options. Since libtorrent has some code in header files, that code will not be compatible with the built library if they see different configurations.

    Always make sure that the same TORRENT_* and BOOST_* macros are defined when you link against libtorrent as when you build it. The simplest way to see the full list of macros defined is to build libtorrent with -n -a switches added to b2 command line, which output all compiler switches.

    So I began investigating how vcpkg was building libtorrent. I was able to find some output at $VCPKG_DIR/buildtrees/libtorrent/install-x64-windows-rel-out.log which showed me all the flags that it was passing to cl for each file. Sure enough, passing every single flag there got my code to compile.

    By a process of elimination, I found that TORRENT_NO_DEPRECATE is the magic sauce that makes it work. Here's the bare minimum you need to get it to compile:

    > cl -DTORRENT_NO_DEPRECATE /nologo /EHsc /Fefoo.exe /IE:\vcpkg\installed\x64-windows\include main.cpp torrent-rasterbar.lib /link /LIBPATH:E:\vcpkg\installed\x64-windows\lib main.cpp
    

    Please note this is just for illustrating a solution to the specific issue of mismatched symbols. You should probably use the full set of defines found in the vcpkg log to make sure there are no surprises down the road from other headers.