DSO 库符号似乎具有 DEFAULT 可见性,尽管应该是 HIDDEN
DSO library symbol seems to have DEFAULT visibility although should be HIDDEN
我在设置共享库的可见性时遇到问题。我想寻求帮助来解决我的问题,如下所述:
我有一堆源文件,我想将其构建为共享库:
+Base
|_Parameter
| |_Parameter.h
| |_Parameter_Exception.h
| |_Parameter_Exception.cpp
|_Data
| |_DataInput.h
| |_DataInput_Exception.h
| |_DataInput_Exception.cpp
...
嗯,里面还有一些文件,但我认为这不会影响我的问题描述。
我正在使用 CMake 来构建这个 SHARED 库。这是我的 CMakeLists.txt 的一部分,它涉及构建库。
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 )
此设置可以毫无问题地构建 libBase.so 共享库。值得一提的是,我已经设置了一些与可见性相关的标志,以便在 linking:
期间使用
set( CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined -fvisibility=hidden -fvisibility-inlines-hidden" )
在基础库中配置 CMakeLists.txt 以上部分列出:
- Base_Export.h header 包含 GCC 可见性属性宏是
由 CMake 生成。然后它包含在我列出的资源中
树在那里。
- 默认情况下,所有符号都应按照设置隐藏
linker 标志 (
-fvisibility=hidden
)
比如一张Parameter_Exception.h:
#include "Base_Export.h"
class SomeException : public std::exception
{
public:
SomeException( void ) {}
...
};
请注意我没有在这里设置任何可见性属性(通过 Base_Export 中定义的宏)。所以我假设,SomeException class 的符号应该对所有 DSO "users" 隐藏(由于 -fvisibility=hidden
)
但似乎并非如此。不幸的是:
一旦我使用了这个库,它的例外是可用的,尽管这个符号应该被隐藏。我预计此代码片段“在库外”会导致 link 失败:
#include "Parameter/Parameter_Exception.h"
...
try
{
...
}
/* THIS SHOULD FAIL IN LINKING DUE TO UNDEFINED SYMBOL, RIGHT? */
catch( const SomeException & e )
{
...
}
我还尝试使用以下命令在 libBase.so 中查找符号:
readelf -Ws libBase.so
它列出了非常长的文本:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 000000000008b7e0 0 SECTION LOCAL DEFAULT 9
....
但我在这里注意到的是,在 "Vis" 列中总是有 DEFAULT ,这对我来说意味着默认可见性( __attribute__((visibility("default")))
)但我希望在那里看到 HIDDEN ( __attribute__((visibility("hidden")))
)
那我做错了什么?还是我的理解不正确?我知道所有 linked 标志都正确传播但似乎没有效果。
CMake 配置脚本列出的我的工具链配置(支持可见性属性的 GCC 版本):
...
-- 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
非常感谢任何愿意帮助我的人以及可能遇到与我相同问题的其他人。
再次感谢,马丁
-fvisibility=hidden
和 -fvisibility-inlines-hidden
是编译器选项,
不是链接器选项。将它们设置为 CMAKE_CXX_FLAGS
CMake 直接支持符号可见性处理,因此您根本不需要触摸 CMAKE_SHARED_LINKER_FLAGS
或 CMAKE_CXX_FLAGS
。您可以像这样在每个目标的基础上设置可见性:
set_target_properties(Base PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN YES
)
CMake 将确保为您添加相关标志。不必为每个目标设置这些属性,通常更方便的是设置关联变量来为所有随后创建的目标设置默认值(这是我通常推荐并在我从事的项目中使用的方法):
cmake_minimum_required(VERSION 3.5)
project(Base)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
add_library(Base SHARED ...)
当与 GenerateExportHeader
模块(您似乎已经在使用)结合使用时,您不仅可以获得 gcc/clang 的支持,还可以获得 Visual Studio 的支持,使其成为控制符号可见性的良好跨平台方式。您不需要知道相关的编译器标志或属性,CMake 将为您处理它们并为您提供跨所有编译器的等效行为。
我在设置共享库的可见性时遇到问题。我想寻求帮助来解决我的问题,如下所述:
我有一堆源文件,我想将其构建为共享库:
+Base
|_Parameter
| |_Parameter.h
| |_Parameter_Exception.h
| |_Parameter_Exception.cpp
|_Data
| |_DataInput.h
| |_DataInput_Exception.h
| |_DataInput_Exception.cpp
...
嗯,里面还有一些文件,但我认为这不会影响我的问题描述。
我正在使用 CMake 来构建这个 SHARED 库。这是我的 CMakeLists.txt 的一部分,它涉及构建库。
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 )
此设置可以毫无问题地构建 libBase.so 共享库。值得一提的是,我已经设置了一些与可见性相关的标志,以便在 linking:
期间使用set( CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined -fvisibility=hidden -fvisibility-inlines-hidden" )
在基础库中配置 CMakeLists.txt 以上部分列出:
- Base_Export.h header 包含 GCC 可见性属性宏是 由 CMake 生成。然后它包含在我列出的资源中 树在那里。
- 默认情况下,所有符号都应按照设置隐藏
linker 标志 (
-fvisibility=hidden
)
比如一张Parameter_Exception.h:
#include "Base_Export.h"
class SomeException : public std::exception
{
public:
SomeException( void ) {}
...
};
请注意我没有在这里设置任何可见性属性(通过 Base_Export 中定义的宏)。所以我假设,SomeException class 的符号应该对所有 DSO "users" 隐藏(由于 -fvisibility=hidden
)
但似乎并非如此。不幸的是:
一旦我使用了这个库,它的例外是可用的,尽管这个符号应该被隐藏。我预计此代码片段“在库外”会导致 link 失败:
#include "Parameter/Parameter_Exception.h"
...
try
{
...
}
/* THIS SHOULD FAIL IN LINKING DUE TO UNDEFINED SYMBOL, RIGHT? */
catch( const SomeException & e )
{
...
}
我还尝试使用以下命令在 libBase.so 中查找符号: readelf -Ws libBase.so
它列出了非常长的文本:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 000000000008b7e0 0 SECTION LOCAL DEFAULT 9
....
但我在这里注意到的是,在 "Vis" 列中总是有 DEFAULT ,这对我来说意味着默认可见性( __attribute__((visibility("default")))
)但我希望在那里看到 HIDDEN ( __attribute__((visibility("hidden")))
)
那我做错了什么?还是我的理解不正确?我知道所有 linked 标志都正确传播但似乎没有效果。
CMake 配置脚本列出的我的工具链配置(支持可见性属性的 GCC 版本):
...
-- 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
非常感谢任何愿意帮助我的人以及可能遇到与我相同问题的其他人。
再次感谢,马丁
-fvisibility=hidden
和 -fvisibility-inlines-hidden
是编译器选项,
不是链接器选项。将它们设置为 CMAKE_CXX_FLAGS
CMake 直接支持符号可见性处理,因此您根本不需要触摸 CMAKE_SHARED_LINKER_FLAGS
或 CMAKE_CXX_FLAGS
。您可以像这样在每个目标的基础上设置可见性:
set_target_properties(Base PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN YES
)
CMake 将确保为您添加相关标志。不必为每个目标设置这些属性,通常更方便的是设置关联变量来为所有随后创建的目标设置默认值(这是我通常推荐并在我从事的项目中使用的方法):
cmake_minimum_required(VERSION 3.5)
project(Base)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
add_library(Base SHARED ...)
当与 GenerateExportHeader
模块(您似乎已经在使用)结合使用时,您不仅可以获得 gcc/clang 的支持,还可以获得 Visual Studio 的支持,使其成为控制符号可见性的良好跨平台方式。您不需要知道相关的编译器标志或属性,CMake 将为您处理它们并为您提供跨所有编译器的等效行为。