automake and custom rpath - linker

I have to ship a third-party library with an application. Because I don't want to set LD_LIBRARY_PATH by hand or require any wrapper script I want automake to set a custom rpath. Unfortunately libtool has its own -rpath option and adding -Wl,-rpath,/foo/bar to LDFLAGS only results in
g++: unrecognized option '-rpath'
because libtool seems to get confused with the command line options. The same happens with the alternative form -Wl,-rpath -Wl,/foo/bar.
Is there any way to specify a custom rpath without libtool interference?

As you said, libtool has its own -rpath option. Any reason you don't want to use it?
% libtool link g++ foo.cc -o foo -rpath /somewhere
libtool: link: g++ foo.cc -o foo -Wl,-rpath -Wl,/somewhere
% readelf -d foo | grep RPATH
0x000000000000000f (RPATH) Library rpath: [/somewhere]
None of the examples in the Automake or Libtool manuals use -Wl to specify -rpath.

Related

Undefined reference issue while creating executable

I am trying to create executable using some libraries.
My GCC command is :-
gcc -fPIC -DLINUX testdenpli /verilog/libdenpli.so -L/local/test/dir/ testpli.c
I have my library with symbols at path '/local/test/dir/'
Error:-
libdenpli.so: undefined reference to `ktlTcl_InitStubs'
libdenpli.so: undefined reference to `ktlitclStubsPtr'
I have the libraries with above symbols at path "'/local/test/dir/" .. But still seeing the issue.
Any one please help.
The error message says that libdenpli.so requires linking another shared library that provides symbols ktlTcl_InitStubs and ktlitclStubsPtr.
Find the shared library that provides those symbols using the following command:
for so in $(find /local/test/dir -name "*.so" -o -name "*.so.*"); do
nm --defined-only --dynamic $so 2>/dev/null | grep -q 'ktlTcl_InitStubs|ktlitclStubsPtr' && echo $so;
done
Then add that library into your linker command line:
gcc -Wall -Wextra -fPIC -DLINUX -o testdenpli testpli.c /verilog/libdenpli.so <full-path-to-found-library>
What is the name of the library containing the symbols? You need to include -lNAME to your compilation.
In general,
gcc file.c -o file -L/path/to/libs -lNAME
Note, the prefix "lib" and the suffix ".so" needn't be mentioned.

How do I compile a static library

I am trying to compile a static library. I followed the steps which were given in an answer to this question but it is not working. Following is my makefile.
PROJECT = lq.a
OBJECTS = dlmalloc.o queue.o.o
CFLAGS = -o -Wall -pedantic
all: $(PROJECT)
.c.o:
gcc -c $(CFLAGS) $<
$(PROJECT): $(OBJECTS)
libtool -o $(PROJECT) -static $(OBJECTS)
And I get the following error.
libtool: unrecognized option `-o'
What is the correct way of writing this makefile?
You can use the program ar to create static libraries using the following syntax:
ar rcs my_library.a file1.o file2.o
So, in your case:
$(PROJECT): $(OBJECTS)
ar rcs $(PROJECT) $(OBJECTS)
You can find an explanation of the options on the man page, but basically:
r says insert the given object files in to the archive (replacing any older versions of the same thing)
c says create the archive if it isn't already there (normally this happens anyway, but this option suppresses the warning).
s says to write an object-file index into the archive.
Well, this is confusing; but I think that the libtool -o $(PROJECT) -static $(OBJECTS) line (also mentioned in objective c - Combine static libraries) comes from Mac; and apparently the libtool there is NOT the same as the one on Linux:
libtool or ar & ranlib - idevgames forums:
I was using libtool to create a static library on OS X because that's what Xcode was doing, which seems to work fine. Then I go over to Linux and it chokes on my libtool command saying "libtool: unrecognized option '-o'". Looking at them, it seems like libtool on OS X and libtool on Linux are two completely different programs. ...
Followup: Yes, it appears that libtool on Linux is indeed glibtool on OS X. I get essentially the same output when doing "glibtool --help" on OS X as "libtool --help" on Linux.
Ok, that explains the difference - but still doesn't explain how -o can be an unrecognized option, when I've just seen it run from a Makefile on Linux! So I found this:
bug-libtool mailing list (2001): Re: bug in libtool?
You need to set the mode before the mode options:
$ libtool --mode=link --help
Usage: libtool [OPTION]... --mode=link LINK-COMMAND...
Oh dear... now what makes it especially confusing, is this note in libtool --mode=link --help:
$ libtool --mode=link --help
Usage: libtool [OPTION]... --mode=link LINK-COMMAND...
...
LINK-COMMAND is a command using the C compiler that you would use to create
a program from several object files.
The following components of LINK-COMMAND are treated specially: ...
-all-static do not do any dynamic linking at all ...
-o OUTPUT-FILE create OUTPUT-FILE from the specified objects ...
-static do not do any dynamic linking of uninstalled libtool libraries
...
All other options (arguments beginning with `-') are ignored.
Every other argument is treated as a filename. Files ending in `.la' are
treated as uninstalled libtool libraries, other files are standard or library
object files.
...
If OUTPUT-FILE ends in `.a' or `.lib', then a standard library is created
using `ar' and `ranlib', or on Windows using `lib'.
So - if I have to specify a LINK-COMMAND - and at the same time, I specify an OUTPUT-FILE which ends in .a; which command should then run, LINK-COMMAND - or the ar+ranlib that extension .a specifies? Well - here's a terminal snippet, just testing the bash script logic of libtool - without any compilation (though an empty archive does get created):
$ libtool -o test.a
libtool: unrecognized option `-o'
libtool: Try `libtool --help' for more information.
$ libtool --mode=link -o test.a
libtool: link: unrecognized option `-o'
libtool: link: Try `libtool --help' for more information.
$ libtool --mode=link gcc -o test.a
libtool: link: ar cru test.a
libtool: link: ranlib test.a
$ libtool --mode=link ar -o test.a
libtool: link: unable to infer tagged configuration
libtool: link: specify a tag with `--tag'
$ cat $(which libtool) | grep "^# ### BEGIN LIBTOOL TAG CONFIG:"
# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
# ### BEGIN LIBTOOL TAG CONFIG: disable-static
# ### BEGIN LIBTOOL TAG CONFIG: CXX
# ### BEGIN LIBTOOL TAG CONFIG: F77
# ### BEGIN LIBTOOL TAG CONFIG: FC
# ### BEGIN LIBTOOL TAG CONFIG: GCJ
# ### BEGIN LIBTOOL TAG CONFIG: RC
# ### BEGIN LIBTOOL TAG CONFIG: BINCC
# ### BEGIN LIBTOOL TAG CONFIG: BINCXX
## CC tag is not listed, but it will (eventually) be accepted:
$ libtool --mode=link ar --tag CC -o test.a
libtool: link: unable to infer tagged configuration
libtool: link: specify a tag with `--tag'
$ libtool --mode=link --tag CC ar -o test.a
libtool: link: ar cru test.a
libtool: link: ranlib test.a
$ libtool --tag=CC --mode=link ar -o test.a
libtool: link: ar cru test.a
libtool: link: ranlib test.a
$ libtool --tag=XX --mode=link ar -o test.a
libtool: ignoring unknown tag XX
libtool: link: ar cru test.a
libtool: link: ranlib test.a
$ libtool --tag=XX --mode=link whatevar -o test.a
libtool: ignoring unknown tag XX
libtool: link: ar cru test.a
libtool: link: ranlib test.a
$ ls -la test.a
-rw-r--r-- 1 user user 8 2013-04-17 23:12 test.a
So - not only do you have to specify a --mode, but if this mode is link, you MUST specify SOME sort of an argument (LINK-COMMAND) referring to a tool; BUT that LINK-COMMAND argument doesn't even need to exist as a real program - because you must specify an output file anyway; and if that output file ends on .a, it will enforce use of ar/ranlib anyways.
Also, should you have a problem with a tag - simply move the --tag argument before the LINK-COMMAND argument - and you can force libtool to run with a non-existing tag and a non-existing LINK-COMMAND (where it's operation is specified solely by the extension .a of the output file) - as long as the arguments are entered in the proper order for the libtool syntax; which I must admit isn't really documented in the script itself.
But to come back to the Mac libtool -o $(PROJECT) -static $(OBJECTS) line, which would combine static libraries; if you try to do the same with proper static library .a files, you will notice that libtool pushes the .a archives as such in the output archive, not their constituent object files - so this output is not a valid ELF object anymore; here is an example of a corresponding Linux libtool line, with two proper library files I've generated:
$ readelf --syms libmy1.a
File: libmy1.a(my1.o)
Symbol table '.symtab' contains 11 entries:
...
$ readelf --syms libmy2.a
File: libmy2.a(my2.o)
Symbol table '.symtab' contains 12 entries:
...
$ libtool --mode=link --tag=CC ar -o libtest.a -static libmy1.a libmy2.a
libtool: link: ar cru libtest.a libmy1.a libmy2.a
libtool: link: ranlib libtest.a
$ readelf --syms libtest.a
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
readelf: Error: libtest.a(libmy1.a): Failed to read file header
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
readelf: Error: libtest.a(libmy2.a): Failed to read file header
So, as the accepted answer says - on Linux, use ar manually to unpack and pack again, to combine static libraries.
Hope this helps someone,
Cheers!
Either use libtool or don't. If you're going to use it, then you should compile the individual files with libtool --mode=compile as well as linking with libtool --mode=link. If you're not going to use libtool, then your link should be done with gcc also, as pointed out in another answer. Also, have you tried man libtool?
The following commands will build your static library:
$gcc -c file1.c -o libfile.o
$ar rcs libfile.a libfile.o

Repeating libs on libtool command line

I'm using automake, and getting a libtool invocation like this:
/bin/sh ../libtool --tag=CC --mode=link gcc -o test_foo test_foo.o -lA -lB -lC -lA -lB -lC
Note that the libraries (which are beyond my control) have circular dependencies that require them to be mentioned more than once. Unfortunately it seems that libtool folds multiple requests for libraries into a single request, and it runs:
gcc -o test_foo test_foo.o -lA -lB -lC
Note that the second pass over the libs is gone; I get a bunch of linker errors. When I manually run that gcc command line with the extra -l flags, it works.
How can I make libtool pass all the libs I've requested to gcc?
How can I make libtool pass all the libs I've requested to gcc?
I don't know how to do that. Note however, that if you are on a system that uses GNU-ld (or gold), you can achieve the same result with
-Wl,--start-group -lA -lB -lC -Wl,--end-group
Perhaps libtool will leave these unmolested? Alas, libtool 2.2.6b moves -Wl,--end-group before all the libraries ;-(
This gross hack does it:
-Wl,--start-group,-lA,-lB,-lC,--end-group
(I find that libtool is wrong 99% of the time and try to avoid it like a plague.)

How can I force gcc to use custom implementations of newlibc implemented functions?

I am working on embedded software for a ARM microcontroller (SAM7) and using Yagarto toolchain.
My code currently links libc.a. However I'd like to use a custom implementation of the builtin function memcpy that my code already has.
I have tried using -fno-builtin and/or -fno-builtin-memcpy as specified in the GCC Manual but the linker still complains will the following warning:
contiki-crazy-horse.a(flashd_efc.o): In function `memcpy':
C:\Users\Melvin\GitRepo\projects\Amatis_Project\SAM7_Contiki\examples\er-rest-example/../../cpu/arm//at91sam7s-x/./flashd_efc.c:669: multiple definition of `memcpy'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-memcpy.o):C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\string/../../../../../newlib-1.19.0/newlib/libc/string/memcpy.c:78: first defined here
collect2: ld returned 1 exit status
make: *** [rest-server-example-nosyms.crazy-horse] Error 1
../../cpu/arm/at91sam7s-x/Makefile.at91sam7s-x:181: recipe for target `rest-server-example-nosyms.crazy-horse' failed
What is the correct way to use custom implementations of certain gcc built-in functions?
Edit 1: Adding the linking command I am using. In the code below Porject.a is an archive file created with all the project's object files.
CC = arm-none-eabi-gcc
CFLAGSNO = -I. -I$(CONTIKI)/core -I$(CONTIKI_CPU) -I$(CONTIKI_CPU)/loader \
-I$(CONTIKI_CPU)/dbg-io \
-I$(CONTIKI)/platform/$(TARGET) \
${addprefix -I,$(APPDIRS)} \
-DWITH_UIP -DWITH_ASCII -DMCK=$(MCK) \
-Wall $(ARCH_FLAGS) -g -D SUBTARGET=$(SUBTARGET)
CFLAGS += $(CFLAGSNO) -O -DRUN_AS_SYSTEM -DROM_RUN -ffunction-sections
LDFLAGS += -L $(CONTIKI_CPU) --verbose -T $(LINKERSCRIPT) -nostartfiles -Wl,-Map,$(TARGET).map
$(CC) $(LDFLAGS) $(CFLAGS) -nostartfiles -o project.elf -lc Project.a
If it is finding memcpy() in libc.a, then it is not conflicting with any "built-in", but rather with the newlib implementation. You may need also to specify -nostdlibs option and explicitly link libc.a and libm.a as necessary.
Object (.o) files are linked before library archives (.a) files are searched, so if a symbol is resolved by an object file, it will not be searched for in the archives. If you place your overrides in an static-link library, then you simply list it ahead of the standard library (or any other libraries that use the standard library) on the linker command line.
[Added] The following was originally a "comment" but should probably be in the answer; it is in response to "Edit 1" in the question, and the comment below about link order:
Change -nostartfiles -o project.elf -lc Project.a to -nostdlib -o project.elf -start-group Project.a -lc -end-group. The switch -nostdlib disables default linking of both start-up files (i.e. -nostartfiles) and standard libraries. The library grouping causes the libraries in the group to be searched iteratively until no further symbols can be resolved, allowing out-of-order and circular dependencies like yours to be resolved. An alternative form for the grouping switches is -( Project.a -lc -).

Undefined reference to SSL_library_init and SSL_load_error_strings

I am implementing a OpenSSL code and have already included required header files but still I am getting errors like *
undefined reference to SSL_library_init
I guess it's a linking error rather than a compilation error.
I am implementing it in Linux box using slickeditor.
Link against libssl and libcrypto. Your LDFLAGS and LDLIBS would be as follows. Order matters for LDLIBS:
LDFLAGS = -L/usr/local/ssl/lib
LDLIBS = -lssl -lcrypto
Don't worry about adding the "lib" in front of library name, or the "so" or "a" suffix. The linker will do it for you.
If you are building from the command line, then you would use the following. Again, order matters.
gcc foo.c -o foo.exe -L/usr/local/ssl/lib -lssl -lcrypto
If you are using the system's OpenSSL, then you can omit -L/usr/local/ssl/lib.
For me this meant to install
apt install libssl1.0-dev
These methods are deprecated in OpenSSL 1.1. You don't need to use it more. You can just remove it. More info in OpenSSL manual.
ldd libssl.so -> libcrypto.so.1.1 => not found
sudo ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1
libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007f17d46c7000)
Simply add -lssl -lcrypto to your Makefile and it should work.
Example of Makefile:
foo: foo.o
g++ -std=c++17 -o foo foo.cpp -lcrypto -lssl

Resources