Lapack 链接错误,使用 -fPIC 重新编译
Lapack linking error, recompile with -fPIC
我有一个复杂的程序,用于用Levenberg-Marquardt方法拟合非线性函数。
该程序使用来自Lapack库的线性方程组的求解器,我在其中使用了:
extern "C" ...
链接到外部 Fortran 库。该程序在我的笔记本电脑上运行没有任何问题(使用 Ubuntu 12.04),我已经使用它进行测试一段时间了。
问题:
现在我搬到了大胖的64核计算机,以便开始做一些真正的计算,计算机上有一个科学的linux 6。事实证明,大型计算机没有安装 lapack,所以我得到了 lapack 3.4.2,对其进行了编译,并按照此处的说明构建了它:
http://matrixprogramming.com/2011/04/using-lapack-from-c/comment-page-1
在那之后,我在我的 cmake 文件中绝对没有更改以前有效的任何内容,只是添加了链接选项:
-L/xdata/Compilers/Sources/lapack-3.4.2
现在我收到错误:
/usr/bin/ld: /xdata/Compilers/Sources/lapack-3.4.2/liblapack.a(dsytrf.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
只是为了记录,我的 cmake 脚本到处都有 -fPIC 和 -fPIE......我使用它的链接:
target_link_libraries(LibsModule -lgsl)
target_link_libraries(LibsModule -lgslcblas)
target_link_libraries(LibsModule -lrt)
target_link_libraries(LibsModule -lpthread)
target_link_libraries(LibsModule -pie)
target_link_libraries(LibsModule -fPIC)
target_link_libraries(LibsModule -L/xdata/Compilers/Sources/lapack-3.4.2)
target_link_libraries(LibsModule -lgfortran)
target_link_libraries(LibsModule -llapack -fPIC)
target_link_libraries(LibsModule -lblas -fPIC)
我做错了什么?请指教。
谢谢。
解决方案是用 -fPIC 重新编译 lapack 本身。因此,在您的make.inc中更改为以下内容:
FORTRAN = gfortran -m64 -fPIC
OPTS = -O2 -m64 -fPIC
DRVOPTS = $(OPTS)
NOOPT = -O0 -m64 -fPIC
LOADER = gfortran -m64 -fPIC
您也可以使用 -O3
进行更好的优化,它工作正常!
选项-m64
取决于您是否要使用 64 位系统。您的选择!
干杯!
如果使用mkdir build; cd build; cmake ..; make
路由,请使用 cmake .. -DBUILD_SHARED_LIBS=ON
。
为什么会这样?-fPIC 选项使 gcc 使用相对地址 [1]
对接受的答案的评论:"更具体地说,共享库应该在进程之间共享,但可能并不总是可以在两个进程的同一地址加载库。如果代码不是独立于位置的,那么每个进程都需要自己的副本" - Simon Richter
[1] GCC -fPIC 选项
- 使用 MINGW gcc 编译时,不会为 std::string 调用重载的新运算符
- 如何编译:Mac上的Synergy(2017年的新工具链)
- 如何编译和运行一个新的 C++ Actor 框架项目?
- C++编译新的警告过滤器
- 每次都构建(make)lib,只有在lib较新时才重新编译项目
- 如何创建指向派生类的新指针,该派生类在C++编译时未知
- 如何在不退出和失去断点的情况下重新加载重新编译的二进制文件
- 在编译时将整数和分数部分宏组合成一个新的宏或双精度
- C++运算符新重载、编译错误
- 在新OSX上编译旧碳应用
- 代码块在尝试编译或创建新文件时出现"An assertion failed!"错误
- 在新的Visual Studio项目中包含任何Eigen 3.3.1文件将无法编译
- RCpp:如何在不重新启动R的情况下重新加载重新编译的C++代码
- 新安装的MinGW问题与编译和可执行文件
- 重新编译二进制类或派生类,以便在基类中添加新方法
- 添加新库以编译任何术语.如何编辑生成文件
- C++,如果其他新文件出现问题,使用g++进行编译可以很好地工作
- 每次添加新的源子文件夹时,Cmake都会重新编译所有内容
- 不完整类型的新内容在包装在模板中时编译
- 使用新的 Qt5 信号/插槽机制连接 QTcpSocket::error() 时编译错误