0

I am familiar with what the --whole-archive linker option does when using a static archive.

Is there a way to achieve the same effect on a per symbol basis, either via some symbol attributes, or any other trick?

To be clear, lets say I have a .a which has two functions :

void foo() {}
void bar() {}

I would like to make sure that any executable that was built by linking against this archive will always have the foo() symbol, regardless of whether foo() is being used or not. I do not similarly care about bar()

Thanks.

MK.
  • 3,597
  • 4
  • 27
  • 40
  • Maybe with a linker script? – Marc Glisse Feb 09 '16 at 01:31
  • https://sourceware.org/binutils/docs/ld/File-Commands.html INPUT "For example, if you always want to include subr.o any time you do a link, but you can't be bothered to put it on every link command line, then you can put `INPUT (subr.o)' in your linker script." – Marc Glisse Feb 11 '16 at 00:48

3 Answers3

0

You can use the option -u for that:

gcc -O2 foo.c -o foo -umysymbol -lmylib

This forces the linker to treat mysymbol as undefined and resolve it by linking it from the specified libraries.

From the manpage of ld:

-u symbol

--undefined=symbol

Force symbol to be entered in the output file as an undefined symbol. Doing this may, for example, trigger linking of additional modules from standard libraries. `-u' may be repeated with different option arguments to enter additional undefined symbols.

Community
  • 1
  • 1
Ctx
  • 17,064
  • 24
  • 33
  • 48
  • --undefined looks good though this means that the final executable's build step needs to be changed. I was hoping to find a way to advertise the public nature of the symbol in the library itself – MK. Feb 08 '16 at 23:38
  • @MK I understand, but I fear this will hardly be possible. It always works the other way round, the main binary triggers which symbols are linked. – Ctx Feb 08 '16 at 23:41
0

I'm afraid you'll need to modify your linkage to achieve this.

You should be clear that the entities within an archive (.a) that can be linked, or not linked, with your executable are not individual symbol definitions but individual archive members, which are object files, each of which may define arbitrarily many symbols. If you want to link a symbol from an archive, you link the whole archive member that defines it.1

The foremost difference between linking an archive (.a) with your executable and linking an object file (.o) is that an object file will be linked, unconditionally, whereas an archive member will be linked only if it provides a definition for at least one symbol that has been referenced but not defined when the archive is examined.

Hence the ordinary, non-roundabout way of ensuring that a symbol foo is linked unconditionally is to link an object file that defines it. There is no way to mark an archive member foo.o as must be linked because, if you must link foo.o, you do it by linking foo.o.

So if foo resides in an archive member foo.o, you can extract that member from the archive:

ar x libthing.a foo.o

and add foo.o to your linkage, even if you don't have the foo source from which to compile foo.o.

If there are a lot of functions that you want to link unconditionally then you might either compile them all from source into a single object file, if you have the source, or you might collect all the object files that define them into a single archive that you link with --whole-archive.

I was hoping to find a way to advertise the public nature of the symbol in the library itself

For linkage purposes, there are nothing but public symbols in a library: by definition any symbols that the linker can see are public.


[1] If you are in a position to compile an object file that goes into to your linkage, then by the use of appropriate compiler and linker flags you can ensure that redundant symbols it may contribute are finally discarded by the linker. See this answer
Community
  • 1
  • 1
Mike Kinghan
  • 46,463
  • 8
  • 124
  • 156
0

The following seems to have worked for me.

In a function in my library that I know is always called, I do the following :

static volatile auto var = &foo

Now, without changing anything in the linking either when creating the archive or building the executable, I see that the executable has the foo symbol.

MK.
  • 3,597
  • 4
  • 27
  • 40