I am compiling a C++
program with -static
so that I can take my program to a server and run it. The server has not all libraries installed I am linking with and when trying to run the program I get the error that libopenblas.so.0
can not be found as OpenBLAS
is not installed:
error while loading shared libraries: libopenblas.so.0: cannot open shared object file: No such file or directory
I need OpenBLAS
for the linear algebra library Armadillo
and I compile with the flags
-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
So is it not possible to statically link OpenBLAS
or did I do something wrong?
EDIT: This is my makefile. I have removed the commands and definitions for other programs for simplicity.
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)
EDIT 2: On my machine all the static (.a
) and shared (.so
) libraries exist and the program runs, but on the server I do not have all of the libraries. That is why I want to build it fully static, but it seems like the dependencies of the libraries are not fully included as shown by 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)
So how can I tell the compiler to include those dependencies in a static way?
Your -static
option is having no effect.
You have written no rule to compile your source files. You are allowing them to be compiled using make's built-in rule:
%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $@ S<
in which:-
$(CXX)
expands to your defined or default C++ compiler$(CPPFLAGS)
expands to your defined Preprocessor flags$(CXXFLAGS)
expands to your defined C++ compiler flagsYou have defined:
CXXFLAGS= -std=c++11 -static -pthread -Ofast -march=native -mtune=native \
-m64 -Wall -Werror -Wextra -Wno-long-long \
-Ishared_methods -Ievaluate_codes/source_files
So -static
is passed to the compilation command by the built-in
recipe. However, it is not a compilation option. It is a linkage option. It
is ignored in compilation. You do not pass it to the linkage command. So it
has no effect.
Two other important make variables that have conventional meanings to make (and are used with those meanings in built-in rules) are:
LDFLAGS
is to be defined as your linkage options, excluding library options
(-lfoo
) and explicitly named librariesLDLIBS
is to be defined as your library options and explicitly named libraries.So -static
, a linkage option, should properly be included in the value of LDFLAGS
, not CXXFLAGS
In many ways your makefile deviates from normal practice and suggests you may not yet be very knowledge about GNU Make. If would be impractical to pick out all the fluff here. Your linkage recipe is:
e_mir: $(OBJS_E_MIR)
$(CXX) $(LDFLAGS) $(OBJS_E_MIR) $(LIBS) -o $(TARGET_E_MIR) $(ENDFLAGS)
The smallest (though not the best) set of corrections that will cause the -static
option to take effect in the linkage is:
-static
from the definition of CXXFLAGS
ENDFLAGS
Be aware that successfully getting -static
to take effect in the linkage does
not mean that the attempted static linkage will succeed: just that it will be
attempted, which is not happening now.
Be aware too that a fully static linkage is a drastic step and is unnecessarily drastic if the problem you are trying to solve is simply that some shared libraries you link with are not available on your target server.
The effect of -static
is require that static versions of all the libraries
required by the linkage must be found by your linkage. Not just your:
-lopenblas -llapack -lgfortran
but also the C runtime library and the Standard C++ library that are linked
by default, plus the Posix Threads library that is requested by -pthread
.
Have you installed the static versions of all those?
If you merely need to link, say, the static versions of libopenblas
and liblapack
, and you have
installed libopenblas.a
liblapack.a
on your system so that the linker
will find them in its default search directories, then you can simply change:
-lopenblas -llapack -lgfortran
to:
-l:libopenblas.a -l:liblapack.a -lgfortran
Whereas -lname
instructs the linker to search the specified (-Ldir
) or
default search directories for either libname.so
(shared library) or libname.a
(static library) and to prefer libfoo.so
if it finds both in the same directory,
-l:name
instructs the linker to search for a file with the exact name name
.
So by specifiying -l:libopenblas.a
you can request linkage of libopenblas.a
with no larger effects than just that.