(Environment: gcc 4.6, c++11, glibc 2.13, binutils 2.21)
Please consider the follow “linking” demo for background:
foo.h:
#pragma once
#include <iostream>
void foo();
foo1.cpp:
#include "foo.h"
void foo()
{
std::cout << "foo1";
}
foo2.cpp:
#include "foo.h"
void foo()
{
std::cout << "foo2";
}
main.cpp:
#include "foo.h"
int main()
{
foo();
}
Makefile:
compile: main.o foo1.o foo2.o
case1: compile
g++ -o case1.x main.o
case2: compile
g++ -o case2.x main.o foo1.cpp
case3: compile
g++ -o case3.x main.o foo1.o foo2.o
clean:
rm *.o *.x
We have a function declaration as follows:
void foo();
and we have multiple definitions of it, one in foo1.cpp and a different one in foo2.cpp.
We compile the .cpp files into .o files:
$ make compile
No problem, main.o, foo1.o and foo2.o are produced.
Case 1
We then try and link just main.o:
$ make case1
error: undefined reference to 'foo()'
Ok, main.o references foo but no definition has been linked.
Case 2
Now we try and link main.o and foo1.o
$ make case2
There is a single definition of foo in foo1.o, so it links without error.
Case 3
Now we try and link main.o foo1.o and foo2.o
$ make case3
error: multiple definition of 'foo()'
The linker finds two definitions of foo in foo1.o and foo2.o, so rather than taking a random one it fails fast with an error and doesn’t link.
Questions
My questions are:
-
Is it possible to mark the definition of foo1.cpp’s version of foo (possibly with some sort of gcc attribute or pragma) as “weak”? Meaning specifically that I want the behavior of case 1 and case 2 to remain the same, while the behavior of case 3 changes to successfully link without warning or error and the definition of foo in foo2.cpp is linked (overriding the “weak” definition in foo1.cpp).
-
Is it possible to test at runtime (and assign to a boolean variable) whether the weak version of foo was linked, or the strong one (without executing the function obviously). ie implement a function in main as follows.
template<typename FunctionPtr> bool is_weak_linked(FunctionPtr fp);
is_weak_linked(foo) should return true in case 2 and false in case 3.
To #1:
To #2: I don’t believe so, not with the static linking you’re doing. That information is lost at link time.
Edit
You can always abstract your way around #2. Some examples: