gfortran 将 c 库与 conda 链接起来

gfortran linking c libraries with conda

我正在尝试在我没有超级用户权限的 Ubuntu 18.04 服务器上使用 conda 编译 C++/Fortran 程序。

我能够在 Ubuntu 18.04 PC(也使用 conda)上使用相同的源代码正确编译程序,但在服务器上我遇到了一堆错误。目前,我遇到了“找不到库 - 未定义的引用”错误:

gfortran -o glm -Wl,--export-dynamic obj/glm_globals.o obj/glm_util.o obj/glm_csv.o obj/glm_mobl.o obj/glm_mixu.o obj/glm_wqual.o obj/glm_layers.o obj/glm_surface.o obj/glm_input.o obj/glm_plot.o obj/glm_output.o obj/glm_ncdf.o obj/glm_lnum.o obj/glm_init.o obj/glm_flow.o obj/glm_mixer.o obj/glm_deep.o obj/glm_stress.o obj/glm_bird.o obj/glm_model.o obj/glm_types.o obj/glm_const.o obj/glm_debug.o obj/glm_main.o obj/glm_zones.o -L/local/XXX/my_name/PycharmProjects/glm/glm_source/GLM/../libutil/lib -lutil -L/local/XXX/my_name/anaconda3/lib -lnetcdf -L/usr/lib -L/local/XXX/my_name/PycharmProjects/glm/glm_source/GLM/../libplot/lib -lplot -lgd -lpng -ljpeg -lm -lX11    -lgfortran

/local/XXX/my_name/anaconda3/bin/ld: warning: libpthread.so.0, needed by /local/XXX/my_name/anaconda3/lib/libnetcdf.so, not found (try using -rpath or -rpath-link)
/local/XXX/my_name/anaconda3/bin/ld: warning: libxcb.so.1, needed by /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libX11.so, not found (try using -rpath or -rpath-link)
/local/XXX/my_name/anaconda3/bin/ld: warning: libdl.so.2, needed by /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libX11.so, not found (try using -rpath or -rpath-link)
/local/XXX/my_name/anaconda3/bin/ld: warning: librt.so.1, needed by /local/XXX/my_name/anaconda3/lib/./libhdf5_hl.so.100, not found (try using -rpath or -rpath-link)
/local/XXX/my_name/anaconda3/bin/ld: warning: libresolv.so.2, needed by /local/XXX/my_name/anaconda3/lib/././libgssapi_krb5.so.2, not found (try using -rpath or -rpath-link)
/local/XXX/my_name/anaconda3/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libX11.so: undefined reference to `dlopen@GLIBC_2.2.5'
/local/XXX/my_name/anaconda3/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libX11.so: undefined reference to `xcb_wait_for_event'
/local/XXX/my_name/anaconda3/bin/ld: /local/XXX/my_name/anaconda3/lib/././libkrb5.so.3: undefined reference to `__res_nsearch@GLIBC_2.2.5'
...

collect2: error: ld returned 1 exit status
Makefile:277: recipe for target 'glm' failed
make: *** [glm] Error 1

我可以看到链接器未找到的共享库 libpthread.so.0、librt.so.1、libdl.so.2、libresolv.so.2 是其中的一部分glibc。所以我假设链接到该库存在某种问题。

在之前的尝试中,我尝试使用 conda 安装 glibc。当我尝试编译时,这导致 conda 崩溃并出现“分段错误(核心已转储)”。我必须重新安装 anaconda 才能让 conda 再次工作。

在过去的几天里,我还尝试按照警告中的建议添加 -rpath,添加 LD_LIBRARY_PATH,添加包含带有 -L 的共享库的目录。没有任何效果。

此刻我感到很失落。知道哪里出了问题吗?

PS:在我电脑上编译和在服务器上编译的区别是我在我电脑上安装了系统缺少的库,但是在服务器上安装了conda。因此,在服务器上编译时,我不得不使用 -L 添加这些库的位置。

此答案是建议的替代工作流程,旨在避免问题,而不是对 OP 中的问题进行准确诊断。

根据我的经验,我发现 Conda Forge 编译器包有助于简化自定义编译环境的创建和使用。例如,here is the YAML definition 用于构建 kallisto 软件的环境。对于你的情况,我希望是

fortran-compiler.yaml

name: fortran-compiler  # name it what you want
channels:
  - conda-forge
  - defaults
dependencies:
  - fortran-compiler
  - cxx-compiler
  - libpng
  - libgd
  - jpeg
  - libnetcdf
  - openlibm
  - xorg-libx11
# include the other required libraries

使用

创建环境
conda env create -f fortran-compiler.yaml

然后运行激活您在此环境下的编译。激活环境应该自动管理链接器的查找位置,以便找到环境中的库(这部分是 Conda Forge *-compiler 包提供的)。这个想法是让尽可能多的库来自环境本身。

我发现这种方法将手动定位和包含库路径的数量降至最低。但是,它确实需要追踪 Conda Forge 中的库(例如,search for libx11),不幸的是,这并不总是从库名称到包名称的 one-to-one 映射。优点是以这种方式定义的编译环境可以促进跨平台传输——例如,我为 kallisto 准备的 YAML 示例适用于 osx-64linux-64 没有任何变化 - 因为它明确定义了 Conda 将提供共享库。

也许有更简单的方法可以做到这一点,但这至少是我在尝试直接使用 gccclang Anaconda 包的多次糟糕经历后发现的方法。