I'm building a shared library that has respective code and compilation rules like the following:
// x.C
struct {
short len;
char s[32700];
} foo;
// u.C
extern struct {
short len;
char s[32700];
} foo;
void blah(void)
{
foo.s[0] = 0 ;
}
$CXX -c x.C -fPIC
$CXX -c u.C -fPIC
$CXX -shared -o x.so.1 -Wl,-soname,x.so.1 x.o u.o
This code compiles and links with the intel (v13-v16) compiler and the clang compiler (v3.6), but with the g++ (version 4.9.2) I get the link error:
u.o: relocation R_X86_64_PC32 against undefined symbol `foo' can not be used when making a shared object; recompile with -fPIC
The link error here about -fPIC is clearly wrong, since the code is compiled with fPIC. I also see a relocation record for the symbol in objdump -x
output:
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000006 R_X86_64_PC32 foo-0x0000000000000003
Both the clang and gcc compilers produce warnings that guide correction of the code that allows it to link (at least this standalone version, the actual code will be harder to figure out where and how to fix) :
u.C:5:10: warning: anonymous type with no linkage used to declare variable '<anonymous struct> foo' with linkage
} foo;
^
and sure enough I can fix this by removing the anonymous structures:
// u.h
struct fooT {
short len;
char s[32700];
} ;
extern fooT foo ;
// u.C
#include "u.h"
void blah(void)
{
foo.s[0] = 0 ;
}
// x.C
#include "u.h"
struct fooT foo ;
So, while I have a fix, I'd like to understand what's going on here. I see some questions that have similar link errors:
- shared library relocation R_X86_64_PC32 error
- linker error "relocation R_X86_64_PC32 against undefined symbol" despite compilation with -fPIC
- Odd linker issue "relocation R_X86_64_32 against" - not a typical -fPIC issue
- linking a static(.a) library with a shared (.so) library, getting error "relocation R_X86_64_32S against a local symbol; recompile with -fPIC"
A couple of these indicate that this might be related to symbol visibility. Is gcc marking this symbol hidden triggering the eventual link error? Which one of the g++, clang++ or intel compilers is behaving properly or improperly here, or is this construct invalid and just plain unportable? If this is invalid code, what part of the C++ standard is it violating?