Reputation: 31
As you see, there are multiple definitions of testfn symbol while linking, but the linker takes the first occurence (in linking order) and ignores the other occurances in other libraries. This probably is the way how the linker works.
But Is there any way to enforce linker to flag error on seeing multiple symbols in different linked libraries ? Or any other options to catch such duplicate definitions ?
Content of test1.h:
#ifndef TEST1
#define TEST1
void testfn();
#endif
Content of test1.cpp
#include "test1.h"
#include <iostream>
using namespace std;
void testfn()
{
cout << "file1" << endl;
}
Content of test.h:
#ifndef TEST
#define TEST
void testfn();
#endif
Content of test.cpp:
#include "test.h"
#include <iostream>
using namespace std;
void testfn()
{
cout << "file" << endl;
}
Content of main.cpp:
#include "test.h"
#include "test1.h"
int main()
{
testfn();
return 0;
}
Created a shared libraries.
g++ -fPIC -shared libtest1.so test1.cpp
g++ -fPIC -shared libtest.so test.cpp
Created executable with library order#1
g++ -o main main.cpp -ltest -ltest1
Created executable with library order#2
g++ -o main1 main.cpp -ltest1 -ltest
Ouput of main
./main
file
Ouput of main1
./main1
file1
Upvotes: 2
Views: 822
Reputation: 340218
I don't see a way to get GNU ld to complain about multiple symbol definitions across shared libraries. However, if normal static library archives are involved, you might be able to use the --whole-archive
/--no-whole-archive
set of options to get what you want:
For example, after building libtest.a
and libtest1.a
instead of the shared library versions, I get no errors with the following link commands:
$ g++ -o main main.cpp -ltest1 -ltest -L.
$ ./main
file1
$ g++ -o main main.cpp -ltest -ltest1 -L.
$ ./main
file
But do get errors for the following:
$ g++ -o main main.cpp -Wl,--whole-archive -ltest1 -ltest -Wl,--no-whole-archive -L.
./libtest.a(test.o): In function `testfn()':
test.cpp:(.text+0x0): multiple definition of `testfn()'
./libtest1.a(test1.o):test1.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
I'm not sure you would want to use --whole-archive
for release builds - maybe only as a sanity check for possibly name conflicts (I think that using --whole-archive
normally will increase the size of your binary for no good reason).
Also, as mentioned before, this seems to have no effect on shared libraries.
Upvotes: 0
Reputation: 103515
First of all, it is honoring the ODR, by only taking one of the methods out of the library. And that's just the way shared libraries work.
If you want to see the compiler complain about this, link them all together, without the library step.
g++ -o main1 main.cpp test1.cpp test.cpp
So your question becomes, "How do I tell if I have two libraries which both contain a indentifier with the same name?" Keep in mind that this is often not a problem and sometimes done intentionally. I'd suggest running the library tool (I'm not familiar with the g++ toolset) to get listing of the libraries, and run DIFF of them.
Upvotes: 2