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...
A symbol is declared but not defined You can fix the errors by including the source code file that contains the definitions as part of the compilation. Alternatively, you can pass . obj files or . lib files that contain the definitions to the linker.
The __imp__ prefix appears whenever you are linking to a DLL. It does not appear when linking to statically linked libraries. Most likely the code is generated to be linked against a DLL import lib, but you have linked it with a static lib instead.
So when we try to assign it a value in the main function, the linker doesn't find the symbol and may result in an “unresolved external symbol” or “undefined reference”. The way to fix this error is to explicitly scope the variable using '::' outside the main before using it.
Unresolved external references occur when the symbol for a function or global variable is referenced in a program, but none of the object files or libraries specified in the link step contain a definition for that symbol.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With