Benjamin Barrois
Benjamin Barrois

Reputation: 2686

Undefined reference error at link using extern keyword

I have a problem at link between two libraries libA.a (static) and libB.so (dynamic), created from C sources.

In one of the source files used to generate libB.so, I have the following functions :

static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, unsigned size) { ... }
static void unassigned_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { ... }

When I run nm libB.so | grep unassigned_mem I've got:

00000000004662a7 t unassigned_mem_read
0000000000466337 t unassigned_mem_write

And in a source file used for making libA.a, I've got:

extern uint64_t unassigned_mem_read(void *opaque, hwaddr addr, unsigned size);
extern void unassigned_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);

and a bit further these methods are called.

When I compile, everything is ok. But then at link, I have:

[build] qmg-mmio.c:47: undefined reference to 'unassigned_mem_read'
[build] qmg-mmio.c:84: undefined reference to 'unassigned_mem_write'

When I do nm libA.a | grep unassigned_mem I've got:

U unassigned_mem_read
U unassigned_mem_write

I link in this order: libB.so, libA.a.

As the symbols are the same, what can make them not being resolved?

Moreover when I compile all the sources together, then I have no problem at link. Is there a subtelty when linking a static and a dynamic library altogether that I miss?

Upvotes: 0

Views: 238

Answers (1)

John Bollinger
John Bollinger

Reputation: 180201

For file-scope identifiers, the static keyword specifies internal linkage. That means that the identifier and any associated definition are essentially private to the translation unit in which they appear. Lest there be any confusion, note well that this is only peripherally related to "static libraries", and especially that functions in static libraries that are intended to be called directly by library users must not be declared static, as that directly and specifically prevents such calls.

Linkage is a property of identifiers, within their scopes, not of the objects or functions they identify, and not necessarily of the same identifier in other scopes. Moreover, the same identifier can be associated with different objects and / or functions in different scopes. In particular, an external declaration of a given identifier is associated with a different function or object than those associated with any internal declarations of the same identifier, so you cannot redefine an internal declaration appearing in one scope as an external one by adding a declaration in some other scope.

Since you seem reluctant to modify the library containing the functions you want to call, I'm supposing that it is provided by a third party. In that case, you should understand that part of the point of declaring those functions static is so that you, the library user, do not call them directly. They are not part of the library's external interface.

Upvotes: 3

Related Questions