I have 4 source files listed below:
//a.h
#pragma once
namespace proj {
class A {} a;
} // namespace proj
//b.h
#pragma once
namespace proj {
int foo();
} // namespace proj
// b.cpp
#include "proj/a.h"
namespace proj {
int foo() {
A b = a;
return 0;
}
} // namespace proj
// c.cpp
#include "proj/a.h"
#include "proj/b.h"
using namespace proj;
int main() {
A b = a;
foo();
return 0;
}
When I try to compile c.cpp
I get the following link error:
duplicate symbol proj::a in:
buck-out/gen/proj/c#compile-c.cpp.ob5f76e97,default/c.cpp.o
buck-out/gen/proj/b#default,static/libb.a(b.cpp.o)
duplicate symbol ___odr_asan._ZN4proj1aE in:
buck-out/gen/proj/c#compile-c.cpp.ob5f76e97,default/c.cpp.o
buck-out/gen/proj/b#default,static/libb.a(b.cpp.o)
ld: 2 duplicate symbols for architecture x86_64
collect2: error: ld returned 1 exit status
Build failed: Command failed with exit code 1.
stderr: duplicate symbol proj::a in:
buck-out/gen/proj/c#compile-c.cpp.ob5f76e97,default/c.cpp.o
buck-out/gen/proj/b#default,static/libb.a(b.cpp.o)
duplicate symbol ___odr_asan._ZN4proj1aE in:
buck-out/gen/proj/c#compile-c.cpp.ob5f76e97,default/c.cpp.o
buck-out/gen/proj/b#default,static/libb.a(b.cpp.o)
ld: 2 duplicate symbols for architecture x86_64
collect2: error: ld returned 1 exit status
I assume this is happening because b.cpp is compiled independently from c.cpp and so the pre-processor includes the header a.h in each file individually and when it comes time to link, the linker finds two versions of the symbol a.
How do I declare one instance of a class (in this case a
) that is usable across my entire program and avoid the above link error?
I am using gcc-7 (gcc-7 (Homebrew GCC 7.2.0_1) 7.2.0
) on Mac OS X 10.13.3 with -std=c++17
.
This should be irrelevant to the question, but including anyways in case someone finds it helpful.
I am using buck to compile the code (although this should be irrelevant) with the following BUCK file:
cxx_library(
name='a',
exported_headers=['a.h'],
visibility=['PUBLIC'],
)
cxx_library(
name='b',
exported_headers=['b.h'],
srcs = ['b.cpp'],
deps = [':a'],
visibility=['PUBLIC'],
)
cxx_binary(
name='c',
srcs = ['c.cpp'],
deps = [':a', ':b'],
)
Since this is tagged C++17, you can take advantage of the new inline variables language feature:
namespace proj {
class A {};
inline A a;
} // namespace proj
inline
variables now behave the same way as inline
functions: your multiple definitions of a
get collapsed into one.