ccompiler-errorsstatic-linkinglibssh

link libssh with static library (libssh.a)


I was trying to link my program with libssh static library.

Following is my simple code copied from libssh tutorial:

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

int main()
{
  ssh_session my_ssh_session;
  my_ssh_session = ssh_new();
  if (my_ssh_session == NULL)
    exit(-1);

  ssh_free(my_ssh_session);
}

I put library file libssh.a into the subdirectory libs/

Then compile it with command gcc sshtest.c -Llibs -lssh -o sshtest

The output is bunch of undefined reference errors like:

libs/libssh.a(wrapper.c.o): In function `crypto_free':
/home/gg/libssh/src/wrapper.c:156: undefined reference to `BN_clear_free'
/home/gg/libssh/src/wrapper.c:157: undefined reference to `BN_clear_free'
libs/libssh.a(libcrypto.c.o): In function `ssh_reseed':
/home/gg/libssh/src/libcrypto.c:77: undefined reference to `RAND_add'
libs/libssh.a(libcrypto.c.o): In function `sha1_init':
/home/gg/libssh/src/libcrypto.c:84: undefined reference to `EVP_MD_CTX_new'

The problem can be fixed by copying dynamic library files (libssh.so, libssh.so.4, libssh.so.4.5.0) into the libs/ folder, but I guess the compiler will link with dynamic library in this case.

Can somebody tell me the proper way to link libssh static library? Thank you !!

Something extra (optional):

Actually, I was trying to build an ssh server application using includeOS, I try to link dynamic library with it by adding target_link_libraries into the cmakelist.txt, and I got an error usr/bin/ld unrecognized option "-Wl,-rpath,path_to_my_sshlib"when I make it. I guess may be unikernel can not support dynamic linking, because includeOS only has one static libray path variable in cmakelist

----------------------Edit--------------------------------

One of the error message:

`/home/gavin/libssh/src/wrapper.c:156: undefined reference to `BN_clear_free'`

wrapper.c, line 156:

  bignum_free(crypto->e);

it was defined in libssh/libcrypto.h which included by wrapper.h

libcrypto.h line 70:

#define bignum_free(num) BN_clear_free(num)

And I notice that void BN_clear_free(BIGNUM *a); is a function defined in openssl library

Could introducing another library cause the problem? if so, how could I fix it? why dynamic linking dose not have this issue?


Solution

    1. Install libssl-dev, cmake and maybe some other dependencies if you don't have them already.
    2. Build libssh from source with static flags.

      • e.g. extract libssh-0.9.3.tar.xz to /home/user/libssh-0.9.3
      • cd /home/user/libssh-0.9.3
      • mkdir build && cd build
      • cmake ../ -DWITH_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DWITH_STATIC_LIB=ON
      • make
      • now you can use /home/user/libssh-0.9.3/build/src/libssh.a
    3. Compile your code with gcc -I/home/user/libssh-0.9.3/include sshtest.c /home/user/libssh-0.9.3/build/src/libssh.a -lssh -lrt -lcrypto -lz -lpthread -ldl -o sshtest -static

    4. You'll still get some warnings about shared libraries from the glibc, but resulted binary is completely static.

    Presumably you'll need to change include order in your source to 1) stdlib.h, stdio.h etc, 2) libssh/libssh.h. And remove #define LIBSSH_STATIC 1