Skip to content

Commit

Permalink
feat: add rocbuild_link_as_needed()
Browse files Browse the repository at this point in the history
  • Loading branch information
zchrissirhcz committed Nov 23, 2024
1 parent 7cb05b7 commit 6c7ed10
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 1 deletion.
17 changes: 16 additions & 1 deletion rocbuild.cmake
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Author: Zhuo Zhang <[email protected]>
# Homepage: https://github.com/zchrissirhcz/rocbuild

cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.13)

# CMake 3.10: include_guard()
# CMake 3.21: $<TARGET_RUNTIME_DLLS:tgt>
# CMake 3.13: target_link_options() use "LINKER:" as a portable way for different compiler + linker combo

include_guard()

Expand Down Expand Up @@ -268,5 +269,19 @@ function(rocbuild_hide_symbols TARGET)
endfunction()


function(rocbuild_link_as_needed 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_link_options(${TARGET} PRIVATE "LINKER:-as-needed")
elseif((CMAKE_C_COMPILER_ID STREQUAL "AppleClang") OR
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"))
target_link_options(${TARGET} PRIVATE "LINKER:-dead_strip_dylibs")
endif()
endif()
endfunction()


rocbuild_set_artifacts_path()
rocbuild_enable_ninja_colorful_output()
38 changes: 38 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,5 +222,43 @@ def test_copy_dlls(self):
self.assertTrue(items[3] == 'test.exe')
shutil.rmtree('build/copy_dlls')

def test_link_as_needed(self):
if os_name == 'linux':
self.check_generate('link_as_needed', args='-DLINK_AS_NEEDED=0')
self.check_build('link_as_needed')
cmd = 'ldd build/link_as_needed/libfoo_math.so'
ret, out = check_output(cmd)
print(out)
self.assertEqual(0, ret, out)
self.assertIn('libfoo.so =>', out)
shutil.rmtree('build/link_as_needed')

self.check_generate('link_as_needed', args='-DLINK_AS_NEEDED=1')
self.check_build('link_as_needed')
cmd = 'ldd build/link_as_needed/libfoo_math.so'
ret, out = check_output(cmd)
print(out)
self.assertEqual(0, ret, out)
self.assertTrue('libfoo.so =>' not in out)
shutil.rmtree('build/link_as_needed')
elif os_name == 'mac':
self.check_generate('link_as_needed', args='-DLINK_AS_NEEDED=0')
self.check_build('link_as_needed')
cmd = 'otool -L build/link_as_needed/libfoo_math.dylib'
ret, out = check_output(cmd)
print(out)
self.assertEqual(0, ret, out)
self.assertIn('@rpath/libfoo.dylib', out)
shutil.rmtree('build/link_as_needed')

self.check_generate('link_as_needed', args='-DLINK_AS_NEEDED=1')
self.check_build('link_as_needed')
cmd = 'otool -L build/link_as_needed/libfoo_math.dylib'
ret, out = check_output(cmd)
print(out)
self.assertEqual(0, ret, out)
self.assertTrue('@rpath/libfoo.dylib' not in out)
shutil.rmtree('build/link_as_needed')

if __name__ == "__main__":
unittest.main()
25 changes: 25 additions & 0 deletions tests/link_as_needed/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.10)
project(test_link_as_needed)

include(../../rocbuild.cmake)

# For test purpose, we explicitly enable `--no-as-needed` for GNU and Clang as the default behavior.
if(CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang)$")
add_link_options("LINKER:--no-as-needed")
endif()

add_library(foo_math SHARED
foo_math.h
foo_math.c
)
target_include_directories(foo_math PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(foo_math PRIVATE FOO_MATH_EXPORTS)

add_library(foo SHARED ../src/foo.c)
target_include_directories(foo PRIVATE ../src)

target_link_libraries(foo_math PRIVATE foo)

if(LINK_AS_NEEDED)
rocbuild_link_as_needed(foo_math)
endif()
21 changes: 21 additions & 0 deletions tests/link_as_needed/foo_math.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "foo_math.h"
#include <stdlib.h>

static int compare(const void *a, const void *b)
{
int int_a = *(int *)a;
int int_b = *(int *)b;

if (int_a < int_b) return -1;
else if (int_a > int_b) return 1;
else return 0;
}

void abs_sort(int n, int* data)
{
for (int i = 0; i < n; i++)
{
data[i] = abs(i);
}
qsort(data, n, sizeof(int), compare);
}
29 changes: 29 additions & 0 deletions tests/link_as_needed/foo_math.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#ifdef FOO_MATH_EXPORTS
# if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
# define FOO_MATH_API __declspec(dllexport)
# elif defined(__GNUC__) && __GNUC__ >= 4
# define FOO_MATH_API __attribute__ ((visibility ("default")))
# endif
#else
# if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
# define FOO_MATH_API __declspec(dllimport)
# else
# define FOO_MATH_API
# endif
#endif

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

FOO_MATH_API
void abs_sort(int n, int* data);

#ifdef __cplusplus
}
#endif

0 comments on commit 6c7ed10

Please sign in to comment.