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..95227ca 100644 --- a/test.py +++ b/test.py @@ -49,111 +49,158 @@ def check_build(self, project_name, args=''): self.assertEqual(0, ret, out) return out.replace('\r\n', '\n') - def test_artifact_path(self): - if os_name == 'windows': - # determine if cl.exe is available - ret, out = check_output('cl') - if ret == 0: - self.check_generate('artifacts_path', args='-G "Ninja Multi-Config"') - self.check_build('artifacts_path', '--config Release') - self.assertTrue(os.path.exists('build/artifacts_path/Release/foo_static.lib')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/foo_shared.dll')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/hello.exe')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/subfoo_static.lib')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/subfoo_shared.dll')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/subhello.exe')) - shutil.rmtree('build/artifacts_path') - - self.check_generate('artifacts_path', args="-G Ninja") - self.check_build('artifacts_path', '--config Release') - self.assertTrue(os.path.exists('build/artifacts_path/foo_static.lib')) - self.assertTrue(os.path.exists('build/artifacts_path/foo_shared.dll')) - self.assertTrue(os.path.exists('build/artifacts_path/hello.exe')) - self.assertTrue(os.path.exists('build/artifacts_path/subfoo_static.lib')) - self.assertTrue(os.path.exists('build/artifacts_path/subfoo_shared.dll')) - self.assertTrue(os.path.exists('build/artifacts_path/subhello.exe')) - shutil.rmtree('build/artifacts_path') - - self.check_generate('artifacts_path') - self.check_build('artifacts_path', '--config Release') - self.assertTrue(os.path.exists('build/artifacts_path/Release/foo_static.lib')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/foo_shared.dll')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/hello.exe')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/subfoo_static.lib')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/subfoo_shared.dll')) - self.assertTrue(os.path.exists('build/artifacts_path/Release/subhello.exe')) - elif os_name == 'linux': - self.check_generate('artifacts_path') - self.check_build('artifacts_path') - self.assertTrue(os.path.exists('build/artifacts_path/libfoo_static.a')) - self.assertTrue(os.path.exists('build/artifacts_path/libfoo_shared.so')) - self.assertTrue(os.path.exists('build/artifacts_path/hello')) - self.assertTrue(os.path.exists('build/artifacts_path/libsubfoo_static.a')) - self.assertTrue(os.path.exists('build/artifacts_path/libsubfoo_shared.so')) - self.assertTrue(os.path.exists('build/artifacts_path/subhello')) + # def test_artifact_path(self): + # if os_name == 'windows': + # # determine if cl.exe is available + # ret, out = check_output('cl') + # if ret == 0: + # self.check_generate('artifacts_path', args='-G "Ninja Multi-Config"') + # self.check_build('artifacts_path', '--config Release') + # self.assertTrue(os.path.exists('build/artifacts_path/Release/foo_static.lib')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/foo_shared.dll')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/hello.exe')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/subfoo_static.lib')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/subfoo_shared.dll')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/subhello.exe')) + # shutil.rmtree('build/artifacts_path') + + # self.check_generate('artifacts_path', args="-G Ninja") + # self.check_build('artifacts_path', '--config Release') + # self.assertTrue(os.path.exists('build/artifacts_path/foo_static.lib')) + # self.assertTrue(os.path.exists('build/artifacts_path/foo_shared.dll')) + # self.assertTrue(os.path.exists('build/artifacts_path/hello.exe')) + # self.assertTrue(os.path.exists('build/artifacts_path/subfoo_static.lib')) + # self.assertTrue(os.path.exists('build/artifacts_path/subfoo_shared.dll')) + # self.assertTrue(os.path.exists('build/artifacts_path/subhello.exe')) + # shutil.rmtree('build/artifacts_path') + + # self.check_generate('artifacts_path') + # self.check_build('artifacts_path', '--config Release') + # self.assertTrue(os.path.exists('build/artifacts_path/Release/foo_static.lib')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/foo_shared.dll')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/hello.exe')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/subfoo_static.lib')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/subfoo_shared.dll')) + # self.assertTrue(os.path.exists('build/artifacts_path/Release/subhello.exe')) + # elif os_name == 'linux': + # self.check_generate('artifacts_path') + # self.check_build('artifacts_path') + # self.assertTrue(os.path.exists('build/artifacts_path/libfoo_static.a')) + # self.assertTrue(os.path.exists('build/artifacts_path/libfoo_shared.so')) + # self.assertTrue(os.path.exists('build/artifacts_path/hello')) + # self.assertTrue(os.path.exists('build/artifacts_path/libsubfoo_static.a')) + # self.assertTrue(os.path.exists('build/artifacts_path/libsubfoo_shared.so')) + # self.assertTrue(os.path.exists('build/artifacts_path/subhello')) + # elif os_name == 'mac': + # self.check_generate('artifacts_path') + # self.check_build('artifacts_path') + # self.assertTrue(os.path.exists('build/artifacts_path/libfoo_static.a')) + # self.assertTrue(os.path.exists('build/artifacts_path/libfoo_shared.dylib')) + # self.assertTrue(os.path.exists('build/artifacts_path/hello')) + # self.assertTrue(os.path.exists('build/artifacts_path/libsubfoo_static.a')) + # self.assertTrue(os.path.exists('build/artifacts_path/libsubfoo_shared.dylib')) + # self.assertTrue(os.path.exists('build/artifacts_path/subhello')) + + # shutil.rmtree('build/artifacts_path') + + # def test_debug_postfix(self): + # if os_name == 'windows': + # # msbuild + # self.check_generate('debug_postfix') + # self.check_build('debug_postfix', '--config Debug') + # self.assertTrue(os.path.exists('build/debug_postfix/Debug/foo_d.lib')) + # self.assertTrue(os.path.exists('build/debug_postfix/Debug/hello_d.exe')) + # shutil.rmtree('build/debug_postfix') + + # ret, out = check_output('cl') + # if ret == 0: + # # ninja + # self.check_generate('debug_postfix', args='-G Ninja') + # self.check_build('debug_postfix') + # self.assertTrue(os.path.exists('build/debug_postfix/foo.lib')) + # self.assertTrue(os.path.exists('build/debug_postfix/hello.exe')) + # shutil.rmtree('build/debug_postfix') + + # self.check_generate('debug_postfix', args='-G Ninja -DCMAKE_BUILD_TYPE=Debug') + # self.check_build('debug_postfix') + # self.assertTrue(os.path.exists('build/debug_postfix/foo.lib')) + # self.assertTrue(os.path.exists('build/debug_postfix/hello.exe')) + # shutil.rmtree('build/debug_postfix') + + # # Ninja Multi-Config + # self.check_generate('debug_postfix', args='-G "Ninja Multi-Config"') + # self.check_build('debug_postfix', '--config Debug') + # self.assertTrue(os.path.exists('build/debug_postfix/Debug/foo_d.lib')) + # self.assertTrue(os.path.exists('build/debug_postfix/Debug/hello_d.exe')) + # shutil.rmtree('build/debug_postfix') + # else: + # # Ninja Multi-Config + # self.check_generate('debug_postfix', args='-G "Ninja Multi-Config"') + # self.check_build('debug_postfix') + # self.assertTrue(os.path.exists('build/debug_postfix/Debug/libfoo_d.a')) + # self.assertTrue(os.path.exists('build/debug_postfix/Debug/hello_d')) + # shutil.rmtree('build/debug_postfix') + + # # make + # self.check_generate('debug_postfix') + # self.check_build('debug_postfix') + # self.assertTrue(os.path.exists('build/debug_postfix/libfoo.a')) + # self.assertTrue(os.path.exists('build/debug_postfix/hello')) + # shutil.rmtree('build/debug_postfix') + + # self.check_generate('debug_postfix', args='-DCMAKE_BUILD_TYPE=Debug') + # self.check_build('debug_postfix') + # self.assertTrue(os.path.exists('build/debug_postfix/libfoo.a')) + # 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('artifacts_path') - self.check_build('artifacts_path') - self.assertTrue(os.path.exists('build/artifacts_path/libfoo_static.a')) - self.assertTrue(os.path.exists('build/artifacts_path/libfoo_shared.dylib')) - self.assertTrue(os.path.exists('build/artifacts_path/hello')) - self.assertTrue(os.path.exists('build/artifacts_path/libsubfoo_static.a')) - self.assertTrue(os.path.exists('build/artifacts_path/libsubfoo_shared.dylib')) - self.assertTrue(os.path.exists('build/artifacts_path/subhello')) - - shutil.rmtree('build/artifacts_path') - - def test_debug_postfix(self): - if os_name == 'windows': - # msbuild - self.check_generate('debug_postfix') - self.check_build('debug_postfix', '--config Debug') - self.assertTrue(os.path.exists('build/debug_postfix/Debug/foo_d.lib')) - self.assertTrue(os.path.exists('build/debug_postfix/Debug/hello_d.exe')) - shutil.rmtree('build/debug_postfix') - - ret, out = check_output('cl') - if ret == 0: - # ninja - self.check_generate('debug_postfix', args='-G Ninja') - self.check_build('debug_postfix') - self.assertTrue(os.path.exists('build/debug_postfix/foo.lib')) - self.assertTrue(os.path.exists('build/debug_postfix/hello.exe')) - shutil.rmtree('build/debug_postfix') - - self.check_generate('debug_postfix', args='-G Ninja -DCMAKE_BUILD_TYPE=Debug') - self.check_build('debug_postfix') - self.assertTrue(os.path.exists('build/debug_postfix/foo.lib')) - self.assertTrue(os.path.exists('build/debug_postfix/hello.exe')) - shutil.rmtree('build/debug_postfix') - - # Ninja Multi-Config - self.check_generate('debug_postfix', args='-G "Ninja Multi-Config"') - self.check_build('debug_postfix', '--config Debug') - self.assertTrue(os.path.exists('build/debug_postfix/Debug/foo_d.lib')) - self.assertTrue(os.path.exists('build/debug_postfix/Debug/hello_d.exe')) - shutil.rmtree('build/debug_postfix') - else: - # Ninja Multi-Config - self.check_generate('debug_postfix', args='-G "Ninja Multi-Config"') - self.check_build('debug_postfix') - self.assertTrue(os.path.exists('build/debug_postfix/Debug/libfoo_d.a')) - self.assertTrue(os.path.exists('build/debug_postfix/Debug/hello_d')) - shutil.rmtree('build/debug_postfix') - - # make - self.check_generate('debug_postfix') - self.check_build('debug_postfix') - self.assertTrue(os.path.exists('build/debug_postfix/libfoo.a')) - self.assertTrue(os.path.exists('build/debug_postfix/hello')) - shutil.rmtree('build/debug_postfix') - - self.check_generate('debug_postfix', args='-DCMAKE_BUILD_TYPE=Debug') - self.check_build('debug_postfix') - self.assertTrue(os.path.exists('build/debug_postfix/libfoo.a')) - self.assertTrue(os.path.exists('build/debug_postfix/hello')) - shutil.rmtree('build/debug_postfix') - + 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