Why won't GCC link to libz? - gcc

gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/vagrant/python/include/python2.7 -c external/KentLib/wWigIO/wWigIO.c -o build/temp.linux-i686-2.7/external/KentLib/wWigIO/wWigIO.o -w -shared -fPIC -p -Iexternal/KentLib/inc
Then:
gcc -pthread -shared build/temp.linux-i686-2.7/external/KentLib/wWigIO/wWigIO.o -o build/lib.linux-i686-2.7/wWigIO.so -DMACHTYPE_x86_64 -lz -lm external/KentLib/lib/jkweb.a
(sorry for the messy-ness of these commands I wanted to copy them verbatim to avoid leaving out important details)
Then, I look at the symbols, and notice that compress is not defined:
$ nm build/lib.linux-i686-2.7/wWigIO.so | grep compress
U compress
0002486d t getDecompressor
00024b28 T lineFileDecompress
00024c0f T lineFileDecompressFd
00024c8b T lineFileDecompressMem
U uncompress
00037cd2 T zUncompress
It doesn't seem to be linking to the either libm or libz:
$ ldd build/lib.linux-i686-2.7/wWigIO.so
linux-gate.so.1 => (0xb76e2000)
libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb7668000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb74be000)
/lib/ld-linux.so.2 (0xb76e3000)
I know that libz is installed and it's in the search path:
$ sudo cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
$ sudo cat /etc/ld.so.conf.d/*.conf
# Multiarch support
/lib/i386-linux-gnu
/usr/lib/i386-linux-gnu
/lib/i686-linux-gnu
/usr/lib/i686-linux-gnu
# libc default configuration
/usr/local/lib
libz is in those locations:
$ locate libz
/lib/i386-linux-gnu/libz.so.1
/lib/i386-linux-gnu/libz.so.1.2.3.4
/usr/lib/i386-linux-gnu/libz.a
/usr/lib/i386-linux-gnu/libz.so
I can see the symbol defined in libz.so
$ nm -D /usr/lib/i386-linux-gnu/libz.so | grep compress
00001d60 T compress
00001c70 T compress2
00001da0 T compressBound
00003d20 T uncompress
The only way I can get this to work is to change the gcc command to this (bold part is added):
gcc -pthread -shared build/temp.linux-i686-2.7/external/KentLib/wWigIO/wWigIO.o -o build/lib.linux-i686-2.7/wWigIO.so -DMACHTYPE_x86_64 -lz -lm external/KentLib/lib/jkweb.a /usr/lib/i386-linux-gnu/libz.a
This makes no sense to me. Why wouldn't libz be linking?

I sort of figured out a solution.
If I set LDFLAGS='-Wl,--no-as-needed -lz' then it does indeed link to libz and the compiled shared library now does not get the undefined symbol error.
However, I'm still confused as to why it doesn't link to libz by just providing the -lz flag.

Related

Same Makefile executing different commands in different computers

During installation of pintos, I had to run make.
Following is the Makefile.
all: setitimer-helper squish-pty squish-unix
CC = gcc
CFLAGS = -Wall -W
LDFLAGS = -lm
setitimer-helper: setitimer-helper.o
squish-pty: squish-pty.o
squish-unix: squish-unix.o
clean:
rm -f *.o setitimer-helper squish-pty squish-unix
In one computer it executed correctly. (output for the command is given below)
gcc -Wall -W -c -o setitimer-helper.o setitimer-helper.c
gcc -lm setitimer-helper.o -o setitimer-helper
gcc -Wall -W -c -o squish-pty.o squish-pty.c
gcc -lm squish-pty.o -o squish-pty
gcc -Wall -W -c -o squish-unix.o squish-unix.c
gcc -lm squish-unix.o -o squish-unix
but in other computer I got the following error
gcc -lm setitimer-helper.o -o setitimer-helper
setitimer-helper.o: In function `main':
setitimer-helper.c:(.text+0xc9): undefined reference to `floor'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'setitimer-helper' failed
make: *** [setitimer-helper] Error 1
If looked at first line of outputs of both make commands
gcc -Wall -W -c -o setitimer-helper.o setitimer-helper.c
and
gcc -lm setitimer-helper.o -o setitimer-helper
They are different.
Why make is executing different commands for the same Makefile? and What should I do to remove error?
In the first computer, the setitimer-helper.o file either doesn't exist or the setitimer-helper.c file is newer, so make needs to rebuild it. Thus it runs the compiler, then afterwards it performs the link operation:
gcc -Wall -W -c -o setitimer-helper.o setitimer-helper.c
gcc -lm setitimer-helper.o -o setitimer-helper
On the second computer, the setitimer-helper.o file already exists and is newer than the setitimer-helper.c file, so the compile command was not needed and the second computer proceeded directly to the link line:
gcc -lm setitimer-helper.o -o setitimer-helper
The real question is why you got the linker error on the second computer.
The answer to that is that the -lm flag needs to come on the linker line after the object files. This happens because you added -lm to the LDFLAGS variable which is not the right one: that should contain options that tell the linker where to look for files, etc. (for example, the -L option).
Libraries should be added to the LDLIBS variable, not LDFLAGS. Change your makefile to this:
all: setitimer-helper squish-pty squish-unix
CC = gcc
CFLAGS = -Wall -W
LDLIBS = -lm
setitimer-helper: setitimer-helper.o
squish-pty: squish-pty.o
squish-unix: squish-unix.o
clean:
rm -f *.o setitimer-helper squish-pty squish-unix
Your link line will then look like:
gcc setitimer-helper.o -o setitimer-helper -lm
and should work properly.

libpng16.so.16: undefined reference to `inflateReset2#ZLIB_1.2.3.4'

I am building a fork of caffe (3D-caffe), on my university cluster which has a different builds of different versions of different software in /software/software/<package>/<version-compiler>/
When cmake executes this compilation step:
g++ -fPIC -Wall -Wno-sign-compare -Wno-uninitialized -O3 -DNDEBUG \
CMakeFiles/caffe.bin.dir/caffe.cpp.o -o caffe -rdynamic ../lib/libcaffe.so \
../lib/libproto.a /software/software/Boost/1.61.0-foss-2016a/lib/libboost_system.so \
/software/software/Boost/1.61.0-foss-2016a/lib/libboost_thread.so \
-lpthread -lglog /software/software/gflags/2.1.2-foss-2016a/lib/libgflags.so \
-lprotobuf -lpthread -lglog \
/software/software/gflags/2.1.2-foss-2016a/lib/libgflags.so \
-lprotobuf -lhdf5_hl -lhdf5 -lrt -lsz -lz -ldl -lm -lpthread -llmdb -lleveldb -lsnappy \
-lcudart -lcurand -lcublas -lcudnn \
/software/software/OpenCV/3.1.0-foss-2016a/lib/libopencv_highgui.so.3.1.0 \
/software/software/OpenCV/3.1.0-foss-2016a/lib/libopencv_imgcodecs.so.3.1.0 \
/software/software/OpenCV/3.1.0-foss-2016a/lib/libopencv_imgproc.so.3.1.0 \
/software/software/OpenCV/3.1.0-foss-2016a/lib/libopencv_core.so.3.1.0 \
-lopenblas -Wl,-rpath,/home/p253591/3D-Caffe/build/lib:/software/software/Boost/1.61.0-foss-2016a/lib:/software/software/gflags/2.1.2-foss-2016a/lib
TL;DR: The essentials form is (note the -lz for linking to libz):
g++ ... .../caffe.cpp.o -o caffe .../libcaffe.so .../libproto.a .../libboost_system.so ...more .so's and -lxyz's... -lz
It errors:
/software/software/libpng/1.6.23-foss-2016a/lib/libpng16.so.16: undefined reference to `inflateReset2#ZLIB_1.2.3.4'
collect2: error: ld returned 1 exit status
And this seems to be correct, because when I specify the -print-file-name=libz.so.1 option to g++, it prints /lib/../lib64/libz.so.1, which is slightly too old regarding version.
I have a newer version in /software/software/zlib/1.2.8-foss-2016a/lib/, but when I:
prepend this path to LD_LIBARY_PATH,
append it to the -rpath option, or
add it using the -L option,
g++ keeps using /lib/../lib64/libz.so.1 as it reports using -print-file-name
What does work, is removing the -lz option and adding /software/software/zlib/1.2.8-foss-2016a/lib/libz.so.1 explicitly as a file to include during compilation/linking. But that seems like a hack.
How can I tell g++ to use /software/software/zlib/1.2.8-foss-2016a/lib/libz.so.1 instead of /lib/../lib64/libz.so.1 when fulfilling the -lz option? Preferably indirectly via cmake (when building caffe).
Thank you in advance!
EDIT
ldd states the right .so is used:
# ldd /software/software/libpng/1.6.23-foss-2016a/lib/libpng16.so.16
linux-vdso.so.1 => (0x00007fff55599000)
libz.so.1 => /software/software/zlib/1.2.8/lib/libz.so.1 (0x00007f7875b29000)
libm.so.6 => /lib64/libm.so.6 (0x00007f7875888000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f787566b000)
libc.so.6 => /lib64/libc.so.6 (0x00007f78752d7000)
/lib64/ld-linux-x86-64.so.2 (0x0000003328800000)
Moreover, the symbol should be there in this libz.so.1:
# nm /software/software/zlib/1.2.8/lib/libz.so.1
...
0000000000008270 T inflateReset2
...
0000000000000000 A ZLIB_1.2.3.4
....
#
I'm assuming the #-notation in de undefined symbol-error somehow needs the A-type symbol to be there as a version check (but I could not find any documentation on this in ld.so man pages)
My guess is that you add -L after -lz which won't work as -L only affects -l which follow it. Also note that -rpath and LD_LIBRARY_PATH are influencing runtime library search (and also ldd output) so they won't have much influence on compilation.

How to convert assembly code to executable in LLVM

I have converted c program into assembly code using following commands in LLVM :
clang -emit-llvm matrix.c -c -o matrix.bc
llc -march=alpha matrix.bc -o matrix.s
Now how to convert matrix.s assembly file into executable file of alpha.
How to do that?
clang can also be used
clang matrix.s -L [additional library locations] -mllvm -Wall -g -L. -Wl,-pie -I. -I[additional include locations] -o [executable output]
Adjust the flags as your needs dictate.
EDIT
Without the need for other includes or libraries just call:
clang matrix.s -mllvm -Wall -g -Wl,-pie -o matrix.out

Ubuntu LDFLAGS --as-needed

I have a C project that won't link correctly, and I suspect it's because of the --as-needed flag passed to the ld program by gcc. Because of that flag, gcc sees any linked library listed as an option before the *.c files as unnecessary, and won't link them.
PREFIX?=/usr/local
CFLAGS=-D_LARGEFILE64_SOURCE=1 -g -Wall -I${PREFIX}/apr/include/apr-1 -I${PREFIX}/apr/include/apr-util-1
LDFLAGS=-lapr-1 -pthread -laprutil-1
all: devpkg
devpkg: bstrlib.o db.o shell.o commands.o
install: all
install -d $(DESTDIR)/$(PREFIX)/bin/
install devpkg $(DESTDIR)/$(PREFIX)/bin/
clean:
rm -f *.o
rm -f devpkg
rm -rf *.dSYM
When I run this makefile I get the following.
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -c -o bstrlib.o bstrlib.c
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -c -o db.o db.c
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -c -o shell.o shell.c
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -c -o commands.o commands.c
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -lapr-1 -pthread -laprutil-1 devpkg.c bstrlib.o db.o shell.o commands.o -o devpkg
/tmp/ccZcAm9b.o: In function `main':
/home/zach/Desktop/devpkgzed/devpkg.c:14: undefined reference to `apr_pool_initialize'
/home/zach/Desktop/devpkgzed/devpkg.c:15: undefined reference to `apr_pool_create_ex'
/home/zach/Desktop/devpkgzed/devpkg.c:29: undefined reference to `apr_getopt_init'
/home/zach/Desktop/devpkgzed/devpkg.c:31: undefined reference to `apr_getopt'
My issue is that I don't really understand how make is coming up with these commands via the CFLAGS that are set. How can I get the linker options to follow the compilation part instead of the other way around, which is triggering this issue?
Make has built-in rules to compile source files and link executables and libraries. The commands you list are produced by these rules.
The reason this fails for you is that, when linking, libraries should be listed after object files, because the linker does a single pass through its arguments and will discard any symbols that are not unresolved at the time they are seen. To correct it, put your libraries in the LDLIBS variable, not the LDFLAGS variable (i.e. just replace LDFLAGS by LDLIBS). The LDFLAGS variable is meant for non-library options for the linker, such as -L or -shared etc

GCC suppress flags

I'm trying to create a shared library with my gcc. It's a gcc for vxworks (thats probably the problem...).
I use the gcc as following:
./gcc -shared -B/path/to/gnutools/bin -o test.so test.c
Result:
/path/to/ld: -r and -shared may not be used together
collect2: ld returned 1 exit status
If I try the same with the linux gcc, there's no problem. So i guess the gcc for VxWorks automatically passes the -r (or -i, which is the same and results in the same) flag to the linker. Is there a way to suppress this?
Greetz
marty
PS: making it static is not really an alternative...
Try compile object file separately with -fPIC and then link:
gcc -Wall -fPIC -c -o test.o test.c
gcc -Wall -shared -o test.so test.o
Another suggestion is to use libtool (at least to figure out the correct flags).
A workaround may be to go directly with ld:
ld -shared -o test.so test.o -lc

Resources