4

I am trying to compile git2go using static libgit2, openssl, and libssh2. My end goal is to be able to compile a go binary that can be deployed without the need to install these libraries. I found a similar question on SO that I have used to create the following scripts that build the libraries

OPENSSL:

#!/bin/sh

set -ex
INSTALL_PATH="$PWD/install"
SUBMODULE_PATH="$PWD/submodules/openssl"

cd $SUBMODULE_PATH &&
mkdir -p $INSTALL_PATH/lib &&
mkdir -p build &&

# Switch to a stable version
git checkout OpenSSL_1_0_2-stable &&
./config threads no-shared --prefix=$INSTALL_PATH -fPIC -DOPENSSL_PIC &&
make depend &&
make &&
make install

LIBSSH2:

#!/bin/sh

set -ex

INSTALL_PATH="$PWD/install"
SUBMODULE_PATH="$PWD/submodules/libssh2"

# without this, the system's openssl shared object gets linked in
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$INSTALL_PATH/lib/pkgconfig:$INSTALL_PATH/lib64/pkgconfig"

cd $SUBMODULE_PATH &&
mkdir -p $INSTALL_PATH/lib &&
mkdir build
cd build &&
cmake -DTHREADSAFE=ON \
      -DBUILD_CLAR=OFF \
      -DBUILD_SHARED_LIBS=OFF \
      -DCMAKE_C_FLAGS=-fPIC \
      -DCMAKE_BUILD_TYPE="RelWithDebInfo" \
      -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH \
      .. &&

cmake --build .
make install

I am applying the following patch to a script in git2go branch next that builds libgit2 in an attempt to ensure that PKG_CONFIG_PATH points to the static openssl and libssh2 libraries

LIBGIT2:

--- build-libgit2-static.sh.orig    2016-04-14 22:49:53.000000000 -0700
+++ build-libgit2-static.sh 2016-04-14 22:52:04.000000000 -0700
@@ -2,10 +2,12 @@

 set -ex

-VENDORED_PATH=vendor/libgit2
+INSTALL_PATH="$PWD/install"
+VENDORED_PATH="$PWD/submodules/git2go/vendor/libgit2"
+export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$INSTALL_PATH/lib/pkgconfig:$INSTALL_PATH/lib64/pkgconfig"

 cd $VENDORED_PATH &&
-mkdir -p install/lib &&
+mkdir -p $INSTALL_PATH/lib &&
 mkdir -p build &&
 cd build &&
 cmake -DTHREADSAFE=ON \
@@ -13,7 +15,8 @@
       -DBUILD_SHARED_LIBS=OFF \
       -DCMAKE_C_FLAGS=-fPIC \
       -DCMAKE_BUILD_TYPE="RelWithDebInfo" \
-      -DCMAKE_INSTALL_PREFIX=../install \
+      -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH \
       .. &&

 cmake --build .
+make install

This setup ultimately creates a local install directory that has all the libraries installed to it. I compile openssl using the above script. Then get the following output when compiling libssh2:

...
Found OpenSSL: (path to project)/install/lib/libssl.a;(path to project)/install/lib/libcrypto.a (found version "1.0.2h-dev")
...
Linking C static library libssh2.a
gmake[3]: Leaving directory `(path to project)/submodules/libssh2/build'
[ 46%] Built target libssh2
gmake[3]: Entering directory `(path to project)/submodules/libssh2/build'
Scanning dependencies of target example-direct_tcpip
gmake[3]: Leaving directory `(path to project)/submodules/libssh2/build'
gmake[3]: Entering directory `(path to project)/submodules/libssh2/build'
[ 48%] Building C object example/CMakeFiles/example-direct_tcpip.dir/direct_tcpip.c.o
Linking C executable example-direct_tcpip
(path to project)/install/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_globallookup':
dso_dlfcn.c:(.text+0x11): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x24): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x2f): undefined reference to `dlclose'
(path to project)/install/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_bind_func':
dso_dlfcn.c:(.text+0x354): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x412): undefined reference to `dlerror'
(path to project)/install/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_bind_var':
dso_dlfcn.c:(.text+0x484): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x542): undefined reference to `dlerror'
(path to project)/install/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_load':
dso_dlfcn.c:(.text+0x5a9): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x60d): undefined reference to `dlclose'
dso_dlfcn.c:(.text+0x645): undefined reference to `dlerror'
(path to project)/install/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_pathbyaddr':
dso_dlfcn.c:(.text+0x6d1): undefined reference to `dladdr'
dso_dlfcn.c:(.text+0x731): undefined reference to `dlerror'
(path to project)/install/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_unload':
dso_dlfcn.c:(.text+0x792): undefined reference to `dlclose'
collect2: error: ld returned 1 exit status
gmake[3]: Leaving directory `(path to project)/submodules/libssh2/build'
gmake[2]: Leaving directory `(path to project)/submodules/libssh2/build'
gmake[1]: Leaving directory `(path to project)(path to project)/submodules/libssh2/build'
gmake[3]: *** [example/example-direct_tcpip] Error 1
gmake[2]: *** [example/CMakeFiles/example-direct_tcpip.dir/all] Error 2
gmake[1]: *** [all] Error 2
make: *** [build-libssh2] Error 2

You can see that the static openssl is being used. Obviously libdl is not getting linked in to libcrypto. The output when compiling openssl has EX_LIBS=-ldl. Should this include the library? I have tried using LDLIBS=-ldl in the openssl install script but still the same error. I have tried nearly every SO answer for the search term libcrypto undefined reference to 'dlopen' to no avail. Any help would be much appreciated

Community
  • 1
  • 1
arynhard
  • 173
  • 9
  • Also see [Cannot find libcrypto library error](http://stackoverflow.com/q/10368671) and the comment *"You need to add `-ldl` when performing the final link"*. Also, *"I have tried using LDLIBS=-ldl in the openssl install ..."* - libssh is having the troubles, not libcrypto. – jww Apr 15 '16 at 21:28
  • @jww if libssh is looking for the reference then why does the error say libcrypto.a ... undefined reference...? A bit confusing – arynhard Apr 15 '16 at 21:33
  • `libcrypto.a` has the dependency. You could be linking your final program or `libssh2` - in both cases, you will need to add `-ldl` because its a dependency. OpenSSL compiles and links with it, so its not an unmet dependency when OpenSSL is built. You can remove OpenSSL's use of the file control functions by configuring with `no-dso`. – jww Apr 16 '16 at 20:43

2 Answers2

0

Since I am not familiar with pig-config I switched to Autoconf:

#!/bin/sh

set -ex

INSTALL_PATH="$PWD/install"
SUBMODULE_PATH="$PWD/submodules/libssh2"

mkdir -p $INSTALL_PATH/lib &&
cd $SUBMODULE_PATH &&
./buildconf
./configure --prefix=$INSTALL_PATH --libdir=$INSTALL_PATH/lib64 --with-openssl CFLAGS="-fPIC" LDFLAGS="-m64 -L$INSTALL_PATH/lib -L$INSTALL_PATH/lib64" LIBS=-ldl
make
make install

This successfully compiles.

arynhard
  • 173
  • 9
0

I found out that adding target_link_libraries(libssh2 ${CMAKE_DL_LIBS}) to src/CMakeLists.txt (as explained here) solves the problem mentioned in the question. Note that I am using libssh2-1.8.0 and latest OpenSSL (5de683d), but I think it's the same story with OpenSSL_1_0_2-stable.

So the LIBSSH2 build code that works is:

# inside libssh2 root
printf '\ntarget_link_libraries(libssh2 ${CMAKE_DL_LIBS})' >> src/CMakeLists.txt
mkdir build && cd build
cmake -DTHREADSAFE=ON \
      -DBUILD_CLAR=OFF \
      -DBUILD_SHARED_LIBS=OFF \
      -DCMAKE_C_FLAGS=-fPIC \
      -DCMAKE_BUILD_TYPE="RelWithDebInfo" \
      -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH \
      .. &&
cmake --build .
make install

Note: I also had to add target_link_libraries(libssh2 pthread) because I was getting undefined references to pthread with the latest versions.

Calin
  • 2,110
  • 1
  • 21
  • 36