[cmake-developers] [PATCH 3/6] Resolve & replace @rpath placeholders

Adam Strzelecki ono at java.pl
Fri Sep 5 13:23:20 EDT 2014


> 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


More information about the cmake-developers mailing list