Reputation: 615
Related topic: Why does const imply internal linkage in c++, when it doesn't in C?
I was following GCC visibility wiki to add visibility to my shared library.
It generates a warning when I'm compiling my source file
warning: 'visibility' attribute ignored [-Wattributes]
Here's my code:
// my_shared_lib.h
#if __GNUC__ >= 4
#define DLL_API __attribute__((visibility("default")))
#define DLL_LOCAL __attribute__((visibility("hidden")))
#else
#define DLL_API
#define DLL_LOCAL
#endif
DLL_LOCAL const int my_local_var;
It generate following warning while compiling:
my_shared_lib.h: 'visibility' attribute ignored [-Wattributes]
DLL_LOCAL const int my_local_var;
^
Here's the entire building message:
make all
Building file: ../src/my_shared_lib.cc
Invoking: Cross G++ Compiler
g++-mp-4.8 -O3 -Wall -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"src/my_shared_lib.d" -MT"src/my_shared_lib.d" -o "src/my_shared_lib.o" "../src/my_shared_lib.cc"
my_shared_lib.h: 'visibility' attribute ignored [-Wattributes]
DLL_LOCAL const int my_local_var;
^
Finished building: ../src/my_shared_lib.cc
Can anyone tell me how to silent this warning and why this warning happened?
Is it because const variable
are hidden
by default?
PS. I'm using g++ 4.8
Upvotes: 9
Views: 17569
Reputation: 94614
You can silence the warning by passing -Wno-attributes
to the compilation.
The warning is happening because, as the related question and answer mentions, in C++
const objects automatically have internal linkage unless they're explicitly marked as extern; i.e. they're hidden by default. The rationale is to encourage putting these const
values into header files as-is (i.e. in the form const int x = value;
). If they were public by default, then you would suffer multiple-linkage issues if the same variable appeared across multiple .cpp
or .o
files, which is what would happen if they were placed in .h
files without the local linkage rule.
You should also be seeing a warning/error:
my_shared_lib.h:...: error: uninitialized const 'my_local_var' [-fpermissive]
which is a variation of the error because the const is implicitly static unless otherwise mentioned.
How do you fix this?
Firstly, use the const
properly in the header when using C++
, it's:
const int my_local_var = VALUE;
If you're sharing this .h
file amongst C
and C++
code then your choices are:
const
- that's actually meaningless for the C
code, and prevents you from accomplishing the private, declared in the header and defined in a .c
file but not exposed in the resulting .so
#define
- yes, it's ugly, but this is more semantically correct than using a const
for C code as it prevents you from accidentally changing the value by erroneous assignment....
DLL_LOCAL extern const int my_local_var;
and then define it in the .cc
/.cpp
file as:
#include "my_shared_lib.h"
const int my_local_var = 42;
You need to add in the #include
or else it doesn't get the extern
which allows it to be exposed for linking in the .o
files that make up the .so
without getting it exposed in the .so
itself.
and so we have (on a mac, but the premise is the same):
Header:
$ cat wodge.h
#define PRIVATE __attribute__((visibility("hidden")))
#define PUBLIC __attribute__((visibility("default")))
PRIVATE extern const int my_local_var;
int do_with_x(int x);
First C++
file:
$ cat wodge.cc
#include "wodge.h"
int
do_with_x(int y)
{
return my_local_var * y;
}
Second C++
file - definition of value:
$ cat wodge2.cc
#include "wodge.h"
const int my_local_var = 42;
Compile and show the resulting symbol table:
$ g++-4.8 -c -O3 -Wall -o wodge.o wodge.cc
$ g++-4.8 -c -O3 -Wall -o wodge2.o wodge2.cc
$ g++-4.8 -shared -o foo.dylib *.o
$ nm foo.dylib
0000000000000fb0 T __Z9do_with_xi
0000000000000fbc s _my_local_var
U dyld_stub_binder
Upvotes: 9