【问题标题】:LIBSSH2 and dso_dlfcn.c: ... undefined reference to `dlopen'LIBSSH2 和 dso_dlfcn.c: ...未定义的对 `dlopen' 的引用
【发布时间】:2016-08-07 14:38:28
【问题描述】:

我正在尝试使用静态libgit2openssllibssh2 编译git2go。我的最终目标是能够编译一个无需安装这些库即可部署的go 二进制文件。我在 SO 上找到了一个类似的 question,我用它来创建以下构建库的脚本

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

我将以下补丁应用于git2go 分支next 中的脚本,该脚本构建libgit2 以确保PKG_CONFIG_PATH 指向静态openssllibssh2

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

此设置最终会创建一个本地 install 目录,其中安装了所有库。我使用上面的脚本编译openssl。然后在编译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

您可以看到正在使用静态openssl。显然libdl 没有链接到libcrypto。编译openssl 时的输出有EX_LIBS=-ldl。这应该包括图书馆吗?我尝试在openssl 安装脚本中使用LDLIBS=-ldl,但仍然出现相同的错误。我已经尝试了搜索词libcrypto undefined reference to 'dlopen' 的几乎所有 SO 答案,但均无济于事。任何帮助将不胜感激

【问题讨论】:

  • 另见Cannot find libcrypto library error和评论“执行最终链接时需要添加-ldl。另外,“我已经尝试在 openssl 安装中使用 LDLIBS=-ldl ...” - libssh 有问题,而不是 libcrypto。
  • @jww 如果 libssh 正在寻找参考,那么为什么错误会说 libcrypto.a ... undefined reference...?有点混乱
  • libcrypto.a 具有依赖关系。您可能正在链接您的最终程序或libssh2 - 在这两种情况下,您都需要添加-ldl,因为它是一个依赖项。 OpenSSL 编译并与之链接,因此在构建 OpenSSL 时它不是未满足的依赖项。您可以通过使用no-dso 进行配置来移除 OpenSSL 对文件控制功能的使用。

标签: linker openssl static-linking libgit2 libssh2


【解决方案1】:

我发现将target_link_libraries(libssh2 ${CMAKE_DL_LIBS}) 添加到src/CMakeLists.txt(如here 所述)可以解决问题中提到的问题。请注意,我使用的是 libssh2-1.8.0 和最新的 OpenSSL (5de683d),但我认为这与 OpenSSL_1_0_2-stable 相同。

所以有效的 LIBSSH2 构建代码是:

# 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

注意:我还必须添加 target_link_libraries(libssh2 pthread),因为我在最新版本中获得了对 pthread 的未定义引用。

【讨论】:

    【解决方案2】:

    由于我对pig-config不熟悉,所以切换到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
    

    这样编译成功。

    【讨论】:

      猜你喜欢
      • 2015-02-20
      • 1970-01-01
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      相关资源
      最近更新 更多