Error when linking *.a and *.o files at llvm - c

I have two static library files (.a) and one bitecode file (.bc) ,which created with an opt pass.In this bitecode file i have added my own code and in this code i need to call a function which is declared in the static libraries. I 've noticed that the llvm-ld tool no longer exists for clang newer versions so i tried two different ways to link these three files (two libraries and one bitecode file):
1. try to link with gcc :
create with llc the object file of file.bc
$llc -filetype=obj file.bc -o file.o
link object and libs with gcc
$gcc -I lib1.a lib2.a -O3 file.o -o file
these commands give me this error:
file.o: In function `main':
file.bc:(.text+0xc0): undefined reference to `function_in_lib'
collect2: error: ld returned 1 exit status
(function_in_lib is the function that i need to call from lib and compilers can't find this function)
2. the second way is with ld command
create with llc the object file of file.bc
$llc -filetype=obj file.bc -o file.o
link object and libs with ld
$ld -o linked lib1.a lib2.a file.o -lc
these commands give me this error:
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002b0
new.o: In function `main':
new.bc:(.text+0xc0): undefined reference to `function_in_lib'
i tried to change the order of arguments but i have more errors when i did it.I think that the fault become from the linking,any idea?

The reason you're getting undefined references is because you're linking your libraries in the wrong way. A linker works in an incremental order - it looks at the first file you provided and gathers a list of things that file references but can't be found. Then the linker moves onto the next library and does the same thing, but also looks for opportunities to fix the undefined references from the previous libraries.
The reason that ld can't find function_in_lib is because it links file.o after the libraries and therefore doesn't get a chance to fill in the references that file.o requires. If you're looking for more specifics about linking and why you're running into this problem, this is a pretty good introduction.
If you just want to fix your problem, move the library files to after file.o in your command, i.e.
ld -o linked file.o lib1.a lib2.a -lc

Related

How to compile gcc with static library?

I have static library lib.a and in all tutorials using:
gcc -o main main.o -L. -lib
But I cant, I have errors:
/usr/bin/ld: cannot find -lib
collect2: error: ld returned 1 exit status
I need to use:
gcc -o main main.o -L. -lib.a
Why? What should I do to repair it ?
From the documentation of gcc -l:
-llibrary:
The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
...
The only difference between using an -l option and specifying a file name is that -l surrounds library with ‘lib’ and ‘.a’ and searches several directories.
So you cannot use -l with a library named 'lib.a'. Use 'lib.a' without the -l to include it. Of course, you cannot use -L then to set the directories to be searched for this particular library.
Do you have the error with this line ?
gcc -o main main.o -L. -llib
As MicroVirus found in the documentation, you will have to rename your library in liblib.a to use my previous line or just pass your library to gcc like a simple file.

Linking static lib into shared lib,are there a better way to make pre declaration? [duplicate]

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)

Make is unable to find the functions

I am trying to compile a C program, while linking the APR library.
I am getting the following error message:
cc -g -Wall -pthread -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -L/usr/local/apr/lib -L .aprutil-1 -L .apr-1 devpkg.c bstrlib.o db.o shell.o commands.o -o devpkg
/tmp/cczC53x5.o: In function `main':
/home/yotam/Dropbox/Development/C/devpkg/devpkg.c:14: undefined reference to `apr_pool_initialize'
/home/yotam/Dropbox/Development/C/devpkg/devpkg.c:15: undefined reference to `apr_pool_create_ex'
/home/yotam/Dropbox/Development/C/devpkg/devpkg.c:29: undefined reference to `apr_getopt_init'
/home/yotam/Dropbox/Development/C/devpkg/devpkg.c:31: undefined reference to `apr_getopt'
db.o: In function `DB_init':
/home/yotam/Development/C/devpkg/db.c:89: undefined reference to `apr_pool_initialize'
/home/yotam/Development/C/devpkg/db.c:90: undefined reference to `apr_pool_create_ex'
/home/yotam/Development/C/devpkg/db.c:93: undefined reference to `apr_dir_make_recursive'
/home/yotam/Development/C/devpkg/db.c:105: undefined reference to `apr_pool_destroy'
/home/yotam/Development/C/devpkg/db.c:109: undefined reference to `apr_pool_destroy'
shell.o: In function `Shell_exec':
/home/yotam/Development/C/devpkg/shell.c:16: undefined reference to `apr_pool_create_ex'
/home/yotam/Development/C/devpkg/shell.c:38: undefined reference to `apr_pool_destroy'
/home/yotam/Development/C/devpkg/shell.c:44: undefined reference to `apr_pool_destroy'
shell.o: In function `Shell_run':
/home/yotam/Development/C/devpkg/shell.c:55: undefined reference to `apr_procattr_create'
/home/yotam/Development/C/devpkg/shell.c:58: undefined reference to `apr_procattr_io_set'
/home/yotam/Development/C/devpkg/shell.c:62: undefined reference to `apr_procattr_dir_set'
/home/yotam/Development/C/devpkg/shell.c:65: undefined reference to `apr_procattr_cmdtype_set'
/home/yotam/Development/C/devpkg/shell.c:68: undefined reference to `apr_proc_create'
/home/yotam/Development/C/devpkg/shell.c:71: undefined reference to `apr_proc_wait'
commands.o: In function `Command_fetch':
/home/yotam/Development/C/devpkg/commands.c:44: undefined reference to `apr_uri_parse'
/home/yotam/Development/C/devpkg/commands.c:48: undefined reference to `apr_fnmatch'
/home/yotam/Development/C/devpkg/commands.c:51: undefined reference to `apr_fnmatch'
/home/yotam/Development/C/devpkg/commands.c:70: undefined reference to `apr_fnmatch'
/home/yotam/Development/C/devpkg/commands.c:78: undefined reference to `apr_dir_make_recursive'
/home/yotam/Development/C/devpkg/commands.c:84: undefined reference to `apr_fnmatch'
/home/yotam/Development/C/devpkg/commands.c:90: undefined reference to `apr_dir_make_recursive'
collect2: error: ld returned 1 exit status
make: *** [devpkg] Error 1
Here is my makefile, it should be able to compile on different computers, where the PREFIX variable is the location relative to the computer.
(this program in essence should one day be portable to any OS. for now I would just like to be able to compile it successfully)
PREFIX?=/usr/local
LDFLAGS= -L${PREFIX}/apr/lib -L .aprutil-1 -L .apr-1
CFLAGS=-g -Wall -pthread -I${PREFIX}/apr/include/apr-1 -I${PREFIX}/apr/include/apr-util-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
I've gone and searched for it myself in the folders and this is what I got:
yotam#yotam-HP-ProBook-450://usr$ grep -r apr_pool_initialize .
./local/apr/include/apr-1/apr_pools.h:APR_DECLARE(apr_status_t) apr_pool_initialize(void);
Binary file ./local/apr/lib/libapr-1.so.0.4.6 matches
Binary file ./local/apr/lib/libapr-1.a matches
Binary file ./local/apr/lib/libapr-1.so.0.5.1 matches
Binary file ./local/apr/lib/libapr-1.so.0.4.5 matches
./local/apr/lib/apr.exp:apr_pool_initialize
After the reaserch I did, I clearly understand that this is a linker problem. but I wasn't able to find the command to do the trick.
Thanks in advance.
Looks like you're missing the link option that tells cc which library to link with. I'm not sure what .aprutil-1 and .apr-1 are in your LDFLAGS macro, since you specify them with -L, I will assume they are directories.
However, if you change your line to add the -l option to specify the library, it should get you closer.
EDIT: Because the linker is a single pass tool, all the libraries need to be listed after the objects, so the symbols will not be optimized away. LDLIBS is a typical name for the macro where libraries are specified, and you can tack them on to the end of the compile/link command and it should work.
LDFLAGS= -L${PREFIX}/apr/lib -L .aprutil-1 -L .apr-1
LDLIBS= -lapr-1 -laprutil-1
The last two args tell the linker which library names (prepended with lib and appended with .a) to use. The -L option specifies additional directories to search for libraries, it doesn't actually include anything.
Alternatively, you can also set LD_LIBRARY_PATH to point to your library directories.
You can consult this site (among others) as a reference, if you need more help debugging.
Try replacing LDFLAGS with LDLIBS, as in:
LDLIBS=-L${PREFIX}/apr/lib -lapr-1 -pthread -laprutil-1
instead of:
LDFLAGS=-L${PREFIX}/apr/lib -lapr-1 -pthread -laprutil-1
This is because the LDFLAGS variable is meant for non-library options for the linker, whereas in this case you are using libraries.

DSO missing from command line although it is available

I am working with c++ code for a physics simulation, which uses a lot of external libraries (like GSL and cern`s ROOT). Trying to recompile project I encountered problems with linking. When running compilation of final file via:
g++ -fno-inline -O2 -fpic -o main.out ${ROOTINCS} main.o ext.o ${ROOTLIBS} $(objects2)
with :
objects2= many .o files made by us
ROOTLIBS=-L/usr/local/lib/root -lTree -lRIO -lNet -lHist -lMathCore -lCore -lGraf -lGraf3d -lGpad -lMatrix -lThread -lCint -lPhysics -lPostscript -lRint -lSpectrum -lg
ROOTINCS=-pthread -m64
I get annoying error:
/usr/bin/ld: /usr/local/lib/root/libHist.so: undefined reference to symbol 'gRandom'
/usr/local/lib/root/libMathCore.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
The problem is nm -C run on libMathCore states 'gRandom' is declared there. Also -lMathCore is present in my command line.
When I run ld to check if it understands the flag:
ld -L/usr/local/lib/root -lMathCore --verbose 2>/dev/null
it does not complain and tries to link properly.
According to https://stackoverflow.com/a/24675715/3602168 order of libraries is correct in my linking (libHist uses libMathCOre and therefore is stated first).
Compilation runs under g++ 4.8.2 on ubuntu 14.04, 64 bit
Converting comment to answer:
Have you tried moving $(objects2) before ${ROOTLIBS}? I think the issue may be that you have libraries specified before the object files that use them.

How are newlibc stubs supposed to be included/linked into one's code

During my project's linking process the linker fails with the following errors unless I make an explicit call in my code to one of of the stub functions (i.e. _sbrk):
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-abort.o): In function `abort':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\stdlib/../../../../../newlib-1.19.0/newlib/libc/stdlib/abort.c:63: undefined reference to `_exit'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-signalr.o): In function `_kill_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/signalr.c:61: undefined reference to `_kill'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-signalr.o): In function `_getpid_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/signalr.c:96: undefined reference to `_getpid'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-sbrkr.o): In function `_sbrk_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/sbrkr.c:60: undefined reference to `_sbrk'
collect2: ld returned 1 exit status
I am aware that I need some stubs functions that newlibc requires and I have a "C" file that contains all of the ones mentioned above as missing and I am also positive that the file is being compiled and added to an archive file (*.a) that is later linked.
I am calling the linker using the following commands
arm-none-eabi-gcc -L -T linkerscript.ld -nostartfiles -Wl,-Map,$(TARGET).map -lc archive.a
My question is simple (I hope) How can I make sure that the linker links my stub functions into the elf file without having to make an explicit function call from one of my project files?
I think those errors you're getting refer to the linker not being able to find the appropriate library. My first suspicion is in how you're using your arguments, specifically your specification of archive directory (-L) and the archive.a file. I'm thinking it should go like this:
arm-none-eabi-gcc -L. -T linkerscript.ld -nostartfiles -Wl,-Map,$(TARGET).map -lc -larchive
where the changes I'd make are:
-L. means use the current directory to look for library files to link.
-lc specifies to use the archive file libc.a.
-larchive specifies to use the archive file libarchive.a.
For more info I'd suggest checking out theGNU GCC reference.
Pass --verbose to gcc to see exactly where archive.a is showing up in the list of libraries and objects passed to the linker.
You need to arrange things so that archive.a is searched after libg.a since that's the archive that contains the objects that end up with undefined references.
You might be able to fix this by adding -lg before archive.a on the gcc command line.
-lg should in libg.a earlier than where it's getting pulled in now by default and more importantly pull it in before archive.a.

Resources