From 3671f9d724d1d8ec66d8d8c11bd531423f7e8efb Mon Sep 17 00:00:00 2001 From: Zhuo Zhang Date: Sat, 23 Nov 2024 23:48:59 +0800 Subject: [PATCH] feat: hide symbols for shared libraries --- rocbuild.cmake | 11 ++++++++ test.py | 47 +++++++++++++++++++++++++++++++ tests/hide_symbols/CMakeLists.txt | 17 +++++++++++ tests/src/bar.c | 4 +++ tests/src/bar.h | 25 ++++++++++++++++ tests/src/bar_internal.c | 6 ++++ tests/src/bar_internal.h | 11 ++++++++ 7 files changed, 121 insertions(+) create mode 100644 tests/hide_symbols/CMakeLists.txt create mode 100644 tests/src/bar.c create mode 100644 tests/src/bar.h create mode 100644 tests/src/bar_internal.c create mode 100644 tests/src/bar_internal.h diff --git a/rocbuild.cmake b/rocbuild.cmake index 8c951e5..33aeaaf 100644 --- a/rocbuild.cmake +++ b/rocbuild.cmake @@ -149,5 +149,16 @@ function(rocbuild_set_debug_postfix TARGET) endfunction() +function(rocbuild_hide_symbols TARGET) + get_target_property(TARGET_TYPE ${TARGET} TYPE) + if(TARGET_TYPE STREQUAL "SHARED_LIBRARY") + if((CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") OR + (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")) + target_compile_options(${TARGET} PRIVATE "-fvisibility=hidden") + endif() + endif() +endfunction() + + rocbuild_set_artifacts_path() rocbuild_enable_ninja_colorful_output() \ No newline at end of file diff --git a/test.py b/test.py index cbbfed9..3f296b8 100644 --- a/test.py +++ b/test.py @@ -154,6 +154,53 @@ def test_debug_postfix(self): self.assertTrue(os.path.exists('build/debug_postfix/hello')) shutil.rmtree('build/debug_postfix') + def test_hide_symbols(self): + if os_name == 'linux': + self.check_generate('hide_symbols', args='-DHIDDEN=1') + self.check_build('hide_symbols') + cmd = 'nm -C build/hide_symbols/libbar.so | grep " T "' + ret, out = check_output(cmd) + self.assertEqual(0, ret, out) + out = out.replace('\r\n', '\n') + lines = out.strip().split('\n') + self.assertEqual(len(lines), 1, lines) + self.assertTrue(lines[0].endswith(' T bar')) + shutil.rmtree('build/hide_symbols') + + self.check_generate('hide_symbols', args='-DHIDDEN=0') + self.check_build('hide_symbols') + cmd = f'nm -C build/hide_symbols/libbar.so | grep " T "' + ret, out = check_output(cmd) + self.assertEqual(0, ret, out) + out = out.replace('\r\n', '\n') + lines = out.strip().split('\n') + self.assertEqual(len(lines), 2, lines) + self.assertTrue(lines[0].endswith(' T bar')) + self.assertTrue(lines[1].endswith(' T bar_internal')) + shutil.rmtree('build/hide_symbols') + elif os_name == 'mac': + self.check_generate('hide_symbols', args='-DHIDDEN=1') + self.check_build('hide_symbols') + cmd = 'nm -C build/hide_symbols/libbar.dylib | grep " T "' + ret, out = check_output(cmd) + self.assertEqual(0, ret, out) + out = out.replace('\r\n', '\n') + lines = out.strip().split('\n') + self.assertEqual(len(lines), 1, lines) + self.assertTrue(lines[0].endswith(' T _bar')) + shutil.rmtree('build/hide_symbols') + + self.check_generate('hide_symbols', args='-DHIDDEN=0') + self.check_build('hide_symbols') + cmd = f'nm -C build/hide_symbols/libbar.dylib | grep " T "' + ret, out = check_output(cmd) + self.assertEqual(0, ret, out) + out = out.replace('\r\n', '\n') + lines = out.strip().split('\n') + self.assertEqual(len(lines), 2, lines) + self.assertTrue(lines[0].endswith(' T _bar')) + self.assertTrue(lines[1].endswith(' T _bar_internal')) + shutil.rmtree('build/hide_symbols') if __name__ == "__main__": unittest.main() \ No newline at end of file diff --git a/tests/hide_symbols/CMakeLists.txt b/tests/hide_symbols/CMakeLists.txt new file mode 100644 index 0000000..2360cab --- /dev/null +++ b/tests/hide_symbols/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.10) +project(test_hide_symbols) + +include(../../rocbuild.cmake) + +add_library(bar SHARED + ../src/bar.h + ../src/bar.c + ../src/bar_internal.h + ../src/bar_internal.c +) +target_include_directories(bar PRIVATE ../src) +target_compile_definitions(bar PRIVATE BAR_EXPORTS) + +if(HIDDEN) + rocbuild_hide_symbols(bar) +endif() diff --git a/tests/src/bar.c b/tests/src/bar.c new file mode 100644 index 0000000..ea149c2 --- /dev/null +++ b/tests/src/bar.c @@ -0,0 +1,4 @@ +#include "bar.h" +#include "bar_internal.h" + +int bar() { return 1 + bar_internal(); } \ No newline at end of file diff --git a/tests/src/bar.h b/tests/src/bar.h new file mode 100644 index 0000000..af593de --- /dev/null +++ b/tests/src/bar.h @@ -0,0 +1,25 @@ +#pragma once + +#ifdef BAR_EXPORTS +# if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) +# define BAR_API __declspec(dllexport) +# elif defined(__GNUC__) && __GNUC__ >= 4 +# define BAR_API __attribute__ ((visibility ("default"))) +# endif +#else +# if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) +# define BAR_API __declspec(dllimport) +# else +# define BAR_API +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +BAR_API int bar(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/tests/src/bar_internal.c b/tests/src/bar_internal.c new file mode 100644 index 0000000..7974c48 --- /dev/null +++ b/tests/src/bar_internal.c @@ -0,0 +1,6 @@ +#include "bar_internal.h" + +int bar_internal() +{ + return 2; +} \ No newline at end of file diff --git a/tests/src/bar_internal.h b/tests/src/bar_internal.h new file mode 100644 index 0000000..7deb627 --- /dev/null +++ b/tests/src/bar_internal.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +int bar_internal(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file