Repository: conan-io/conan

Issue:
cmake_find_package_generator does not generate guards
To help us debug your issue please explain:

Ubuntu 16.04, conan 1.5.1, cmake 3.11.4:
Using the cmake_find_package generator with a project that calls find_package multiple times on the same library is not safe because the generated find_package script does not guard against being called multiple times. Since the script generates targets, this will cause cmake to fail the build.

- [x] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [x] I've specified the Conan version, operating system version and any tool that can be relevant.
- [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.




Discussion:

Resolving patch:
diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py
--- a/conans/client/generators/cmake_find_package.py
+++ b/conans/client/generators/cmake_find_package.py
@@ -25,13 +25,17 @@
     find_library(CONAN_FOUND_LIBRARY NAME ${{_LIBRARY_NAME}} PATHS ${{{name}_LIB_DIRS}}
                  NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
     if(CONAN_FOUND_LIBRARY)
-        if(${{CMAKE_VERSION}} VERSION_LESS "3.0")
-            list(APPEND {name}_LIBRARIES ${{CONAN_FOUND_LIBRARY}})
-        else() # Create a micro-target for each lib/a found
+        list(APPEND {name}_LIBRARIES ${{CONAN_FOUND_LIBRARY}})
+        if(NOT ${{CMAKE_VERSION}} VERSION_LESS "3.0")
             set(_LIB_NAME CONAN_LIB::{name}_${{_LIBRARY_NAME}})
-            add_library(${{_LIB_NAME}} UNKNOWN IMPORTED)
-            set_target_properties(${{_LIB_NAME}} PROPERTIES IMPORTED_LOCATION ${{CONAN_FOUND_LIBRARY}})
-            list(APPEND {name}_LIBRARIES_TARGETS ${{_LIB_NAME}})
+            if(NOT TARGET ${{_LIB_NAME}})
+                # Create a micro-target for each lib/a found
+                add_library(${{_LIB_NAME}} UNKNOWN IMPORTED)
+                set_target_properties(${{_LIB_NAME}} PROPERTIES IMPORTED_LOCATION ${{CONAN_FOUND_LIBRARY}})
+                list(APPEND {name}_LIBRARIES_TARGETS ${{_LIB_NAME}})
+            else()
+                message(STATUS "Skipping already existing target: ${{_LIB_NAME}}")
+            endif()
         endif()
         message(STATUS "Found: ${{CONAN_FOUND_LIBRARY}}")
     else()


Test patch:
diff --git a/conans/test/generators/cmake_find_package_test.py b/conans/test/generators/cmake_find_package_test.py
--- a/conans/test/generators/cmake_find_package_test.py
+++ b/conans/test/generators/cmake_find_package_test.py
@@ -56,6 +56,35 @@ def build(self):
         self.assertIn("Target libs: fake_lib;shared_link_flag", client.out)
         self.assertIn("Compile options: a_cxx_flag;a_flag", client.out)
 
+    def cmake_lock_target_redefinition_test(self):
+        client = TestClient()
+        files = cpp_hello_conan_files(name="Hello0",
+                                      settings='"os", "compiler", "arch", "build_type"')
+        client.save(files)
+        client.run("create . user/channel -s build_type=Release")
+
+        # Consume the previous Hello0 with auto generated FindHello0.cmake
+        # The module path will point to the "install" folder automatically (CMake helper)
+        files = cpp_hello_conan_files(name="Hello1", deps=["Hello0/0.1@user/channel"],
+                                      settings='"os", "compiler", "arch", "build_type"')
+        files["conanfile.py"] = files["conanfile.py"].replace(
+            'generators = "cmake", "gcc"',
+            'generators = "cmake_find_package"')
+        files["CMakeLists.txt"] = """
+set(CMAKE_CXX_COMPILER_WORKS 1)
+set(CMAKE_CXX_ABI_COMPILED 1)
+project(MyHello CXX)
+cmake_minimum_required(VERSION 2.8)
+# Create a target first to check if it is not redefined
+add_library(CONAN_LIB::Hello0_helloHello0)
+
+find_package(Hello0 REQUIRED)
+
+"""
+        client.save(files, clean_first=True)
+        client.run("create . user/channel -s build_type=Release", ignore_error=True)
+        self.assertIn("Skipping already existing target: CONAN_LIB::Hello0_helloHello0", client.out)
+
     def cmake_find_package_test(self):
         """First package without custom find_package"""
         client = TestClient()
@@ -81,6 +110,9 @@ def cmake_find_package_test(self):
 
 add_library(helloHello1 hello.cpp)
 target_link_libraries(helloHello1 PUBLIC Hello0::Hello0)
+if(Hello0_LIBRARIES)
+    MESSAGE("Hello0_LIBRARIES set")
+endif()
 add_executable(say_hello main.cpp)
 target_link_libraries(say_hello helloHello1)
 
@@ -88,6 +120,8 @@ def cmake_find_package_test(self):
         client.save(files, clean_first=True)
         client.run("create . user/channel -s build_type=Release")
         self.assertIn("Conan: Using autogenerated FindHello0.cmake", client.out)
+        self.assertIn("Hello0_LIBRARIES set", client.out)
+        self.assertNotIn("Skipping already existing target", client.out)
 
         # Now link with old cmake
         files["CMakeLists.txt"] = """