问题描述
我试图在没有超级用户权限的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,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),不幸的是,这并不总是从库名到包名的一对一映射。好处是,以这种方式定义的编译环境可以促进跨平台的传输-例如,我为Kallisto编写的示例YAML在 osx-64 和 linux-64 上均可工作无需任何更改-因为它明确定义了Conda将提供共享库。
也许有更简单的方法可以做到这一点,但这至少是我在尝试直接使用gcc
或clang
Anaconda软件包遇到了许多不良经验之后发现的。