From 9a6b102205045e457db24bd00777ef000c30e242 Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Mon, 21 Nov 2011 16:45:49 -0700 Subject: [PATCH 1/5] GetPrerequisites: Add support for @rpath on Mac OS X. Handle @rpath much like other Unixes, by doing a find_file with the given directories. Also, consider a library to be local if it is found in the same directory or a subdirectory relative to the user executable/library. Previously, it was local only if found in the same directory. This case is encountered when @rpath is used with framework libraries, which are inside a directory tree. --- Modules/GetPrerequisites.cmake | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index 2efa07999..fbbaf9c4f 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -303,6 +303,26 @@ function(gp_resolve_item context item exepath dirs resolved_item_var) endif(item MATCHES "@loader_path") endif(NOT resolved) + if(NOT resolved) + if(item MATCHES "@rpath") + # + # @rpath references are relative to the paths built into the binaries with -rpath + # We handle this case like we do for other Unixes + # + string(REPLACE "@rpath/" "" norpath_item "${item}") + + set(ri "ri-NOTFOUND") + find_file(ri "${norpath_item}" ${exepath} ${dirs} NO_DEFAULT_PATH) + if(ri) + #message(STATUS "info: 'find_file' in exepath/dirs (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + set(ri "ri-NOTFOUND") + endif(ri) + + endif(item MATCHES "@rpath") + endif(NOT resolved) + if(NOT resolved) set(ri "ri-NOTFOUND") find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH) @@ -458,9 +478,13 @@ function(gp_resolved_file_type original_file file exepath dirs type_var) if(NOT is_system) get_filename_component(original_path "${original_lower}" PATH) - get_filename_component(path "${lower}" PATH) - if("${original_path}" STREQUAL "${path}") - set(is_local 1) + string(LENGTH "${original_path}/" original_length) + string(LENGTH "${lower}" path_length) + if(${path_length} GREATER ${original_length}) + string(SUBSTRING "${lower}" 0 ${original_length} path) + if("${original_path}/" STREQUAL "${path}") + set(is_local 1) + endif() endif() endif() endif() From 880139a6421649b9b3ff8048418cd556e7ddf2c1 Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Thu, 19 Jan 2012 18:10:01 -0700 Subject: [PATCH 2/5] GetPrerequisites: Add support for @rpath on Mac OS X. Change to consider a library embedded if it is found in a subdirectory relative to the using executable/library. Previous commit considered them local. This case is encountered when @rpath is used with framework libraries, which are inside a directory tree. --- Modules/GetPrerequisites.cmake | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index fbbaf9c4f..8761f400f 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -478,12 +478,17 @@ function(gp_resolved_file_type original_file file exepath dirs type_var) if(NOT is_system) get_filename_component(original_path "${original_lower}" PATH) - string(LENGTH "${original_path}/" original_length) - string(LENGTH "${lower}" path_length) - if(${path_length} GREATER ${original_length}) - string(SUBSTRING "${lower}" 0 ${original_length} path) - if("${original_path}/" STREQUAL "${path}") - set(is_local 1) + get_filename_component(path "${lower}" PATH) + if("${original_path}" STREQUAL "${path}") + set(is_local 1) + else() + string(LENGTH "${original_path}/" original_length) + string(LENGTH "${lower}" path_length) + if(${path_length} GREATER ${original_length}) + string(SUBSTRING "${lower}" 0 ${original_length} path) + if("${original_path}/" STREQUAL "${path}") + set(is_embedded 1) + endif() endif() endif() endif() From 0d96decdd069451c9b805e411abe0fc6225c8ee9 Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Thu, 19 Jan 2012 22:03:06 -0700 Subject: [PATCH 3/5] GetPrerequisites: Add test for @rpath support. --- Tests/BundleUtilities/CMakeLists.txt | 49 ++++++++++++++++++++++ Tests/BundleUtilities/testbundleutils3.cpp | 33 +++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 Tests/BundleUtilities/testbundleutils3.cpp diff --git a/Tests/BundleUtilities/CMakeLists.txt b/Tests/BundleUtilities/CMakeLists.txt index 6209c8fcd..bb870e82c 100644 --- a/Tests/BundleUtilities/CMakeLists.txt +++ b/Tests/BundleUtilities/CMakeLists.txt @@ -82,3 +82,52 @@ add_custom_target(testbundleutils2_test ALL DEPENDS testbundleutils1 module2 ) add_dependencies(testbundleutils2_test testbundleutils2) + + +if(APPLE AND CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0) +###### Test a Bundle application using dependencies +###### and @rpaths on Mac OS X 10.5 or greater + + # a shared library + add_library(shared-3 SHARED shared.cpp shared.h) + + # another shared library + add_library(shared2-3 SHARED shared2.cpp shared2.h) + + # a framework library + add_library(framework-3 SHARED framework.cpp framework.h) + set_target_properties(framework-3 PROPERTIES FRAMEWORK 1) + + # build dependencies with @rpath install name + set_target_properties(shared-3 shared2-3 framework-3 PROPERTIES + INSTALL_NAME_DIR "@rpath" + BUILD_WITH_INSTALL_RPATH 1) + + # a loadable module (depends on shared2) + # testbundleutils1 will load this at runtime + add_library(module3 MODULE module.cpp module.h) + set_target_properties(module3 PROPERTIES PREFIX "" LINK_FLAGS "-Wl,-rpath,${CMAKE_CURRENT_BINARY_DIR}/testdir3") + get_target_property(module_loc module3 LOCATION) + target_link_libraries(module3 shared2-3) + + # a non-bundle application + add_executable(testbundleutils3 testbundleutils3.cpp) + target_link_libraries(testbundleutils3 shared-3 framework-3 ${CMAKE_DL_LIBS}) + get_target_property(loc testbundleutils3 LOCATION) + + set_target_properties(testbundleutils3 module3 PROPERTIES + LINK_FLAGS "-Wl,-rpath,${CMAKE_CURRENT_BINARY_DIR}/testdir3") + + # add custom target to install and test the app + add_custom_target(testbundleutils3_test ALL + COMMAND ${CMAKE_COMMAND} + "-DINPUT=${loc}" + "-DMODULE=${module_loc}" + "-DINPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" + "-DOUTPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/testdir3" + -P "${CMAKE_CURRENT_SOURCE_DIR}/bundleutils.cmake" + DEPENDS testbundleutils3 module3 + ) + + add_dependencies(testbundleutils3_test testbundleutils3) +endif() diff --git a/Tests/BundleUtilities/testbundleutils3.cpp b/Tests/BundleUtilities/testbundleutils3.cpp new file mode 100644 index 000000000..9df13e988 --- /dev/null +++ b/Tests/BundleUtilities/testbundleutils3.cpp @@ -0,0 +1,33 @@ + +#include "framework.h" +#include "shared.h" +#include "stdio.h" + +#if defined(WIN32) +#include +#else +#include "dlfcn.h" +#endif + +int main(int, char**) +{ + framework(); + shared(); + +#if defined(WIN32) + HANDLE lib = LoadLibraryA("module3.dll"); + if(!lib) + { + printf("Failed to open module3\n"); + } +#else + void* lib = dlopen("module3.so", RTLD_LAZY); + if(!lib) + { + printf("Failed to open module3\n%s\n", dlerror()); + } +#endif + + + return lib == 0 ? 1 : 0; +} From 36d66416f4f47ecf0cf84b1618b60bb7d853f2e5 Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Fri, 20 Jan 2012 06:59:17 -0700 Subject: [PATCH 4/5] Fix new BundleUtilities test failure on Mac 10.4.x --- Tests/BundleUtilities/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/BundleUtilities/CMakeLists.txt b/Tests/BundleUtilities/CMakeLists.txt index bb870e82c..efbf1522d 100644 --- a/Tests/BundleUtilities/CMakeLists.txt +++ b/Tests/BundleUtilities/CMakeLists.txt @@ -84,7 +84,7 @@ add_custom_target(testbundleutils2_test ALL add_dependencies(testbundleutils2_test testbundleutils2) -if(APPLE AND CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0) +if(APPLE AND NOT CMAKE_SYSTEM_VERSION VERSION_LESS 9.0) ###### Test a Bundle application using dependencies ###### and @rpaths on Mac OS X 10.5 or greater From 98d20316bdf701865a3e3c4df7d378917224b8b0 Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Fri, 20 Jan 2012 22:02:01 -0700 Subject: [PATCH 5/5] Fix BundleUtilities test failure with space in build path. --- Tests/BundleUtilities/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/BundleUtilities/CMakeLists.txt b/Tests/BundleUtilities/CMakeLists.txt index efbf1522d..8f24afe9a 100644 --- a/Tests/BundleUtilities/CMakeLists.txt +++ b/Tests/BundleUtilities/CMakeLists.txt @@ -106,7 +106,7 @@ if(APPLE AND NOT CMAKE_SYSTEM_VERSION VERSION_LESS 9.0) # a loadable module (depends on shared2) # testbundleutils1 will load this at runtime add_library(module3 MODULE module.cpp module.h) - set_target_properties(module3 PROPERTIES PREFIX "" LINK_FLAGS "-Wl,-rpath,${CMAKE_CURRENT_BINARY_DIR}/testdir3") + set_target_properties(module3 PROPERTIES PREFIX "" LINK_FLAGS "-Wl,-rpath,@loader_path/") get_target_property(module_loc module3 LOCATION) target_link_libraries(module3 shared2-3) @@ -116,7 +116,7 @@ if(APPLE AND NOT CMAKE_SYSTEM_VERSION VERSION_LESS 9.0) get_target_property(loc testbundleutils3 LOCATION) set_target_properties(testbundleutils3 module3 PROPERTIES - LINK_FLAGS "-Wl,-rpath,${CMAKE_CURRENT_BINARY_DIR}/testdir3") + LINK_FLAGS "-Wl,-rpath,@loader_path/") # add custom target to install and test the app add_custom_target(testbundleutils3_test ALL