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...
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
.
Don't know if it is your case, but the imp prefix may mean that you are compiling a x64 library in a Win32 project.
Somewhat late to the party, but I got the same error when mixing libraries with static and dynamic linkage to the CRT
Using a .DEF File
If you choose to use __declspec(dllimport) along with a .DEF file, you should change the .DEF file to use DATA or CONSTANT to reduce the likelihood that incorrect coding will cause a problem:
// project.def
LIBRARY project
EXPORTS
ulDataInDll CONSTANT
The following table shows why:
Keyword Emits in the import library Exports
CONSTANT _imp_ulDataInDll _ulDataInDll
_ulDataInDll
DATA _imp_ulDataInDll _ulDataInDll
http://msdn.microsoft.com/en-us/library/aa271769(v=vs.60).aspx
BUT CONSTANT is now deprecated
i found another way, in the .DEF file of exported .lib use :
mainthreadid=_mainthreadid
and regenerate the lib with LIB.exe
in the import header file of the dll code...
extern "C" {
extern const __declspec(dllexport) ulong mainthreadid;
}