Android ndk static linking to openssl failed with BIO_new_dgram undefined - android-ndk

I built libssl.a and libcryto.a. But when I want to link my.so to it, I got this error:
Error:(130) undefined reference to 'BIO_new_dgram'
If I delete this call, I can compile it succeed.
Did I build the library of openssl in a wrong way?
BIO_new_dgram is in libcrypto.a:
nm libcrypto.a | grep BIO_new_dgram
0000081c T BIO_new_dgram
I configure Openssl with:
./config shared --openssldir=$install_dir --prefix=$install_dir
and link command:
/home/choury/bin/Android/android-sdk-linux/ndk-bundle/toolchains/llvm/prebuilt/l
inux-x86_64/bin/clang++ --target=aarch64-none-linux-android --gcc-toolchain=/ho
me/choury/bin/Android/android-sdk-linux/ndk-bundle/toolchains/aarch64-linux-andr
oid-4.9/prebuilt/linux-x86_64 --sysroot=/home/choury/bin/Android/android-sdk-lin
ux/ndk-bundle/platforms/android-21/arch-arm64 -fPIC -std=c++11 -Wall -fPIC -ggdb
-O0 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-und
efined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -Wl,--build
-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noe
xecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,my.so -o
$outpath/my.so $mypath/a.o $mypath/b.o $install_dir/lib/libssl.a $install_dir/li
b/libcrypto.a -ldl my.a -lz -llog -lm "/home/choury/bin/Android/android-sdk-linux
/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/arm64-v8a/libsupc++.a" "/home/
choury/bin/Android/android-sdk-linux/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9
/libs/arm64-v8a/libgnustl_shared.so"
I build the project with cmake, the Openssl part of it:
set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT_DIR}/include)
set(OPENSSL_LIBRARIES ${OPENSSL_ROOT_DIR}/lib)
set(OPENSSL_CRYPTO_LIBRARY ${OPENSSL_LIBRARIES}/libcrypto.a)
set(OPENSSL_SSL_LIBRARY ${OPENSSL_LIBRARIES}/libssl.a)
find_package(OpenSSL REQUIRED IMPORTED)
The OPENSSL_ROOT_DIR is set with $install_dir in build.gradle.

The linker in NDK is sensitive to the order of static libraries on command line. If libA.a depends on libB.a, the command line should be
clang++ … a.o b.o a/libA.a b/libB.a … -Llibs -lm -ldl -lz -llog -o libqq.so
here I assume libm.so, libdl.so, libz.so and liblog.so. Note that the following command is equivalent:
clang++ … a.o b.o -La -lA -Lb -lB … -Llibs -lm -ldl -lz -llog -o libqq.so

Related

make "cannot find libraries"

I am trying to compile til parameter estimation tool PEST (http://www.pesthomepage.org/) for linux.
According to the PEST-manual I did:
make -f pest.mak all
but I get following error message:
gfortran -c -O3 -static pestdata.for
gfortran -c -O3 -static pest.for
gfortran -c -O3 -static pestsub2.for
gfortran -c -O3 -static writall.for
gfortran -c -O3 -static pardef.for
gfortran -c -O3 -static readpest.for
gfortran -c -O3 -static runpest.for
gfortran -static -o pest \
pest.o pestsub1.o pestsub2.o dercalc.o modrun.o writall.o \
linpos.o lapack1.o writsig.o common.o \
pgetcl.o pestwait.o writint.o pardef.o\
drealrd.o space.o optwt.o cgsolve.o compress.o \
readpest.o runpest.o lsqr.o orthog.o ms_stubs.o pestdata.o
/bin/ld: cannot find -lgfortran
/bin/ld: cannot find -lm
/bin/ld: cannot find -lquadmath
/bin/ld: cannot find -lm
/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
make: *** [pest] Error 1
After goggling I have tried different things, but without results. Can somebody please help
me?
Regards Tanja
Solutions to a problem shouldn't be hidden in comments, which is why I write this answer.
The make output shows that the Makefile tries to link statically.
That requires the libraries that can be linked statically, notably libm.a, libgfortran.a, libquadmath.a and libc.a
A possible solution is to remove the -static flag in the final step.
The resulting executable will of course need the shared objects (libm.so and friends) in order to be able to run. In most situations that's not a problem though.

Makefile for Linux and Mac with address sanitizer

I am trying to write a makefile that I can use on linux and mac that builds with an address sanitizer. This works on my vagrant instance:
CC = gcc
ASAN_FLAGS = -fsanitize=address -fno-omit-frame-pointer -Wno-format-security
ASAN_LIBS = -static-libasan
CFLAGS := -Wall -Werror --std=gnu99 -g3
LDFLAGS += -lpthread
all: hello
hello: tiny_queue.o hello.o
$(CC) -o $# $(CFLAGS) $(ASAN_FLAGS) $(CURL_CFLAGS) $^ $(LDFLAGS) $(CURL_LIBS) $(ASAN_LIBS)
This works on ubuntu/trusty64 but fails on my mac with
$ make
gcc -Wall -Werror --std=gnu99 -g3 -I/opt/X11/include -c -o hello.o hello.c
gcc -o hello -Wall -Werror --std=gnu99 -g3 -fsanitize=address -fno-omit-frame-pointer -Wno-format-security tiny_queue.o hello.o -lpthread -static-libasan
clang: error: unknown argument: '-static-libasan'
make: *** [hello] Error 1
Does anyone know how to write a compatible makefile for the mac and linux?
p.s. I'm very new to C, sorry if this question is super basic.
CC = gcc
ASAN_FLAGS = -fsanitize=address -fno-omit-frame-pointer -Wno-format-security
ASAN_LIBS = -static-libasan
CFLAGS := -Wall -Werror --std=gnu99 -g3
LDFLAGS += -lpthread
all: hello
hello: tiny_queue.o hello.o
$(CC) -o $# $(CFLAGS) $(ASAN_FLAGS) $(CURL_CFLAGS) $^ $(LDFLAGS) $(CURL_LIBS) $(ASAN_LIBS)
You should not specify an Asan library (or a UBsan library, for that matter). Since you are using the compiler driver to drive link, just use -fsanitize=address (this is the recommended way of doing it). Do not add -static-libasan. The compiler driver will add the proper libraries for you.

Undefined references to any libc symbol despite direct link with archive

I am working with the ARM-gcc cross compiler and am having issues linking to any implementation within libc.
Compiling prog.c, writing to prog.o...
~/.programs/arm-gcc/bin/arm-none-eabi-gcc -Wall -fno-common -mcpu=cortex-m4 -mthumb -O0 -g -DF_CPU=72000000 -I~/.programs/arm-gcc/arm-none-eabi/include -I../include -I. -I../src/include -c prog.c -o prog.o > prog.lst
Compiling ../common/sysinit.c, writing to sysinit.o...
~/.programs/arm-gcc/bin/arm-none-eabi-gcc -Wall -fno-common -mcpu=cortex-m4 -mthumb -O0 -g -DF_CPU=72000000 -I~/.programs/arm-gcc/arm-none-eabi/include -I../include -I. -I../src/include -c ../common/sysinit.c -o sysinit.o > sysinit.lst
Assembling ../common/crt0.s, writing to crt0.o...
~/.programs/arm-gcc/bin/arm-none-eabi-as -mcpu=cortex-m4 -o crt0.o ../common/crt0.s > crt0.lst
Compiling uart.c, writing to uart.o...
~/.programs/arm-gcc/bin/arm-none-eabi-gcc -Wall -fno-common -mcpu=cortex-m4 -mthumb -O0 -g -DF_CPU=72000000 -I~/.programs/arm-gcc/arm-none-eabi/include -I../include -I. -I../src/include -c uart.c -o uart.o > uart.lst
~/.programs/arm-gcc/bin/arm-none-eabi-ld prog.o sysinit.o crt0.o uart.o -Map=prog.map -T../common/Teensy31_flash.ld -L~/.programs/arm-gcc/arm-none-eabi/lib -o prog.elf
prog.o: In function `print_char':
/home/user/workspace/prog/src/prog.c:47: undefined reference to `sprintf'
/home/user/workspace/prog/src/prog.c:48: undefined reference to `printf'
/home/user/workspace/prog/src/prog.c:49: undefined reference to `strlen'
prog.o: In function `main':
/home/user/workspace/prog/src/prog.c:72: undefined reference to `memset'
make: *** [makefile:133: prog.elf] Error 1
I threw in a few calls to stdlib to make the point. I have tried to explicitly link against libc using -lc but am met with:
/home/prog/.programs/arm-gcc/bin/arm-none-eabi-ld: cannot find -lc
The archive directory is passed to the linker via:
L~/.programs/arm-gcc/arm-none-eabi/lib
I have checked the contents of this directory and verified the archive to be present:
$ ls ~/.programs/arm-gcc/arm-none-eabi/lib
aprofile-validation.specs libc_s.a linux.specs
aprofile-ve.specs libg.a nano.specs
armv6-m libgloss-linux.a nosys.specs
armv7-ar libg_s.a pid.specs
armv7e-m libm.a rdimon-crt0.o
armv7-m libnosys.a rdimon.specs
cpu-init librdimon.a rdpmon-crt0.o
crt0.o librdimon_s.a rdpmon.specs
fpu librdpmon.a redboot-crt0.o
iq80310.specs libstdc++.a redboot.ld
ldscripts libstdc++.a-gdb.py redboot.specs
libarm_cortexM0l_math.a libstdc++_s.a redboot-syscalls.o
libarm_cortexM4lf_math.a libsupc++.a thumb
libarm_cortexM4l_math.a libsupc++_s.a
libc.a linux-crt0.o
And, finally, the libc does export sprintf (and others)
$ nm libc.a | grep "sprintf"
...
lib_a-sprintf.o:
00000000 T sprintf
00000000 T _sprintf_r
U sprintf
U _sprintf_r
...
Info on the ARM-GCC build I am using:
$ ./arm-none-eabi-gcc -v
Using built-in specs.
COLLECT_GCC=./arm-none-eabi-gcc
COLLECT_LTO_WRAPPER=/home/user/.programs/arm-gcc/bin/../lib/gcc/arm-none-eabi/5.4.1/lto-wrapper
Target: arm-none-eabi
Configured with: /home/build/work/GCC-5-0-build/src/gcc/configure --target=arm-none-eabi --prefix=/home/build/work/GCC-5-0-build/install-native --libexecdir=/home/build/work/GCC-5-0-build/install-native/lib --infodir=/home/build/work/GCC-5-0-build/install-native/share/doc/gcc-arm-none-eabi/info --mandir=/home/build/work/GCC-5-0-build/install-native/share/doc/gcc-arm-none-eabi/man --htmldir=/home/build/work/GCC-5-0-build/install-native/share/doc/gcc-arm-none-eabi/html --pdfdir=/home/build/work/GCC-5-0-build/install-native/share/doc/gcc-arm-none-eabi/pdf --enable-languages=c,c++ --enable-plugins --disable-decimal-float --disable-libffi --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-tls --with-gnu-as --with-gnu-ld --with-newlib --with-headers=yes --with-python-dir=share/gcc-arm-none-eabi --with-sysroot=/home/build/work/GCC-5-0-build/install-native/arm-none-eabi --build=i686-linux-gnu --host=i686-linux-gnu --with-gmp=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-mpfr=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-mpc=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-isl=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-cloog=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-libelf=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --with-pkgversion='GNU Tools for ARM Embedded Processors' --with-multilib-list=armv6-m,armv7-m,armv7e-m,armv7-r,armv8-m.base,armv8-m.main
Thread model: single
gcc version 5.4.1 20160609 (release) [ARM/embedded-5-branch revision 237715] (GNU Tools for ARM Embedded Processors)
The ~ in -L~/.programs/arm-gcc/arm-none-eabi/lib doesn't get expanded. It is the shell that expands ~ into /home/user, but only when it is at the beginning of a word.
Actually, it isn't necessary to add this -L option, because this is already in gcc's default search path. However, you link directly with ld instead of with gcc. That is not a good idea. It is better to link with gcc and allow it to add the default search paths and other required libraries, like libc and libgcc. Since you supply your own crt0, add -nostartfiles to the arguments. So link with:
~/.programs/arm-gcc/bin/arm-none-eabi-gcc prog.o sysinit.o crt0.o uart.o \
-Wl,-Map=prog.map -Wl,-T../common/Teensy31_flash.ld -nostartfiles -o prog.elf

Converting makefile from Intel Fortran Compiler to GFortran

I'm working on implementing a user subroutine for LS-DYNA in linux Red Hat 5.11. To implement the subroutine an executable object file needs to be complied that includes the subroutine fortran code. I have a makefile that needs to be executed to create the .o file.
The problem is that the makefile was written for the Intel Fortran compiler but I only have assess to GFortran. I've already switched the compiler directory but I'm unsure what the other compiler commands do and how to execute those in GFortran. Here's the makefile:
lsdyna: dyn21.o dyn21b.o couple2other_user.o
/usr/bin/gfortran -o lsdyna init_once.o init_keywrd.o dynm.o dyn21.o dyn21b.o couple2other_user.o adummy_graph.o orderByMetis.o adummy_msc.o mscapi.o libdyna.a libbcsext4.a liblsda.a liblssecurity.a liblcpack.a libspooles.a libcparse.a libmf2.a liblsm.a liblscrypt.a libresurf.a libsfg.a libmetis.a libfemster_wrap.a libfemster_wrap2d.a libfemster_wrap1d.a libfemster.a libfemster2d.a libfemster1d.a libpfem.a libmetis.a libblas.a liblapack.a libfftw3.a libsprng.a intel64_101_libansysdp.a libdyna.a libblas.a liblapack.a libmetis.a -i-static -L/usr/X11R6/lib64 -lX11 -openmp -lstdc++ -lrt -lstdc++
dyn21.o: dyn21.f nhisparm.inc
/usr/bin/gfortran -c -w95 -zero -assume byterecl,buffered_io,protect_parens -mP2OPT_hpo_dist_factor=21 -ftz -nopad -fpp2 -openmp -i8 -r8 -DINTEL -DAdd_ -xW -fp-model precise -O2 -I. dyn21.f
dyn21b.o: dyn21b.f nhisparm.inc
/usr/bin/gfortran -c -w95 -zero -assume byterecl,buffered_io,protect_parens -mP2OPT_hpo_dist_factor=21 -ftz -nopad -fpp2 -openmp -i8 -r8 -DINTEL -DAdd_ -xW -fp-model precise -O2 -I. dyn21b.f
couple2other_user.o: couple2other_user.f
/usr/bin/gfortran -c -w95 -zero -assume byterecl,buffered_io,protect_parens -mP2OPT_hpo_dist_factor=21 -ftz -nopad -fpp2 -openmp -i8 -r8 -DINTEL -DAdd_ -xW -fp-model precise -O2 -I. couple2other_user.f

Linking OpenSSL libraries to a program

I have built OpenSSL from source (an intentionally old version; built with ./config && make && make test) and would prefer to use what I have built without doing make install to link against my program.
The command that's failing is:
gcc -Wall -Wextra -Werror -static -Lopenssl/openssl-0.9.8k/ -lssl -lcrypto
-Iopenssl/openssl-0.9.8k/include -o myApp source1.o source2.o common.o`
And I receive a series of errors similar to:
common.c:(.text+0x1ea): undefined reference to `SSL_write'
This makes me think there's something funky with my OpenSSL. If I omit -Lopenssl/openssl-0.9.8k/ from my command, the error changes to being unable to:
/usr/bin/ld: cannot find -lssl
/usr/bin/ld: cannot find -lcrypto
Am I compiling OpenSSL incorrectly? Or how should I best resolve this?
Silly "Linux-isms" strike again! Apparently, I need to change my command such that the -L and -l stuff is at the end like (despite what man gcc seems to indicate):
gcc -Wall -Wextra -Werror -static -o myApp source1.o source2.o common.o -Lopenssl/openssl-0.9.8k/ -lssl -lcrypto -Iopenssl/openssl-0.9.8k/include
Why don't you want to use make install? It can copy generated binaries in the directory you want if you previously passed it to ./configure --prefix $HOME/target_library_install_directory
If you used this trick with every library you build and install, you could then add the target directory to the LIBRARY_PATH environment variable and avoid using -L option.
If you use Autotools, or you are building an Autools project like cURL, then you should be able to use pkg-config. The idea is the Autotools package will read OpenSSL's package configuration and things will "just work" for you.
The OpenSSL package configuration library name is openssl.
You would use it like so in a makefile based project.
%.o: %.c
$(CC) -o $# -c `pkg-config --cflags openssl` $^
target: foo.o bar.o baz.o
$(CC) -o $# `pkg-config --libs openssl` $^
Also see How to use pkg-config in Make and How to use pkg-config to link a library statically.
Another approach is to use pkg-config to preserve compatibility. This is an example of makefile when needs to link OpenSSL.
CC = gcc
CFLAGS = \
-I. \
-D_GNU_SOURCE=1
LDFLAGS = `pkg-config --libs inih`
LDFLAGS += `pkg-config --libs libcurl`
LDFLAGS += `pkg-config --libs liburiparser`
LDFLAGS += `pkg-config --libs openssl`
# Executable
foo: foo.o
$(CC) -o $# $^ $(LDFLAGS)
foo.o: foo.c
$(CC) -c $(CFLAGS) $< -o $#

Resources