Repository: conan-io/conan

Issue:
[bug] Cmake targets glue C and CXX flags
<!--
  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 (include every applicable attribute)
  * Operating System+version: Ubuntu 20.04 in docker
  * Compiler+version: GCC 9.3 and GCC 9.2 cross for arm
  * Conan version: 1.28.0
  * Python version:  3.8.2

### Steps to reproduce (Include if Applicable)
  1. Make package with CXX specific flags, eg. -fno-exceptions, -fno-rtti
  2. Use cmake generator with target aproach and link that package to your target.
  3. Enable languages: C and C++ and add one .c and one .cpp file
  4. Compile using cmake

### Logs (Executed commands with output) (Include/Attach if Applicable)
`[build] cc1: warning: command line option '-fno-rtti' is valid for C++/D/ObjC++ but not for C`

### Possible solution:
There are lines for every target in conanbuildinfo.cmake:
```
set_property(TARGET CONAN_PKG::PACKAGE_NAME PROPERTY INTERFACE_COMPILE_OPTIONS ${CONAN_C_FLAGS_PACKAGE_NAME_LIST} ${CONAN_CXX_FLAGS_PACKAGE_NAME_LIST}
                                                                  $<$<CONFIG:Release>:${CONAN_C_FLAGS_PACKAGE_NAME_RELEASE_LIST} ${CONAN_CXX_FLAGS_PACKAGE_NAME_RELEASE_LIST}>
                                                                  $<$<CONFIG:RelWithDebInfo>:${CONAN_C_FLAGS_PACKAGE_NAME_RELWITHDEBINFO_LIST} ${CONAN_CXX_FLAGS_PACKAGE_NAME_RELWITHDEBINFO_LIST}>
                                                                  $<$<CONFIG:MinSizeRel>:${CONAN_C_FLAGS_PACKAGE_NAME_MINSIZEREL_LIST} ${CONAN_CXX_FLAGS_PACKAGE_NAME_MINSIZEREL_LIST}>
                                                                  $<$<CONFIG:Debug>:${CONAN_C_FLAGS_PACKAGE_NAME_DEBUG_LIST}  ${CONAN_CXX_FLAGS_PACKAGE_NAME_DEBUG_LIST}>)
```

Those lines should be changed to use additinal generator expression: `<$<COMPILE_LANGUAGE:(CXX|C)>`, eg.

```
set_property(TARGET CONAN_PKG::PACKAGE_NAME PROPERTY INTERFACE_COMPILE_OPTIONS (
    $<$<COMPILE_LANGUAGE:C>:${CONAN_C_FLAGS_PACKAGE_NAME_LIST}> 
    $<$<COMPILE_LANGUAGE:CXX>:${CONAN_CXX_FLAGS_PACKAGE_NAME_LIST}>
    $<$<CONFIG:Release>:
        $<$<COMPILE_LANGUAGE:C>:${CONAN_C_FLAGS_PACKAGE_NAME_RELEASE_LIST}> 
        $<$<COMPILE_LANGUAGE:CXX>:${CONAN_CXX_FLAGS_PACKAGE_NAME_RELEASE_LIST}>>
    $<$<CONFIG:RelWithDebInfo>:
        $<$<COMPILE_LANGUAGE:C>:${CONAN_C_FLAGS_PACKAGE_NAME_RELWITHDEBINFO_LIST}> 
        $<$<COMPILE_LANGUAGE:CXX>:${CONAN_CXX_FLAGS_PACKAGE_NAME_RELWITHDEBINFO_LIST}>>
    $<$<CONFIG:MinSizeRel>:
        $<$<COMPILE_LANGUAGE:C>:${CONAN_C_FLAGS_PACKAGE_NAME_MINSIZEREL_LIST}> 
        $<$<COMPILE_LANGUAGE:CXX>:${CONAN_CXX_FLAGS_PACKAGE_NAME_MINSIZEREL_LIST}>>
    $<$<CONFIG:Debug>:
        $<$<COMPILE_LANGUAGE:C>:${CONAN_C_FLAGS_PACKAGE_NAME_DEBUG_LIST}>  
        $<$<COMPILE_LANGUAGE:CXX>:${CONAN_CXX_FLAGS_PACKAGE_NAME_DEBUG_LIST}>>)
```

I haven't check it yet but I use this expression to set rtti flags in cmake project and it works correctly:
```
   add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>)
   add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>)
```

<!--
  Your log content should be related to the bug description, it can be:
  - Conan command output
  - Server output (Artifactory, conan_server)
-->



Discussion:
Hi @pgorgon-hem 

Thanks for reporting this issue.
Just to understand the severity of the issue, what is the typical effect, just that warning, but the flag is safely ignored by the compilers? Does it fail in some scenarios?

This might need to be changed in other generators as well. As it seems this code section is getting some complexity and would be error prone, I wonder if this could be templatized. 
Hi,
The typical effect is just warning and flag is safety ignored by gcc, but I've tested it only with gcc 9 and -fno-rtti and -fno-exception flags. I don't know how it behaves with other compilers and other flags. But I can imagine that some build parameters for c and c++ objects might be different and can't link when flags set wrongly. Eg. I have external library packaged with conan. This library is also distributed for embedded targets (compiled without RTTI) and when I link that library to my executable it can't find typeinfo for objects from library, so I need to add -fno-rtti to my executable compilation to link it properly. Because I'm always traying to achive no warnings in compilation I added these flags manually in my cmake (for whole project).

This fragment of cmake code is from [conan/conans/client/generators/cmake_common.py:203](https://github.com/conan-io/conan/blob/74548ddf0a3eabf87cdc7f1e9e38a238ed16667a/conans/client/generators/cmake_common.py#L203). This file is included in every cmake generator, but it is used in generate_targets_section method which is used in CMakeGenerator and CMakeMultiGenerator, so I think it have influence on cmake and cmake-multi generators only. 

I thought about making fix of that by myself but I have only little experience in conan so I can't predict all effects of changes.

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
@@ -97,7 +97,8 @@ class CMakeFindPackageGenerator(Generator):
         set({{ pkg_name }}_{{ comp_name }}_RES_DIRS {{ comp.res_paths }})
         set({{ pkg_name }}_{{ comp_name }}_DEFINITIONS {{ comp.defines }})
         set({{ pkg_name }}_{{ comp_name }}_COMPILE_DEFINITIONS {{ comp.compile_definitions }})
-        set({{ pkg_name }}_{{ comp_name }}_COMPILE_OPTIONS_LIST "{{ comp.cxxflags_list }}" "{{ comp.cflags_list }}")
+        set({{ pkg_name }}_{{ comp_name }}_COMPILE_OPTIONS_C "{{ comp.cflags_list }}")
+        set({{ pkg_name }}_{{ comp_name }}_COMPILE_OPTIONS_CXX "{{ comp.cxxflags_list }}")
         set({{ pkg_name }}_{{ comp_name }}_LIBS {{ comp.libs }})
         set({{ pkg_name }}_{{ comp_name }}_SYSTEM_LIBS {{ comp.system_libs }})
         set({{ pkg_name }}_{{ comp_name }}_FRAMEWORK_DIRS {{ comp.framework_paths }})
@@ -182,7 +183,7 @@ class CMakeFindPackageGenerator(Generator):
                 set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_COMPILE_DEFINITIONS
                                       "{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_DEFINITIONS}' }}")
                 set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_COMPILE_OPTIONS
-                                      "{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_LIST}' }}")
+                                      "{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_C}' }};{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_CXX}' }}")
             endif()
         endif()
 
@@ -267,7 +268,7 @@ def _find_for_dep(self, pkg_name, pkg_findname, pkg_filename, cpp_info):
         pkg_public_deps_filenames = [self._get_filename(self.deps_build_info[public_dep])
                                      for public_dep in cpp_info.public_deps]
         pkg_public_deps_names = [self._get_name(self.deps_build_info[public_dep])
-                                     for public_dep in cpp_info.public_deps]
+                                 for public_dep in cpp_info.public_deps]
         deps_names = ";".join(["{n}::{n}".format(n=n) for n in pkg_public_deps_names])
         if cpp_info.components:
             components = self._get_components(pkg_name, pkg_findname, cpp_info)
diff --git a/conans/client/generators/cmake_find_package_common.py b/conans/client/generators/cmake_find_package_common.py
--- a/conans/client/generators/cmake_find_package_common.py
+++ b/conans/client/generators/cmake_find_package_common.py
@@ -15,6 +15,8 @@
 )
 set({name}_COMPILE_DEFINITIONS{build_type_suffix} {deps.compile_definitions})
 set({name}_COMPILE_OPTIONS{build_type_suffix}_LIST "{deps.cxxflags_list}" "{deps.cflags_list}")
+set({name}_COMPILE_OPTIONS_C{build_type_suffix} "{deps.cflags_list}")
+set({name}_COMPILE_OPTIONS_CXX{build_type_suffix} "{deps.cxxflags_list}")
 set({name}_LIBRARIES_TARGETS{build_type_suffix} "") # Will be filled later, if CMake 3
 set({name}_LIBRARIES{build_type_suffix} "") # Will be filled later
 set({name}_LIBS{build_type_suffix} "") # Same as {name}_LIBRARIES
diff --git a/conans/client/generators/cmake_find_package_multi.py b/conans/client/generators/cmake_find_package_multi.py
--- a/conans/client/generators/cmake_find_package_multi.py
+++ b/conans/client/generators/cmake_find_package_multi.py
@@ -119,7 +119,8 @@ class CMakeFindPackageMultiGenerator(CMakeFindPackageGenerator):
         set({{ pkg_name }}_{{ comp_name }}_RES_DIRS_{{ build_type }} {{ comp.res_paths }})
         set({{ pkg_name }}_{{ comp_name }}_DEFINITIONS_{{ build_type }} {{ comp.defines }})
         set({{ pkg_name }}_{{ comp_name }}_COMPILE_DEFINITIONS_{{ build_type }} {{ comp.compile_definitions }})
-        set({{ pkg_name }}_{{ comp_name }}_COMPILE_OPTIONS_LIST_{{ build_type }} "{{ comp.cxxflags_list }}" "{{ comp.cflags_list }}")
+        set({{ pkg_name }}_{{ comp_name }}_COMPILE_OPTIONS_C_{{ build_type }} "{{ comp.cflags_list }}")
+        set({{ pkg_name }}_{{ comp_name }}_COMPILE_OPTIONS_CXX_{{ build_type }} "{{ comp.cxxflags_list }}")
         set({{ pkg_name }}_{{ comp_name }}_LIBS_{{ build_type }} {{ comp.libs }})
         set({{ pkg_name }}_{{ comp_name }}_SYSTEM_LIBS_{{ build_type }} {{ comp.system_libs }})
         set({{ pkg_name }}_{{ comp_name }}_FRAMEWORK_DIRS_{{ build_type }} {{ comp.framework_paths }})
@@ -239,10 +240,18 @@ class CMakeFindPackageMultiGenerator(CMakeFindPackageGenerator):
                          $<$<CONFIG:MinSizeRel>:{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_DEFINITIONS_MINSIZEREL}' }}>
                          $<$<CONFIG:Debug>:{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_DEFINITIONS_DEBUG}' }}>)
         set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_OPTIONS
-                         $<$<CONFIG:Release>:{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_LIST_RELEASE}' }}>
-                         $<$<CONFIG:RelWithDebInfo>:{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_LIST_RELWITHDEBINFO}' }}>
-                         $<$<CONFIG:MinSizeRel>:{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_LIST_MINSIZEREL}' }}>
-                         $<$<CONFIG:Debug>:{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_LIST_DEBUG}' }}>)
+                         $<$<CONFIG:Release>:
+                             {{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_C_RELEASE}' }}
+                             {{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_CXX_RELEASE}' }}>
+                         $<$<CONFIG:RelWithDebInfo>:
+                             {{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_C_RELWITHDEBINFO}' }}
+                             {{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_CXX_RELWITHDEBINFO}' }}>
+                         $<$<CONFIG:MinSizeRel>:
+                             {{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_C_MINSIZEREL}' }}
+                             {{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_CXX_MINSIZEREL}' }}>
+                         $<$<CONFIG:Debug>:
+                             {{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_C_DEBUG}' }}
+                             {{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_CXX_DEBUG}' }}>)
         set({{ pkg_name }}_{{ comp_name }}_TARGET_PROPERTIES TRUE)
 
         {%- endfor %}


Test patch:
diff --git a/conans/test/functional/generators/cmake_test.py b/conans/test/functional/generators/cmake_test.py
--- a/conans/test/functional/generators/cmake_test.py
+++ b/conans/test/functional/generators/cmake_test.py
@@ -380,3 +380,125 @@ def build(self):
 
         client.run('create .')
         self.assertIn("POLICY CMP0054 IS OLD", client.out)
+
+    def do_not_mix_cflags_cxxflags_test(self):
+        client = TestClient()
+
+        def run_test(consumer_generator, consumer_cmakelists, with_components=True):
+
+            def generate_files(upstream_cpp_info, consumer_generator, consumer_cmakelists):
+                upstream_conanfile = GenConanfile().with_name("upstream").with_version("1.0")\
+                    .with_package_info(cpp_info=upstream_cpp_info, env_info={})
+                client.save({"conanfile.py": upstream_conanfile}, clean_first=True)
+                client.run("create .")
+                consumer_conanfile = textwrap.dedent("""
+                    from conans import ConanFile, CMake
+        
+                    class Consumer(ConanFile):
+                        name = "consumer"
+                        version = "1.0"
+                        settings = "os", "compiler", "arch", "build_type"
+                        exports_sources = "CMakeLists.txt"
+                        requires = "upstream/1.0"
+                        generators = "{}"
+                        
+                        def build(self):
+                            cmake = CMake(self)
+                            cmake.configure()
+                    """)
+                client.save({"conanfile.py": consumer_conanfile.format(consumer_generator),
+                             "CMakeLists.txt": consumer_cmakelists})
+                client.run("create .")
+
+            if consumer_generator in ["cmake_find_package", "cmake_find_package_multi"]:
+                if with_components:
+                    cpp_info = {"components": {"comp": {"cflags": ["one", "two"],
+                                                        "cxxflags": ["three", "four"]}}}
+                else:
+                    cpp_info = {"cflags": ["one", "two"], "cxxflags": ["three", "four"]}
+                generate_files(cpp_info, consumer_generator, consumer_cmakelists)
+                self.assertIn("compile options: three;four;one;two", client.out)
+                self.assertIn("cflags: one;two", client.out)
+                self.assertIn("cxxflags: three;four", client.out)
+                if with_components:
+                    self.assertIn("comp cflags: one;two", client.out)
+                    self.assertIn("comp cxxflags: three;four", client.out)
+                    if consumer_generator == "cmake_find_package":
+                        self.assertIn("comp compile options: one;two;three;four", client.out)
+                    else:
+                        self.assertIn("$<$<CONFIG:Release>:;one;two;three;four>;"
+                                      "$<$<CONFIG:RelWithDebInfo>:;>;"
+                                      "$<$<CONFIG:MinSizeRel>:;>;"
+                                      "$<$<CONFIG:Debug>:;>", client.out)
+            else:
+                generate_files({"cflags": ["one", "two"], "cxxflags": ["three", "four"]},
+                               consumer_generator, consumer_cmakelists)
+                self.assertIn("global cflags: one two", client.out)
+                self.assertIn("global cxxflags: three four", client.out)
+                self.assertIn("upstream cflags: one two", client.out)
+                self.assertIn("upstream cxxflags: three four", client.out)
+
+        # Test cmake generator
+        cmakelists = textwrap.dedent("""
+            cmake_minimum_required(VERSION 2.8)
+            set(CMAKE_CXX_COMPILER_WORKS 1)
+            project(consumer)
+            include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
+            message("global cflags: ${CONAN_C_FLAGS}")
+            message("global cxxflags: ${CONAN_CXX_FLAGS}")
+            message("upstream cflags: ${CONAN_C_FLAGS_UPSTREAM}")
+            message("upstream cxxflags: ${CONAN_CXX_FLAGS_UPSTREAM}")
+            """)
+        run_test("cmake", cmakelists)
+
+        # Test cmake_multi generator
+        cmakelists = textwrap.dedent("""
+            cmake_minimum_required(VERSION 2.8)
+            set(CMAKE_CXX_COMPILER_WORKS 1)
+            project(consumer)
+            include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake)
+            message("global cflags: ${CONAN_C_FLAGS_RELEASE}")
+            message("global cxxflags: ${CONAN_CXX_FLAGS_RELEASE}")
+            message("upstream cflags: ${CONAN_C_FLAGS_UPSTREAM_RELEASE}")
+            message("upstream cxxflags: ${CONAN_CXX_FLAGS_UPSTREAM_RELEASE}")
+            """)
+        run_test("cmake_multi", cmakelists)
+
+        # Test cmake_find_package generator
+        cmakelists = textwrap.dedent("""
+            cmake_minimum_required(VERSION 2.8)
+            set(CMAKE_CXX_COMPILER_WORKS 1)
+            project(consumer)
+            find_package(upstream)
+            message("compile options: ${upstream_COMPILE_OPTIONS_LIST}")
+            message("cflags: ${upstream_COMPILE_OPTIONS_C}")
+            message("cxxflags: ${upstream_COMPILE_OPTIONS_CXX}")
+            message("comp cflags: ${upstream_comp_COMPILE_OPTIONS_C}")
+            message("comp cxxflags: ${upstream_comp_COMPILE_OPTIONS_CXX}")
+            get_target_property(tmp upstream::comp INTERFACE_COMPILE_OPTIONS)
+            message("comp compile options: ${tmp}")
+            """)
+        run_test("cmake_find_package", cmakelists)
+        print(client.out)
+
+        # Test cmake_find_package generator without components
+        run_test("cmake_find_package", cmakelists, with_components=False)
+
+        # Test cmake_find_package_multi generator
+        cmakelists = textwrap.dedent("""
+            cmake_minimum_required(VERSION 2.8)
+            set(CMAKE_CXX_COMPILER_WORKS 1)
+            project(consumer)
+            find_package(upstream)
+            message("compile options: ${upstream_COMPILE_OPTIONS_RELEASE_LIST}")
+            message("cflags: ${upstream_COMPILE_OPTIONS_C_RELEASE}")
+            message("cxxflags: ${upstream_COMPILE_OPTIONS_CXX_RELEASE}")
+            message("comp cflags: ${upstream_comp_COMPILE_OPTIONS_C_RELEASE}")
+            message("comp cxxflags: ${upstream_comp_COMPILE_OPTIONS_CXX_RELEASE}")
+            get_target_property(tmp upstream::comp INTERFACE_COMPILE_OPTIONS)
+            message("comp compile options: ${tmp}")
+            """)
+        run_test("cmake_find_package_multi", cmakelists)
+
+        # Test cmake_find_package_multi generator without components
+        run_test("cmake_find_package_multi", cmakelists, with_components=False)