Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
After that change is dropped, I give a +1 for the patch set. Done, both in attached 3/5 patch and GitHub branch of mine. --Adam -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
FYI I pushed stage/fix-OSX-bundle-rpaths-and-Qt5 topic for final review. Regards, -- Adam -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
On Thursday, September 18, 2014 06:15:51 PM Adam Strzelecki wrote: FYI I pushed stage/fix-OSX-bundle-rpaths-and-Qt5 topic for final review. Regards, Does the functionality you add allow us to modify CMake/Tests/BundleUtilities/CMakeLists.txt such that the last part in the tests where @rpath is used can be changed to separate the binaries into bin/ and lib/ directories instead of everything in one directory. I assume so since you added the the ability to extract rpaths from a binary. Then eventually, someone can add the same capability for Linux. I'm hoping the parameter you added to functions in GetPrerequisite.cmake is not OS X specific (at the moment, it appears so). Thanks, - Clint -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
On Wednesday, September 17, 2014 01:13:45 AM Adam Strzelecki wrote: What is the new optional parameter to gp_file_type() used for? My intention was to pass exepath rather than take it from the path of original_file. But this is in fact not necessary. I don't see any code in your branch calling that function with the new parameter. You are right, I am not using that. So I can drop that change. --Adam After that change is dropped, I give a +1 for the patch set. Thanks, Clint -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
[cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
This is done by gathering LC_RPATH commands for main bundle executable and using it for @rpath lookup in dependent frameworks. To achieve this all utility functions now take path to executable rather than path to its directory. This enabled apps using @rpath to be bundled correctly, which will be necessary for upcoming Qt 5.4 that will use @rpath for all frameworks. --- Modules/BundleUtilities.cmake | 171 + Modules/GetPrerequisites.cmake | 51 ++-- 2 files changed, 131 insertions(+), 91 deletions(-) diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 7e2b173..817ac78 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -19,6 +19,7 @@ #get_bundle_and_executable #get_bundle_all_executables #get_item_key +#get_item_rpaths #clear_bundle_keys #set_bundle_key_values #get_bundle_keys @@ -75,7 +76,7 @@ # # :: # -# GET_DOTAPP_DIR(exe dotapp_dir_var) +# GET_DOTAPP_DIR(executable dotapp_dir_var) # # Returns the nearest parent dir whose name ends with .app given the # full path to an executable. If there is no such parent dir, then @@ -123,7 +124,7 @@ # # :: # -# SET_BUNDLE_KEY_VALUES(keys_var context item exepath dirs +# SET_BUNDLE_KEY_VALUES(keys_var context item executable dirs # copyflag) # # Add a key to the list (if necessary) for the given item. If added, @@ -163,7 +164,7 @@ # # :: # -# FIXUP_BUNDLE_ITEM(resolved_embedded_item exepath dirs) +# FIXUP_BUNDLE_ITEM(resolved_embedded_item executable dirs) # # Get the direct/non-system prerequisites of the resolved embedded item. # For each prerequisite, change the way it is referenced to the value of @@ -189,11 +190,11 @@ # # :: # -# VERIFY_BUNDLE_PREREQUISITES(bundle result_var info_var) +# VERIFY_BUNDLE_PREREQUISITES(bundle result_var info_var [executable]) # # Verifies that the sum of all prerequisites of all files inside the -# bundle are contained within the bundle or are system libraries, -# presumed to exist everywhere. +# bundle with given optional main executable location are contained within the +# bundle or are system libraries, presumed to exist everywhere. # # :: # @@ -285,8 +286,8 @@ function(get_bundle_main_executable bundle result_var) endfunction() -function(get_dotapp_dir exe dotapp_dir_var) - set(s ${exe}) +function(get_dotapp_dir executable dotapp_dir_var) + set(s ${executable}) if(s MATCHES /.*\\.app/) # If there is a .app parent directory, @@ -407,6 +408,29 @@ function(get_bundle_all_executables bundle exes_var) endfunction() +function(get_item_rpaths item rpaths_var) + if(APPLE) +find_program(otool_cmd otool) +mark_as_advanced(otool_cmd) + endif() + + if(otool_cmd) +execute_process( + COMMAND ${otool_cmd} -l ${item} + OUTPUT_VARIABLE load_cmds_ov + ) +string(REGEX REPLACE [^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n rpath \\1\n load_cmds_ov ${load_cmds_ov}) +string(REGEX MATCHALL rpath [^\n]+ load_cmds_ov ${load_cmds_ov}) +string(REGEX REPLACE rpath load_cmds_ov ${load_cmds_ov}) +if(load_cmds_ov) + gp_append_unique(${rpaths_var} ${load_cmds_ov}) +endif() + endif() + + set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE) +endfunction() + + function(get_item_key item key_var) get_filename_component(item_name ${item} NAME) if(WIN32) @@ -425,12 +449,13 @@ function(clear_bundle_keys keys_var) set(${key}_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_RESOLVED_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_COPYFLAG PARENT_SCOPE) +set(${key}_RPATHS PARENT_SCOPE) endforeach() set(${keys_var} PARENT_SCOPE) endfunction() -function(set_bundle_key_values keys_var context item exepath dirs copyflag) +function(set_bundle_key_values keys_var context item executable dirs copyflag) get_filename_component(item_name ${item} NAME) get_item_key(${item} key) @@ -440,10 +465,17 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag) list(LENGTH ${keys_var} length_after) if(NOT length_before EQUAL length_after) -gp_resolve_item(${context} ${item} ${exepath} ${dirs} resolved_item) +# Always use the exepath of the main bundle executable for @executable_path +# replacements: +# +get_filename_component(exepath ${executable} PATH) + +gp_resolve_item(${context} ${item} ${executable} ${dirs} resolved_item) gp_item_default_embedded_path(${item} default_embedded_path) +get_item_rpaths(${resolved_item} rpaths) + if(item MATCHES [^/]+\\.framework/) # For frameworks, construct the name under the embedded path from the # opening ${item_name}.framework/ to the closing /${item_name}: @@ -479,6 +511,7 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag) set(${key}_EMBEDDED_ITEM ${embedded_item} PARENT_SCOPE)
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
This patch has problems. You are calling BundleUtilities::get_item_key() from GetPrerequisites::gp_resolve_item(). There are users, including myself, which sometimes use GetPrerequisites.cmake but don't use BundleUtilities.cmake. So you cannot call BundleUtilities functions from GetPrerequisites. You also modified the signature of the gp_resolve_item_override() function which is defined by some users. There are a few others which were modified as well. Instead of taking an exepath, your patch changes them to take a executable. Instead, can you extract rpaths for a binary in BundleUtilities and pass that into gp_resolve_item via the existing dirs argument? Clint On Tuesday, September 16, 2014 06:32:20 PM Adam Strzelecki wrote: This is done by gathering LC_RPATH commands for main bundle executable and using it for @rpath lookup in dependent frameworks. To achieve this all utility functions now take path to executable rather than path to its directory. This enabled apps using @rpath to be bundled correctly, which will be necessary for upcoming Qt 5.4 that will use @rpath for all frameworks. --- Modules/BundleUtilities.cmake | 171 + Modules/GetPrerequisites.cmake | 51 ++-- 2 files changed, 131 insertions(+), 91 deletions(-) diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 7e2b173..817ac78 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -19,6 +19,7 @@ #get_bundle_and_executable #get_bundle_all_executables #get_item_key +#get_item_rpaths #clear_bundle_keys #set_bundle_key_values #get_bundle_keys @@ -75,7 +76,7 @@ # # :: # -# GET_DOTAPP_DIR(exe dotapp_dir_var) +# GET_DOTAPP_DIR(executable dotapp_dir_var) # # Returns the nearest parent dir whose name ends with .app given the # full path to an executable. If there is no such parent dir, then @@ -123,7 +124,7 @@ # # :: # -# SET_BUNDLE_KEY_VALUES(keys_var context item exepath dirs +# SET_BUNDLE_KEY_VALUES(keys_var context item executable dirs # copyflag) # # Add a key to the list (if necessary) for the given item. If added, @@ -163,7 +164,7 @@ # # :: # -# FIXUP_BUNDLE_ITEM(resolved_embedded_item exepath dirs) +# FIXUP_BUNDLE_ITEM(resolved_embedded_item executable dirs) # # Get the direct/non-system prerequisites of the resolved embedded item. # For each prerequisite, change the way it is referenced to the value of @@ -189,11 +190,11 @@ # # :: # -# VERIFY_BUNDLE_PREREQUISITES(bundle result_var info_var) +# VERIFY_BUNDLE_PREREQUISITES(bundle result_var info_var [executable]) # # Verifies that the sum of all prerequisites of all files inside the -# bundle are contained within the bundle or are system libraries, -# presumed to exist everywhere. +# bundle with given optional main executable location are contained within the +# bundle or are system libraries, presumed to exist everywhere. # # :: # @@ -285,8 +286,8 @@ function(get_bundle_main_executable bundle result_var) endfunction() -function(get_dotapp_dir exe dotapp_dir_var) - set(s ${exe}) +function(get_dotapp_dir executable dotapp_dir_var) + set(s ${executable}) if(s MATCHES /.*\\.app/) # If there is a .app parent directory, @@ -407,6 +408,29 @@ function(get_bundle_all_executables bundle exes_var) endfunction() +function(get_item_rpaths item rpaths_var) + if(APPLE) +find_program(otool_cmd otool) +mark_as_advanced(otool_cmd) + endif() + + if(otool_cmd) +execute_process( + COMMAND ${otool_cmd} -l ${item} + OUTPUT_VARIABLE load_cmds_ov + ) +string(REGEX REPLACE [^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n rpath \\1\n load_cmds_ov ${load_cmds_ov}) + string(REGEX MATCHALL rpath [^\n]+ load_cmds_ov ${load_cmds_ov}) + string(REGEX REPLACE rpath load_cmds_ov ${load_cmds_ov}) + if(load_cmds_ov) + gp_append_unique(${rpaths_var} ${load_cmds_ov}) +endif() + endif() + + set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE) +endfunction() + + function(get_item_key item key_var) get_filename_component(item_name ${item} NAME) if(WIN32) @@ -425,12 +449,13 @@ function(clear_bundle_keys keys_var) set(${key}_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_RESOLVED_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_COPYFLAG PARENT_SCOPE) +set(${key}_RPATHS PARENT_SCOPE) endforeach() set(${keys_var} PARENT_SCOPE) endfunction() -function(set_bundle_key_values keys_var context item exepath dirs copyflag) +function(set_bundle_key_values keys_var context item executable dirs copyflag) get_filename_component(item_name ${item} NAME) get_item_key(${item} key) @@ -440,10 +465,17 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag) list(LENGTH ${keys_var}
[cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
This is done by gathering LC_RPATH commands for main bundle executable and using it for @rpath lookup in dependent frameworks. To achieve this all utility functions now take path to executable rather than path to its directory. This enabled apps using @rpath to be bundled correctly, which will be necessary for upcoming Qt 5.4 that will use @rpath for all frameworks. --- Modules/BundleUtilities.cmake | 174 + Modules/GetPrerequisites.cmake | 55 +++-- 2 files changed, 137 insertions(+), 92 deletions(-) diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 7e2b173..ab26157 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -19,6 +19,7 @@ #get_bundle_and_executable #get_bundle_all_executables #get_item_key +#get_item_rpaths #clear_bundle_keys #set_bundle_key_values #get_bundle_keys @@ -75,7 +76,7 @@ # # :: # -# GET_DOTAPP_DIR(exe dotapp_dir_var) +# GET_DOTAPP_DIR(executable dotapp_dir_var) # # Returns the nearest parent dir whose name ends with .app given the # full path to an executable. If there is no such parent dir, then @@ -123,7 +124,7 @@ # # :: # -# SET_BUNDLE_KEY_VALUES(keys_var context item exepath dirs +# SET_BUNDLE_KEY_VALUES(keys_var context item executable dirs # copyflag) # # Add a key to the list (if necessary) for the given item. If added, @@ -163,7 +164,7 @@ # # :: # -# FIXUP_BUNDLE_ITEM(resolved_embedded_item exepath dirs) +# FIXUP_BUNDLE_ITEM(resolved_embedded_item executable dirs) # # Get the direct/non-system prerequisites of the resolved embedded item. # For each prerequisite, change the way it is referenced to the value of @@ -189,11 +190,11 @@ # # :: # -# VERIFY_BUNDLE_PREREQUISITES(bundle result_var info_var) +# VERIFY_BUNDLE_PREREQUISITES(bundle result_var info_var [executable]) # # Verifies that the sum of all prerequisites of all files inside the -# bundle are contained within the bundle or are system libraries, -# presumed to exist everywhere. +# bundle with given optional main executable location are contained within the +# bundle or are system libraries, presumed to exist everywhere. # # :: # @@ -285,8 +286,8 @@ function(get_bundle_main_executable bundle result_var) endfunction() -function(get_dotapp_dir exe dotapp_dir_var) - set(s ${exe}) +function(get_dotapp_dir executable dotapp_dir_var) + set(s ${executable}) if(s MATCHES /.*\\.app/) # If there is a .app parent directory, @@ -407,6 +408,29 @@ function(get_bundle_all_executables bundle exes_var) endfunction() +function(get_item_rpaths item rpaths_var) + if(APPLE) +find_program(otool_cmd otool) +mark_as_advanced(otool_cmd) + endif() + + if(otool_cmd) +execute_process( + COMMAND ${otool_cmd} -l ${item} + OUTPUT_VARIABLE load_cmds_ov + ) +string(REGEX REPLACE [^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n rpath \\1\n load_cmds_ov ${load_cmds_ov}) +string(REGEX MATCHALL rpath [^\n]+ load_cmds_ov ${load_cmds_ov}) +string(REGEX REPLACE rpath load_cmds_ov ${load_cmds_ov}) +if(load_cmds_ov) + gp_append_unique(${rpaths_var} ${load_cmds_ov}) +endif() + endif() + + set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE) +endfunction() + + function(get_item_key item key_var) get_filename_component(item_name ${item} NAME) if(WIN32) @@ -425,12 +449,13 @@ function(clear_bundle_keys keys_var) set(${key}_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_RESOLVED_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_COPYFLAG PARENT_SCOPE) +set(${key}_RPATHS PARENT_SCOPE) endforeach() set(${keys_var} PARENT_SCOPE) endfunction() -function(set_bundle_key_values keys_var context item exepath dirs copyflag) +function(set_bundle_key_values keys_var context item executable dirs copyflag) get_filename_component(item_name ${item} NAME) get_item_key(${item} key) @@ -440,10 +465,19 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag) list(LENGTH ${keys_var} length_after) if(NOT length_before EQUAL length_after) -gp_resolve_item(${context} ${item} ${exepath} ${dirs} resolved_item) +# Always use the exepath of the main bundle executable for @executable_path +# replacements: +# +get_filename_component(exepath ${executable} PATH) + +get_item_key(${executable} executable_key) + +gp_resolve_item(${context} ${item} ${executable} ${dirs} resolved_item ${${executable_key}_RPATHS}) gp_item_default_embedded_path(${item} default_embedded_path) +get_item_rpaths(${resolved_item} rpaths) + if(item MATCHES [^/]+\\.framework/) # For frameworks, construct the name under the embedded path from the # opening ${item_name}.framework/ to the closing /${item_name}: @@ -479,6 +513,7 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag)
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
Instead, can you extract rpaths for a binary in BundleUtilities and pass that into gp_resolve_item via the existing dirs argument? Okay, fixed this in the new 3/6 + 4/6 patches, attached to previous patch post. FYI I cannot use existing dirs arguments because other replacements search paths shouldn't look into rpath, only @rpath replacements. So instead I added extra optional rpaths argument to all GetPrerequisites functions that somewhere call gp_resolve_item so need to carry rpaths. WDYT? --Adam -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
On Tuesday, September 16, 2014 08:48:31 PM Adam Strzelecki wrote: Instead, can you extract rpaths for a binary in BundleUtilities and pass that into gp_resolve_item via the existing dirs argument? Okay, fixed this in the new 3/6 + 4/6 patches, attached to previous patch post. FYI I cannot use existing dirs arguments because other replacements search paths shouldn't look into rpath, only @rpath replacements. Sure, but the caller can also check for @rpath and in that case add the rpaths to the existing dirs argument. Yes, there are other find_file() searches in there, that could potentially mess up if the actual filename had @rpath in it. But I would also argue that the general fallback find_file(ri ${item} ${exepath} ${dirs} /usr/lib) can undesirably be affected by other variables such as CMAKE_INCLUDE_PATH. So instead I added extra optional rpaths argument to all GetPrerequisites functions that somewhere call gp_resolve_item so need to carry rpaths. WDYT? --Adam Can you explain the exepath to executable change in the function signatures? I have the impression you changed the signature of several functions to accept /path/to/executable instead of /path/to/ No? These functions are called by other codes and we can't just change the meaning of the arguments. -- Clinton Stimpson Elemental Technologies, Inc Computational Simulation Software, LLC www.csimsoft.com -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
No? These functions are called by other codes and we can't just change the meaning of the arguments. You are completely right. I am changing all stuff back, once I pass rpath as optional argument we can have exepath everywhere. Thanks for your feedback. Regards, -- Adam -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
I have sent [PATCH 3/5] Resolve replace @rpath placeholders which replaces previous 3/6 and obsoletes 4/6. Since it is getting messy like checking fixing maybe stage account and topic branch would be more accurate. --Adam -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
On Tuesday, September 16, 2014 10:53:14 PM Adam Strzelecki wrote: I have sent [PATCH 3/5] Resolve replace @rpath placeholders which replaces previous 3/6 and obsoletes 4/6. Since it is getting messy like checking fixing maybe stage account and topic branch would be more accurate. --Adam Yes, it would be easier to review on stage or on github. Thanks. -- Clinton Stimpson Elemental Technologies, Inc Computational Simulation Software, LLC www.csimsoft.com -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
Yes, it would be easier to review on stage or on github. Thanks. Here it is: https://github.com/nanoant/CMake/commits/fix-bundle-rpaths I would love to get stage access though ;) Cheers, -- Adam -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
On Tuesday, September 16, 2014 11:01:33 PM Adam Strzelecki wrote: Yes, it would be easier to review on stage or on github. Thanks. Here it is: https://github.com/nanoant/CMake/commits/fix-bundle-rpaths I would love to get stage access though ;) Cheers, What is the new optional parameter to gp_file_type() used for? I don't see any code in your branch calling that function with the new parameter. -- Clinton Stimpson Elemental Technologies, Inc Computational Simulation Software, LLC www.csimsoft.com -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
[cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
This is done by gathering LC_RPATH commands for main bundle executable and using it for @rpath lookup in dependent frameworks. To achieve this all utility functions now take path to executable rather than path to its directory. This enabled apps using @rpath to be bundled correctly, which will be necessary for upcoming Qt 5.4 that will use @rpath for all frameworks. --- Modules/BundleUtilities.cmake | 169 - Modules/GetPrerequisites.cmake | 48 ++-- 2 files changed, 124 insertions(+), 93 deletions(-) diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 7e2b173..9733bc9 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -19,6 +19,7 @@ #get_bundle_and_executable #get_bundle_all_executables #get_item_key +#get_item_rpaths #clear_bundle_keys #set_bundle_key_values #get_bundle_keys @@ -75,7 +76,7 @@ # # :: # -# GET_DOTAPP_DIR(exe dotapp_dir_var) +# GET_DOTAPP_DIR(executable dotapp_dir_var) # # Returns the nearest parent dir whose name ends with .app given the # full path to an executable. If there is no such parent dir, then @@ -123,7 +124,7 @@ # # :: # -# SET_BUNDLE_KEY_VALUES(keys_var context item exepath dirs +# SET_BUNDLE_KEY_VALUES(keys_var context item executable dirs # copyflag) # # Add a key to the list (if necessary) for the given item. If added, @@ -163,7 +164,7 @@ # # :: # -# FIXUP_BUNDLE_ITEM(resolved_embedded_item exepath dirs) +# FIXUP_BUNDLE_ITEM(resolved_embedded_item executable dirs) # # Get the direct/non-system prerequisites of the resolved embedded item. # For each prerequisite, change the way it is referenced to the value of @@ -189,11 +190,11 @@ # # :: # -# VERIFY_BUNDLE_PREREQUISITES(bundle result_var info_var) +# VERIFY_BUNDLE_PREREQUISITES(bundle executable result_var info_var) # # Verifies that the sum of all prerequisites of all files inside the -# bundle are contained within the bundle or are system libraries, -# presumed to exist everywhere. +# bundle with given main executable are contained within the bundle or are +# system libraries, presumed to exist everywhere. # # :: # @@ -285,8 +286,8 @@ function(get_bundle_main_executable bundle result_var) endfunction() -function(get_dotapp_dir exe dotapp_dir_var) - set(s ${exe}) +function(get_dotapp_dir executable dotapp_dir_var) + set(s ${executable}) if(s MATCHES /.*\\.app/) # If there is a .app parent directory, @@ -407,6 +408,29 @@ function(get_bundle_all_executables bundle exes_var) endfunction() +function(get_item_rpaths item rpaths_var) + if(APPLE) +find_program(otool_cmd otool) +mark_as_advanced(otool_cmd) + endif() + + if(otool_cmd) +execute_process( + COMMAND ${otool_cmd} -l ${item} + OUTPUT_VARIABLE load_cmds_ov + ) +string(REGEX REPLACE [^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n rpath \\1\n load_cmds_ov ${load_cmds_ov}) +string(REGEX MATCHALL rpath [^\n]+ load_cmds_ov ${load_cmds_ov}) +string(REGEX REPLACE rpath load_cmds_ov ${load_cmds_ov}) +if(load_cmds_ov) + gp_append_unique(${rpaths_var} ${load_cmds_ov}) +endif() + endif() + + set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE) +endfunction() + + function(get_item_key item key_var) get_filename_component(item_name ${item} NAME) if(WIN32) @@ -425,12 +449,13 @@ function(clear_bundle_keys keys_var) set(${key}_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_RESOLVED_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_COPYFLAG PARENT_SCOPE) +set(${key}_RPATHS PARENT_SCOPE) endforeach() set(${keys_var} PARENT_SCOPE) endfunction() -function(set_bundle_key_values keys_var context item exepath dirs copyflag) +function(set_bundle_key_values keys_var context item executable dirs copyflag) get_filename_component(item_name ${item} NAME) get_item_key(${item} key) @@ -440,10 +465,17 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag) list(LENGTH ${keys_var} length_after) if(NOT length_before EQUAL length_after) -gp_resolve_item(${context} ${item} ${exepath} ${dirs} resolved_item) +# Always use the exepath of the main bundle executable for @executable_path +# replacements: +# +get_filename_component(exepath ${executable} PATH) + +gp_resolve_item(${context} ${item} ${executable} ${dirs} resolved_item) gp_item_default_embedded_path(${item} default_embedded_path) +get_item_rpaths(${resolved_item} rpaths) + if(item MATCHES [^/]+\\.framework/) # For frameworks, construct the name under the embedded path from the # opening ${item_name}.framework/ to the closing /${item_name}: @@ -479,6 +511,7 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag) set(${key}_EMBEDDED_ITEM ${embedded_item} PARENT_SCOPE) set(${key}_RESOLVED_EMBEDDED_ITEM
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
I think it would be nice to move get_item_rpaths() from BundleUtilities.cmake to gp_item_get_rpaths() in GetPrerequisites.cmake. And how does your patch or patch set handle @loader_path being used in the rpath? Also, I think the function signature should include the rpath vs runpath distinction. I realize OS X doesn't have the runpath concept, but if one were to add support for Linux, one may need that where the runpath affects only finding immediate dependencies. Below is what I have for Linux and OS X. It include rpath vs. runpath, and expands out the @loader_path variable. Does it help, or did you have something else in mind? # Get rpaths for a binary. function(get_rpaths binary rpaths run_paths) get_filename_component(binary_dir ${binary} PATH) unset(myrpaths) unset(myrunpaths) if(APPLE) execute_process(COMMAND otool -l ${binary} COMMAND grep -A2 LC_RPATH COMMAND grep path OUTPUT_VARIABLE paths) string(REPLACE \n ; paths ${paths}) foreach(str ${paths}) string(REGEX REPLACE path (.*) \\(offset.* \\1 rpath ${str}) string(STRIP ${rpath} rpath) string(REPLACE @loader_path ${binary_dir} rpath ${rpath}) list(APPEND myrpaths ${rpath}) endforeach() else() execute_process(COMMAND objdump -p ${binary} COMMAND grep RPATH OUTPUT_VARIABLE paths) execute_process(COMMAND objdump -p ${binary} COMMAND grep RUNPATH OUTPUT_VARIABLE paths2) string(REPLACE \n ; paths ${paths}) string(REPLACE \n ; paths2 ${paths2}) foreach(str ${paths}) string(REGEX REPLACE RPATH[ ]*(.*) \\1 rpath ${str}) string(STRIP ${rpath} rpath) string(REPLACE \$ORIGIN ${binary_dir} rpath ${rpath}) list(APPEND myrpaths ${rpath}) endforeach() foreach(str ${paths2}) string(REGEX REPLACE RUNPATH[ ]*(.*) \\1 rpath ${str}) string(STRIP ${rpath} rpath) string(REPLACE \$ORIGIN ${binary_dir} rpath ${rpath}) list(APPEND myrunpaths ${rpath}) endforeach() endif() string(REPLACE : ; myrpaths ${myrpaths}) string(REPLACE : ; myrunpaths ${myrunpaths}) set(${rpaths} ${myrpaths} PARENT_SCOPE) set(${run_paths} ${myrunpaths} PARENT_SCOPE) endfunction() Clint - Original Message - This is done by gathering LC_RPATH commands for main bundle executable and using it for @rpath lookup in dependent frameworks. To achieve this all utility functions now take path to executable rather than path to its directory. This enabled apps using @rpath to be bundled correctly, which will be necessary for upcoming Qt 5.4 that will use @rpath for all frameworks. --- Modules/BundleUtilities.cmake | 169 - Modules/GetPrerequisites.cmake | 48 ++-- 2 files changed, 124 insertions(+), 93 deletions(-) diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 7e2b173..9733bc9 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -19,6 +19,7 @@ #get_bundle_and_executable #get_bundle_all_executables #get_item_key +#get_item_rpaths #clear_bundle_keys #set_bundle_key_values #get_bundle_keys @@ -75,7 +76,7 @@ # # :: # -# GET_DOTAPP_DIR(exe dotapp_dir_var) +# GET_DOTAPP_DIR(executable dotapp_dir_var) # # Returns the nearest parent dir whose name ends with .app given the # full path to an executable. If there is no such parent dir, then @@ -123,7 +124,7 @@ # # :: # -# SET_BUNDLE_KEY_VALUES(keys_var context item exepath dirs +# SET_BUNDLE_KEY_VALUES(keys_var context item executable dirs # copyflag) # # Add a key to the list (if necessary) for the given item. If added, @@ -163,7 +164,7 @@ # # :: # -# FIXUP_BUNDLE_ITEM(resolved_embedded_item exepath dirs) +# FIXUP_BUNDLE_ITEM(resolved_embedded_item executable dirs) # # Get the direct/non-system prerequisites of the resolved embedded item. # For each prerequisite, change the way it is referenced to the value of @@ -189,11 +190,11 @@ # # :: # -# VERIFY_BUNDLE_PREREQUISITES(bundle result_var info_var) +# VERIFY_BUNDLE_PREREQUISITES(bundle executable result_var info_var) # # Verifies that the sum of all prerequisites of all files inside the -# bundle are contained within the bundle or are system libraries, -# presumed to exist everywhere. +# bundle with given main executable are contained within the bundle or are +# system libraries, presumed to exist everywhere. # # :: # @@ -285,8 +286,8 @@ function(get_bundle_main_executable bundle result_var) endfunction() -function(get_dotapp_dir exe dotapp_dir_var) - set(s ${exe}) +function(get_dotapp_dir executable dotapp_dir_var) + set(s ${executable}) if(s MATCHES /.*\\.app/) # If there is a .app parent directory, @@
Re: [cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
I think it would be nice to move get_item_rpaths() from BundleUtilities.cmake to gp_item_get_rpaths() in GetPrerequisites.cmake. Well, this function is generic enough to (possible) serve other routines or even in CMakeLists.txt, so I'd leave it as it is. And how does your patch or patch set handle @loader_path being used in the rpath? My patch doesn't change anything in this regard, this is handles as it was done previously via ${context} which is expected to be the referencing library/executable. Also, I think the function signature should include the rpath vs runpath distinction. I realize OS X doesn't have the runpath concept, but if one were to add support for Linux, one may need that where the runpath affects only finding immediate dependencies. Well, this is fine. Can you please submit your patches once my code gets merged. It would be best to do it step by step. WDYT? Below is what I have for Linux and OS X. It include rpath vs. runpath, and expands out the @loader_path variable. Well I think this is incorrect, because @loader_path gets expanded to image containing LC_RPATH not image that is actually loading image, which may be different binary (library), e.g.: bin/MyApp - @rpath/libsome.so lib/libsome.so - @rpath/libsomeplugin.so lib/plugins/libsomeplugin.so Now let's assume bin/MyApp has following LC_RPATHs: @loader_path/plugins @loader_path/../lib Then with your script plugins/ would be resolved to be bin/plugins/ but in fact dyld will resolve it to lib/plugins/ because it is lib/libsome.so which is loader of @rpath/libsomeplugin.so. (...) if(APPLE) execute_process(COMMAND otool -l ${binary} COMMAND grep -A2 LC_RPATH COMMAND grep path OUTPUT_VARIABLE paths) string(REPLACE \n ; paths ${paths}) foreach(str ${paths}) string(REGEX REPLACE path (.*) \\(offset.* \\1 rpath ${str}) string(STRIP ${rpath} rpath) string(REPLACE @loader_path ${binary_dir} rpath ${rpath}) list(APPEND myrpaths ${rpath}) endforeach() (...) Current implementation with my patches doesn't do @loader|executable_path substitution in LC_RPATH because of simple reason. If your binary has LC_RPATHs with these then in 99% cases the dependencies are already in the bundle. So only LC_RPATH with absolute paths will cause copy. --Adam -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers
[cmake-developers] [PATCH 3/6] Resolve replace @rpath placeholders
This is done by gathering LC_RPATH commands for main bundle executable and using it for @rpath lookup in dependent frameworks. To achieve this all utility functions now take path to executable rather than path to its directory. This enabled apps using @rpath to be bundled correctly, which will be necessary for upcoming Qt 5.4 that will use @rpath for all frameworks. --- Modules/BundleUtilities.cmake | 90 +- Modules/GetPrerequisites.cmake | 47 +++--- 2 files changed, 86 insertions(+), 51 deletions(-) diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 7e2b173..dece0d9 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -19,6 +19,7 @@ #get_bundle_and_executable #get_bundle_all_executables #get_item_key +#get_item_rpaths #clear_bundle_keys #set_bundle_key_values #get_bundle_keys @@ -123,7 +124,7 @@ # # :: # -# SET_BUNDLE_KEY_VALUES(keys_var context item exepath dirs +# SET_BUNDLE_KEY_VALUES(keys_var context item executable dirs # copyflag) # # Add a key to the list (if necessary) for the given item. If added, @@ -163,7 +164,7 @@ # # :: # -# FIXUP_BUNDLE_ITEM(resolved_embedded_item exepath dirs) +# FIXUP_BUNDLE_ITEM(resolved_embedded_item executable dirs) # # Get the direct/non-system prerequisites of the resolved embedded item. # For each prerequisite, change the way it is referenced to the value of @@ -285,7 +286,7 @@ function(get_bundle_main_executable bundle result_var) endfunction() -function(get_dotapp_dir exe dotapp_dir_var) +function(get_dotapp_dir executable dotapp_dir_var) set(s ${exe}) if(s MATCHES /.*\\.app/) @@ -407,6 +408,29 @@ function(get_bundle_all_executables bundle exes_var) endfunction() +function(get_item_rpaths item rpaths_var) + if(APPLE) +find_program(otool_cmd otool) +mark_as_advanced(otool_cmd) + endif() + + if(otool_cmd) +execute_process( + COMMAND ${otool_cmd} -l ${item} + OUTPUT_VARIABLE load_cmds_ov + ) +string(REGEX REPLACE [^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n rpath \\1\n load_cmds_ov ${load_cmds_ov}) +string(REGEX MATCHALL rpath [^\n]+ load_cmds_ov ${load_cmds_ov}) +string(REGEX REPLACE rpath load_cmds_ov ${load_cmds_ov}) +if(load_cmds_ov) + gp_append_unique(${rpaths_var} ${load_cmds_ov}) +endif() + endif() + + set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE) +endfunction() + + function(get_item_key item key_var) get_filename_component(item_name ${item} NAME) if(WIN32) @@ -425,12 +449,13 @@ function(clear_bundle_keys keys_var) set(${key}_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_RESOLVED_EMBEDDED_ITEM PARENT_SCOPE) set(${key}_COPYFLAG PARENT_SCOPE) +set(${key}_RPATHS PARENT_SCOPE) endforeach() set(${keys_var} PARENT_SCOPE) endfunction() -function(set_bundle_key_values keys_var context item exepath dirs copyflag) +function(set_bundle_key_values keys_var context item executable dirs copyflag) get_filename_component(item_name ${item} NAME) get_item_key(${item} key) @@ -440,10 +465,17 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag) list(LENGTH ${keys_var} length_after) if(NOT length_before EQUAL length_after) -gp_resolve_item(${context} ${item} ${exepath} ${dirs} resolved_item) +# Always use the exepath of the main bundle executable for @executable_path +# replacements: +# +get_filename_component(exepath ${executable} PATH) + +gp_resolve_item(${context} ${item} ${executable} ${dirs} resolved_item) gp_item_default_embedded_path(${item} default_embedded_path) +get_item_rpaths(${resolved_item} rpaths) + if(item MATCHES [^/]+\\.framework/) # For frameworks, construct the name under the embedded path from the # opening ${item_name}.framework/ to the closing /${item_name}: @@ -479,6 +511,7 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag) set(${key}_EMBEDDED_ITEM ${embedded_item} PARENT_SCOPE) set(${key}_RESOLVED_EMBEDDED_ITEM ${resolved_embedded_item} PARENT_SCOPE) set(${key}_COPYFLAG ${copyflag} PARENT_SCOPE) +set(${key}_RPATHS ${rpaths} PARENT_SCOPE) else() #message(warning: item key '${key}' already in the list, subsequent references assumed identical to first) endif() @@ -490,11 +523,6 @@ function(get_bundle_keys app libs dirs keys_var) get_bundle_and_executable(${app} bundle executable valid) if(valid) -# Always use the exepath of the main bundle executable for @executable_path -# replacements: -# -get_filename_component(exepath ${executable} PATH) - # But do fixups on all executables in the bundle: # get_bundle_all_executables(${bundle} exes) @@ -505,12 +533,12 @@ function(get_bundle_keys app libs dirs keys_var) # but that do not show up