c++visual-studiocmakepodofo

Unresolved external symbols from libxml functions when compiling PoDoFo in Visual Studio


I am trying to compile the PoDoFo library for my application, and I have stumbled across a problem that I cannot make head or tail of.

When working with PoDoFo's CMake files (please see further details below), I have managed to reach the point where I can save and generate CMake cache without any errors. However when I try to build the library I receive a bunch of linker errors (classic LNK2001 and LNK2019), which all point to some problems with the libxml2 library. I do not understand though is how to deal with this issue, as I have explicitly assigned all relevant references to the library's headers and the required .lib file, with CMake not making any complaints.

Is the problem about the LibXml2.lib or could it be something else?

I used precompiled libraries from podofo-deps and used VS's CMake Settings Editor to link them to the constants used in the CMakeLists.txt (I'm pretty sure there are better terms to describe this, but, alas, I am not very familiar with the terminology):

ZLIB_INCLUDE_DIR: <path>/podofo-deps-master/3rdparty/zlib/include
ZLIB_LIBRARY_DEBUG: <path>/podofo-deps-master/3rdparty/zlib/lib/Win64/zlibd.lib
OPENSSL_INCLUDE_DIR: <path>/podofo-deps-master/3rdparty/openssl/include
OPENSSL_ROOT_DIR: <path>/podofo-deps-master/3rdparty/openssl/lib/Win64
FREETYPE_LIBRARY_DEBUG: <path>/podofo-deps-master/3rdparty/freetype/lib/Win64/freetyped.lib
FREETYPE_LIBRARY_RELEASE: <path>/podofo-deps-master/3rdparty/freetype/lib/Win64/freetype.lib
FREETYPE_INCLUDE_DIR_freetype2: <path>/podofo-deps-master/3rdparty/freetype/include
FREETYPE_INCLUDE_DIR_ft2build: <path>/podofo-deps-master/3rdparty/freetype/include/freetype2
LIBXML2_INCLUDE_DIR: <path>/podofo-deps-master/3rdparty/libxml2/include
LIBXML2_LIBRARY_DEBUG: <path>/podofo-deps-master/3rdparty/libxml2/lib/Win64/libxml2d.lib
LIBXML2_LIBRARY_RELEASE: <path>/podofo-deps-master/3rdparty/libxml2/lib/Win64/libxml2.lib
PODOFO_BUILD_STATIC: TRUE
ZLIB_LIBRARY_RELEASE: <path>/podofo-deps-master/3rdparty/zlib/lib/Win64/zlib.lib

Below is an example of the linker errors popping up:

Error   LNK2019 unresolved external symbol __imp_xmlNodeGetContent referenced in function "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl utls::GetAttributeValue(struct _xmlAttr * const)" (?GetAttributeValue@utls@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAU_xmlAttr@@@Z)  <path>\podofo-master\out\build\x64-Debug\podofo-master  <path>\podofo-master\out\build\x64-Debug\podofo_private.lib(XmlUtils.cpp.obj)

The above is generated by the code

string utls::GetAttributeValue(xmlAttrPtr attr)
{
    PODOFO_ASSERT(attr != nullptr);
    xmlChar* content = xmlNodeGetContent((xmlNodePtr)attr);
    unique_ptr<xmlChar, decltype(xmlFree)> contentFree(content, xmlFree);
    return string((const char*)content);
}

Since it is about the linker, the function's declaration could not be matched with the actual function, but it beats me why that could be the case. The lib used is an actual static library, and not an import one.


Solution

  • The project Podofo correctly looks for libxml2 library with

    find_package(LibXml2)
    

    and correctly uses results of this call as LibXml2::LibXml2 target.

    However, the script FindLibXml2.cmake, which is shipped with CMake and processes that find_package call, doesn't correctly handles the case of the static library and doesn't add LIBXML_STATIC macro definition. But that macro definition is very important on Windows, where a library's header needs to distinguish between providing a library's function as imported (dllimport) or not.

    As a simple workaround you may modify CMakeLists.txt of Podofo and attach the required macro definition to the LibXml2::LibXml2 target:

    # Existing line
    find_package(LibXml2 REQUIRED)
    # Add this line **only** when use **static** libxml2 library.
    set_target_properties(LibXml2::LibXml2 PROPERTIES INTERFACE_COMPILE_DEFINITIONS LIBXML_STATIC)