1

Problem: getting a simple program using the libssh library to compile successfully without getting a linker error.

Program:

#include <iostream>

#define LIBSSH_STATIC 1
#include <libssh/libssh.h>
#include <stdlib.h>

void sftpSession()
{
    ssh_session test_session = ssh_new();
    if (!test_session) {
        throw std::runtime_error("Could not create a session?!");
        return;
    }
    ssh_free(test_session);
    std::cout << "Session created & freed successfully." << std::endl;
}

int main(int argc, char **argv)
{
    std::cout << "SFTP test program" << std::endl;
    try {
        sftpSession();
    }
    catch (const std::runtime_error &e) {
        std::cout << "thrown: " << e.what() << std::endl;
    }
    return EXIT_SUCCESS;
}

Machine is 64-bit, running Windows. Using MinGW (via CodeBlocks) and the build log (edited slightly for readability) shows the compiler command as:

x86_64-w64-mingw32-g++.exe 
  -Wall -fexceptions -O2 -std=c++0x -g -m64 -Dmine_dev=1 
  -I"C:\Program Files\zlib\zlib-1.2.8-dll\include" 
  -I"C:\Program Files (x86)\libssh\libssh-0.6.5\include" 
  -c C:\Users\ ... \SFTP_testing\main.cpp 
  -o obj\Release\main.o

x86_64-w64-mingw32-g++.exe 
  -L"C:\Program Files (x86)\Ingres\IngresII\ingres\lib" 
  -o bin\Release\SFTP_testing.exe 
  obj\Release\main.o  
  -s  
  "C:\Program Files (x86)\libssh\libssh-0.6.5\lib\libssh.dll.a"

obj\Release\main.o: In function `sftpSession()':
C:/Users/ ... /SFTP_testing/main.cpp:9: undefined reference to `ssh_new'
C:/Users/ ... /SFTP_testing/main.cpp:14: undefined reference to `ssh_free'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 2 second(s))
3 error(s), 0 warning(s) (0 minute(s), 2 second(s))

Things I have tried/investigated

I understand that the undefined reference to refers to the linker being able to find the declaration of the functions, but not their definitions.

  • The compiler is indeed finding the header file and the functions' definitions.

  • The header file does have the necessary extern "C" code, including the following:

    #ifdef __cplusplus
    extern "C" {
    #endif
    ...
    LIBSSH_API ssh_session ssh_new(void);
    ...
    LIBSSH_API void ssh_free(ssh_session session);
    ...
    #ifdef __cplusplus
    }
    #endif
    
  • The linker is sucessfully finding the library. (Checked via the ProcessMonitor program. It is definitely accessing the libssh.dll.a file.)

  • Using the nm utility I checked that the object code in libssh.dll.a did indeed contain references for ssh_new and ssh_free

  • Checked no confusion between 32-bit/64-bit issues: there are two versions of the pre-compiled library supplied. One is ...\libssh-0.6.5\bin\libssh.dll and the other is ...\libssh-0.6.5\lib\libssh.dll.a and the former gives me the following error: i386 architecture of input file 'C:\Program Files (x86)\libssh\libssh-0.6.5\bin\libssh.dll' is incompatible with i386:x86-64 output but the latter gives no such error, so I assume that the libssh.dll.a file is the correct library file to use.

  • Checked the advice given in this very similar question about libssh2 about the order of libraries linked, but here the call to g++ looks right as the libssh.dll.a argument is right at the end.

  • Checked the more general advice about linker errors too but could not find anything that seemed to be applicable.

  • Cleaned before rebuilding to avoid effects from "dead wood".

  • Tried other older versions of the library. Same error message.

  • Tried (unsuccessfully) to compile a newer version of libssh.

Community
  • 1
  • 1
Alnitak
  • 141
  • 5
  • 1
    `libssh.dll.a` sounds to me like an import library for dynamic linking with a dll. However you `#define LIBSSH_STATIC 1` as if you are going to link with a static library. – Eelke Jan 20 '17 at 12:06
  • If I don't have that `#define LIBSSH_STATIC 1` line then I get errors `undefined reference to `__imp_ssh_new'` and `undefined reference to `__imp_ssh_free'` – Alnitak Jan 20 '17 at 12:14
  • 1
    `.dll.a` looks strange. `.a` indicates it's a static library. `.dll` indicates it's a dynamic library. – Simon Kraemer Jan 20 '17 at 12:18
  • I pretty much assume that `libssh.dll.a` is a static 32-bit library you are trying to compile into a 64-bit executable. That won't work. – Simon Kraemer Jan 20 '17 at 12:21
  • Looks like there are no precompiled 64-bit libraries available for libssh. In this case you need to either compile your program as 32-bit or compile libssh as a 64-bit library yourself – Simon Kraemer Jan 20 '17 at 12:25

1 Answers1

0

The libssh is not linked. The correct way to do this is to copy the libssh directory (which contains the headers) under the include directory of you Code Blocks installation. and copy the .dll.a file under the lib directory of your CodeBlocks installation. Also delete the #define LIBSSH_STATIC 1 line if you are going to do it this way.

svink
  • 101
  • 1
  • 9