I have a problem with setting up a visibility of my shared library. I would like to ask for help in resolving my issue as described below:
I have a bunch of source files which I would like to build as shared library:
+Base
|_Parameter
| |_Parameter.h
| |_Parameter_Exception.h
| |_Parameter_Exception.cpp
|_Data
| |_DataInput.h
| |_DataInput_Exception.h
| |_DataInput_Exception.cpp
...
Well there are some more files in there but I think it does not influence my problem description.
I am using CMake in order to build this SHARED library. Here is part of my CMakeLists.txt which deals with building the library.
project( Base )
cmake_minimum_required(VERSION 3.5
set( Base_HEADERS
Parameter/Parameter.h
Parameter/Parameter_Exception.h
Data/DataInput.h
Data/DataInput_Exception.h
)
set( Base_SOURCES
Parameter/Parameter_Exception.cpp
Data/DataInput_Exception.cpp
)
set( LIBRARY_OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} )
add_library( Base SHARED ${Base_SOURCES} ${Base_HEADERS} )
generate_export_header( ${PROJECT_NAME} EXPORT_FILE_NAME ${PROJECT_NAME}_Export.h )
This setup builds libBase.so shared library without any problem. It is important to mention that I have set some visibility related flags to be used during linking:
set( CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined -fvisibility=hidden -fvisibility-inlines-hidden" )
As configured in Base library CMakeLists.txt partly listed above:
- Base_Export.h header containig GCC visibility attributes macros is generated by CMake. It is then included in my sources listed in the tree up there.
- By default all the symbols shall be hidden as set in
linker flags (
-fvisibility=hidden
)
For example a piece of Parameter_Exception.h:
#include "Base_Export.h"
class SomeException : public std::exception
{
public:
SomeException( void ) {}
...
};
Please notice I have not set any visibility attribute here (by a macro defined in Base_Export). So I would assume, the symbol of SomeException class shall be hidden to all the DSO "users" (due to -fvisibility=hidden
)
But it doesn't seem so. Unfortunately:
Once I use the library, it the exception is usable although the symbol should be hidden. I would expect link failure cause by this code snippet "outside the library":
#include "Parameter/Parameter_Exception.h"
...
try
{
...
}
/* THIS SHOULD FAIL IN LINKING DUE TO UNDEFINED SYMBOL, RIGHT? */
catch( const SomeException & e )
{
...
}
I have also tried to look for the symbol in the libBase.so using the command: readelf -Ws libBase.so
it lists enormously long text:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 000000000008b7e0 0 SECTION LOCAL DEFAULT 9
....
but what I have noticed here is that in "Vis" column up there there is always DEFAULT which implies a default visibility ( __attribute__((visibility("default")))
) to me BUT I would expect to see HIDDEN in there ( __attribute__((visibility("hidden")))
)
So what am I doing wrong? Or my understanding is not correct? I know all the linked flags are propagated correctly but seem to have no effect.
My toolchain configuration as listed by CMake configuration script (GCC version that supports visibility attributes):
...
-- The CXX compiler identification is GNU 5.3.1
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
...
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY - Success
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY - Success
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Success
-- Configuring done
-- Generating done
Many thanks in advance to anybody willing to help me and possibly others having the same trouble as I do.
Thanks again, Martin