静态链接到 libopenblas
static linking to libopenblas
我正在用 -static
编译一个 C++
程序,这样我就可以将我的程序带到服务器并 运行 它。服务器没有安装我正在 link 使用的所有库,当尝试 运行 程序时,我收到错误消息 libopenblas.so.0
找不到,因为 OpenBLAS
未安装:
error while loading shared libraries: libopenblas.so.0: cannot open shared object file: No such file or directory
我需要 OpenBLAS
用于线性代数库 Armadillo
并且我使用标志
进行编译
-std=c++11 -static -pthread -Ofast -march=native -mtune=native -m64 -Wall -Werror -Wextra -Wno-long-long -Ishared_methods -Icreate_codes/source_files -Ievaluate_codes/source_files -Igenomes/source_files -lopenblas -llapack -lgfortran
那么是不是不能静态linkOpenBLAS
还是我做错了什么?
编辑:这是我的 makefile。为了简单起见,我删除了其他程序的命令和定义。
CXX = h5c++
CXXFLAGS= -std=c++11 -static -pthread -Ofast -march=native -mtune=native -m64 -Wall -Werror -Wextra -Wno-long-long -Ishared_methods -Ievaluate_codes/source_files
ENDFLAGS = -lopenblas -llapack -lgfortran
RELDIR_E = ./evaluate_codes/source_files
RELDIR_M = ./shared_methods
HEADERS = $(RELDIR_M)/methods.h
SRCS_E_MIR = $(RELDIR_E)/mir.cpp \
$(RELDIR_M)/methods.cpp
OBJS_E_MIR = $(SRCS_E_MIR:.cpp=.o)
TARGET_E_MIR = evaluate_codes/mir.out
e_mir: $(OBJS_E_MIR)
$(CXX) $(LDFLAGS) $(OBJS_E_MIR) $(LIBS) -o $(TARGET_E_MIR) $(ENDFLAGS)
clean_e_mir:
rm -f $(OBJS_E_MIR) $(TARGET_E_MIR)
编辑 2:在我的机器上存在所有静态 (.a
) 和共享 (.so
) 库和程序 运行s,但在服务器上我没有所有的图书馆。这就是为什么我想完全静态地构建它,但似乎没有完全包含库的依赖项,如 ldd mir.out
:
所示
linux-vdso.so.1 => (0x00007fff74532000)
libopenblas.so.0 => /usr/lib/libopenblas.so.0 (0x00007fe73dbc8000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe73d9ab000)
libsz.so.2 => /usr/lib/x86_64-linux-gnu/libsz.so.2 (0x00007fe73d7a8000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fe73d58e000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe73d38a000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fe73d008000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe73ccff000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe73cae9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe73c71f000)
libgfortran.so.3 => /usr/lib/x86_64-linux-gnu/libgfortran.so.3 (0x00007fe73c3f4000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe73fc5c000)
libaec.so.0 => /usr/lib/x86_64-linux-gnu/libaec.so.0 (0x00007fe73c1ec000)
libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007fe73bfad000)
那么我如何告诉编译器以静态方式包含这些依赖项?
您的 -static
选项无效。
您没有编写编译源文件的规则。您允许使用 make 的 built-in rule:
编译它们
%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $@ S<
其中:-
$(CXX)
扩展为您定义的或默认的 C++ 编译器
$(CPPFLAGS)
扩展为您定义的预处理器标志
$(CXXFLAGS)
扩展为您定义的 C++ 编译器标志
您已定义:
CXXFLAGS= -std=c++11 -static -pthread -Ofast -march=native -mtune=native \
-m64 -Wall -Werror -Wextra -Wno-long-long \
-Ishared_methods -Ievaluate_codes/source_files
所以-static
被built-in传递给编译命令
食谱。但是,它不是一个编译选项。这是一个 linkage 选项。它
在编译中被忽略。您不会将其传递给 linkage 命令。所以
没有效果。
另外两个重要的 make 变量具有常规意义 make(并被使用
built-in 规则中的那些含义)是:
LDFLAGS
将定义为您的 link 年龄选项,不包括图书馆选项
(-lfoo
) 和明确命名的库
LDLIBS
将定义为您的库选项并明确命名库。
所以 -static
,一个 linkage 选项,应该正确地包含在 LDFLAGS
的值中,而不是 CXXFLAGS
您的 makefile 在许多方面都偏离了正常做法,并建议您
可能还不是很了解 GNU Make。如果挑出来不切实际
这里所有的绒毛。您的link年龄配方是:
e_mir: $(OBJS_E_MIR)
$(CXX) $(LDFLAGS) $(OBJS_E_MIR) $(LIBS) -o $(TARGET_E_MIR) $(ENDFLAGS)
将导致 -static
的最小(虽然不是最好)一组更正
在link年龄生效的选项是:
- 从
CXXFLAGS
的定义中删除 -static
- 将其添加到
ENDFLAGS
的定义中
请注意,成功让-static
在link年龄生效
并不意味着尝试的静态 linkage 会 成功 :只是它将是
尝试过,但现在没有发生。
还要注意,完全静态 linkage 是一个激烈的步骤,没有必要
如果你试图解决的问题仅仅是一些共享
您 link 使用的库在您的目标服务器上不可用。
-static
的效果是要求所有库的静态版本
link年龄要求的必须根据您的link年龄找到。不只是你的:
-lopenblas -llapack -lgfortran
还有 linked 的 C 运行时库和标准 C++ 库
默认情况下,加上 -pthread
请求的 Posix 线程库。
您是否安装了所有这些的静态版本?
如果您只需要 link,比如 libopenblas
和 liblapack
的静态版本,那么您有
在您的系统上安装了 libopenblas.a
liblapack.a
以便 linker
将在其默认搜索目录中找到它们,然后您只需更改:
-lopenblas -llapack -lgfortran
至:
-l:libopenblas.a -l:liblapack.a -lgfortran
而 -lname
指示 linker 搜索指定的 (-Ldir
) 或
libname.so
(共享库)或 libname.a
的默认搜索目录
(静态库),如果在同一目录中找到两者,则更喜欢 libfoo.so
,
-l:name
指示 link 用户搜索具有确切名称 name
的文件。
因此,通过指定 -l:libopenblas.a
,您可以请求 linkage of libopenblas.a
没有比这更大的影响了。
我正在用 -static
编译一个 C++
程序,这样我就可以将我的程序带到服务器并 运行 它。服务器没有安装我正在 link 使用的所有库,当尝试 运行 程序时,我收到错误消息 libopenblas.so.0
找不到,因为 OpenBLAS
未安装:
error while loading shared libraries: libopenblas.so.0: cannot open shared object file: No such file or directory
我需要 OpenBLAS
用于线性代数库 Armadillo
并且我使用标志
-std=c++11 -static -pthread -Ofast -march=native -mtune=native -m64 -Wall -Werror -Wextra -Wno-long-long -Ishared_methods -Icreate_codes/source_files -Ievaluate_codes/source_files -Igenomes/source_files -lopenblas -llapack -lgfortran
那么是不是不能静态linkOpenBLAS
还是我做错了什么?
编辑:这是我的 makefile。为了简单起见,我删除了其他程序的命令和定义。
CXX = h5c++
CXXFLAGS= -std=c++11 -static -pthread -Ofast -march=native -mtune=native -m64 -Wall -Werror -Wextra -Wno-long-long -Ishared_methods -Ievaluate_codes/source_files
ENDFLAGS = -lopenblas -llapack -lgfortran
RELDIR_E = ./evaluate_codes/source_files
RELDIR_M = ./shared_methods
HEADERS = $(RELDIR_M)/methods.h
SRCS_E_MIR = $(RELDIR_E)/mir.cpp \
$(RELDIR_M)/methods.cpp
OBJS_E_MIR = $(SRCS_E_MIR:.cpp=.o)
TARGET_E_MIR = evaluate_codes/mir.out
e_mir: $(OBJS_E_MIR)
$(CXX) $(LDFLAGS) $(OBJS_E_MIR) $(LIBS) -o $(TARGET_E_MIR) $(ENDFLAGS)
clean_e_mir:
rm -f $(OBJS_E_MIR) $(TARGET_E_MIR)
编辑 2:在我的机器上存在所有静态 (.a
) 和共享 (.so
) 库和程序 运行s,但在服务器上我没有所有的图书馆。这就是为什么我想完全静态地构建它,但似乎没有完全包含库的依赖项,如 ldd mir.out
:
linux-vdso.so.1 => (0x00007fff74532000)
libopenblas.so.0 => /usr/lib/libopenblas.so.0 (0x00007fe73dbc8000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe73d9ab000)
libsz.so.2 => /usr/lib/x86_64-linux-gnu/libsz.so.2 (0x00007fe73d7a8000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fe73d58e000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe73d38a000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fe73d008000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe73ccff000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe73cae9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe73c71f000)
libgfortran.so.3 => /usr/lib/x86_64-linux-gnu/libgfortran.so.3 (0x00007fe73c3f4000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe73fc5c000)
libaec.so.0 => /usr/lib/x86_64-linux-gnu/libaec.so.0 (0x00007fe73c1ec000)
libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007fe73bfad000)
那么我如何告诉编译器以静态方式包含这些依赖项?
您的 -static
选项无效。
您没有编写编译源文件的规则。您允许使用 make 的 built-in rule:
编译它们%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $@ S<
其中:-
$(CXX)
扩展为您定义的或默认的 C++ 编译器$(CPPFLAGS)
扩展为您定义的预处理器标志$(CXXFLAGS)
扩展为您定义的 C++ 编译器标志
您已定义:
CXXFLAGS= -std=c++11 -static -pthread -Ofast -march=native -mtune=native \
-m64 -Wall -Werror -Wextra -Wno-long-long \
-Ishared_methods -Ievaluate_codes/source_files
所以-static
被built-in传递给编译命令
食谱。但是,它不是一个编译选项。这是一个 linkage 选项。它
在编译中被忽略。您不会将其传递给 linkage 命令。所以
没有效果。
另外两个重要的 make 变量具有常规意义 make(并被使用 built-in 规则中的那些含义)是:
LDFLAGS
将定义为您的 link 年龄选项,不包括图书馆选项 (-lfoo
) 和明确命名的库LDLIBS
将定义为您的库选项并明确命名库。
所以 -static
,一个 linkage 选项,应该正确地包含在 LDFLAGS
的值中,而不是 CXXFLAGS
您的 makefile 在许多方面都偏离了正常做法,并建议您 可能还不是很了解 GNU Make。如果挑出来不切实际 这里所有的绒毛。您的link年龄配方是:
e_mir: $(OBJS_E_MIR)
$(CXX) $(LDFLAGS) $(OBJS_E_MIR) $(LIBS) -o $(TARGET_E_MIR) $(ENDFLAGS)
将导致 -static
的最小(虽然不是最好)一组更正
在link年龄生效的选项是:
- 从
CXXFLAGS
的定义中删除 - 将其添加到
ENDFLAGS
的定义中
-static
请注意,成功让-static
在link年龄生效
并不意味着尝试的静态 linkage 会 成功 :只是它将是
尝试过,但现在没有发生。
还要注意,完全静态 linkage 是一个激烈的步骤,没有必要 如果你试图解决的问题仅仅是一些共享 您 link 使用的库在您的目标服务器上不可用。
-static
的效果是要求所有库的静态版本
link年龄要求的必须根据您的link年龄找到。不只是你的:
-lopenblas -llapack -lgfortran
还有 linked 的 C 运行时库和标准 C++ 库
默认情况下,加上 -pthread
请求的 Posix 线程库。
您是否安装了所有这些的静态版本?
如果您只需要 link,比如 libopenblas
和 liblapack
的静态版本,那么您有
在您的系统上安装了 libopenblas.a
liblapack.a
以便 linker
将在其默认搜索目录中找到它们,然后您只需更改:
-lopenblas -llapack -lgfortran
至:
-l:libopenblas.a -l:liblapack.a -lgfortran
而 -lname
指示 linker 搜索指定的 (-Ldir
) 或
libname.so
(共享库)或 libname.a
的默认搜索目录
(静态库),如果在同一目录中找到两者,则更喜欢 libfoo.so
,
-l:name
指示 link 用户搜索具有确切名称 name
的文件。
因此,通过指定 -l:libopenblas.a
,您可以请求 linkage of libopenblas.a
没有比这更大的影响了。