OpenSSL link libcrypto.a in a static way - linux

I have the following makefile and I would add the library "libcrypto.a" in a static way. I need to do this because the target system cannot install the openssl libraries.
# Environment
MKDIR=mkdir
CP=cp
GREP=grep
NM=x86_64-linux-nm
CCADMIN=CCadmin
RANLIB=x86_64-linux-ranlib
CC=x86_64-linux-gnu-gcc
CCC=x86_64-linux-gnu-g++
CXX=x86_64-linux-gnu-g++
FC=x86_64-linux-gfortran
AS=x86_64-linux-as
# Macros
CND_PLATFORM=GNU-Linux
CND_DLIB_EXT=so
CND_CONF=Release_x86_64
CND_DISTDIR=dist
CND_BUILDDIR=build
# Include project Makefile
include Makefile
# Object Directory
OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
# Object Files
OBJECTFILES= \
${OBJECTDIR}/_ext/7daaf93a/DtaCommand.o \
${OBJECTDIR}/_ext/7daaf93a/DtaDev.o \
${OBJECTDIR}/_ext/7daaf93a/DtaDevGeneric.o \
${OBJECTDIR}/_ext/7daaf93a/DtaDevOpal.o \
${OBJECTDIR}/_ext/7daaf93a/DtaDevOpal1.o \
${OBJECTDIR}/_ext/7daaf93a/DtaDevOpal2.o \
${OBJECTDIR}/_ext/7daaf93a/DtaHashPwd.o \
${OBJECTDIR}/_ext/7daaf93a/DtaHexDump.o \
${OBJECTDIR}/_ext/7daaf93a/DtaResponse.o \
${OBJECTDIR}/_ext/7daaf93a/DtaSession.o \
${OBJECTDIR}/_ext/b7b9df0c/blockwise.o \
${OBJECTDIR}/_ext/b7b9df0c/chash.o \
${OBJECTDIR}/_ext/b7b9df0c/hmac.o \
${OBJECTDIR}/_ext/b7b9df0c/pbkdf2.o \
${OBJECTDIR}/_ext/b7b9df0c/sha1.o \
${OBJECTDIR}/_ext/822bcbe5/DtaDevLinuxNvme.o \
${OBJECTDIR}/_ext/822bcbe5/DtaDevLinuxSata.o \
${OBJECTDIR}/_ext/822bcbe5/DtaDevOS.o \
${OBJECTDIR}/GetPassPhrase.o \
${OBJECTDIR}/LinuxPBA.o \
${OBJECTDIR}/UnlockSEDs.o
# C Compiler Flags
CFLAGS=-m64
# CC Compiler Flags
CCFLAGS=-m64
CXXFLAGS=-m64
# Link Libraries and Options
LDLIBSOPTIONS=-lcurses -ltinfo
# Build Targets
.build-conf: ${BUILD_SUBPROJECTS}
"${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/linuxpba
${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/linuxpba: ${OBJECTFILES}
${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/linuxpba ${OBJECTFILES} ${LDLIBSOPTIONS} -s
${OBJECTDIR}/_ext/7daaf93a/DtaCommand.o: ../Common/DtaCommand.cpp
${MKDIR} -p ${OBJECTDIR}/_ext/7daaf93a
${RM} "$#.d"
$(COMPILE.cc) -O2 -Werror -I../linux -I../Common -I../Common/pbkdf2 -std=c++11 -MMD -MP -MF "$#.d" -o ${OBJECTDIR}/_ext/7daaf93a/DtaCommand.o ../Common/DtaCommand.cpp
#...... SIMILAR FOR THE OTHER ELEMENTS OF "OBJECTDIR ......"
I tried to add to my "LDLIBSOPTIONS" several things but I don't find the correct way to do this, for example:
"-lcrypto" it links the library in a dynamic way (not good for my case)
"[absolute path]/libcrypto.a" it returns "libcrypto.a(dso_dlfcn.o): undefined reference to symbol 'dlclose##GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libdl.so.2: error adding symbols: DSO missing from command line".
"[absolute path]/libcrypto.a -ldl"libcrypto.a(evp_enc.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
Any suggestion ?

OpenSSL link lincrypto.a in a static way
...
"-lcrypto" it links the library in a dynamic way (not good for my case)
Use -l:libcrypto.a. It specifies the full name of the library. Below is from the LD(1) man page. See the part about :filename.
-l namespec
--library=namespec
Add the archive or object file specified by namespec to the list of
files to link. This option may be used any number of times. If
namespec is of the form :filename, ld will search the library path for
a file called filename, otherwise it will search the library path for
a file called libnamespec.a.
On systems which support shared libraries, ld may also search for
files other than libnamespec.a. Specifically, on ELF and SunOS
systems, ld will search a directory for a library called
libnamespec.so before searching for one called libnamespec.a. (By
convention, a .so extension indicates a shared library.) Note that
this behavior does not apply to :filename, which always specifies a
file called filename.
The linker will search an archive only once, at the location where it
is specified on the command line. If the archive defines a symbol
which was undefined in some object which appeared before the archive
on the command line, the linker will include the appropriate file(s)
from the archive. However, an undefined symbol in an object appearing
later on the command line will not cause the linker to search the
archive again.
See the -( option for a way to force the linker to search archives
multiple times.
You may list the same archive multiple times on the command line.
This type of archive searching is standard for Unix linkers. However,
if you are using ld on AIX, note that it is different from the
behaviour of the AIX linker.
"[absolute path]/libcrypto.a" it returns "libcrypto.a(dso_dlfcn.o): undefined reference to symbol 'dlclose##GLIBC_2.2.5' //lib/x86_64-linux-gnu/libdl.so.2: error adding symbols: DSO missing from command line"
For this problem, add -ldl after libcrypto and libssl in your link command.
"[absolute path]/libcrypto.a -ldl"libcrypto.a(evp_enc.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
For this problem, see What does .rodata and -fPIC mean when compiling OpenSSL? and Compilation fails with “relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a shared object”.
The short of it is, you need to configure OpenSSL with the shared option. If you don't want to build the shared libraries, the add -fPIC to CFLAGS. Also see Compilation and Installation on the OpenSSL wiki.

It looks like your libcrypto.a is not compiled as PIC (or at least as PIE), and your toolchain defaults to creating PIE-enabled executables. You probably have to link with a command like this:
gcc -fno-pie -no-pie … -Wl,-Bstatic -lcrypto -Wl,-Bdynamic -ldl -lpthread
Some parts of libcrypto depend on libdl and libpthread, so these libraries are required, too, but you must link them dynamically because they are part of glibc.

Related

Makefile searching for a library file

In an auxiliary make file (named arch.make) which contains some libraries, I have wrote
FFLAGS=-g -O2
FPPFLAGS= -DMPI -DFC_HAVE_FLUSH -DFC_HAVE_ABORT
LDFLAGS=-L/export/apps/computer/lapack-3.2
LAPACK_LIBS=-llapack_LINUX
LIBS=$(LAPACK_LIBS)
Then, the Makefile contains
siesta: check-siesta what version $(MPI_INTERFACE) $(FDF) $(WXML) $(XMLPARSER) \
$(COMP_LIBS) $(ALL_OBJS)
$(FC) -o siesta \
$(LDFLAGS) $(ALL_OBJS) $(FDF) $(WXML) $(XMLPARSER) $(MPI_INTERFACE)\
$(COMP_LIBS) $(FoX_LIBS) $(LIBS)
Other variables are fine. Please note $(LIBS) and $(LDFLAGS) which are defined in arch.make.
That library file really exists according to
root#cluster:ObjPar# ls /export/apps/computer/lapack-3.2/lapack_LINUX.a -l
-rw-r--r-- 1 root root 18296682 Jul 10 20:50 /export/apps/computer/lapack-3.2/lapack_LINUX.a
However, the make process exits with the following error
......
dc_lapack.a `FoX/FoX-config --libs --wcml` -llapack_LINUX -lblas
/usr/bin/ld: cannot find -llapack_LINUX
collect2: ld returned 1 exit status
There are many lines before that but I omitted them.
What should I do?
The linker does not find a file called liblapack_LINUX.a or liblapack_LINUX.so. You will need to point to the file directly with
LAPACK_LIBS=/export/apps/computer/lapack-3.2/lapack_LINUX.a
The LDFLAGS variable may be removed.
You are likely to have to link the BLAS library in this way as well if the library is not called libblas.a or libblas.so. The order of linking may also be important. BLAS before LAPACK.

undefined reference while linking with a shared object

I'm a dumb newbie.
I've got a file named file.c with the functions my_putstr(char *) and my_strlen(char *)
my_putstr() writes the parameter with write() (unistd.h)
I wanted to create a library from file.c so I did :
gcc -fPIC -c file.c
gcc -shared -o libfile.so file.o
Then I created a main.c file and called my_putstr() from it.
I tried to compile and link my .so
gcc -L. -lfile main.c -o test
But I got an undefined reference to my_putstr()
I tried to create a .h with my_putstr() and my_strlen() in it, and include it to the main but I got the same error.
Sorry for stupid questions.
Havaniceday.
Your question suffers lack of information, but I can suggest you at first try
gcc main.c ./libfile.so -Wl,-rpath . -o test
If this will fail, you have something wrong with your sources.
If everything is ok at this point, then try
gcc main.c -L . -lfile -Wl,-rpath . -o test
If this will output undefined reference, then probably you already have something like libfile.a without my_putstr(may be from previous experiments) in your lib path.
If everything is ok with it, then your linker is sensible to order in which libraries is supplied to command string, and you must remember, then library always comes after object, that uses this library.

How to build *.so module in Automake and a libtool-using project?

I have the same problem as others have:
I have a *.la file generated by libtool in an Automake project (e.g. module.la),
but I need the *.so of it to use it for dlopen() (eg. module.so).
But: project is configured and built with --disable-shared to make sure the created main binary is one big statically linked program, e.g. main.x (easier for deployment and debugging). Thus *.so files are not created.
The program main.x is a huge framework-like application which is capable of loading extensions (modules) via dlopen() -- despite it being linked statically.
This works fine when I build module.so by hand. But putting this to work in Makefile.am seems impossible to me. Yes, I can write lib_LTLIBRARIES, but with my standard --disable-shared I do not get a *.so file.
lib_LTLIBRARIES = module.la
module_so_SOURCES = module.cpp
The file module.la is created, which dlopen() refuses to load (of course).
I tried to put rules into Makefile.am building it manually and that works:
# Makefile.am (yes, .am)
all: mm_cpp_logger.so
SUFFIXES = .so
%.so: %.cpp
$(CXX) $(CXXFLAGS) -fPIC -fpic -c -I $(top_srcdir)/include -o $# $<
%.so: %.o
$(CXX) $(LDFLAGS) -shared -fPIC -fpic -o $# $<
But this can only be a workaround. I do not get all the nice auto-features like dependency-checking and installation.
How can I build module.so with still building the main program with --disable-shared (or with the same effect) in the Makefile.am-way?
can I postprocess *.la files to *.so files with a special automake rule?
can I tweak the lib_LTLIBRARIES process to create *.so files in any case?
What you are looking for is called a module. You can tell Autotools to create a static binary (executable) by adding -all-static to the LDFLAGS of the application. I think this is the preferred way over using --disable-shared configure flag (which really is aimed at the libraries rather than the executable)
Something like this should do the trick:
AM_CPPFLAGS=-I$(top_srcdir)/include
lib_LTLIBRARIES = module.la
module_la_LDFLAGS = -module -avoid-version -shared
module_la_SOURCES = mm_cpp_logger.cpp
bin_PROGRAMS = application
application_LDFLAGS = -all-static
application_SOURCES = main.cpp
The .so file will (as usual) end up in the .libs/ subdirectory (unless you install it, of course).
And you can build both your application and plugins in one go (even with a single Makefile.am), so there is no need to call configure multiple times.
The use of -fPIC (and friends) should be auto-detected by Autotools.
Update: here's a little trick to make the shared-libraries available where you expect them. Since all shlibs end up in .libs/, it is sometimes nice to have them in a non-hidden directory.
The following makefile snippet creates convenience links (on platforms that support symlinks; otherwise they are copied). Simply adding the snippet to your makefile (i usually use an -include convenience-link.mk) should be enough (you might need an AC_PROG_LN_S in your configure.ac)
.PHONY: convenience-link clean-convenience-link
convenience-link: $(lib_LTLIBRARIES)
#for soname in `echo | $(EGREP) "^dlname=" $^ | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do \
echo "$$soname: creating convenience link from $(abs_builddir)/.libs to $(top_builddir)"; \
rm -f $(top_builddir)/$$soname ; \
test -e $(abs_builddir)/.libs/$$soname && \
cd $(top_builddir) && \
$(LN_S) $(abs_builddir)/.libs/$$soname $$soname || true;\
done
clean-convenience-link:
#for soname in `echo | $(EGREP) "^dlname=" $(lib_LTLIBRARIES) | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do \
echo "$$soname: cleaning convenience links"; \
test -L $(top_builddir)/$$soname && rm -f $(top_builddir)/$$soname || true; \
done
all-local:: convenience-link
clean-local:: clean-convenience-link
I've solved a similar problem using the noinst_LTLIBRARIES macro.
The noinst_LTLIBRARIES macro creates static, non installable libraries to be only used internally. all noinst_LTLIBRARIES static libraries are created also if you specify the --disable-static configure option.
lib_LTLIBRARIES = libtokenclient.la
noinst_LTLIBRARIES = libtokenclient_static.la
libtokenclient_la_SOURCES = $(TOKEN_SERVER_CLIENT_SOURCES) cDynlib.c cDynlib.h token_mod.h
libtokenclient_la_CFLAGS = #BASE_CFLAGS#
libtokenclient_la_CXXFLAGS = $(libtokenclient_la_CFLAGS)
libtokenclient_la_LIBADD = #B_BASE_OS_LIBS#
libtokenclient_la_LDFLAGS = #LT_PLUGIN_LIBS_FLAGS# #LIBS_FLAGS# $(TOKEN_SERVER_CLIENT_EXPORT_SYMBOLS)
libtokenclient_static_la_SOURCES = $(libtokenclient_la_SOURCES)
libtokenclient_static_la_CFLAGS = $(libtokenclient_la_CFLAGS)
libtokenclient_static_la_CXXFLAGS = $(libtokenclient_static_la_CFLAGS)
token_test_SOURCES = $(TEST_SOURCES)
token_test_LDADD = #B_BASE_OS_LIBS# libtokenclient_static.la
token_test_CFLAGS = #BASE_CFLAGS#
token_test_CXXFLAGS = $(token_test_CFLAGS)
I use noinst_LTLIBRARIES static libraries for 2 reasons:
to speed up compile time I create static libraries to be used as intermediate containers for code that shall be linked against more than once: the code is compiled just once, otherwise automake would compile same source files once for each target
to statically link the code to some executable
One thing that could work according to the libtool documentation for LT_INIT is to partition your build into two packages: the main application and the plugins. That way you could (in theory) invoke:
./configure --enable-shared=plugins
and things would work the way you would expect.

What's the difference between object file and static library(archive file)?

Seems archive file can be generated from object file:
ar rvs libprofile.a profile.o
What's the difference between object file and archive file?
It seems to me that both can be used with gcc directly,e.g.:
gcc *.c profile.o or gcc *.c libprofile.a
What's the difference?
The static library is a collection of one or more object files, with an index to allow rapid searching. There are some minor differences in how the compiler deals with them. With an object file you link like this:
gcc f1.o f2.o -o myexe
with libraries you can also do that:
gcc f1.o libf2.a -o myexe
or you can use shorthand:
gcc d1.o -lf2 -L. -o myexe
Also, gcc will ALWAYS link .o files, but it will only search libraries and link from them if there are undefined names still to resolve.

How to include all objects of an archive in a shared object?

When compiling our project, we create several archives (static libraries), say liby.a and libz.a that each contains an object file defining a function y_function() and z_function(). Then, these archives are joined in a shared object, say libyz.so, that is one of our main distributable target.
g++ -fPIC -c -o y.o y.cpp
ar cr liby.a y.o
g++ -fPIC -c -o z.o z.cpp
ar cr libz.a z.o
g++ -shared -L. -ly -lz -o libyz.so
When using this shared object into the example program, say x.c, the link fails because of an undefined references to functions y_function() and z_function().
g++ x.o -L. -lyz -o xyz
It works however when I link the final executable directly with the archives (static libraries).
g++ x.o -L. -ly -lz -o xyz
My guess is that the object files contained in the archives are not linked into the shared library because they are not used in it. How to force inclusion?
Edit:
Inclusion can be forced using --whole-archive ld option. But if results in compilation errors:
g++ -shared '-Wl,--whole-archive' -L. -ly -lz -o libyz.so
/usr/lib/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x1d): undefined reference to `__init_array_end'
/usr/bin/ld: /usr/lib/libc_nonshared.a(elf-init.oS): relocation R_X86_64_PC32 against undefined hidden symbol `__init_array_end' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value
Any idea where this comes from?
You could try (ld(2)):
--whole-archive
For each archive mentioned on the command line after the --whole-archive option, include every object file in the
archive in the link, rather than searching the archive for the required object files. This is normally used to turn
an archive file into a shared library, forcing every object to be included in the resulting shared library. This
option may be used more than once.
(gcc -Wl,--whole-archive)
Plus, you should put -Wl,--no-whole-archive at the end of the library list. (as said by Dmitry Yudakov in the comment below)

Resources