67

I developed cross platform software in c++. As I know, Linux .so exported all the symbols by default, well through "gcc -fvisibility=hidden" I can set all the exported symbols as hidden, then set __attribute__(visibility("default")) for the class and function I want to export, so I can control what I want to export.

My question is, using CMake, how can I do the work as "gcc -fvisibility=hidden" control?

Joe
  • 6,497
  • 4
  • 29
  • 55
sailing
  • 670
  • 1
  • 5
  • 11

2 Answers2

112

Instead of setting compiler flags directly, you should be using a current CMake version and the <LANG>_VISIBILITY_PRESET properties instead. This way you can avoid compiler specifics in your CMakeLists and improve cross platform applicability (avoiding errors such as supporting GCC and not Clang).

I.e., if you are using C++ you would either call set(CMAKE_CXX_VISIBILITY_PRESET hidden) to set the property globally, or set_target_properties(MyTarget PROPERTIES CXX_VISIBILITY_PRESET hidden) to limit the setting to a specific library or executable target. If you are using C just replace CXX by C in the aforementioned commands. You may also want to investigate the VISIBLITY_INLINES_HIDDEN property as well.

The documentation for GENERATE_EXPORT_HEADER includes some more tips and examples related to both properties.

david
  • 1,311
  • 12
  • 32
Joe
  • 6,497
  • 4
  • 29
  • 55
  • 4
    I can't find any proper example of this. Could you elaborate? My guess would be for c++ SET_TARGET_PROPERTIES( mytarget CXX_VISIBILITY_PRESET hidden ) – Abai Jul 09 '15 at 13:34
  • @Abai further details added – Joe Jul 09 '15 at 14:04
4

You can add a flag to the Cmake compiler like that:

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")

To make sure that this only done under Linux you can use this code:

if(UNIX AND CMAKE_COMPILER_IS_GNUCC)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
endif()
Gio
  • 3,242
  • 1
  • 25
  • 53
tune2fs
  • 7,605
  • 5
  • 41
  • 57
  • 2
    In fact, -fvisibility=hidden can be also used with clang so if you want to be able to use both compilers with this feature you can use something like: IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") ... ENDIF() – piponazo Sep 30 '14 at 18:17