visual-c++cmakedllimportlnk2019imp

Linking error LNK2019 in MSVC, unresolved symbols with __imp__ prefix, but should be from static lib


I'm running into linking problems in MSVC for a project that I wrote for g++. Here's the problem:

I build libssh as a static library as part of my application, adding the target in cmake with

add_library(ssh_static STATIC $libssh_SRCS)

Libssh is in C, so I have 'extern "C" {...}' wrapping the includes in my c++ sources. I then link the ssh_static target to my executable, sshconnectiontest, with

target_link_libraries(sshconnectiontest ... ssh_static ...)

This all works fine in linux with gcc, but now in MSVC I get

error LNK2019: unresolved external symbol __imp__[function names here] referenced in [filename]

for every libssh function I use.

Any ideas whats going wrong? I've read somewhere that the imp prefix means that the linker is expecting to link a .dll, but this should not be the case since ssh_static is declared a static library in the add_library call...


Solution

  • From what I remember of my Windows days, in MinGW-built DLLs, the __imp__ symbol prefix is used for the trampoline function that calls into the DLL proper. This symbol is then provided by a small static library with the extension .dll.a.

    When you include libssh headers, you need to set a #define to indicate that you're expecting to link statically. If you don't, the libssh functions in the header will be declared __declspec(dllimport) and so the __imp__ symbols will be expected at link time.

    I had a look at the libssh source and found this at the top of libssh.h:

    #ifdef LIBSSH_STATIC
      #define LIBSSH_API
    #else
      #if defined _WIN32 || defined __CYGWIN__
        #ifdef LIBSSH_EXPORTS
          #ifdef __GNUC__
            #define LIBSSH_API __attribute__((dllexport))
          #else
            #define LIBSSH_API __declspec(dllexport)
          #endif
        #else
          #ifdef __GNUC__
            #define LIBSSH_API __attribute__((dllimport))
          #else
            #define LIBSSH_API __declspec(dllimport)
          #endif
        #endif
      #else
        #if __GNUC__ >= 4
          #define LIBSSH_API __attribute__((visibility("default")))
        #else
          #define LIBSSH_API
        #endif
      #endif
    #endif
    

    You need to define LIBSSH_STATIC, either through #define before the #include <libssh.h> line, or as a /D option. Since you're using CMake, you'll probably do this through add_definitions in CMakeLists.txt.