Linking Libraries that contain circular references in GCC - gcc

I am trying to link an application with multiple static libraries in GCC.
There are two libraries that cause problems. Libsupport provides a terminal for the application. It relies on libcpu to provide a serial link, timing and syncronisation. Libcpu relies on libsupport to provide queueing for serial data and more.
If I specify libsupport first when linking libcpu cannot be linked with the queue functions. Is I specify libcpu first lib support can not link the serial link (and more) functions.
It looks like GCC parses a library only once and discard any unused objects.
Can I ask gcc to parse libraries multiple times or to include all objects?

gcc ... -lsupport -lcpu -lsupport -lcpu
-> Each mention of a library will cause resolution of libraries that came before it (but not necessarily ones specified afterwards), which is why you may need to specify more "-lsupport -lcpu" in future.
Alternatively, try --start-group -lsupport -lcpu --end-group once.

Here is detailed explanation of why either repeating libraries or using --start/--end-group is required in this situation.

You can normally specify a library more than once to get around this kind of problem, e.g.
$ gcc ... -lsupport -lcpu -lsupport ...

Note that --start-group /  --end-group are linker options which are unknown to the compiler, so if you use gcc / g++ for linking, you should specify them as:
gcc ... -Wl,--start-group -lsupport -lcpu -Wl,--end-group
Otherwise you will get:
gcc.exe: error: unrecognized command-line option '--start-group'
gcc.exe: error: unrecognized command-line option '--end-group'

Related

Mingw gcc, "-shared -static" passing together

When studying Scintilla's makefile for MinGW under windows, I noticed that it is passing -shared and -static together as LDFLAGS to gcc.
LDFLAGS=-shared -static -mwindows $(LDMINGW)
I googled, and only find some information from clang: https://reviews.llvm.org/D43811
[MinGW, CrossWindows] Allow passing -static together with -shared
In these combinations, link a DLL as usual, but pass -Bstatic instead of -Bdynamic to indicate prefering static libraries.
My question is: Would GCC do the same?
I haven't find any proof yet.
You can pass both -static and -shared in a GCC linkage. Their
combined effect is the same as you found described in your llvm link,
and this has always been the case for GCC.
-shared directs a GCC linkage to produce a shared library rather than a program,
which it achieves by passing on the option -shared to its invocation of
the linker.
-static directs a GCC linkage to ignore shared libraries when resolving
input library options -lname. By default -lname would be resolved by
searching the specified or default linker search directories for either
the shared library libname.so (on Windows, [lib]name.dll)
or the static library libname.a (on Windows also [lib]name.lib) and to prefer
the shared library if both of them are found in the same directory. -static
simply excludes all shared libraries from the search. GCC achieves this by passing the option -Bstatic
through to its invocation of the linker at a position in the generated linker
commandline that precedes all of the -lname options.
The GNU linker documentation of -Bstatic is explicit
that this option is consistent with -shared and that the effect is to produce a shared library
all of whose dependent libraries have been statically resolved.
-Bstatic
-dn
-non_shared
-static
Do not link against shared libraries. This is only meaningful on platforms for which shared libraries are supported.
The different variants of this option are for compatibility with various systems. You may use this option multiple times on the command line:
it affects library searching for -l options which follow it. This option also implies --unresolved-symbols=report-all.
This option can be used with -shared. Doing so means that a shared library is being created but that all of the library’s external references must be resolved by pulling in entries from static libraries.
(emphasis mine).
Although static linkage of shared library is in principle just a linkage restricted
in the same way as static linkage of a program, in practice it frequently encounters
a snag on Unix and Linux because all the object code linked into an ELF shared library
libname.so must be Position Independent Code,
as produced by the GCC compilation option -fPIC, whereas object files that are destined to be
archived in static libraries are customarily not compiled with -fPIC. Linkages using
-shared ... -static are thus apt to fail because necessary static libraries contain
non-PIC object files.
You do not have this worry with GCC on Windows, however, because there
is no such distinction as PIC v. non-PIC in Windows PE
object code.

GNU GCC/LD : Which libraries are linked by default?

I am a regular C programmer, and there's something I have wondered for some time about GNU GCC/LD internals.
I have noticed that, when passing a sequence of object files to GCC (e.g gcc main.o otherfile.o), GCC automatically links libc.a library file without my explicitly specifying -lc in the options. Similarly, when I compile a program using ncurses, I just need to specify -lncurses and libtinfo.a gets linked automatically (no need to specify -ltinfo). In other words, even though ncurses functions use functions from libtinfo (for instance, unctrl()), I don't need to explicitly link libtinfo.
How can it be possible?
Does GCC/LD have a list of "default libraries" where it looks for missing symbols when linking? If such a table exists, where is it and how can it be configured?
A direct answer is that you can see what libraries are linked by command line options by adding -v to the linking command line. This will show you the commands as they are executed.
The C library and the GCC support library or libraries are linked automatically; other libraries have to be specified manually.
The case of -lncurses and libtinfo.a (libtinfo.so?) is rather different. There, the link command used to build libncurses.so tells the linker that this library also needs -ltinfo, so it automatically picks up the extra library.

OSX: How do I convert a static library to a dynamic one?

Suppose I have a third party library called somelib.a on a Mac running Mountain Lion with Xcode 4.4 installed. I want to get a dynamic library out of it called somelib.dylib. An appropriate Linux command would be:
g++ -fpic -shared -Wl,-whole-archive somelib.a -Wl,-no-whole-archive -o somelib.so
where -whole-archive and -no-whole-archive are passed to the linker.
When I do the equivalent for Mac:
g++ -fpic -shared -Wl,-whole-archive somelib.a -Wl,-no-whole-archive -o somelib.dylib
ld fails with an error:
ld: unknown option: -whole-archive
It seems that the ld on OSX is different from GNU ld. How do I have to modify above command so I will get the desired result?
Thank you in advance!
I found out the solution to my problem:
g++ -fpic -shared -Wl,-force_load somelib.a -o somelib.dylib
The required argument is -force_load:
Which needs to be followed by a single library you wanna ensure gets loaded.
I mean, it needs to be repeated for each library (unlike -noall_load approach, which wrapped them).
For example, -Wl,-force_load libYetAnotherFile.a (where -Wl, part is only required because we don't pass parameter directly to linker).
Note that Old answer (before edit) was using -noall_load instead, but nowadays that causes a linker error (as -noall_load has been removed, was obsolete previously).
Note: A link for the documentation of the OSX ld linker.
http://www.unix.com/man-page/osx/1/ld/
I know it is late to give an answer for this, but I do not have enough reputation to make a comment on #hanslovsky answer.
However, it helps me a lot to have the docs of the options too.
It helps what the options do exactly, and that other options the ld linker also has.
So I just wanted to share with others who finds linking an issue.
UPDATE:
After the comment from #GhostCat I have decided to expand my answer.
The docs for -all_load is:
-all_load
Loads all members of static archive libraries.
So it loads for all static libraries that you note.
If you want something similar to --whole-archive and --no-whole-archive, then you need to use -force_load and -noall_load.
-force_load "path_to_archive"
Loads all members of the specified static archive library. Note: -
all_load forces all members of all archives to be loaded.
This option allows you to target a specific archive.
-noall_load
This is the default. This option is obsolete.
Then you can define which libraries to fully load with -force_load and then later turn it off again with -noall_load.
According to the ld manual, -noall_load is the default and is ignored. (If you use it, you get an error message: ld: warning: option -noall_load is obsolete and being ignored)
Apparently the way to get -all_load to apply to only one library is as follows:
-Wl,-force_load,somelib.a

Difference between linking a library with -ldl and -l

I'm trying to link some VTK libraries in my program...and It is not working like this
-ldl /usr/lib/libvtkIO.so, which is the way CMake does. But If I compile it manually using -L -lvtkIO, it works. What is the difference ?
Is dynamic versus static linking?
Thanks
CMake tries to use the full path to the library, rather than letting the linker search the library path(s). If you use ldd on the resulting binaries you will see they are linked to the same thing (dynamically in both cases). For things like VTK it is generally best to use CMake as it also tracks things like interface libraries for you.
I think you have misunderstood some of the arguments to the linker, -lvtkIO would link to a library in the library path called libvtkIO.so, -ldl would link to a library called libdl.so. The -L argument is used to add additional paths the linker should search for libraries.

GCC link order changed?

I am trying to link a C++ module using GCC, essentially like this:
gcc -c hello.c
g++ -c world.cpp
gcc -ohello -lstdc++ hello.o world.o
Note that I use -lstdc++ to link the C++ module in, so that I can use gcc instead of g++. The problem is that I'm getting the error:
undefined reference to `operator new(unsigned long)'
(Assuming that world.cpp contains at least one call to new.)
This error is fixed if I put -lstdc++ at the end of the linker line, like this:
gcc -ohello hello.o world.o -lstdc++
I am aware that this question has been asked many times here, but I have a special requirement. I am not directly calling GCC. I am using a build system for a different programming language (Mercury) which is calling GCC on my behalf, and I can't easily modify the way it calls GCC (though I can specify additional libraries using the LDFLAGS environment variable). So I have two additional requirements:
I cannot use g++ to link (only gcc) -- that is why I am doing the -lstdc++ trick above rather than simply linking with g++).
I don't think that I can control the order of the linker commands -- Mercury will put the .o files on the command-line after any libraries.
I understand the basic reason why the order is important, but what is baffling me is why did this break now? I just updated to Ubuntu 11.10 / GCC 4.6.1. I have been successfully compiling this program for years using precisely the above technique (putting -lstdc++ first). Only now has this error come up. An unrelated program of mine links against OpenGL using -lgl and that too broke when I upgraded and I had to move -lgl to the end of the command-line. I'm probably going to discover that dozens of my programs no longer compile. Why did this change? Is there something wrong with my new system or is that the way it is now? Note that these are ordinary shared libraries, not statically linked.
Is there anything I can do to make GCC go back to the old way, where the order of libraries doesn't matter? Is there any other way I can convince GCC to link libstdc++ properly without moving it after the .o files on the command-line?
If Mercury puts object files after libraries, Mercury is broken. Libraries belong after object files - always. You may sometimes get away with the reverse order, but not reliably. (Static libraries must go after the object files that reference symbols in the static library. Sometimes, a linker will note the symbols defined by a shared library even when none of the symbols are used; sometimes, the linker will only note the shared library symbols if the shared library provides at least one symbol.)

Resources