Repository: conan-io/conan

Issue:
CMAKE_SKIP_INSTALL_RPATH is not set on macOS
Hi,

According to the docs `conan_basic_setup()` sets `CMAKE_SKIP_RPATH 1` on macOS.
However, `otool -L my_installed_lib.dylib` gives the following output:

>@rpath/libmy_installed_lib.dylib (compatibility version 0.0.0, current version 0.0.0)

Whereas the one in the build folder doesn't have the `@rpath/` prefix.

Is this intended? I'm kind of a n00b with rpaths.

EDIT: setting `cmake.definitions["CMAKE_SKIP_INSTALL_RPATH"] = "ON"` in my recipe fixes the issue.
EDIT2: that's weird though, the CMake doc says that CMAKE_SKIP_RPATH includes CMAKE_SKIP_INSTALL_RPATH...


Discussion:
Yes, it should work only with CMAKE_SKIP_RPATH according to the docs, but I didn't try it with install.
Can you see the message "Conan: Adjusting default RPATHs Conan policies"? In that case, CMAKE_SKIP_RPATH is set.
In any case, `cmake.definitions["CMAKE_SKIP_INSTALL_RPATH"]` is totally ok, I would recommend a custom rpath management by recipe creator, we learned that there are several different approaches with RPATHS, so we introduced the SKIP_RPATH to let the user adjust it. 
I've upgraded my CMake to v3.9.6, and had a warning about this [CMP0068 policy](https://cmake.org/cmake/help/v3.9/policy/CMP0068.html).

I've removed the `conan_basic_setup(TARGETS)` line in my CMakeLists.txt, and settings explicitely `set(CMAKE_INSTALL_NAME_DIR "")` effectively removed the `@rpath/` from the installed shared library.

~~Having this line with the `conan_basic_setup` had no effect though.~~
EDIT: Was wrong about my last statement, adding `cmake.definitions["CMAKE_INSTALL_NAME_DIR"] = ""` works.
I'm not sure to grasp every detail about the install_name and the rpath, but right now this issue only arose with CMake based projects, IIRC conan recommands to replace the `install_name` flag in AutoTools based projects.
If you remove the `conan_basic_setup(TARGETS)` you are going to lose many things, the targets of the dependencies, for example.

You can deactivate the `rpath` management calling `conan_basic_setup(TARGETS SKIP_RPATH)` and adjust all manually.

About the recommendation of clearing the install_name, and rpaths in general. You probably don't want your executables and shared libraries containing an absolute path to your local cache, because if you share these binaries, they will be useless in another computer. That's why we recommend to clear them.

But, there are some other approaches, for example using the `@executable_path` in Macos to specify a relative path to the executable.

You can read more here: http://conanio.readthedocs.io/en/latest/howtos/shared/rpaths.html
Thanks, I spent the whole day learning a lot about rpaths :)

However I believe the issue is in CMake, I rollbacked everything to use `conan_basic_setup(TARGETS)`, and I still get the `@rpath/` prefix only on the installed binaries.

I trimmed the CMakeLists.txt to look almost exactly to the bzip2 one, but still get the same issue. I'll simply set `CMAKE_INSTALL_DIR_NAME` to an empty string to workaround that.

I will post details if I discover something, thanks for the help!
I do still think this line from the CMP0068 is quite relevant to my issue:

>If SKIP_BUILD_RPATH, CMAKE_SKIP_RPATH or CMAKE_SKIP_INSTALL_RPATH were used to strip the directory portion of the install_name of a target, one may set INSTALL_NAME_DIR="" instead.

I rechecked every shared library, and those using CMake's `install` method have the same issue. Applying the proposed fix (i.e. INSTALL_NAME_DIR="") works for every case.

EDIT: CMake 3.9 (released on July, 17th) and newer are affected, should `set(INSTALL_NAME_DIR "")` be added to `conan_set_rpath()` to keep the older releases' behavior?
Thanks, yes, probably we should add it. I'm a little worried about break something, but probably we should do it.

Resolving patch:
diff --git a/conans/client/generators/cmake_common.py b/conans/client/generators/cmake_common.py
--- a/conans/client/generators/cmake_common.py
+++ b/conans/client/generators/cmake_common.py
@@ -247,7 +247,8 @@ def generate_targets_section(dependencies):
         set(CMAKE_SKIP_RPATH 1)  # AVOID RPATH FOR *.dylib, ALL LIBS BETWEEN THEM AND THE EXE
                                  # SHOULD BE ON THE LINKER RESOLVER PATH (./ IS ONE OF THEM)
         # Policy CMP0068
-        set(CMAKE_SKIP_INSTALL_RPATH 1) # In previous versions to 3.9 it is explicitly necessary
+        # We want the old behavior, in CMake >= 3.9 CMAKE_SKIP_RPATH won't affect the install_name in OSX
+        set(CMAKE_INSTALL_NAME_DIR "")
     endif()
 endmacro()
 
@@ -452,7 +453,7 @@ def generate_targets_section(dependencies):
 
 cmake_macros = """
 macro(conan_basic_setup)
-    set(options TARGETS NO_OUTPUT_DIRS SKIP_RPATH)
+    set(options TARGETS NO_OUTPUT_DIRS SKIP_RPATH KEEP_RPATHS)
     cmake_parse_arguments(ARGUMENTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
     if(CONAN_EXPORTED)
         message(STATUS "Conan: called by CMake conan helper")
@@ -469,7 +470,12 @@ def generate_targets_section(dependencies):
         message(STATUS "Conan: Using cmake targets configuration")
         conan_define_targets()
     endif()
-    if(NOT ARGUMENTS_SKIP_RPATH)
+    if(ARGUMENTS_SKIP_RPATH)
+        # Change by "DEPRECATION" or "SEND_ERROR" when we are ready
+        message(WARNING "Conan: SKIP_RPATH is deprecated, it has been renamed to KEEP_RPATHS")
+    endif()
+    if(NOT ARGUMENTS_SKIP_RPATH AND NOT ARGUMENTS_KEEP_RPATHS)
+        # Parameter has renamed, but we keep the compatibility with old SKIP_RPATH
         message(STATUS "Conan: Adjusting default RPATHs Conan policies")
         conan_set_rpath()
     endif()


Test patch:
diff --git a/conans/test/build_helpers/cmake_test.py b/conans/test/build_helpers/cmake_test.py
--- a/conans/test/build_helpers/cmake_test.py
+++ b/conans/test/build_helpers/cmake_test.py
@@ -196,7 +196,6 @@ def check(text, build_config, generator=None):
               '-DCONAN_COMPILER="Visual Studio" -DCONAN_COMPILER_VERSION="12" -Wno-dev',
               "--config Debug")
 
-
     def deleted_os_test(self):
         partial_settings = """
 os: [Linux]
diff --git a/conans/test/functional/cmake_skip_rpath_test.py b/conans/test/functional/cmake_skip_rpath_test.py
--- a/conans/test/functional/cmake_skip_rpath_test.py
+++ b/conans/test/functional/cmake_skip_rpath_test.py
@@ -1,3 +1,4 @@
+import platform
 import unittest
 from conans.test.utils.tools import TestClient
 
@@ -21,10 +22,10 @@ class HelloConan(ConanFile):
 cmake_minimum_required(VERSION 2.8.12)
 
 include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
-conan_basic_setup(TARGETS SKIP_RPATH)
+conan_basic_setup(TARGETS %s)
 
 IF(APPLE AND CMAKE_SKIP_RPATH)
-    MESSAGE(FATAL_ERROR "RPath was not skipped")
+    MESSAGE(FATAL_ERROR "RPath was skipped")
 ENDIF()
 """
 
@@ -32,31 +33,36 @@ class HelloConan(ConanFile):
 class CMakeSkipRpathTest(unittest.TestCase):
 
     def test_skip_flag(self):
-        client = TestClient()
-        client.save({"conanfile.py": conanfile_py})
-        client.run("export lasote/testing")
-        client.save({"conanfile.txt": conanfile,
-                     "CMakeLists.txt": cmake}, clean_first=True)
-
-        client.run('install -g cmake --build')
-        client.runner("cmake .", cwd=client.current_folder)
-        self.assertNotIn("Conan: Adjusting default RPATHs Conan policies", client.user_io.out)
-        self.assertIn("Build files have been written", client.user_io.out)
-
-        client.save({"conanfile.txt": conanfile,
-                     "CMakeLists.txt": cmake.replace("TARGETS SKIP_RPATH", "SKIP_RPATH")},
-                    clean_first=True)
-
-        client.run('install -g cmake --build')
-        client.runner("cmake .", cwd=client.current_folder)
-        self.assertNotIn("Conan: Adjusting default RPATHs Conan policies", client.user_io.out)
-        self.assertIn("Build files have been written", client.user_io.out)
-
-        client.save({"conanfile.txt": conanfile,
-                     "CMakeLists.txt": cmake.replace("SKIP_RPATH", "")},
-                    clean_first=True)
-
-        client.run('install -g cmake --build')
-        client.runner("cmake .", cwd=client.current_folder)
-        self.assertIn("Conan: Adjusting default RPATHs Conan policies", client.user_io.out)
-        self.assertIn("Build files have been written", client.user_io.out)
+        for way_to_skip in ("SKIP_RPATH", "KEEP_RPATHS"):
+            client = TestClient()
+            client.save({"conanfile.py": conanfile_py})
+            client.run("export lasote/testing")
+            client.save({"conanfile.txt": conanfile,
+                         "CMakeLists.txt": cmake % way_to_skip}, clean_first=True)
+            client.run('install -g cmake --build')
+            client.runner("cmake .", cwd=client.current_folder)
+            self.assertNotIn("Conan: Adjusting default RPATHs Conan policies", client.out)
+            self.assertIn("Build files have been written", client.out)
+            if way_to_skip == "SKIP_RPATH":
+                self.assertIn("Conan: SKIP_RPATH is deprecated, it has been renamed to KEEP_RPATHS",
+                              client.out)
+
+            client.save({"conanfile.txt": conanfile,
+                         "CMakeLists.txt": (cmake % way_to_skip).replace("TARGETS", "")},
+                        clean_first=True)
+
+            client.run('install -g cmake --build')
+            client.runner("cmake .", cwd=client.current_folder)
+            self.assertNotIn("Conan: Adjusting default RPATHs Conan policies", client.out)
+            self.assertIn("Build files have been written", client.out)
+
+            client.save({"conanfile.txt": conanfile,
+                         "CMakeLists.txt": (cmake % "").replace("FATAL_ERROR", "INFO")},
+                        clean_first=True)
+
+            if platform.system() == "Darwin":
+                client.run('install -g cmake --build')
+                client.runner("cmake .", cwd=client.current_folder)
+                self.assertIn("Conan: Adjusting default RPATHs Conan policies", client.out)
+                self.assertIn("Build files have been written", client.out)
+                self.assertIn("RPath was skipped", client.out)
diff --git a/conans/test/generators/cmake_test.py b/conans/test/generators/cmake_test.py
--- a/conans/test/generators/cmake_test.py
+++ b/conans/test/generators/cmake_test.py
@@ -97,7 +97,7 @@ def aux_cmake_test_setup_test(self):
         # extract the conan_basic_setup macro
         macro = self._extract_macro("conan_basic_setup", aux_cmake_test_setup)
         self.assertEqual("""macro(conan_basic_setup)
-    set(options TARGETS NO_OUTPUT_DIRS SKIP_RPATH)
+    set(options TARGETS NO_OUTPUT_DIRS SKIP_RPATH KEEP_RPATHS)
     cmake_parse_arguments(ARGUMENTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
     if(CONAN_EXPORTED)
         message(STATUS "Conan: called by CMake conan helper")
@@ -114,7 +114,12 @@ def aux_cmake_test_setup_test(self):
         message(STATUS "Conan: Using cmake targets configuration")
         conan_define_targets()
     endif()
-    if(NOT ARGUMENTS_SKIP_RPATH)
+    if(ARGUMENTS_SKIP_RPATH)
+        # Change by "DEPRECATION" or "SEND_ERROR" when we are ready
+        message(WARNING "Conan: SKIP_RPATH is deprecated, it has been renamed to KEEP_RPATHS")
+    endif()
+    if(NOT ARGUMENTS_SKIP_RPATH AND NOT ARGUMENTS_KEEP_RPATHS)
+        # Parameter has renamed, but we keep the compatibility with old SKIP_RPATH
         message(STATUS "Conan: Adjusting default RPATHs Conan policies")
         conan_set_rpath()
     endif()