Repository: conan-io/conan

Issue:
[bug] exelinkflags for components are not properly escaped in CMakeDeps generator
<!--
  Please don't forget to update the issue title.
  Include all applicable information to help us reproduce your problem.

  To help us debug your issue please explain:
-->

### Environment Details
  * Operating System+version: Windows 10 x64
  * Compiler+version: arm-none-eabi-gcc 8.3.1
  * Conan version: 1.43.0
  * Python version: 3.9

### Steps to reproduce (Include if Applicable)
1. Create from following recipe:
```
from conans import ConanFile

required_conan_version = '1.43.0'

class Package(ConanFile):
    name = 'my-pkg'
    version = '1.0.0'
    url = 'https://example.org'
    license = 'DOES_NOT_MATTER'
    description = 'MY_PKG'
    settings = 'compiler', 'build_type', 'arch'
    options = {}
    generators = 'CMakeDeps'
    requires = ()

    def package_info(self):
        self.cpp_info.components['component'].exelinkflags = ['-Wl,-undefined=_startup']
        self.cpp_info.components['component'].libs = []
        self.cpp_info.components['component'].includedirs = []
```
2. Create CMake project with Ninja generator consuming `my-pkg` package
3. Add executable linking to `my-pkg::component`:
```
find_package(my-pkg)

add_executable(test src/main.cpp)
target_link_libraries(test PUBLIC my-pkg::component)
```
4. Try to build using `ninja test`
5. GCC/LD reports: `arm-none-eabi-g++.exe: error: "-Wl,-undefined=_startup": Invalid argument`

### Logs
Executed command line (as seen by `ninja -v`):
```
arm-none-eabi-g++.exe  -Wl,--build-id=none -Wl,-gc-sections -g -mcpu=cortex-m3 -mfloat-abi=soft -mthumb \"-Wl,-undefined=_startup\" -o test.elf -Wl,--start-group   CMakeFiles/test.dir/src/main.cpp.obj -Wl,--end-group
```

Escaped quotes around `-Wl,-undefined=_startup` are interpreted by GCC and invalid option is reported. 

If `exelinkflags` is specified for root `cpp_info` (`self.cpp_info.exelinkflags =  ['-Wl,-undefined=_startup']`) generated command line is correct. In `my-pkg-debug-arm_cortex-data.cmake` following lines are generated:
```
set(my-pkg_my-pkg_component_LINKER_FLAGS_DEBUG
        $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:>
        $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:>
        $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:"-Wl,-undefined=_startup">
)
```

Quotes in last line are escaped by CMake and passed to GCC. If `exelinkflags` is specified for root `cpp_info` link flags are passed indirectly by variable and no extra quotes are added:
```
# in my-pkg-debug-arm_cortex-data.cmake
set(my-pkg_EXE_LINK_FLAGS_DEBUG "-Wl,-undefined=_startup")

# In my-pkg-Target-debug.cmake
set(my-pkg_LINKER_FLAGS_DEBUG
    "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:${my-pkg_SHARED_LINK_FLAGS_DEBUG}>"
    "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:${my-pkg_SHARED_LINK_FLAGS_DEBUG}>"
    "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:${my-pkg_EXE_LINK_FLAGS_DEBUG}>")
```

### Suggestion
Main different between component and root link flags is passing by variable for root link flags. I suppose that generating something like this:
```
set(my-pkg_my-pkg_component_LINKER_FLAGS_EXECUTABLE_DEBUG "-Wl,-undefined=_startup")
set(my-pkg_my-pkg_component_LINKER_FLAGS_DEBUG
        $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:>
        $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:>
        $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:${my-pkg_my-pkg_component_LINKER_FLAGS_EXECUTABLE_DEBUG}>
)
```

would solve this issue.



Discussion:

Resolving patch:
diff --git a/conan/tools/cmake/cmakedeps/templates/target_data.py b/conan/tools/cmake/cmakedeps/templates/target_data.py
--- a/conan/tools/cmake/cmakedeps/templates/target_data.py
+++ b/conan/tools/cmake/cmakedeps/templates/target_data.py
@@ -101,10 +101,12 @@ def template(self):
               set({{ pkg_name }}_{{ comp_variable_name }}_FRAMEWORK_DIRS{{ config_suffix }} {{ cpp.framework_paths }})
               set({{ pkg_name }}_{{ comp_variable_name }}_FRAMEWORKS{{ config_suffix }} {{ cpp.frameworks }})
               set({{ pkg_name }}_{{ comp_variable_name }}_DEPENDENCIES{{ config_suffix }} {{ cpp.public_deps }})
+              set({{ pkg_name }}_{{ comp_variable_name }}_SHARED_LINK_FLAGS{{ config_suffix }} {{ cpp.sharedlinkflags_list }})
+              set({{ pkg_name }}_{{ comp_variable_name }}_EXE_LINK_FLAGS{{ config_suffix }} {{ cpp.exelinkflags_list }})
               set({{ pkg_name }}_{{ comp_variable_name }}_LINKER_FLAGS{{ config_suffix }}
-                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:{{ cpp.sharedlinkflags_list }}>
-                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:{{ cpp.sharedlinkflags_list }}>
-                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:{{ cpp.exelinkflags_list }}>
+                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>{{ ':${' }}{{ pkg_name }}_{{ comp_variable_name }}_SHARED_LINK_FLAGS{{ config_suffix }}}>
+                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>{{ ':${' }}{{ pkg_name }}_{{ comp_variable_name }}_SHARED_LINK_FLAGS{{ config_suffix }}}>
+                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>{{ ':${' }}{{ pkg_name }}_{{ comp_variable_name }}_EXE_LINK_FLAGS{{ config_suffix }}}>
               )
               {%- endfor %}
           """)


Test patch:
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components.py
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components.py
@@ -215,3 +215,111 @@ def build(self):
             '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:>>') in t.out
     # NOTE: If there is no "conan install -s build_type=Debug", the properties won't contain the
     #       <CONFIG:Debug>
+
+
+@pytest.mark.tool_cmake
+def test_components_exelinkflags():
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+
+        class Requirement(ConanFile):
+            name = "requirement"
+            version = "system"
+
+            settings = "os", "arch", "compiler", "build_type"
+
+            def package_info(self):
+                self.cpp_info.components["component"].exelinkflags = ["-Wl,-link1", "-Wl,-link2"]
+    """)
+    t = TestClient()
+    t.save({"conanfile.py": conanfile})
+    t.run("create .")
+
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+        from conan.tools.cmake import CMake
+
+        class Consumer(ConanFile):
+            name = "consumer"
+            version = "0.1"
+            requires = "requirement/system"
+            generators = "CMakeDeps", "CMakeToolchain"
+            exports_sources = "CMakeLists.txt"
+            settings = "os", "arch", "compiler", "build_type"
+
+            def build(self):
+                cmake = CMake(self)
+                cmake.configure()
+    """)
+
+    cmakelists = textwrap.dedent("""
+        project(consumer)
+        cmake_minimum_required(VERSION 3.1)
+        find_package(requirement)
+        get_target_property(tmp_options requirement::component INTERFACE_LINK_OPTIONS)
+        message("component options: ${tmp_options}")
+    """)
+
+    t.save({"conanfile.py": conanfile, "CMakeLists.txt": cmakelists})
+    t.run("create . --build missing -s build_type=Release")
+    assert ('component options: '
+            '$<$<CONFIG:Release>:'
+            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:>;'
+            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:>;'
+            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:-Wl,-link1;-Wl,-link2>>') in t.out
+    # NOTE: If there is no "conan install -s build_type=Debug", the properties won't contain the
+    #       <CONFIG:Debug>
+
+
+@pytest.mark.tool_cmake
+def test_components_sharedlinkflags():
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+
+        class Requirement(ConanFile):
+            name = "requirement"
+            version = "system"
+
+            settings = "os", "arch", "compiler", "build_type"
+
+            def package_info(self):
+                self.cpp_info.components["component"].sharedlinkflags = ["-Wl,-link1", "-Wl,-link2"]
+    """)
+    t = TestClient()
+    t.save({"conanfile.py": conanfile})
+    t.run("create .")
+
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+        from conan.tools.cmake import CMake
+
+        class Consumer(ConanFile):
+            name = "consumer"
+            version = "0.1"
+            requires = "requirement/system"
+            generators = "CMakeDeps", "CMakeToolchain"
+            exports_sources = "CMakeLists.txt"
+            settings = "os", "arch", "compiler", "build_type"
+
+            def build(self):
+                cmake = CMake(self)
+                cmake.configure()
+    """)
+
+    cmakelists = textwrap.dedent("""
+        project(consumer)
+        cmake_minimum_required(VERSION 3.1)
+        find_package(requirement)
+        get_target_property(tmp_options requirement::component INTERFACE_LINK_OPTIONS)
+        message("component options: ${tmp_options}")
+    """)
+
+    t.save({"conanfile.py": conanfile, "CMakeLists.txt": cmakelists})
+    t.run("create . --build missing -s build_type=Release")
+    assert ('component options: '
+            '$<$<CONFIG:Release>:'
+            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:-Wl,-link1;-Wl,-link2>;'
+            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:-Wl,-link1;-Wl,-link2>;'
+            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:>>') in t.out
+    # NOTE: If there is no "conan install -s build_type=Debug", the properties won't contain the
+    #       <CONFIG:Debug>