Repository: conan-io/conan
Pull request #11527 (2022-06-25 10:22:18)

Keep only one flavor of the same libs in `collect_libs()`
closes https://github.com/conan-io/conan/issues/11282
closes https://github.com/conan-io/conan/issues/11526

Changelog: (Fix): In `conans.tools.collect_libs` and `conan.tools.files.collect_libs`, avoids to list other flavors (version, soversion) of the same `dylib` on macOS, so that behavior is consistent on Linux & macOS.
Docs: https://github.com/conan-io/docs/pull/2610

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [x] I've followed the PEP8 style guides for Python code.
- [x] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one. 

<sup>**Note:** By default this PR will skip the slower tests and will use a limited set of python versions. Check [here](https://github.com/conan-io/conan/blob/develop/.github/PR_INCREASE_TESTING.md) how to increase the testing level by writing some tags in the current PR body text.</sup>



Patch:
diff --git a/conan/tools/apple/xcodedeps.py b/conan/tools/apple/xcodedeps.py
index 24c3fc16a..a15c533d1 100644
--- a/conan/tools/apple/xcodedeps.py
+++ b/conan/tools/apple/xcodedeps.py
@@ -1,5 +1,6 @@
 import os
 import textwrap
+from collections import OrderedDict
 
 from jinja2 import Template
 
@@ -60,14 +61,14 @@ class XcodeDeps(object):
     general_name = "conandeps.xcconfig"
 
     _conf_xconfig = textwrap.dedent("""\
-        // Compiler options for {{pkg_name}}::{{pkg_name}}
+        // Compiler options for {{pkg_name}}::{{comp_name}}
         HEADER_SEARCH_PATHS_{{pkg_name}}_{{comp_name}}{{condition}} = {{include_dirs}}
         GCC_PREPROCESSOR_DEFINITIONS_{{pkg_name}}_{{comp_name}}{{condition}} = {{definitions}}
         OTHER_CFLAGS_{{pkg_name}}_{{comp_name}}{{condition}} = {{c_compiler_flags}}
         OTHER_CPLUSPLUSFLAGS_{{pkg_name}}_{{comp_name}}{{condition}} = {{cxx_compiler_flags}}
         FRAMEWORK_SEARCH_PATHS_{{pkg_name}}_{{comp_name}}{{condition}} = {{frameworkdirs}}
 
-        // Link options for {{name}}
+        // Link options for {{pkg_name}}::{{comp_name}}
         LIBRARY_SEARCH_PATHS_{{pkg_name}}_{{comp_name}}{{condition}} = {{lib_dirs}}
         OTHER_LDFLAGS_{{pkg_name}}_{{comp_name}}{{condition}} = {{linker_flags}} {{libs}} {{system_libs}} {{frameworks}}
         """)
@@ -121,25 +122,28 @@ class XcodeDeps(object):
         for generator_file, content in generator_files.items():
             save(generator_file, content)
 
-    def _conf_xconfig_file(self, pkg_name, comp_name, cpp_info):
+    def _conf_xconfig_file(self, pkg_name, comp_name, transitive_cpp_infos):
         """
         content for conan_poco_x86_release.xcconfig, containing the activation
         """
+        def _merged_vars(name):
+            merged = [var for cpp_info in transitive_cpp_infos for var in getattr(cpp_info, name)]
+            return list(OrderedDict.fromkeys(merged).keys())
 
         fields = {
             'pkg_name': pkg_name,
             'comp_name': comp_name,
-            'include_dirs': " ".join('"{}"'.format(p) for p in cpp_info.includedirs),
-            'lib_dirs': " ".join('"{}"'.format(p) for p in cpp_info.libdirs),
-            'libs': " ".join("-l{}".format(lib) for lib in cpp_info.libs),
-            'system_libs': " ".join("-l{}".format(sys_lib) for sys_lib in cpp_info.system_libs),
-            'frameworksdirs': " ".join('"{}"'.format(p) for p in cpp_info.frameworkdirs),
-            'frameworks': " ".join("-framework {}".format(framework) for framework in cpp_info.frameworks),
-            'definitions': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in cpp_info.defines),
-            'c_compiler_flags': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in cpp_info.cflags),
-            'cxx_compiler_flags': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in cpp_info.cxxflags),
-            'linker_flags': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in cpp_info.sharedlinkflags),
-            'exe_flags': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in cpp_info.exelinkflags),
+            'include_dirs': " ".join('"{}"'.format(p) for p in _merged_vars("includedirs")),
+            'lib_dirs': " ".join('"{}"'.format(p) for p in _merged_vars("libdirs")),
+            'libs': " ".join("-l{}".format(lib) for lib in _merged_vars("libs")),
+            'system_libs': " ".join("-l{}".format(sys_lib) for sys_lib in _merged_vars("system_libs")),
+            'frameworkdirs': " ".join('"{}"'.format(p) for p in _merged_vars("frameworkdirs")),
+            'frameworks': " ".join("-framework {}".format(framework) for framework in _merged_vars("frameworks")),
+            'definitions': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in _merged_vars("defines")),
+            'c_compiler_flags': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in _merged_vars("cflags")),
+            'cxx_compiler_flags': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in _merged_vars("cxxflags")),
+            'linker_flags': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in _merged_vars("sharedlinkflags")),
+            'exe_flags': " ".join('"{}"'.format(p.replace('"', '\\"')) for p in _merged_vars("exelinkflags")),
             'condition': _xcconfig_conditional(self._conanfile.settings)
         }
 
@@ -193,17 +197,17 @@ class XcodeDeps(object):
                                                GLOBAL_XCCONFIG_TEMPLATE,
                                                [self.general_name])
 
-    def get_content_for_component(self, pkg_name, component_name, cpp_info, reqs):
+    def get_content_for_component(self, pkg_name, component_name, transitive_internal, transitive_external):
         result = {}
 
         conf_name = _xcconfig_settings_filename(self._conanfile.settings)
 
         props_name = "conan_{}_{}{}.xcconfig".format(pkg_name, component_name, conf_name)
-        result[props_name] = self._conf_xconfig_file(pkg_name, component_name, cpp_info)
+        result[props_name] = self._conf_xconfig_file(pkg_name, component_name, transitive_internal)
 
         # The entry point for each package
         file_dep_name = "conan_{}_{}.xcconfig".format(pkg_name, component_name)
-        dep_content = self._dep_xconfig_file(pkg_name, component_name, file_dep_name, props_name, reqs)
+        dep_content = self._dep_xconfig_file(pkg_name, component_name, file_dep_name, props_name, transitive_external)
 
         result[file_dep_name] = dep_content
         return result
@@ -213,28 +217,60 @@ class XcodeDeps(object):
 
         # Generate the config files for each component with name conan_pkgname_compname.xcconfig
         # If a package has no components the name is conan_pkgname_pkgname.xcconfig
-        # Then all components are included in the conan_pkgname.xcconfig file
+        # All components are included in the conan_pkgname.xcconfig file
         host_req = self._conanfile.dependencies.host
         test_req = self._conanfile.dependencies.test
-        for dep in list(host_req.values()) + list(test_req.values()):
+        all_deps = list(host_req.values()) + list(test_req.values())
+        for dep in all_deps:
+
             dep_name = _format_name(dep.ref.name)
 
             include_components_names = []
             if dep.cpp_info.has_components:
-                for comp_name, comp_cpp_info in dep.cpp_info.get_sorted_components().items():
-                    component_deps = []
-                    for req in comp_cpp_info.requires:
-                        req_pkg, req_cmp = req.split("::") if "::" in req else (dep_name, req)
-                        component_deps.append((req_pkg, req_cmp))
 
-                    component_content = self.get_content_for_component(dep_name, comp_name, comp_cpp_info, component_deps)
+                sorted_components = dep.cpp_info.get_sorted_components().items()
+                for comp_name, comp_cpp_info in sorted_components:
+
+                    # returns: ("list of cpp infos from required components in same package",
+                    #           "list of names from required components from other packages")
+                    def _get_component_requires(component):
+                        requires_external = [(req.split("::")[0], req.split("::")[1]) for req in
+                                             component.requires if "::" in req]
+                        requires_internal = [dep.cpp_info.components.get(req) for req in
+                                             component.requires if "::" not in req]
+                        return requires_internal, requires_external
+
+                    # these are the transitive dependencies between components of the same package
+                    transitive_internal = []
+                    # these are the transitive dependencies to components from other packages
+                    transitive_external = []
+
+                    # return the internal cpp_infos and external components names
+                    def _transitive_components(component):
+                        requires_internal, requires_external = _get_component_requires(component)
+                        transitive_internal.append(component)
+                        transitive_internal.extend(requires_internal)
+                        transitive_external.extend(requires_external)
+                        for require in requires_internal:
+                            _transitive_components(require)
+
+                    _transitive_components(comp_cpp_info)
+
+                    # remove duplicates
+                    transitive_internal = list(OrderedDict.fromkeys(transitive_internal).keys())
+                    transitive_external = list(OrderedDict.fromkeys(transitive_external).keys())
+
+                    component_content = self.get_content_for_component(dep_name, comp_name,
+                                                                       transitive_internal,
+                                                                       transitive_external)
                     include_components_names.append((dep_name, comp_name))
                     result.update(component_content)
             else:
                 public_deps = [(_format_name(d.ref.name),) * 2 for r, d in
                                dep.dependencies.direct_host.items() if r.visible]
                 required_components = dep.cpp_info.required_components if dep.cpp_info.required_components else public_deps
-                root_content = self.get_content_for_component(dep_name, dep_name, dep.cpp_info, required_components)
+                root_content = self.get_content_for_component(dep_name, dep_name, [dep.cpp_info],
+                                                              required_components)
                 include_components_names.append((dep_name, dep_name))
                 result.update(root_content)
 
diff --git a/conan/tools/build/cpu.py b/conan/tools/build/cpu.py
index d9a6ecefa..2de22771b 100644
--- a/conan/tools/build/cpu.py
+++ b/conan/tools/build/cpu.py
@@ -1,5 +1,6 @@
 import math
 import multiprocessing
+import os
 
 from conans.util.files import load
 
@@ -15,8 +16,18 @@ def _cpu_count():
     try:
         try:
             # This is necessary to deduce docker cpu_count
-            cfs_quota_us = int(load("/sys/fs/cgroup/cpu/cpu.cfs_quota_us"))
-            cfs_period_us = int(load("/sys/fs/cgroup/cpu/cpu.cfs_period_us"))
+            cfs_quota_us = cfs_period_us = 0
+            # cgroup2
+            if os.path.exists("/sys/fs/cgroup/cgroup.controllers"):
+                cpu_max = load("/sys/fs/cgroup/cpu.max").split()
+                if cpu_max[0] != "max":
+                    if len(cpu_max) == 1:
+                        cfs_quota_us, cfs_period_us = int(cpu_max[0]), 100_000
+                    else:
+                        cfs_quota_us, cfs_period_us = map(int, cpu_max)
+            else:  # cgroup1
+                cfs_quota_us = int(load("/sys/fs/cgroup/cpu/cpu.cfs_quota_us"))
+                cfs_period_us = int(load("/sys/fs/cgroup/cpu/cpu.cfs_period_us"))
             if cfs_quota_us > 0 and cfs_period_us > 0:
                 return int(math.ceil(cfs_quota_us / cfs_period_us))
         except (EnvironmentError, TypeError):
diff --git a/conan/tools/cmake/cmake.py b/conan/tools/cmake/cmake.py
index b3d6535a5..d30e4274f 100644
--- a/conan/tools/cmake/cmake.py
+++ b/conan/tools/cmake/cmake.py
@@ -1,11 +1,9 @@
 import os
-import platform
 
 from conan.tools.build import build_jobs
 from conan.tools.cmake.presets import load_cmake_presets, get_configure_preset
 from conan.tools.cmake.utils import is_multi_configuration
 from conan.tools.files import chdir, mkdir
-from conan.tools.files.files import load_toolchain_args
 from conan.tools.microsoft.msbuild import msbuild_verbosity_cmd_line_arg
 from conans.client.tools.oss import args_to_string
 from conans.errors import ConanException
@@ -153,7 +151,8 @@ class CMake(object):
             return
         if not target:
             is_multi = is_multi_configuration(self._generator)
-            target = "RUN_TESTS" if is_multi else "test"
+            is_ninja = "Ninja" in self._generator
+            target = "RUN_TESTS" if is_multi and not is_ninja else "test"
 
         self._build(build_type=build_type, target=target, cli_args=cli_args,
                     build_tool_args=build_tool_args)
diff --git a/conan/tools/cmake/cmakedeps/templates/config.py b/conan/tools/cmake/cmakedeps/templates/config.py
index bb7cdd3b8..5892a4160 100644
--- a/conan/tools/cmake/cmakedeps/templates/config.py
+++ b/conan/tools/cmake/cmakedeps/templates/config.py
@@ -66,7 +66,7 @@ class ConfigTemplate(CMakeDepsFileTemplate):
 
         # Only the first installed configuration is included to avoid the collision
         foreach(_BUILD_MODULE {{ '${' + pkg_name + '_BUILD_MODULES_PATHS' + config_suffix + '}' }} )
-            conan_message(STATUS "Conan: Including build module from '${_BUILD_MODULE}'")
+            message(STATUS "Conan: Including build module from '${_BUILD_MODULE}'")
             include({{ '${_BUILD_MODULE}' }})
         endforeach()
 
@@ -76,9 +76,9 @@ class ConfigTemplate(CMakeDepsFileTemplate):
         if({{ file_name }}_FIND_COMPONENTS)
             foreach(_FIND_COMPONENT {{ '${'+file_name+'_FIND_COMPONENTS}' }})
                 if (TARGET ${_FIND_COMPONENT})
-                    conan_message(STATUS "Conan: Component '${_FIND_COMPONENT}' found in package '{{ pkg_name }}'")
+                    message(STATUS "Conan: Component '${_FIND_COMPONENT}' found in package '{{ pkg_name }}'")
                 else()
-                    conan_message(FATAL_ERROR "Conan: Component '${_FIND_COMPONENT}' NOT found in package '{{ pkg_name }}'")
+                    message(FATAL_ERROR "Conan: Component '${_FIND_COMPONENT}' NOT found in package '{{ pkg_name }}'")
                 endif()
             endforeach()
         endif()
diff --git a/conan/tools/cmake/cmakedeps/templates/macros.py b/conan/tools/cmake/cmakedeps/templates/macros.py
index 8888535a0..9d3965c0e 100644
--- a/conan/tools/cmake/cmakedeps/templates/macros.py
+++ b/conan/tools/cmake/cmakedeps/templates/macros.py
@@ -26,12 +26,6 @@ class MacrosTemplate(CMakeDepsFileTemplate):
     @property
     def template(self):
         return textwrap.dedent("""
-        function(conan_message MESSAGE_TYPE MESSAGE_CONTENT)
-            if(NOT CONAN_CMAKE_SILENT_OUTPUT)
-                message(${MESSAGE_TYPE} "${MESSAGE_CONTENT}")
-            endif()
-        endfunction()
-
        macro(conan_find_apple_frameworks FRAMEWORKS_FOUND FRAMEWORKS FRAMEWORKS_DIRS)
            if(APPLE)
                foreach(_FRAMEWORK ${FRAMEWORKS})
@@ -39,9 +33,9 @@ class MacrosTemplate(CMakeDepsFileTemplate):
                    find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAMES ${_FRAMEWORK} PATHS ${FRAMEWORKS_DIRS} CMAKE_FIND_ROOT_PATH_BOTH)
                    if(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND)
                        list(APPEND ${FRAMEWORKS_FOUND} ${CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND})
-                       conan_message(DEBUG "Framework found! ${FRAMEWORKS_FOUND}")
+                       message(VERBOSE "Framework found! ${FRAMEWORKS_FOUND}")
                    else()
-                       conan_message(FATAL_ERROR "Framework library ${_FRAMEWORK} not found in paths: ${FRAMEWORKS_DIRS}")
+                       message(FATAL_ERROR "Framework library ${_FRAMEWORK} not found in paths: ${FRAMEWORKS_DIRS}")
                    endif()
                endforeach()
            endif()
@@ -56,7 +50,7 @@ class MacrosTemplate(CMakeDepsFileTemplate):
                find_library(CONAN_FOUND_LIBRARY NAMES ${_LIBRARY_NAME} PATHS ${package_libdir}
                             NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
                if(CONAN_FOUND_LIBRARY)
-                   conan_message(DEBUG "Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}")
+                   message(VERBOSE "Conan: Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}")
                    list(APPEND _out_libraries ${CONAN_FOUND_LIBRARY})
 
                    # Create a micro-target for each lib/a found
@@ -69,12 +63,12 @@ class MacrosTemplate(CMakeDepsFileTemplate):
                        set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION ${CONAN_FOUND_LIBRARY})
                        list(APPEND _CONAN_ACTUAL_TARGETS ${_LIB_NAME})
                    else()
-                       conan_message(STATUS "Skipping already existing target: ${_LIB_NAME}")
+                       message(VERBOSE "Conan: Skipping already existing target: ${_LIB_NAME}")
                    endif()
                    list(APPEND _out_libraries_target ${_LIB_NAME})
-                   conan_message(DEBUG "Found: ${CONAN_FOUND_LIBRARY}")
+                   message(VERBOSE "Conan: Found: ${CONAN_FOUND_LIBRARY}")
                else()
-                   conan_message(FATAL_ERROR "Library '${_LIBRARY_NAME}' not found in package. If '${_LIBRARY_NAME}' is a system library, declare it with 'cpp_info.system_libs' property")
+                   message(FATAL_ERROR "Library '${_LIBRARY_NAME}' not found in package. If '${_LIBRARY_NAME}' is a system library, declare it with 'cpp_info.system_libs' property")
                endif()
                unset(CONAN_FOUND_LIBRARY CACHE)
            endforeach()
diff --git a/conan/tools/cmake/cmakedeps/templates/target_configuration.py b/conan/tools/cmake/cmakedeps/templates/target_configuration.py
index 277b5814b..f969bdd25 100644
--- a/conan/tools/cmake/cmakedeps/templates/target_configuration.py
+++ b/conan/tools/cmake/cmakedeps/templates/target_configuration.py
@@ -112,7 +112,7 @@ class TargetConfigurationTemplate(CMakeDepsFileTemplate):
         {%- endfor %}
 
 
-
+        {% if not components_names %}
         ########## GLOBAL TARGET PROPERTIES {{ configuration }} ########################################
         set_property(TARGET {{root_target_name}}
                      PROPERTY INTERFACE_LINK_LIBRARIES
@@ -139,6 +139,9 @@ class TargetConfigurationTemplate(CMakeDepsFileTemplate):
                      PROPERTY INTERFACE_LINK_DIRECTORIES
                      $<$<CONFIG:{{configuration}}>:${{'{'}}{{pkg_name}}_LIB_DIRS{{config_suffix}}}> APPEND)
         {%- endif %}
+
+        {%- else %}
+
         ########## COMPONENTS TARGET PROPERTIES {{ configuration }} ########################################
 
         {%- for comp_variable_name, comp_target_name in components_names %}
@@ -168,6 +171,15 @@ class TargetConfigurationTemplate(CMakeDepsFileTemplate):
         {%- endfor %}
 
 
+        ########## AGGREGATED GLOBAL TARGET WITH THE COMPONENTS #####################
+        {%- for comp_variable_name, comp_target_name in components_names %}
+
+        target_link_libraries({{root_target_name}} INTERFACE {{ comp_target_name }})
+
+        {%- endfor %}
+
+        {%- endif %}
+
         """)
 
     def get_declared_components_targets_names(self):
diff --git a/conan/tools/cmake/cmakedeps/templates/target_data.py b/conan/tools/cmake/cmakedeps/templates/target_data.py
index 34c459c12..f3c2671b4 100644
--- a/conan/tools/cmake/cmakedeps/templates/target_data.py
+++ b/conan/tools/cmake/cmakedeps/templates/target_data.py
@@ -49,6 +49,7 @@ class ConfigDataTemplate(CMakeDepsFileTemplate):
         package_folder = package_folder.replace('\\', '/').replace('$', '\\$').replace('"', '\\"')
 
         return {"global_cpp": global_cpp,
+                "has_components": self.conanfile.cpp_info.has_components,
                 "pkg_name": self.pkg_name,
                 "file_name": self.file_name,
                 "package_folder": package_folder,
@@ -84,6 +85,10 @@ class ConfigDataTemplate(CMakeDepsFileTemplate):
               ########### VARIABLES #######################################################################
               #############################################################################################
               set({{ pkg_name }}_PACKAGE_FOLDER{{ config_suffix }} "{{ package_folder }}")
+              set({{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ global_cpp.build_modules_paths }})
+
+              {% if not has_components %}
+
               set({{ pkg_name }}_INCLUDE_DIRS{{ config_suffix }} {{ global_cpp.include_paths }})
               set({{ pkg_name }}_RES_DIRS{{ config_suffix }} {{ global_cpp.res_paths }})
               set({{ pkg_name }}_DEFINITIONS{{ config_suffix }} {{ global_cpp.defines }})
@@ -98,13 +103,11 @@ class ConfigDataTemplate(CMakeDepsFileTemplate):
               set({{ pkg_name }}_SYSTEM_LIBS{{ config_suffix }} {{ global_cpp.system_libs }})
               set({{ pkg_name }}_FRAMEWORK_DIRS{{ config_suffix }} {{ global_cpp.framework_paths }})
               set({{ pkg_name }}_FRAMEWORKS{{ config_suffix }} {{ global_cpp.frameworks }})
-              set({{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ global_cpp.build_modules_paths }})
               set({{ pkg_name }}_BUILD_DIRS{{ config_suffix }} {{ global_cpp.build_paths }})
+              {% else %}
 
               set({{ pkg_name }}_COMPONENTS{{ config_suffix }} {{ components_names }})
-
               {%- for comp_variable_name, comp_target_name, cpp in components_cpp %}
-
               ########### COMPONENT {{ comp_target_name }} VARIABLES #############################################
               set({{ pkg_name }}_{{ comp_variable_name }}_INCLUDE_DIRS{{ config_suffix }} {{ cpp.include_paths }})
               set({{ pkg_name }}_{{ comp_variable_name }}_LIB_DIRS{{ config_suffix }} {{ cpp.lib_paths }})
@@ -126,15 +129,16 @@ class ConfigDataTemplate(CMakeDepsFileTemplate):
                       $<$<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 }}}>
               )
-              list(APPEND {{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ cpp.build_modules_paths }})
               {%- endfor %}
+
+              {%- endif %}
           """)
         return ret
 
     def _get_global_cpp_cmake(self):
-        global_cppinfo = self.conanfile.cpp_info.aggregated_components()
         pfolder_var_name = "{}_PACKAGE_FOLDER{}".format(self.pkg_name, self.config_suffix)
-        return _TargetDataContext(global_cppinfo, pfolder_var_name, self.conanfile.package_folder)
+        return _TargetDataContext(self.conanfile.cpp_info, pfolder_var_name,
+                                  self.conanfile.package_folder)
 
     def _get_required_components_cpp(self):
         """Returns a list of (component_name, DepsCppCMake)"""
diff --git a/conan/tools/cmake/cmakedeps/templates/targets.py b/conan/tools/cmake/cmakedeps/templates/targets.py
index 8096b9712..c3cea116d 100644
--- a/conan/tools/cmake/cmakedeps/templates/targets.py
+++ b/conan/tools/cmake/cmakedeps/templates/targets.py
@@ -66,13 +66,13 @@ class TargetsTemplate(CMakeDepsFileTemplate):
         foreach(_COMPONENT {{ '${' + pkg_name + '_COMPONENT_NAMES' + '}' }} )
             if(NOT TARGET ${_COMPONENT})
                 add_library(${_COMPONENT} INTERFACE IMPORTED)
-                conan_message(STATUS "Conan: Component target declared '${_COMPONENT}'")
+                message(STATUS "Conan: Component target declared '${_COMPONENT}'")
             endif()
         endforeach()
 
         if(NOT TARGET {{ root_target_name }})
             add_library({{ root_target_name }} INTERFACE IMPORTED)
-            conan_message(STATUS "Conan: Target declared '{{ root_target_name }}'")
+            message(STATUS "Conan: Target declared '{{ root_target_name }}'")
         endif()
 
         {%- for alias, target in cmake_target_aliases.items() %}
diff --git a/conan/tools/cmake/layout.py b/conan/tools/cmake/layout.py
index 18f78c5e3..6a464f5c3 100644
--- a/conan/tools/cmake/layout.py
+++ b/conan/tools/cmake/layout.py
@@ -14,13 +14,14 @@ def cmake_layout(conanfile, generator=None, src_folder="."):
         else:
             multi = False
 
-    conanfile.folders.source = src_folder
+    subproject = conanfile.folders.subproject
+    conanfile.folders.source = src_folder if not subproject else os.path.join(subproject, src_folder)
     try:
         build_type = str(conanfile.settings.build_type)
     except ConanException:
         raise ConanException("'build_type' setting not defined, it is necessary for cmake_layout()")
 
-    build_folder = "build"
+    build_folder = "build" if not subproject else os.path.join(subproject, "build")
     custom_conf = get_build_folder_custom_vars(conanfile)
     if custom_conf:
         build_folder = "{}/{}".format(build_folder, custom_conf)
diff --git a/conan/tools/cmake/presets.py b/conan/tools/cmake/presets.py
index 918f6a831..03449a059 100644
--- a/conan/tools/cmake/presets.py
+++ b/conan/tools/cmake/presets.py
@@ -4,11 +4,12 @@ import platform
 
 from conan.tools.cmake.layout import get_build_folder_custom_vars
 from conan.tools.cmake.utils import is_multi_configuration
+from conan.tools.microsoft import is_msvc
 from conans.errors import ConanException
 from conans.util.files import save, load
 
 
-def _add_build_preset(conanfile, multiconfig):
+def _build_preset(conanfile, multiconfig):
     build_type = conanfile.settings.get_safe("build_type")
     configure_preset_name = _configure_preset_name(conanfile, multiconfig)
     ret = {"name": _build_preset_name(conanfile),
@@ -42,7 +43,7 @@ def _configure_preset_name(conanfile, multiconfig):
         return str(build_type).lower()
 
 
-def _add_configure_preset(conanfile, generator, cache_variables, toolchain_file, multiconfig):
+def _configure_preset(conanfile, generator, cache_variables, toolchain_file, multiconfig):
     build_type = conanfile.settings.get_safe("build_type")
     name = _configure_preset_name(conanfile, multiconfig)
     if not multiconfig and build_type:
@@ -53,8 +54,31 @@ def _add_configure_preset(conanfile, generator, cache_variables, toolchain_file,
             "description": "'{}' configure using '{}' generator".format(name, generator),
             "generator": generator,
             "cacheVariables": cache_variables,
-            "toolchainFile": toolchain_file,
            }
+    if "Ninja" in generator and is_msvc(conanfile):
+        toolset_arch = conanfile.conf.get("tools.cmake.cmaketoolchain:toolset_arch")
+        if toolset_arch:
+            toolset_arch = "host={}".format(toolset_arch)
+            ret["toolset"] = {
+                "value": toolset_arch,
+                "strategy": "external"
+            }
+        arch = {"x86": "x86",
+                "x86_64": "x64",
+                "armv7": "ARM",
+                "armv8": "ARM64"}.get(conanfile.settings.get_safe("arch"))
+
+        if arch:
+            ret["architecture"] = {
+                "value": arch,
+                "strategy": "external"
+            }
+
+    if not _forced_schema_2(conanfile):
+        ret["toolchainFile"] = toolchain_file
+    else:
+        ret["cacheVariables"]["CMAKE_TOOLCHAIN_FILE"] = toolchain_file
+
     if conanfile.build_folder:
         # If we are installing a ref: "conan install <ref>", we don't have build_folder, because
         # we don't even have a conanfile with a `layout()` to determine the build folder.
@@ -63,16 +87,42 @@ def _add_configure_preset(conanfile, generator, cache_variables, toolchain_file,
     return ret
 
 
+def _forced_schema_2(conanfile):
+    version = conanfile.conf.get("tools.cmake.cmaketoolchain.presets:max_schema_version",
+                                 check_type=int)
+    if not version:
+        return False
+
+    if version < 2:
+        raise ConanException("The minimum value for 'tools.cmake.cmaketoolchain.presets:"
+                             "schema_version' is 2")
+    if version < 4:
+        return True
+
+    return False
+
+
+def _schema_version(conanfile, default):
+    if _forced_schema_2(conanfile):
+        return 2
+
+    return default
+
+
 def _contents(conanfile, toolchain_file, cache_variables, generator):
-    ret = {"version": 3,
+    """
+    Contents for the CMakePresets.json
+    It uses schema version 3 unless it is forced to 2
+    """
+    ret = {"version": _schema_version(conanfile, default=3),
            "cmakeMinimumRequired": {"major": 3, "minor": 15, "patch": 0},
            "configurePresets": [],
            "buildPresets": [],
            "testPresets": []
           }
     multiconfig = is_multi_configuration(generator)
-    ret["buildPresets"].append(_add_build_preset(conanfile, multiconfig))
-    _conf = _add_configure_preset(conanfile, generator, cache_variables, toolchain_file, multiconfig)
+    ret["buildPresets"].append(_build_preset(conanfile, multiconfig))
+    _conf = _configure_preset(conanfile, generator, cache_variables, toolchain_file, multiconfig)
     ret["configurePresets"].append(_conf)
     return ret
 
@@ -95,47 +145,92 @@ def write_cmake_presets(conanfile, toolchain_file, generator, cache_variables):
     multiconfig = is_multi_configuration(generator)
 
     if os.path.exists(preset_path):
-        # We append the new configuration making sure that we don't overwrite it
         data = json.loads(load(preset_path))
-        if multiconfig:
-            new_build_preset_name = _build_preset_name(conanfile)
-            already_exist = any([b["name"] for b in data["buildPresets"]
-                                 if b["name"] == new_build_preset_name])
-            if not already_exist:
-                data["buildPresets"].append(_add_build_preset(conanfile, multiconfig))
+        build_preset = _build_preset(conanfile, multiconfig)
+        position = _get_already_existing_preset_index(build_preset["name"], data["buildPresets"])
+        if position is not None:
+            data["buildPresets"][position] = build_preset
         else:
-            new_configure_preset_name = _configure_preset_name(conanfile, multiconfig)
-            already_exist = any([c["name"] for c in data["configurePresets"]
-                                 if c["name"] == new_configure_preset_name])
-            if not already_exist:
-                conf_preset = _add_configure_preset(conanfile, generator, cache_variables,
-                                                    toolchain_file, multiconfig)
-                data["configurePresets"].append(conf_preset)
-                data["buildPresets"].append(_add_build_preset(conanfile, multiconfig))
+            data["buildPresets"].append(build_preset)
+
+        configure_preset = _configure_preset(conanfile, generator, cache_variables, toolchain_file,
+                                             multiconfig)
+        position = _get_already_existing_preset_index(configure_preset["name"],
+                                                      data["configurePresets"])
+        if position is not None:
+            data["configurePresets"][position] = configure_preset
+        else:
+            data["configurePresets"].append(configure_preset)
     else:
         data = _contents(conanfile, toolchain_file, cache_variables, generator)
 
     data = json.dumps(data, indent=4)
     save(preset_path, data)
+    save_cmake_user_presets(conanfile, preset_path)
+
 
+def save_cmake_user_presets(conanfile, preset_path):
     # Try to save the CMakeUserPresets.json if layout declared and CMakeLists.txt found
     if conanfile.source_folder and conanfile.source_folder != conanfile.generators_folder:
         if os.path.exists(os.path.join(conanfile.source_folder, "CMakeLists.txt")):
+            """
+                Contents for the CMakeUserPresets.json
+                It uses schema version 4 unless it is forced to 2
+            """
             user_presets_path = os.path.join(conanfile.source_folder, "CMakeUserPresets.json")
             if not os.path.exists(user_presets_path):
-                data = {"version": 4, "include": [preset_path], "vendor": {"conan": dict()}}
+                data = {"version": _schema_version(conanfile, default=4),
+                        "vendor": {"conan": dict()}}
             else:
                 data = json.loads(load(user_presets_path))
-                if "conan" in data.get("vendor", {}):
-                    # Clear the folders that have been deleted
-                    data["include"] = [i for i in data.get("include", []) if os.path.exists(i)]
-                    if preset_path not in data["include"]:
-                        data["include"].append(preset_path)
-
+                if "conan" not in data.get("vendor", {}):
+                    # The file is not ours, we cannot overwrite it
+                    return
+            data = _append_user_preset_path(conanfile, data, preset_path)
             data = json.dumps(data, indent=4)
             save(user_presets_path, data)
 
 
+def _get_already_existing_preset_index(name, presets):
+    """Get the index of a Preset with a given name, this is used to replace it with updated contents
+    """
+    positions = [index for index, p in enumerate(presets)
+                 if p["name"] == name]
+    if positions:
+        return positions[0]
+    return None
+
+
+def _append_user_preset_path(conanfile, data, preset_path):
+    """ - Appends a 'include' to preset_path if the schema supports it.
+        - Otherwise it merges to "data" all the configurePresets, buildPresets etc from the
+          read preset_path.
+    """
+    if not _forced_schema_2(conanfile):
+        if "include" not in data:
+            data["include"] = []
+        # Clear the folders that have been deleted
+        data["include"] = [i for i in data.get("include", []) if os.path.exists(i)]
+        if preset_path not in data["include"]:
+            data["include"].append(preset_path)
+        return data
+    else:
+        # Merge the presets
+        cmake_preset = json.loads(load(preset_path))
+        for preset_type in ("configurePresets", "buildPresets", "testPresets"):
+            for preset in cmake_preset.get(preset_type, []):
+                if preset_type not in data:
+                    data[preset_type] = []
+
+                position = _get_already_existing_preset_index(preset["name"], data[preset_type])
+                if position is not None:
+                    # If the preset already existed, replace the element with the new one
+                    data[preset_type][position] = preset
+                else:
+                    data[preset_type].append(preset)
+        return data
+
+
 def load_cmake_presets(folder):
     tmp = load(os.path.join(folder, "CMakePresets.json"))
     return json.loads(tmp)
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index fca65c2fc..5db4af04e 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -286,7 +286,9 @@ class AndroidSystemBlock(Block):
     template = textwrap.dedent("""
         # New toolchain things
         set(ANDROID_PLATFORM {{ android_platform }})
+        {% if android_stl %}
         set(ANDROID_STL {{ android_stl }})
+        {% endif %}
         set(ANDROID_ABI {{ android_abi }})
         include({{ android_ndk_path }}/build/cmake/android.toolchain.cmake)
         """)
@@ -303,7 +305,7 @@ class AndroidSystemBlock(Block):
 
         # TODO: only 'c++_shared' y 'c++_static' supported?
         #  https://developer.android.com/ndk/guides/cpp-support
-        libcxx_str = str(self._conanfile.settings.compiler.libcxx)
+        libcxx_str = self._conanfile.settings.get_safe("compiler.libcxx")
 
         android_ndk_path = self._conanfile.conf.get("tools.android:ndk_path")
         if not android_ndk_path:
@@ -852,13 +854,21 @@ class OutputDirsBlock(Block):
 
         return textwrap.dedent("""
            set(CMAKE_INSTALL_PREFIX "{{package_folder}}")
+           {% if default_bin %}
            set(CMAKE_INSTALL_BINDIR "{{default_bin}}")
            set(CMAKE_INSTALL_SBINDIR "{{default_bin}}")
            set(CMAKE_INSTALL_LIBEXECDIR "{{default_bin}}")
+           {% endif %}
+           {% if default_lib %}
            set(CMAKE_INSTALL_LIBDIR "{{default_lib}}")
+           {% endif %}
+           {% if default_include %}
            set(CMAKE_INSTALL_INCLUDEDIR "{{default_include}}")
            set(CMAKE_INSTALL_OLDINCLUDEDIR "{{default_include}}")
+           {% endif %}
+           {% if default_res %}
            set(CMAKE_INSTALL_DATAROOTDIR "{{default_res}}")
+           {% endif %}
         """)
 
     def _get_cpp_info_value(self, name):
diff --git a/conan/tools/cmake/toolchain/toolchain.py b/conan/tools/cmake/toolchain/toolchain.py
index 9b74a5b76..4227efae4 100644
--- a/conan/tools/cmake/toolchain/toolchain.py
+++ b/conan/tools/cmake/toolchain/toolchain.py
@@ -176,7 +176,8 @@ class CMakeToolchain(object):
         # Generators like Ninja or NMake requires an active vcvars
         elif self.generator is not None and "Visual" not in self.generator:
             VCVars(self._conanfile).generate()
-        toolchain = os.path.join(self._conanfile.generators_folder, toolchain_file or self.filename)
+        toolchain = os.path.abspath(os.path.join(self._conanfile.generators_folder,
+                                                 toolchain_file or self.filename))
         cache_variables = {}
         for name, value in self.cache_variables.items():
             if isinstance(value, bool):
diff --git a/conan/tools/files/files.py b/conan/tools/files/files.py
index 7eca6af89..899bb9325 100644
--- a/conan/tools/files/files.py
+++ b/conan/tools/files/files.py
@@ -11,6 +11,8 @@ from contextlib import contextmanager
 from fnmatch import fnmatch
 
 import six
+from urllib.parse import urlparse
+from urllib.request import url2pathname
 
 from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE, CONAN_TOOLCHAIN_ARGS_SECTION
 from conan.tools.apple.apple import is_apple_os
@@ -165,10 +167,13 @@ def download(conanfile, url, filename, verify=True, retry=None, retry_wait=None,
 
     def _download_file(file_url):
         # The download cache is only used if a checksum is provided, otherwise, a normal download
-        run_downloader(requester=requester, output=out, verify=verify, download_cache=download_cache,
-                       user_download=True, url=file_url,
-                       file_path=filename, retry=retry, retry_wait=retry_wait, overwrite=overwrite,
-                       auth=auth, headers=headers, md5=md5, sha1=sha1, sha256=sha256)
+        if file_url.startswith("file:"):
+            _copy_local_file_from_uri(conanfile, url=file_url, file_path=filename, md5=md5, sha1=sha1, sha256=sha256)
+        else:
+            run_downloader(requester=requester, output=out, verify=verify, download_cache=download_cache,
+                        user_download=True, url=file_url,
+                        file_path=filename, retry=retry, retry_wait=retry_wait, overwrite=overwrite,
+                        auth=auth, headers=headers, md5=md5, sha1=sha1, sha256=sha256)
         out.writeln("")
 
     if not isinstance(url, (list, tuple)):
@@ -184,6 +189,21 @@ def download(conanfile, url, filename, verify=True, retry=None, retry_wait=None,
         else:
             raise ConanException("All downloads from ({}) URLs have failed.".format(len(url)))
 
+def _copy_local_file_from_uri(conanfile, url, file_path, md5=None, sha1=None, sha256=None):
+    file_origin = _path_from_file_uri(url)
+    shutil.copyfile(file_origin, file_path)
+
+    if md5:
+        check_md5(conanfile, file_path, md5)
+    if sha1:
+        check_sha1(conanfile, file_path, sha1)
+    if sha256:
+        check_sha256(conanfile, file_path, sha256)
+
+def _path_from_file_uri(uri):
+    path = urlparse(uri).path
+    return url2pathname(path)
+
 
 def rename(conanfile, src, dst):
     """
@@ -494,24 +514,29 @@ def collect_libs(conanfile, folder=None):
     else:
         lib_folders = [os.path.join(conanfile.package_folder, folder)
                        for folder in conanfile.cpp_info.libdirs]
-    result = []
+
+    ref_libs = {}
     for lib_folder in lib_folders:
         if not os.path.exists(lib_folder):
             conanfile.output.warn("Lib folder doesn't exist, can't collect libraries: "
                                   "{0}".format(lib_folder))
             continue
+        # In case of symlinks, only keep shortest file name in the same "group"
         files = os.listdir(lib_folder)
         for f in files:
             name, ext = os.path.splitext(f)
             if ext in (".so", ".lib", ".a", ".dylib", ".bc"):
-                if ext != ".lib" and name.startswith("lib"):
-                    name = name[3:]
-                if name in result:
-                    conanfile.output.warn("Library '%s' was either already found in a previous "
-                                          "'conanfile.cpp_info.libdirs' folder or appears several "
-                                          "times with a different file extension" % name)
-                else:
-                    result.append(name)
+                real_lib = os.path.basename(os.path.realpath(os.path.join(lib_folder, f)))
+                if real_lib not in ref_libs or len(f) < len(ref_libs[real_lib]):
+                    ref_libs[real_lib] = f
+
+    result = []
+    for f in ref_libs.values():
+        name, ext = os.path.splitext(f)
+        if ext != ".lib" and name.startswith("lib"):
+            name = name[3:]
+        if name not in result:
+            result.append(name)
     result.sort()
     return result
 
diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py
index 52ee17a39..d10f36d3b 100644
--- a/conan/tools/gnu/autotoolstoolchain.py
+++ b/conan/tools/gnu/autotoolstoolchain.py
@@ -22,10 +22,10 @@ class AutotoolsToolchain:
         self.make_args = []
 
         # Flags
-        self.cxxflags = []
-        self.cflags = []
-        self.ldflags = []
-        self.defines = []
+        self.extra_cxxflags = []
+        self.extra_cflags = []
+        self.extra_ldflags = []
+        self.extra_defines = []
 
         # Defines
         self.gcc_cxx11_abi = self._get_cxx11_abi_define()
@@ -122,46 +122,52 @@ class AutotoolsToolchain:
     def _filter_list_empty_fields(v):
         return list(filter(bool, v))
 
-    def _get_extra_flags(self):
-        # Now, it's time to get all the flags defined by the user
-        cxxflags = self._conanfile.conf.get("tools.build:cxxflags", default=[], check_type=list)
-        cflags = self._conanfile.conf.get("tools.build:cflags", default=[], check_type=list)
-        sharedlinkflags = self._conanfile.conf.get("tools.build:sharedlinkflags", default=[], check_type=list)
-        exelinkflags = self._conanfile.conf.get("tools.build:exelinkflags", default=[], check_type=list)
-        defines = self._conanfile.conf.get("tools.build:defines", default=[], check_type=list)
-        return {
-            "cxxflags": cxxflags,
-            "cflags": cflags,
-            "defines": defines,
-            "ldflags": sharedlinkflags + exelinkflags
-        }
-
-    def environment(self):
-        env = Environment()
-
+    @property
+    def cxxflags(self):
+        fpic = "-fPIC" if self.fpic else None
+        ret = [self.libcxx, self.cppstd, self.arch_flag, fpic, self.msvc_runtime_flag,
+               self.sysroot_flag]
         apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]
+        conf_flags = self._conanfile.conf.get("tools.build:cxxflags", default=[], check_type=list)
+        ret = ret + self.build_type_flags + apple_flags + conf_flags + self.extra_cxxflags
+        return self._filter_list_empty_fields(ret)
+
+    @property
+    def cflags(self):
         fpic = "-fPIC" if self.fpic else None
-        extra_flags = self._get_extra_flags()
+        ret = [self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag]
+        apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]
+        conf_flags = self._conanfile.conf.get("tools.build:cflags", default=[], check_type=list)
+        ret = ret + self.build_type_flags + apple_flags + conf_flags + self.extra_cflags
+        return self._filter_list_empty_fields(ret)
 
-        self.cxxflags.extend([self.libcxx, self.cppstd,
-                              self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag]
-                             + self.build_type_flags + apple_flags + extra_flags["cxxflags"])
-        self.cflags.extend([self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag]
-                           + self.build_type_flags + apple_flags + extra_flags["cflags"])
-        self.ldflags.extend([self.arch_flag, self.sysroot_flag] + self.build_type_link_flags
-                            + apple_flags + extra_flags["ldflags"])
-        self.defines.extend([self.ndebug, self.gcc_cxx11_abi] + extra_flags["defines"])
+    @property
+    def ldflags(self):
+        ret = [self.arch_flag, self.sysroot_flag]
+        apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]
+        conf_flags = self._conanfile.conf.get("tools.build:sharedlinkflags", default=[],
+                                              check_type=list)
+        conf_flags.extend(self._conanfile.conf.get("tools.build:exelinkflags", default=[],
+                                                   check_type=list))
+        ret = ret + apple_flags + conf_flags + self.build_type_link_flags + self.extra_ldflags
+        return self._filter_list_empty_fields(ret)
+
+    @property
+    def defines(self):
+        conf_flags = self._conanfile.conf.get("tools.build:defines", default=[], check_type=list)
+        ret = [self.ndebug, self.gcc_cxx11_abi] + conf_flags + self.extra_defines
+        return self._filter_list_empty_fields(ret)
 
+    def environment(self):
+        env = Environment()
         if is_msvc(self._conanfile):
             env.define("CXX", "cl")
             env.define("CC", "cl")
-
-        env.append("CPPFLAGS", ["-D{}".format(d) for d in self._filter_list_empty_fields(self.defines)])
-        env.append("CXXFLAGS", self._filter_list_empty_fields(self.cxxflags))
-        env.append("CFLAGS", self._filter_list_empty_fields(self.cflags))
-        env.append("LDFLAGS", self._filter_list_empty_fields(self.ldflags))
+        env.append("CPPFLAGS", ["-D{}".format(d) for d in self.defines])
+        env.append("CXXFLAGS", self.cxxflags)
+        env.append("CFLAGS", self.cflags)
+        env.append("LDFLAGS", self.ldflags)
         env.prepend_path("PKG_CONFIG_PATH", self._conanfile.generators_folder)
-
         return env
 
     def vars(self):
diff --git a/conan/tools/gnu/gnudeps_flags.py b/conan/tools/gnu/gnudeps_flags.py
index 734254329..2546c7831 100644
--- a/conan/tools/gnu/gnudeps_flags.py
+++ b/conan/tools/gnu/gnudeps_flags.py
@@ -48,7 +48,6 @@ class GnuDepsFlags(object):
         os_ = self._conanfile.settings.get_safe("os")
         if not frameworks or not is_apple_os(os_):
             return []
-        # FIXME: Missing support for subsystems
         compiler = self._conanfile.settings.get_safe("compiler")
         if str(compiler) not in self._GCC_LIKE:
             return []
@@ -60,15 +59,14 @@ class GnuDepsFlags(object):
     def _format_include_paths(self, include_paths):
         if not include_paths:
             return []
-        # FIXME: Missing support for subsystems
-        return ["-I%s" % (self._adjust_path(include_path))
+        pattern = "/I%s" if is_msvc(self._conanfile) else "-I%s"
+        return [pattern % (self._adjust_path(include_path))
                 for include_path in include_paths if include_path]
 
     def _format_library_paths(self, library_paths):
         if not library_paths:
             return []
-        # FIXME: Missing support for subsystems
-        pattern = "-LIBPATH:%s" if is_msvc(self._conanfile) else "-L%s"
+        pattern = "/LIBPATH:%s" if is_msvc(self._conanfile) else "-L%s"
         return [pattern % self._adjust_path(library_path)
                 for library_path in library_paths if library_path]
 
diff --git a/conan/tools/google/bazeldeps.py b/conan/tools/google/bazeldeps.py
index 8a7b1af20..c6966c043 100644
--- a/conan/tools/google/bazeldeps.py
+++ b/conan/tools/google/bazeldeps.py
@@ -62,7 +62,7 @@ class BazelDeps(object):
             {% for libname, filepath in libs.items() %}
             cc_import(
                 name = "{{ libname }}_precompiled",
-                {{ library_type }} = "{{ filepath }}"
+                {{ library_type }} = "{{ filepath }}",
             )
             {% endfor %}
 
@@ -91,6 +91,7 @@ class BazelDeps(object):
                 visibility = ["//visibility:public"],
                 {% if libs or shared_with_interface_libs %}
                 deps = [
+                    # do not sort
                 {% for lib in libs %}
                 ":{{ lib }}_precompiled",
                 {% endfor %}
diff --git a/conan/tools/layout/__init__.py b/conan/tools/layout/__init__.py
index 9cd971712..8f64e14e7 100644
--- a/conan/tools/layout/__init__.py
+++ b/conan/tools/layout/__init__.py
@@ -6,10 +6,12 @@ from conan.tools.google import bazel_layout
 
 
 def basic_layout(conanfile, src_folder="."):
-    conanfile.folders.build = "build"
+    subproject = conanfile.folders.subproject
+
+    conanfile.folders.source = src_folder if not subproject else os.path.join(subproject, src_folder)
+    conanfile.folders.build = "build" if not subproject else os.path.join(subproject, "build")
     if conanfile.settings.get_safe("build_type"):
         conanfile.folders.build += "-{}".format(str(conanfile.settings.build_type).lower())
     conanfile.folders.generators = os.path.join(conanfile.folders.build, "conan")
     conanfile.cpp.build.bindirs = ["."]
     conanfile.cpp.build.libdirs = ["."]
-    conanfile.folders.source = src_folder
diff --git a/conan/tools/meson/__init__.py b/conan/tools/meson/__init__.py
index 9f317238a..b1fe7d9b9 100644
--- a/conan/tools/meson/__init__.py
+++ b/conan/tools/meson/__init__.py
@@ -1,3 +1,4 @@
-from conan.tools.meson.toolchain import MesonToolchain
 from conan.tools.meson.meson import Meson
+from conan.tools.meson.mesondeps import MesonDeps
+from conan.tools.meson.toolchain import MesonToolchain
 
diff --git a/conan/tools/meson/meson.py b/conan/tools/meson/meson.py
index 1285bab47..82ed7e745 100644
--- a/conan/tools/meson/meson.py
+++ b/conan/tools/meson/meson.py
@@ -1,7 +1,8 @@
 import os
 
 from conan.tools.build import build_jobs
-from conan.tools.meson import MesonToolchain
+from conan.tools.meson.toolchain import MesonToolchain
+from conan.tools.meson.mesondeps import MesonDeps
 
 
 class Meson(object):
@@ -15,10 +16,18 @@ class Meson(object):
         generators_folder = self._conanfile.generators_folder
         cross = os.path.join(generators_folder, MesonToolchain.cross_filename)
         native = os.path.join(generators_folder, MesonToolchain.native_filename)
+        deps_flags = os.path.join(generators_folder, MesonDeps.filename)  # extra machine files layer
+        has_deps_flags = os.path.exists(deps_flags)
+
         if os.path.exists(cross):
             cmd += ' --cross-file "{}"'.format(cross)
+            if has_deps_flags:
+                cmd += ' --cross-file "{}"'.format(deps_flags)
         else:
             cmd += ' --native-file "{}"'.format(native)
+            if has_deps_flags:
+                cmd += ' --native-file "{}"'.format(deps_flags)
+
         cmd += ' "{}" "{}"'.format(build_folder, source_folder)
         if self._conanfile.package_folder:
             cmd += ' -Dprefix="{}"'.format(self._conanfile.package_folder)
@@ -45,6 +54,8 @@ class Meson(object):
         self._conanfile.run(cmd)
 
     def test(self):
+        if self._conanfile.conf.get("tools.build:skip_test"):
+            return
         meson_build_folder = self._conanfile.build_folder
         cmd = 'meson test -v -C "{}"'.format(meson_build_folder)
         # TODO: Do we need vcvars for test?
diff --git a/conan/tools/meson/mesondeps.py b/conan/tools/meson/mesondeps.py
new file mode 100644
index 000000000..84ec1e582
--- /dev/null
+++ b/conan/tools/meson/mesondeps.py
@@ -0,0 +1,105 @@
+import textwrap
+
+from jinja2 import Template
+
+from conan.tools.gnu.gnudeps_flags import GnuDepsFlags
+from conan.tools.meson.helpers import to_meson_value
+from conans.model.new_build_info import NewCppInfo
+from conans.util.files import save
+
+
+class MesonDeps(object):
+    """Generator that manages all the GNU flags from all the dependencies"""
+
+    filename = "conan_meson_deps_flags.ini"
+
+    _meson_file_template = textwrap.dedent("""
+    [constants]
+    deps_c_args = {{c_args}}
+    deps_c_link_args = {{c_link_args}}
+    deps_cpp_args = {{cpp_args}}
+    deps_cpp_link_args = {{cpp_link_args}}
+    """)
+
+    def __init__(self, conanfile):
+        self._conanfile = conanfile
+        self._ordered_deps = []
+        # constants
+        self.c_args = []
+        self.c_link_args = []
+        self.cpp_args = []
+        self.cpp_link_args = []
+
+    # TODO: Add all this logic to GnuDepsFlags? Distinguish between GnuFlags and GnuDepsFlags?
+    @property
+    def ordered_deps(self):
+        if not self._ordered_deps:
+            deps = self._conanfile.dependencies.host.topological_sort
+            self._ordered_deps = [dep for dep in reversed(deps.values())]
+        return self._ordered_deps
+
+    def _get_cpp_info(self):
+        ret = NewCppInfo()
+        for dep in self.ordered_deps:
+            dep_cppinfo = dep.cpp_info.aggregated_components()
+            # In case we have components, aggregate them, we do not support isolated
+            # "targets" with autotools
+            ret.merge(dep_cppinfo)
+        return ret
+
+    def _rpaths_flags(self):
+        flags = []
+        for dep in self.ordered_deps:
+            flags.extend(["-Wl,-rpath -Wl,{}".format(libdir) for libdir in dep.cpp_info.libdirs
+                          if dep.options.get_safe("shared", False)])
+        return flags
+
+    def get_gnu_flags(self):
+        flags = GnuDepsFlags(self._conanfile, self._get_cpp_info())
+
+        # cpp_flags
+        cpp_flags = []
+        cpp_flags.extend(flags.include_paths)
+        cpp_flags.extend(flags.defines)
+
+        # Ldflags
+        ldflags = flags.sharedlinkflags
+        ldflags.extend(flags.exelinkflags)
+        ldflags.extend(flags.frameworks)
+        ldflags.extend(flags.framework_paths)
+        ldflags.extend(flags.lib_paths)
+
+        # set the rpath in Macos so that the library are found in the configure step
+        if self._conanfile.settings.get_safe("os") == "Macos":
+            ldflags.extend(self._rpaths_flags())
+
+        # libs
+        libs = flags.libs
+        libs.extend(flags.system_libs)
+
+        # cflags
+        cflags = flags.cflags
+        cxxflags = flags.cxxflags
+        return cflags, cxxflags, cpp_flags, ldflags, libs
+
+    def _context(self):
+        cflags, cxxflags, cpp_flags, ldflags, _ = self.get_gnu_flags()
+        self.c_args.extend(cflags + cpp_flags)
+        self.cpp_args.extend(cxxflags + cpp_flags)
+        self.c_link_args.extend(ldflags)
+        self.cpp_link_args.extend(ldflags)
+
+        return {
+            "c_args": to_meson_value(self.c_args),
+            "c_link_args": to_meson_value(self.c_link_args),
+            "cpp_args": to_meson_value(self.cpp_args),
+            "cpp_link_args": to_meson_value(self.cpp_link_args),
+        }
+
+    def _content(self):
+        context = self._context()
+        content = Template(self._meson_file_template).render(context)
+        return content
+
+    def generate(self):
+        save(self.filename, self._content())
diff --git a/conan/tools/meson/toolchain.py b/conan/tools/meson/toolchain.py
index cbedd32c2..d0e264227 100644
--- a/conan/tools/meson/toolchain.py
+++ b/conan/tools/meson/toolchain.py
@@ -26,6 +26,11 @@ class MesonToolchain(object):
     [constants]
     preprocessor_definitions = [{% for it, value in preprocessor_definitions.items() -%}
     '-D{{ it }}="{{ value}}"'{%- if not loop.last %}, {% endif %}{% endfor %}]
+    # Constants to be overridden by conan_meson_deps_flags.ini (if exists)
+    deps_c_args = []
+    deps_c_link_args = []
+    deps_cpp_args = []
+    deps_cpp_link_args = []
 
     [project options]
     {% for it, value in project_options.items() -%}
@@ -35,6 +40,10 @@ class MesonToolchain(object):
     [binaries]
     {% if c %}c = '{{c}}'{% endif %}
     {% if cpp %}cpp = '{{cpp}}'{% endif %}
+    {% if is_apple_system %}
+    {% if objc %}objc = '{{objc}}'{% endif %}
+    {% if objcpp %}objcpp = '{{objcpp}}'{% endif %}
+    {% endif %}
     {% if c_ld %}c_ld = '{{c_ld}}'{% endif %}
     {% if cpp_ld %}cpp_ld = '{{cpp_ld}}'{% endif %}
     {% if ar %}ar = '{{ar}}'{% endif %}
@@ -52,11 +61,19 @@ class MesonToolchain(object):
     {% if b_staticpic %}b_staticpic = {{b_staticpic}}{% endif %}
     {% if cpp_std %}cpp_std = '{{cpp_std}}' {% endif %}
     {% if backend %}backend = '{{backend}}' {% endif %}
-    c_args = {{c_args}} + preprocessor_definitions
-    c_link_args = {{c_link_args}}
-    cpp_args = {{cpp_args}} + preprocessor_definitions
-    cpp_link_args = {{cpp_link_args}}
     {% if pkg_config_path %}pkg_config_path = '{{pkg_config_path}}'{% endif %}
+    # C/C++ arguments
+    c_args = {{c_args}} + preprocessor_definitions + deps_c_args
+    c_link_args = {{c_link_args}} + deps_c_link_args
+    cpp_args = {{cpp_args}} + preprocessor_definitions + deps_cpp_args
+    cpp_link_args = {{cpp_link_args}} + deps_cpp_link_args
+    {% if is_apple_system %}
+    # Objective-C/C++ arguments
+    objc_args = {{objc_args}} + preprocessor_definitions + deps_c_args
+    objc_link_args = {{objc_link_args}} + deps_c_link_args
+    objcpp_args = {{objcpp_args}} + preprocessor_definitions + deps_cpp_args
+    objcpp_link_args = {{objcpp_link_args}} + deps_cpp_link_args
+    {% endif %}
 
     {% for context, values in cross_build.items() %}
     [{{context}}_machine]
@@ -70,6 +87,7 @@ class MesonToolchain(object):
     def __init__(self, conanfile, backend=None):
         self._conanfile = conanfile
         self._os = self._conanfile.settings.get_safe("os")
+        self._is_apple_system = is_apple_os(self._os)
 
         # Values are kept as Python built-ins so users can modify them more easily, and they are
         # only converted to Meson file syntax for rendering
@@ -108,6 +126,9 @@ class MesonToolchain(object):
         self.project_options = {
             "wrap_mode": "nofallback"  # https://github.com/conan-io/conan/issues/10671
         }
+        # Add all the default dirs
+        self.project_options.update(self._get_default_dirs())
+
         self.preprocessor_definitions = {}
         self.pkg_config_path = self._conanfile.generators_folder
 
@@ -156,16 +177,61 @@ class MesonToolchain(object):
         self.cpp_args = self._get_env_list(build_env.get("CXXFLAGS", []))
         self.cpp_link_args = self._get_env_list(build_env.get("LDFLAGS", []))
 
-        # Apple flags
+        # Apple flags and variables
         self.apple_arch_flag = []
         self.apple_isysroot_flag = []
         self.apple_min_version_flag = []
-
-        self._resolve_apple_flags()
+        self.objc = None
+        self.objcpp = None
+        self.objc_args = []
+        self.objc_link_args = []
+        self.objcpp_args = []
+        self.objcpp_link_args = []
+
+        self._resolve_apple_flags_and_variables(build_env)
         self._resolve_android_cross_compilation()
 
-    def _resolve_apple_flags(self):
-        if not is_apple_os(self._os):
+    def _get_default_dirs(self):
+        """
+        Get all the default directories from cpp.package.
+
+        Issues related:
+            - https://github.com/conan-io/conan/issues/9713
+            - https://github.com/conan-io/conan/issues/11596
+        """
+        def _get_cpp_info_value(name):
+            elements = getattr(self._conanfile.cpp.package, name)
+            return elements[0] if elements else None
+
+        if not self._conanfile.package_folder:
+            return {}
+
+        ret = {}
+        bindir = _get_cpp_info_value("bindirs")
+        datadir = _get_cpp_info_value("resdirs")
+        libdir = _get_cpp_info_value("libdirs")
+        includedir = _get_cpp_info_value("includedirs")
+        if bindir:
+            ret.update({
+                'bindir': bindir,
+                'sbindir': bindir,
+                'libexecdir': bindir
+            })
+        if datadir:
+            ret.update({
+                'datadir': datadir,
+                'localedir': datadir,
+                'mandir': datadir,
+                'infodir': datadir
+            })
+        if includedir:
+            ret["includedir"] = includedir
+        if libdir:
+            ret["libdir"] = libdir
+        return ret
+
+    def _resolve_apple_flags_and_variables(self, build_env):
+        if not self._is_apple_system:
             return
         # SDK path is mandatory for cross-building
         sdk_path = self._conanfile.conf.get("tools.apple:sdk_path")
@@ -182,6 +248,13 @@ class MesonToolchain(object):
         self.apple_arch_flag = ["-arch", arch] if arch else []
         self.apple_isysroot_flag = ["-isysroot", sdk_path] if sdk_path else []
         self.apple_min_version_flag = [apple_min_version_flag(self._conanfile)]
+        # Objective C/C++ ones
+        self.objc = "clang"
+        self.objcpp = "clang++"
+        self.objc_args = self._get_env_list(build_env.get('OBJCFLAGS', []))
+        self.objc_link_args = self._get_env_list(build_env.get('LDFLAGS', []))
+        self.objcpp_args = self._get_env_list(build_env.get('OBJCXXFLAGS', []))
+        self.objcpp_link_args = self._get_env_list(build_env.get('LDFLAGS', []))
 
     def _resolve_android_cross_compilation(self):
         if not self.cross_build or not self.cross_build["host"]["system"] == "android":
@@ -233,6 +306,12 @@ class MesonToolchain(object):
         self.cpp_args.extend(apple_flags + extra_flags["cxxflags"])
         self.c_link_args.extend(apple_flags + extra_flags["ldflags"])
         self.cpp_link_args.extend(apple_flags + extra_flags["ldflags"])
+        # Objective C/C++
+        self.objc_args.extend(self.c_args)
+        self.objcpp_args.extend(self.cpp_args)
+        # These link_args have already the LDFLAGS env value so let's add only the new possible ones
+        self.objc_link_args.extend(apple_flags + extra_flags["ldflags"])
+        self.objcpp_link_args.extend(apple_flags + extra_flags["ldflags"])
 
         return {
             # https://mesonbuild.com/Machine-files.html#properties
@@ -245,6 +324,8 @@ class MesonToolchain(object):
             # https://mesonbuild.com/Reference-tables.html#compiler-and-linker-selection-variables
             "c": self.c,
             "cpp": self.cpp,
+            "objc": self.objc,
+            "objcpp": self.objcpp,
             "c_ld": self.c_ld,
             "cpp_ld": self.cpp_ld,
             "ar": self.ar,
@@ -266,9 +347,14 @@ class MesonToolchain(object):
             "c_link_args": to_meson_value(self._filter_list_empty_fields(self.c_link_args)),
             "cpp_args": to_meson_value(self._filter_list_empty_fields(self.cpp_args)),
             "cpp_link_args": to_meson_value(self._filter_list_empty_fields(self.cpp_link_args)),
+            "objc_args": to_meson_value(self._filter_list_empty_fields(self.objc_args)),
+            "objc_link_args": to_meson_value(self._filter_list_empty_fields(self.objc_link_args)),
+            "objcpp_args": to_meson_value(self._filter_list_empty_fields(self.objcpp_args)),
+            "objcpp_link_args": to_meson_value(self._filter_list_empty_fields(self.objcpp_link_args)),
             "pkg_config_path": self.pkg_config_path,
             "preprocessor_definitions": self.preprocessor_definitions,
-            "cross_build": self.cross_build
+            "cross_build": self.cross_build,
+            "is_apple_system": self._is_apple_system
         }
 
     @property
diff --git a/conan/tools/microsoft/layout.py b/conan/tools/microsoft/layout.py
index 9d3a045e0..4da792179 100644
--- a/conan/tools/microsoft/layout.py
+++ b/conan/tools/microsoft/layout.py
@@ -15,13 +15,14 @@ def vs_layout(conanfile):
         if not arch:
             raise ConanException("The 'vs_layout' doesn't "
                                  "work with the arch '{}'".format(conanfile.settings.arch))
-        base = os.path.join(arch, str(conanfile.settings.build_type))
+        bindirs = os.path.join(arch, str(conanfile.settings.build_type))
     else:
-        base = str(conanfile.settings.build_type)
+        bindirs = str(conanfile.settings.build_type)
 
-    conanfile.folders.build = "."
-    conanfile.folders.generators = "conan"
-    conanfile.folders.source = "."
-    conanfile.cpp.build.libdirs = [base]
-    conanfile.cpp.build.bindirs = [base]
+    subproject = conanfile.folders.subproject
+    conanfile.folders.build = subproject or "."
+    conanfile.folders.generators = os.path.join(subproject, "conan") if subproject else "conan"
+    conanfile.folders.source = subproject or "."
+    conanfile.cpp.build.libdirs = [bindirs]
+    conanfile.cpp.build.bindirs = [bindirs]
     conanfile.cpp.source.includedirs = ["include"]
diff --git a/conan/tools/microsoft/msbuilddeps.py b/conan/tools/microsoft/msbuilddeps.py
index 151b7bc50..8b1165823 100644
--- a/conan/tools/microsoft/msbuilddeps.py
+++ b/conan/tools/microsoft/msbuilddeps.py
@@ -6,6 +6,7 @@ from xml.dom import minidom
 from jinja2 import Template
 
 from conan.tools._check_build_profile import check_using_build_profile
+from conans.client.graph.graph import CONTEXT_BUILD
 from conans.errors import ConanException
 from conans.util.files import load, save
 
@@ -13,6 +14,10 @@ VALID_LIB_EXTENSIONS = (".so", ".lib", ".a", ".dylib", ".bc")
 
 
 class MSBuildDeps(object):
+    """
+    conandeps.props: unconditional import of all *direct* dependencies only
+
+    """
 
     _vars_props = textwrap.dedent("""\
         <?xml version="1.0" encoding="utf-8"?>
@@ -48,7 +53,8 @@ class MSBuildDeps(object):
           </ImportGroup>
           {% if host_context %}
           <PropertyGroup>
-            <LocalDebuggerEnvironment>PATH=%PATH%;$(Conan{{name}}BinaryDirectories)$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
+            <ConanDebugPath>$(Conan{{name}}BinaryDirectories);$(ConanDebugPath)</ConanDebugPath>
+            <LocalDebuggerEnvironment>PATH=$(ConanDebugPath);%PATH%</LocalDebuggerEnvironment>
             <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
             {% if ca_exclude %}
             <CAExcludePath>$(Conan{{name}}IncludeDirectories);$(CAExcludePath)</CAExcludePath>
@@ -117,65 +123,21 @@ class MSBuildDeps(object):
         condition = " And ".join("'$(%s)' == '%s'" % (k, v) for k, v in props)
         return condition
 
-    def _conf_props_file(self, dep_name, vars_props_name, deps, build):
-        """
-        content for conan_poco_x86_release.props, containing the activation
-        """
-        # TODO: This must include somehow the user/channel, most likely pattern to exclude/include
-        # Probably also the negation pattern, exclude all not @mycompany/*
-        ca_exclude = any(fnmatch.fnmatch(dep_name, p) for p in self.exclude_code_analysis or ())
-
-        deps = [] if build else deps  # build-requires do not propagate dependencies
-        template = Template(self._conf_props, trim_blocks=True, lstrip_blocks=True)
-        content_multi = template.render(host_context=not build,
-                                        name=dep_name, ca_exclude=ca_exclude,
-                                        vars_filename=vars_props_name, deps=deps)
-        return content_multi
-
     @staticmethod
-    def _dep_props_file(name, name_general, dep_props_filename, condition):
-        # Current directory is the generators_folder
-        multi_path = name_general
-        if os.path.isfile(multi_path):
-            content_multi = load(multi_path)
-        else:
-            content_multi = textwrap.dedent("""\
-            <?xml version="1.0" encoding="utf-8"?>
-            <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-              <ImportGroup Label="PropertySheets">
-              </ImportGroup>
-              <PropertyGroup>
-                <conan_{{name}}_props_imported>True</conan_{{name}}_props_imported>
-              </PropertyGroup>
-            </Project>
-            """)
-            content_multi = Template(content_multi).render({"name": name})
-
-        # parse the multi_file and add new import statement if needed
-        dom = minidom.parseString(content_multi)
-        import_vars = dom.getElementsByTagName('ImportGroup')[0]
-
-        # Current vars
-        children = import_vars.getElementsByTagName("Import")
-        for node in children:
-            if (dep_props_filename == node.getAttribute("Project") and
-                    condition == node.getAttribute("Condition")):
-                break  # the import statement already exists
-        else:  # create a new import statement
-            import_node = dom.createElement('Import')
-            import_node.setAttribute('Condition', condition)
-            import_node.setAttribute('Project', dep_props_filename)
-            import_vars.appendChild(import_node)
-
-        content_multi = dom.toprettyxml()
-        content_multi = "\n".join(line for line in content_multi.splitlines() if line.strip())
-        return content_multi
+    def _dep_name(dep, build):
+        dep_name = dep.ref.name
+        dep_name = dep_name.replace(".", "_")
+        if build:  # dep.context == CONTEXT_BUILD:
+            dep_name += "_build"
+        return dep_name
 
     def _vars_props_file(self, dep, name, cpp_info, deps, build):
         """
-        content for conan_vars_poco_x86_release.props, containing the variables
+        content for conan_vars_poco_x86_release.props, containing the variables for 1 config
+        This will be for 1 package or for one component of a package
+        :return: varfile content
         """
-        # returns a .props file with the variables definition for one package for one configuration
+
         def add_valid_ext(libname):
             ext = os.path.splitext(libname)[1]
             return '%s;' % libname if ext in VALID_LIB_EXTENSIONS else '%s.lib;' % libname
@@ -189,18 +151,15 @@ class MSBuildDeps(object):
             return path.replace("\\", "/").lstrip("/")
 
         def join_paths(paths):
-            # ALmost copied from CMakeDeps TargetDataContext
+            # TODO: ALmost copied from CMakeDeps TargetDataContext
             ret = []
             for p in paths:
                 assert os.path.isabs(p), "{} is not absolute".format(p)
-
-                if p.startswith(package_folder):
-                    rel = p[len(package_folder):]
-                    rel = escape_path(rel)
-                    norm_path = ("${%s}/%s" % (pkg_placeholder, rel))
-                else:
-                    norm_path = escape_path(p)
-                ret.append(norm_path)
+                full_path = escape_path(p)
+                if full_path.startswith(package_folder):
+                    rel = full_path[len(package_folder)+1:]
+                    full_path = ("%s/%s" % (pkg_placeholder, rel))
+                ret.append(full_path)
             return "".join("{};".format(e) for e in ret)
 
         package_folder = escape_path(dep.package_folder)
@@ -218,56 +177,96 @@ class MSBuildDeps(object):
             'definitions': "".join("%s;" % d for d in cpp_info.defines),
             'compiler_flags': " ".join(cpp_info.cxxflags + cpp_info.cflags),
             'linker_flags': " ".join(cpp_info.sharedlinkflags + cpp_info.exelinkflags),
-            'dependencies': ";".join(deps) if not build else "",
+            'dependencies': ";".join(deps),
             'host_context': not build
         }
         formatted_template = Template(self._vars_props, trim_blocks=True,
                                       lstrip_blocks=True).render(**fields)
         return formatted_template
 
-    def _all_props_file(self, name_general):
-        """ this is a .props file including direct declared dependencies
+    def _activate_props_file(self, dep_name, vars_filename, deps, build):
+        """
+        Actual activation of the VS variables, per configuration
+            - conan_pkgname_x86_release.props / conan_pkgname_compname_x86_release.props
+        :param dep_name: pkgname / pkgname_compname
+        :param deps: the name of other things to be included: [dep1, dep2:compA, ...]
+        :param build: if it is a build require or not
+        """
+
+        # TODO: This must include somehow the user/channel, most likely pattern to exclude/include
+        # Probably also the negation pattern, exclude all not @mycompany/*
+        ca_exclude = any(fnmatch.fnmatch(dep_name, p) for p in self.exclude_code_analysis or ())
+        template = Template(self._conf_props, trim_blocks=True, lstrip_blocks=True)
+        content_multi = template.render(host_context=not build, name=dep_name, ca_exclude=ca_exclude,
+                                        vars_filename=vars_filename, deps=deps)
+        return content_multi
+
+    @staticmethod
+    def _dep_props_file(dep_name, filename, aggregated_filename, condition, content=None):
+        """
+        The file aggregating all configurations for a given pkg / component
+            - conan_pkgname.props
         """
         # Current directory is the generators_folder
-        multi_path = name_general
-        if os.path.isfile(multi_path):
-            content_multi = load(multi_path)
+        if content:
+            content_multi = content  # Useful for aggregating multiple components in one pass
+        elif os.path.isfile(filename):
+            content_multi = load(filename)
         else:
             content_multi = textwrap.dedent("""\
             <?xml version="1.0" encoding="utf-8"?>
             <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
               <ImportGroup Label="PropertySheets">
               </ImportGroup>
+              <PropertyGroup>
+                <conan_{{name}}_props_imported>True</conan_{{name}}_props_imported>
+              </PropertyGroup>
             </Project>
             """)
+            content_multi = Template(content_multi).render({"name": dep_name})
 
-        # parse the multi_file and add a new import statement if needed
+        # parse the multi_file and add new import statement if needed
         dom = minidom.parseString(content_multi)
-        import_group = dom.getElementsByTagName('ImportGroup')[0]
-        children = import_group.getElementsByTagName("Import")
-        direct_deps = self._conanfile.dependencies.filter({"direct": True})
-        for req, dep in direct_deps.items():
-            dep_name = dep.ref.name.replace(".", "_")
-            if req.build:
-                dep_name += "_build"
-            conf_props_name = "conan_%s.props" % dep_name
-            for node in children:
-                if conf_props_name == node.getAttribute("Project"):
-                    # the import statement already exists
-                    break
-            else:
-                # create a new import statement
-                import_node = dom.createElement('Import')
-                dep_imported = "'$(conan_%s_props_imported)' != 'True'" % dep_name
-                import_node.setAttribute('Project', conf_props_name)
-                import_node.setAttribute('Condition', dep_imported)
-                # add it to the import group
-                import_group.appendChild(import_node)
+        import_vars = dom.getElementsByTagName('ImportGroup')[0]
+
+        # Current vars
+        children = import_vars.getElementsByTagName("Import")
+        for node in children:
+            if aggregated_filename == node.getAttribute("Project") \
+                    and condition == node.getAttribute("Condition"):
+                break
+        else:  # create a new import statement
+            import_node = dom.createElement('Import')
+            import_node.setAttribute('Condition', condition)
+            import_node.setAttribute('Project', aggregated_filename)
+            import_vars.appendChild(import_node)
+
         content_multi = dom.toprettyxml()
-        # To remove all extra blank lines
         content_multi = "\n".join(line for line in content_multi.splitlines() if line.strip())
         return content_multi
 
+    def _conandeps(self):
+        """ this is a .props file including direct declared dependencies
+        """
+        # Current directory is the generators_folder
+        conandeps_filename = "conandeps.props"
+        direct_deps = self._conanfile.dependencies.filter({"direct": True})
+        pkg_aggregated_content = textwrap.dedent("""\
+            <?xml version="1.0" encoding="utf-8"?>
+            <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+              <ImportGroup Label="PropertySheets">
+              </ImportGroup>
+            </Project>
+            """)
+        for req, dep in direct_deps.items():
+            dep_name = self._dep_name(dep, req.build)
+            filename = "conan_%s.props" % dep_name
+            comp_condition = "'$(conan_%s_props_imported)' != 'True'" % dep_name
+            pkg_aggregated_content = self._dep_props_file("", conandeps_filename, filename,
+                                                          condition=comp_condition,
+                                                          content=pkg_aggregated_content)
+        return {conandeps_filename: pkg_aggregated_content}
+
     def _package_props_files(self, dep, build=False):
         """ all the files for a given package:
         - conan_pkgname_vars_config.props: definition of variables, one per config
@@ -277,26 +276,50 @@ class MSBuildDeps(object):
         """
         conf_name = self._config_filename()
         condition = self._condition()
-        dep_name = dep.ref.name
-        dep_name = dep_name.replace(".", "_")
-        if build:
-            dep_name += "_build"
-        cpp_info = dep.cpp_info.aggregated_components()
-        public_deps = [d.ref.name.replace(".", "_")
-                       for r, d in dep.dependencies.direct_host.items() if r.visible]
+        dep_name = self._dep_name(dep, build)
         result = {}
-        # One file per configuration, with just the variables
-        vars_props_name = "conan_%s_vars%s.props" % (dep_name, conf_name)
-        result[vars_props_name] = self._vars_props_file(dep, dep_name, cpp_info, public_deps,
-                                                        build=build)
-        props_name = "conan_%s%s.props" % (dep_name, conf_name)
-        result[props_name] = self._conf_props_file(dep_name, vars_props_name, public_deps,
-                                                   build=build)
-
-        # The entry point for each package, it will have conditionals to the others
-        file_dep_name = "conan_%s.props" % dep_name
-        dep_content = self._dep_props_file(dep_name, file_dep_name, props_name, condition)
-        result[file_dep_name] = dep_content
+        if dep.cpp_info.has_components:
+            pkg_aggregated_content = None
+            for comp_name, comp_info in dep.cpp_info.components.items():
+                if comp_name is None:
+                    continue
+                full_comp_name = "{}_{}".format(dep_name, comp_name)
+                vars_filename = "conan_%s_vars%s.props" % (full_comp_name, conf_name)
+                activate_filename = "conan_%s%s.props" % (full_comp_name, conf_name)
+                comp_filename = "conan_%s.props" % full_comp_name
+                pkg_filename = "conan_%s.props" % dep_name
+
+                public_deps = []
+                for r in comp_info.requires:
+                    if "::" in r:  # Points to a component of a different package
+                        pkg, cmp_name = r.split("::")
+                        public_deps.append(pkg if pkg == cmp_name else "{}_{}".format(pkg, cmp_name))
+                    else:  # Points to a component of same package
+                        public_deps.append("{}_{}".format(dep_name, r))
+                result[vars_filename] = self._vars_props_file(dep, full_comp_name, comp_info,
+                                                              public_deps, build=build)
+                result[activate_filename] = self._activate_props_file(full_comp_name, vars_filename,
+                                                                      public_deps, build=build)
+                result[comp_filename] = self._dep_props_file(full_comp_name, comp_filename,
+                                                             activate_filename, condition)
+                comp_condition = "'$(conan_%s_props_imported)' != 'True'" % full_comp_name
+                pkg_aggregated_content = self._dep_props_file(dep_name, pkg_filename, comp_filename,
+                                                              condition=comp_condition,
+                                                              content=pkg_aggregated_content)
+                result[pkg_filename] = pkg_aggregated_content
+        else:
+            cpp_info = dep.cpp_info
+            vars_filename = "conan_%s_vars%s.props" % (dep_name, conf_name)
+            activate_filename = "conan_%s%s.props" % (dep_name, conf_name)
+            pkg_filename = "conan_%s.props" % dep_name
+            public_deps = [self._dep_name(d, build)
+                           for r, d in dep.dependencies.direct_host.items() if r.visible]
+            result[vars_filename] = self._vars_props_file(dep, dep_name, cpp_info,
+                                                          public_deps, build=build)
+            result[activate_filename] = self._activate_props_file(dep_name, vars_filename,
+                                                                  public_deps, build=build)
+            result[pkg_filename] = self._dep_props_file(dep_name, pkg_filename, activate_filename,
+                                                        condition=condition)
         return result
 
     def _content(self):
@@ -306,18 +329,14 @@ class MSBuildDeps(object):
 
         host_req = list(self._conanfile.dependencies.host.values())
         test_req = list(self._conanfile.dependencies.test.values())
-
         for dep in host_req + test_req:
-            files = self._package_props_files(dep, build=False)
-            result.update(files)
+            result.update(self._package_props_files(dep, build=False))
 
         build_req = list(self._conanfile.dependencies.build.values())
         for dep in build_req:
-            files = self._package_props_files(dep, build=True)
-            result.update(files)
+            result.update(self._package_props_files(dep, build=True))
 
         # Include all direct build_requires for host context. This might change
-        conandeps_filename = "conandeps.props"
-        result[conandeps_filename] = self._all_props_file(conandeps_filename)
+        result.update(self._conandeps())
 
         return result
diff --git a/conan/tools/system/package_manager.py b/conan/tools/system/package_manager.py
index 9f7539c78..435350a4b 100644
--- a/conan/tools/system/package_manager.py
+++ b/conan/tools/system/package_manager.py
@@ -11,6 +11,9 @@ class _SystemPackageManagerTool(object):
     install_command = ""
     update_command = ""
     check_command = ""
+    accepted_install_codes = [0]
+    accepted_update_codes = [0]
+    accepted_check_codes = [0, 1]
 
     def __init__(self, conanfile):
         self._conanfile = conanfile
@@ -30,7 +33,7 @@ class _SystemPackageManagerTool(object):
             os_name = distro.id() or os_name
         elif os_name == "Windows" and self._conanfile.conf.get("tools.microsoft.bash:subsystem") == "msys2":
             os_name = "msys2"
-        manager_mapping = {"apt-get": ["Linux", "ubuntu", "debian"],
+        manager_mapping = {"apt-get": ["Linux", "ubuntu", "debian", "raspbian"],
                            "yum": ["pidora", "scientific", "xenserver", "amazon", "oracle", "amzn",
                                    "almalinux", "rocky"],
                            "dnf": ["fedora", "rhel", "centos", "mageia"],
@@ -40,9 +43,17 @@ class _SystemPackageManagerTool(object):
                            "zypper": ["opensuse", "sles"],
                            "pkg": ["freebsd"],
                            "pkgutil": ["Solaris"]}
+        # first check exact match of name
         for tool, distros in manager_mapping.items():
             if os_name in distros:
                 return tool
+        # in case we did not detect any exact match, check
+        # if the name is contained inside the returned distro name
+        # like for opensuse, that can have opensuse-version names
+        for tool, distros in manager_mapping.items():
+            for d in distros:
+                if d in os_name:
+                    return tool
 
     def get_package_name(self, package):
         # TODO: should we only add the arch if cross-building?
@@ -61,6 +72,12 @@ class _SystemPackageManagerTool(object):
         if self._active_tool == self.__class__.tool_name:
             return method(*args, **kwargs)
 
+    def _conanfile_run(self, command, accepted_returns):
+        ret = self._conanfile.run(command, ignore_errors=True)
+        if ret not in accepted_returns:
+            raise ConanException("Command '%s' failed" % command)
+        return ret
+
     def install_substitutes(self, *args, **kwargs):
         return self.run(self._install_substitutes, *args, **kwargs)
 
@@ -86,9 +103,6 @@ class _SystemPackageManagerTool(object):
         raise ConanException("None of the installs for the package substitutes succeeded.")
 
     def _install(self, packages, update=False, check=True, **kwargs):
-        if update:
-            self.update()
-
         if check:
             packages = self.check(packages)
 
@@ -103,28 +117,26 @@ class _SystemPackageManagerTool(object):
                                                                                      self.mode_check,
                                                                                      self.mode_install))
         elif packages:
+            if update:
+                self.update()
+
             packages_arch = [self.get_package_name(package) for package in packages]
             if packages_arch:
                 command = self.install_command.format(sudo=self.sudo_str,
                                                       tool=self.tool_name,
                                                       packages=" ".join(packages_arch),
                                                       **kwargs)
-                return self._conanfile.run(command)
+                return self._conanfile_run(command, self.accepted_install_codes)
         else:
             self._conanfile.output.info("System requirements: {} already "
                                         "installed".format(" ".join(packages)))
 
     def _update(self):
-        if self._mode == self.mode_check:
-            raise ConanException("Can't update because tools.system.package_manager:mode is '{0}'."
-                                 "Please update packages manually or set "
-                                 "'tools.system.package_manager:mode' "
-                                 "to '{1}' in the [conf] section of the profile, "
-                                 "or in the command line using "
-                                 "'-c tools.system.package_manager:mode={1}'".format(self.mode_check,
-                                                                                     self.mode_install))
-        command = self.update_command.format(sudo=self.sudo_str, tool=self.tool_name)
-        return self._conanfile.run(command)
+        # we just update the package manager database in case we are in 'install mode'
+        # in case we are in check mode just ignore
+        if self._mode == self.mode_install:
+            command = self.update_command.format(sudo=self.sudo_str, tool=self.tool_name)
+            return self._conanfile_run(command, self.accepted_update_codes)
 
     def _check(self, packages):
         missing = [pkg for pkg in packages if self.check_package(self.get_package_name(pkg)) != 0]
@@ -133,7 +145,7 @@ class _SystemPackageManagerTool(object):
     def check_package(self, package):
         command = self.check_command.format(tool=self.tool_name,
                                             package=package)
-        return self._conanfile.run(command, ignore_errors=True)
+        return self._conanfile_run(command, self.accepted_check_codes)
 
 
 class Apt(_SystemPackageManagerTool):
@@ -167,6 +179,7 @@ class Yum(_SystemPackageManagerTool):
     install_command = "{sudo}{tool} install -y {packages}"
     update_command = "{sudo}{tool} check-update -y"
     check_command = "rpm -q {package}"
+    accepted_update_codes = [0, 100]
 
     def __init__(self, conanfile, arch_names=None):
         super(Yum, self).__init__(conanfile)
diff --git a/conans/__init__.py b/conans/__init__.py
index d8a442f17..87a5a9d81 100644
--- a/conans/__init__.py
+++ b/conans/__init__.py
@@ -20,4 +20,4 @@ OAUTH_TOKEN = "oauth_token"
 SERVER_CAPABILITIES = [COMPLEX_SEARCH_CAPABILITY, REVISIONS]  # Server is always with revisions
 DEFAULT_REVISION_V1 = "0"
 
-__version__ = '1.50.0-dev'
+__version__ = '1.51.0-dev'
diff --git a/conans/assets/templates/new_v2_meson.py b/conans/assets/templates/new_v2_meson.py
index e0e962070..f71712b52 100644
--- a/conans/assets/templates/new_v2_meson.py
+++ b/conans/assets/templates/new_v2_meson.py
@@ -37,11 +37,6 @@ class {package_name}Conan(ConanFile):
     def package(self):
         meson = Meson(self)
         meson.install()
-        # Meson cannot install dll/so in "bin" and .a/.lib in "lib"
-        lib = os.path.join(self.package_folder, "lib")
-        bin = os.path.join(self.package_folder, "bin")
-        copy(self, "*.so", lib, bin)
-        copy(self, "*.dll", lib, bin)
 
     def package_info(self):
         self.cpp_info.libs = ["{name}"]
@@ -86,7 +81,7 @@ executable('example', 'src/example.cpp', dependencies: {name})
 
 _meson_build = """\
 project('{name} ', 'cpp')
-library('{name}', 'src/{name}.cpp', install: true, install_dir: 'lib')
+library('{name}', 'src/{name}.cpp', install: true)
 install_headers('src/{name}.h')
 """
 
diff --git a/conans/client/conan_command_output.py b/conans/client/conan_command_output.py
index 588b48240..91a6fff6a 100644
--- a/conans/client/conan_command_output.py
+++ b/conans/client/conan_command_output.py
@@ -140,6 +140,10 @@ class CommandOutputer(object):
             item_data["build_id"] = build_id(conanfile)
             item_data["context"] = conanfile.context
 
+            item_data["invalid_build"] = node.cant_build is not False
+            if node.cant_build:
+                item_data["invalid_build_reason"] = node.cant_build
+
             python_requires = getattr(conanfile, "python_requires", None)
             if python_requires and not isinstance(python_requires, dict):  # no old python requires
                 item_data["python_requires"] = [repr(r)
diff --git a/conans/client/conf/config_installer.py b/conans/client/conf/config_installer.py
index e6f1e25ab..4e54c6b9b 100644
--- a/conans/client/conf/config_installer.py
+++ b/conans/client/conf/config_installer.py
@@ -113,7 +113,7 @@ def _process_file(directory, filename, config, cache, output, folder):
         raise ConanException("remotes.json install is not supported yet. Use 'remotes.txt'")
     else:
         # This is ugly, should be removed in Conan 2.0
-        if filename in ("README.md", "LICENSE.txt"):
+        if filename in ("README.md", "LICENSE.txt") and not directory.startswith("templates"):
             output.info("Skip %s" % filename)
         else:
             relpath = os.path.relpath(directory, folder)
diff --git a/conans/client/generators/__init__.py b/conans/client/generators/__init__.py
index 9c76dd41b..246af0a51 100644
--- a/conans/client/generators/__init__.py
+++ b/conans/client/generators/__init__.py
@@ -72,7 +72,8 @@ class GeneratorManager(object):
                                 "MesonToolchain", "MSBuildDeps", "QbsToolchain", "msbuild",
                                 "VirtualRunEnv", "VirtualBuildEnv", "AutotoolsDeps",
                                 "AutotoolsToolchain", "BazelDeps", "BazelToolchain", "PkgConfigDeps",
-                                "VCVars", "IntelCC", "XcodeDeps", "PremakeDeps", "XcodeToolchain"]
+                                "VCVars", "IntelCC", "XcodeDeps", "PremakeDeps", "XcodeToolchain",
+                                "MesonDeps"]
 
     def add(self, name, generator_class, custom=False):
         if name not in self._generators or custom:
@@ -113,6 +114,9 @@ class GeneratorManager(object):
         elif generator_name == "MesonToolchain":
             from conan.tools.meson import MesonToolchain
             return MesonToolchain
+        elif generator_name == "MesonDeps":
+            from conan.tools.meson import MesonDeps
+            return MesonDeps
         elif generator_name in ("MSBuildDeps", "msbuild"):
             from conan.tools.microsoft import MSBuildDeps
             return MSBuildDeps
diff --git a/conans/client/generators/cmake_common.py b/conans/client/generators/cmake_common.py
index 06d0d2294..ddb4bf8dd 100644
--- a/conans/client/generators/cmake_common.py
+++ b/conans/client/generators/cmake_common.py
@@ -257,7 +257,7 @@ class CMakeCommonMacros:
     conan_find_libraries_abs_path = textwrap.dedent("""
         function(conan_find_libraries_abs_path libraries package_libdir libraries_abs_path)
             foreach(_LIBRARY_NAME ${libraries})
-                find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${package_libdir}
+                find_library(CONAN_FOUND_LIBRARY NAMES ${_LIBRARY_NAME} PATHS ${package_libdir}
                              NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
                 if(CONAN_FOUND_LIBRARY)
                     conan_message(STATUS "Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}")
@@ -277,7 +277,7 @@ class CMakeCommonMacros:
             unset(_CONAN_ACTUAL_TARGETS CACHE)
             unset(_CONAN_FOUND_SYSTEM_LIBS CACHE)
             foreach(_LIBRARY_NAME ${libraries})
-                find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${package_libdir}
+                find_library(CONAN_FOUND_LIBRARY NAMES ${_LIBRARY_NAME} PATHS ${package_libdir}
                              NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
                 if(CONAN_FOUND_LIBRARY)
                     conan_message(STATUS "Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}")
@@ -856,7 +856,7 @@ class CMakeCommonMacros:
                 endif()
                 foreach(_FRAMEWORK ${FRAMEWORKS})
                     # https://cmake.org/pipermail/cmake-developers/2017-August/030199.html
-                    find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAME ${_FRAMEWORK} PATHS ${CONAN_FRAMEWORK_DIRS${SUFFIX}} CMAKE_FIND_ROOT_PATH_BOTH)
+                    find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAMES ${_FRAMEWORK} PATHS ${CONAN_FRAMEWORK_DIRS${SUFFIX}} CMAKE_FIND_ROOT_PATH_BOTH)
                     if(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND)
                         list(APPEND ${FRAMEWORKS_FOUND} ${CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND})
                     else()
diff --git a/conans/client/generators/cmake_find_package_common.py b/conans/client/generators/cmake_find_package_common.py
index de54ea56a..11acbe640 100644
--- a/conans/client/generators/cmake_find_package_common.py
+++ b/conans/client/generators/cmake_find_package_common.py
@@ -112,7 +112,7 @@ class CMakeFindPackageCommonMacros:
             if(APPLE)
                 foreach(_FRAMEWORK ${FRAMEWORKS})
                     # https://cmake.org/pipermail/cmake-developers/2017-August/030199.html
-                    find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAME ${_FRAMEWORK} PATHS ${FRAMEWORKS_DIRS} CMAKE_FIND_ROOT_PATH_BOTH)
+                    find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAMES ${_FRAMEWORK} PATHS ${FRAMEWORKS_DIRS} CMAKE_FIND_ROOT_PATH_BOTH)
                     if(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND)
                         list(APPEND ${FRAMEWORKS_FOUND} ${CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND})
                     else()
@@ -128,7 +128,7 @@ class CMakeFindPackageCommonMacros:
             unset(_CONAN_ACTUAL_TARGETS CACHE)
             unset(_CONAN_FOUND_SYSTEM_LIBS CACHE)
             foreach(_LIBRARY_NAME ${libraries})
-                find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${package_libdir}
+                find_library(CONAN_FOUND_LIBRARY NAMES ${_LIBRARY_NAME} PATHS ${package_libdir}
                              NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
                 if(CONAN_FOUND_LIBRARY)
                     conan_message(STATUS "Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}")
diff --git a/conans/client/graph/graph.py b/conans/client/graph/graph.py
index dbfc5ea5c..fbcfac5c5 100644
--- a/conans/client/graph/graph.py
+++ b/conans/client/graph/graph.py
@@ -91,6 +91,8 @@ class Node(object):
         self.id_direct_prefs = None
         self.id_indirect_prefs = None
 
+        self.cant_build = False  # It will set to a str with a reason if the validate_build() fails
+
     @property
     def id(self):
         return self._id
diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py
index 103832b2a..4977e2d68 100644
--- a/conans/client/graph/graph_binaries.py
+++ b/conans/client/graph/graph_binaries.py
@@ -48,7 +48,10 @@ class GraphBinariesAnalyzer(object):
                     break
         if build_mode.forced(conanfile, ref, with_deps_to_build):
             conanfile.output.info('Forced build from source')
-            node.binary = BINARY_BUILD
+            if node.cant_build:
+                node.binary = BINARY_INVALID
+            else:
+                node.binary = BINARY_BUILD
             node.prev = None
             return True
 
@@ -178,7 +181,10 @@ class GraphBinariesAnalyzer(object):
             pref = PackageReference(locked.ref, locked.package_id, locked.prev)  # Keep locked PREV
             self._process_node(node, pref, build_mode, update, remotes)
             if node.binary == BINARY_MISSING and build_mode.allowed(node.conanfile):
-                node.binary = BINARY_BUILD
+                if node.cant_build:
+                    node.binary = BINARY_INVALID
+                else:
+                    node.binary = BINARY_BUILD
             if node.binary == BINARY_BUILD:
                 locked.unlock_prev()
 
@@ -231,7 +237,10 @@ class GraphBinariesAnalyzer(object):
                     if node.binary == BINARY_MISSING and node.package_id == PACKAGE_ID_INVALID:
                         node.binary = BINARY_INVALID
                 if node.binary == BINARY_MISSING and build_mode.allowed(node.conanfile):
-                    node.binary = BINARY_BUILD
+                    if node.cant_build:
+                        node.binary = BINARY_INVALID
+                    else:
+                        node.binary = BINARY_BUILD
 
             if locked:
                 # package_id was not locked, this means a base lockfile that is being completed
@@ -253,6 +262,8 @@ class GraphBinariesAnalyzer(object):
             node.binary = BINARY_INVALID
             return
 
+
+
         if self._evaluate_build(node, build_mode):
             return
 
@@ -293,7 +304,10 @@ class GraphBinariesAnalyzer(object):
                 local_recipe_hash = package_layout.recipe_manifest().summary_hash
                 if local_recipe_hash != recipe_hash:
                     conanfile.output.info("Outdated package!")
-                    node.binary = BINARY_BUILD
+                    if node.cant_build:
+                        node.binary = BINARY_INVALID
+                    else:
+                        node.binary = BINARY_BUILD
                     node.prev = None
                 else:
                     conanfile.output.info("Package is up to date")
@@ -400,6 +414,14 @@ class GraphBinariesAnalyzer(object):
                 except ConanInvalidConfiguration as e:
                     conanfile.info.invalid = str(e)
 
+        if hasattr(conanfile, "validate_build") and callable(conanfile.validate_build):
+            with conanfile_exception_formatter(str(conanfile), "validate_build"):
+                try:
+                    conanfile.validate_build()
+                except ConanInvalidConfiguration as e:
+                    # This 'cant_build' will be ignored if we don't have to build the node.
+                    node.cant_build = str(e)
+
         info = conanfile.info
         node.package_id = info.package_id()
 
diff --git a/conans/client/graph/graph_builder.py b/conans/client/graph/graph_builder.py
index 9f9d3baa6..05b7ef1df 100644
--- a/conans/client/graph/graph_builder.py
+++ b/conans/client/graph/graph_builder.py
@@ -3,7 +3,7 @@ import time
 from conans.client.conanfile.configure import run_configure_method
 from conans.client.graph.graph import DepsGraph, Node, RECIPE_EDITABLE, CONTEXT_HOST, CONTEXT_BUILD
 from conans.errors import (ConanException, ConanExceptionInUserConanfileMethod,
-                           conanfile_exception_formatter)
+                           conanfile_exception_formatter, ConanInvalidConfiguration)
 from conans.model.conan_file import get_env_context_manager
 from conans.model.ref import ConanFileReference
 from conans.model.requires import Requirements, Requirement
@@ -65,7 +65,9 @@ class DepsGraphBuilder(object):
         t1 = time.time()
         self._expand_node(root_node, dep_graph, Requirements(), None, None, check_updates,
                           update, remotes, profile_host, profile_build, graph_lock)
+
         logger.debug("GRAPH: Time to load deps %s" % (time.time() - t1))
+
         return dep_graph
 
     def extend_build_requires(self, graph, node, build_requires_refs, check_updates, update,
@@ -471,4 +473,5 @@ class DepsGraphBuilder(object):
 
         dep_graph.add_node(new_node)
         dep_graph.add_edge(current_node, new_node, requirement)
+
         return new_node
diff --git a/conans/client/graph/graph_manager.py b/conans/client/graph/graph_manager.py
index 3568566e7..10a75d463 100644
--- a/conans/client/graph/graph_manager.py
+++ b/conans/client/graph/graph_manager.py
@@ -124,6 +124,7 @@ class GraphManager(object):
         root_node = self._load_root_node(reference, create_reference, profile_host, graph_lock,
                                          root_ref, lockfile_node_id, is_build_require,
                                          require_overrides)
+
         deps_graph = self._resolve_graph(root_node, profile_host, profile_build, graph_lock,
                                          build_mode, check_updates, update, remotes, recorder,
                                          apply_build_requires=apply_build_requires)
diff --git a/conans/client/installer.py b/conans/client/installer.py
index 65649b942..260c7dcdd 100644
--- a/conans/client/installer.py
+++ b/conans/client/installer.py
@@ -423,7 +423,13 @@ class BinaryInstaller(object):
         if invalid:
             msg = ["There are invalid packages (packages that cannot exist for this configuration):"]
             for node in invalid:
-                msg.append("{}: Invalid ID: {}".format(node.conanfile, node.conanfile.info.invalid))
+                if node.cant_build:
+                    msg.append("{}: Cannot build "
+                               "for this configuration: {}".format(node.conanfile,
+                                                                   node.cant_build))
+                else:
+                    msg.append("{}: Invalid ID: {}".format(node.conanfile,
+                                                           node.conanfile.info.invalid))
             raise ConanInvalidConfiguration("\n".join(msg))
         self._raise_missing(missing)
         processed_package_refs = {}
diff --git a/conans/client/loader.py b/conans/client/loader.py
index 4fafe8197..d1d89130d 100644
--- a/conans/client/loader.py
+++ b/conans/client/loader.py
@@ -8,6 +8,8 @@ import uuid
 
 import yaml
 
+from pathlib import Path
+
 from conan.tools.cmake import cmake_layout
 from conan.tools.google import bazel_layout
 from conan.tools.microsoft import vs_layout
@@ -73,6 +75,7 @@ class ConanFileLoader(object):
                 self._pyreq_loader.load_py_requires(conanfile, lock_python_requires, self)
 
             conanfile.recipe_folder = os.path.dirname(conanfile_path)
+            conanfile.recipe_path = Path(conanfile.recipe_folder)
 
             # If the scm is inherited, create my own instance
             if hasattr(conanfile, "scm") and "scm" not in conanfile.__class__.__dict__:
diff --git a/conans/client/migrations_settings.py b/conans/client/migrations_settings.py
index 25b2bd1bf..db79c4f07 100644
--- a/conans/client/migrations_settings.py
+++ b/conans/client/migrations_settings.py
@@ -3713,3 +3713,5 @@ cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
 """
 
 settings_1_50_0 = settings_1_49_0
+
+settings_1_51_0 = settings_1_50_0
diff --git a/conans/client/rest/rest_client.py b/conans/client/rest/rest_client.py
index ab7549083..aa4c74ad3 100644
--- a/conans/client/rest/rest_client.py
+++ b/conans/client/rest/rest_client.py
@@ -111,7 +111,8 @@ class RestApiClient(object):
 
     def authenticate(self, user, password):
         api_v1 = RestV1Methods(self._remote_url, self._token, self._custom_headers, self._output,
-                               self._requester, self._verify_ssl, self._artifacts_properties)
+                               self._requester, self._config, self._verify_ssl,
+                               self._artifacts_properties)
 
         if self._refresh_token and self._token:
             token, refresh_token = api_v1.refresh_token(self._token, self._refresh_token)
diff --git a/conans/client/tools/files.py b/conans/client/tools/files.py
index 199581c0e..a8444b23c 100644
--- a/conans/client/tools/files.py
+++ b/conans/client/tools/files.py
@@ -351,24 +351,29 @@ def collect_libs(conanfile, folder=None):
     else:
         lib_folders = [os.path.join(conanfile.package_folder, folder)
                        for folder in conanfile.cpp_info.libdirs]
-    result = []
+
+    ref_libs = {}
     for lib_folder in lib_folders:
         if not os.path.exists(lib_folder):
             conanfile.output.warn("Lib folder doesn't exist, can't collect libraries: "
                                   "{0}".format(lib_folder))
             continue
+        # In case of symlinks, only keep shortest file name in the same "group"
         files = os.listdir(lib_folder)
         for f in files:
             name, ext = os.path.splitext(f)
             if ext in VALID_LIB_EXTENSIONS:
-                if ext != ".lib" and name.startswith("lib"):
-                    name = name[3:]
-                if name in result:
-                    conanfile.output.warn("Library '%s' was either already found in a previous "
-                                          "'conanfile.cpp_info.libdirs' folder or appears several "
-                                          "times with a different file extension" % name)
-                else:
-                    result.append(name)
+                real_lib = os.path.basename(os.path.realpath(os.path.join(lib_folder, f)))
+                if real_lib not in ref_libs or len(f) < len(ref_libs[real_lib]):
+                    ref_libs[real_lib] = f
+
+    result = []
+    for f in ref_libs.values():
+        name, ext = os.path.splitext(f)
+        if ext != ".lib" and name.startswith("lib"):
+            name = name[3:]
+        if name not in result:
+            result.append(name)
     result.sort()
     return result
 
diff --git a/conans/model/conan_file.py b/conans/model/conan_file.py
index ce9a2ba2a..69fe57e1a 100644
--- a/conans/model/conan_file.py
+++ b/conans/model/conan_file.py
@@ -1,6 +1,7 @@
 import os
 import platform
 from contextlib import contextmanager
+from pathlib import Path
 
 import six
 from six import string_types
@@ -258,6 +259,11 @@ class ConanFile(object):
     def source_folder(self):
         return self.folders.source_folder
 
+    @property
+    def source_path(self) -> Path:
+        assert self.source_folder is not None, "`source_folder` is `None`"
+        return Path(self.source_folder)
+
     @property
     def export_sources_folder(self):
         """points to the base source folder when calling source() and to the cache export sources
@@ -265,18 +271,38 @@ class ConanFile(object):
         'no_copy_export_sources' and point to the right location always."""
         return self.folders.base_export_sources
 
+    @property
+    def export_sources_path(self) -> Path:
+        assert self.export_sources_folder is not None, "`export_sources_folder` is `None`"
+        return Path(self.export_sources_folder)
+
     @property
     def export_folder(self):
         return self.folders.base_export
 
+    @property
+    def export_path(self) -> Path:
+        assert self.export_folder is not None, "`export_folder` is `None`"
+        return Path(self.export_folder)
+
     @property
     def build_folder(self):
         return self.folders.build_folder
 
+    @property
+    def build_path(self) -> Path:
+        assert self.build_folder is not None, "`build_folder` is `None`"
+        return Path(self.build_folder)
+
     @property
     def package_folder(self):
         return self.folders.base_package
 
+    @property
+    def package_path(self) -> Path:
+        assert self.package_folder is not None, "`package_folder` is `None`"
+        return Path(self.package_folder)
+
     @property
     def install_folder(self):
         # FIXME: Remove in 2.0, no self.install_folder
@@ -287,6 +313,11 @@ class ConanFile(object):
         # FIXME: Remove in 2.0, no self.install_folder
         return self.folders.generators_folder if self.folders.generators else self.install_folder
 
+    @property
+    def generators_path(self) -> Path:
+        assert self.generators_folder is not None, "`generators_folder` is `None`"
+        return Path(self.generators_folder)
+
     @property
     def imports_folder(self):
         return self.folders.imports_folder
diff --git a/conans/model/conanfile_interface.py b/conans/model/conanfile_interface.py
index 22617a72d..fd9c8b5d1 100644
--- a/conans/model/conanfile_interface.py
+++ b/conans/model/conanfile_interface.py
@@ -1,3 +1,4 @@
+from pathlib import Path
 from conans.client.graph.graph import CONTEXT_BUILD
 
 
@@ -29,6 +30,11 @@ class ConanFileInterface:
     def package_folder(self):
         return self._conanfile.package_folder
 
+    @property
+    def package_path(self) -> Path:
+        assert self.package_folder is not None, "`package_folder` is `None`"
+        return Path(self.package_folder)
+
     @property
     def ref(self):
         return self._conanfile.ref
diff --git a/conans/model/conf.py b/conans/model/conf.py
index 1c37c95e3..968bcd87b 100644
--- a/conans/model/conf.py
+++ b/conans/model/conf.py
@@ -21,6 +21,7 @@ BUILT_IN_CONFS = {
     "tools.cmake.cmaketoolchain:system_name": "Define CMAKE_SYSTEM_NAME in CMakeToolchain",
     "tools.cmake.cmaketoolchain:system_version": "Define CMAKE_SYSTEM_VERSION in CMakeToolchain",
     "tools.cmake.cmaketoolchain:system_processor": "Define CMAKE_SYSTEM_PROCESSOR in CMakeToolchain",
+    "tools.cmake.cmaketoolchain.presets:max_schema_version": "Generate CMakeUserPreset.json compatible with the supplied schema version",
     "tools.env.virtualenv:auto_use": "Automatically activate virtualenv file generation",
     "tools.cmake.cmake_layout:build_folder_vars": "Settings and Options that will produce a different build folder and different CMake presets names",
     "tools.files.download:retry": "Number of retries in case of failure when downloading",
diff --git a/conans/model/layout.py b/conans/model/layout.py
index cce15ddd5..d3c4828cb 100644
--- a/conans/model/layout.py
+++ b/conans/model/layout.py
@@ -31,6 +31,10 @@ class Folders(object):
         # Relative location of the project root, if the conanfile is not in that project root, but
         # in a subfolder: e.g: If the conanfile is in a subfolder then self.root = ".."
         self.root = None
+        # The relative location with respect to the project root of the subproject containing the
+        # conanfile.py, that makes most of the output folders defined in layouts (cmake_layout, etc)
+        # start from the subproject again
+        self.subproject = None
 
     def __repr__(self):
         return str(self.__dict__)
diff --git a/pyinstaller.py b/pyinstaller.py
index 9b7cb4b9d..b3e17251f 100644
--- a/pyinstaller.py
+++ b/pyinstaller.py
@@ -98,7 +98,7 @@ def pyinstall(source_folder):
               "--hidden-import=conan.tools.files --hidden-import=conan.tools.gnu "
               "--hidden-import=conan.tools.google --hidden-import=conan.tools.intel "
               "--hidden-import=conan.tools.layout --hidden-import=conan.tools.premake "
-              "--hidden-import=conan.tools.qbs")
+              "--hidden-import=conan.tools.qbs --hidden-import=conan.tools.scm")
     if platform.system() != "Windows":
         hidden += " --hidden-import=setuptools.msvc"
         win_ver = ""


Test patch:
diff --git a/conans/test/assets/autotools.py b/conans/test/assets/autotools.py
index 473b291d2..96c0559a3 100644
--- a/conans/test/assets/autotools.py
+++ b/conans/test/assets/autotools.py
@@ -55,12 +55,12 @@ def gen_makefile(**context):
         {% for lib in libs %}
         {%- set link_libs.str = link_libs.str + ' -l' + lib|string  %}
         lib{{lib}}.a: {{lib}}.o
-        	$(AR) rcs lib{{lib}}.a {{lib}}.o
+        	$(AR) rcs lib{{lib}}.a {{lib}}.o {%if static_runtime%}--static{%endif%}
         {% endfor %}
 
         {% for s in apps %}
         {{s}}: {{s}}.o libs
-        	$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o {{s}} {{s}}.o $(LIBS) {{link_libs.str}} -L.
+        	$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o {{s}} {{s}}.o $(LIBS) {{link_libs.str}} -L. {%if static_runtime%}--static{%endif%}
         {% endfor %}
         """)
 
diff --git a/conans/test/conftest.py b/conans/test/conftest.py
index 07905171f..5a8716836 100644
--- a/conans/test/conftest.py
+++ b/conans/test/conftest.py
@@ -92,6 +92,13 @@ tools_locations = {
         "exe": "mingw32-make",
         "system": {"path": {'Windows': "C:/msys64/mingw32/bin"}},
     },
+    'ucrt64': {
+        "disabled": True,
+        "platform": "Windows",
+        "default": "system",
+        "exe": "mingw32-make",
+        "system": {"path": {'Windows': "C:/msys64/ucrt64/bin"}},
+    },
     'mingw64': {
         "platform": "Windows",
         "default": "system",
@@ -104,6 +111,20 @@ tools_locations = {
         "exe": "make",
         "system": {"path": {'Windows': "C:/msys64/usr/bin"}},
     },
+    'msys2_clang64': {
+        "disabled": True,
+        "platform": "Windows",
+        "default": "system",
+        "exe": "mingw32-make",
+        "system": {"path": {'Windows': "C:/msys64/clang64/bin"}},
+    },
+    'msys2_mingw64_clang64': {
+        "disabled": True,
+        "platform": "Windows",
+        "default": "system",
+        "exe": "mingw32-make",
+        "system": {"path": {'Windows': "C:/msys64/mingw64/bin"}},
+    },
     'cygwin': {
         "platform": "Windows",
         "default": "system",
@@ -156,6 +177,8 @@ except ImportError as e:
 tools_environments = {
     'mingw32': {'Windows': {'MSYSTEM': 'MINGW32'}},
     'mingw64': {'Windows': {'MSYSTEM': 'MINGW64'}},
+    'ucrt64': {'Windows': {'MSYSTEM': 'UCRT64'}},
+    'msys2_clang64': {"Windows": {"MSYSTEM": "CLANG64"}},
     'android_ndk': {'Darwin': {'TEST_CONAN_ANDROID_NDK': '/usr/local/share/android-ndk'}}
 }
 
diff --git a/conans/test/functional/layout/test_in_subfolder.py b/conans/test/functional/layout/test_in_subfolder.py
index 33925fa67..af3f58293 100644
--- a/conans/test/functional/layout/test_in_subfolder.py
+++ b/conans/test/functional/layout/test_in_subfolder.py
@@ -1,5 +1,9 @@
 import textwrap
 
+import pytest
+
+from conans.test.assets.cmake import gen_cmakelists
+from conans.test.assets.sources import gen_function_cpp
 from conans.test.utils.tools import TestClient
 
 
@@ -54,3 +58,113 @@ def test_exports_sources_own_code_in_subfolder():
     c.run("build conan")
     assert "conanfile.py (pkg/0.1): MYCMAKE-BUILD: mycmake!" in c.out
     assert c.load("build/mylib.a") == "mylib"
+
+
+def test_exports_sources_common_code():
+    """ very similar to the above, but intended for a multi-package project sharing some
+    common code
+    """
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        import os
+        from conan import ConanFile
+        from conan.tools.files import load, copy, save
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "0.1"
+
+            def layout(self):
+                self.folders.root = ".."
+                self.folders.source = "pkg"
+                self.folders.build = "build"
+
+            def export_sources(self):
+                source_folder = os.path.join(self.recipe_folder, "..")
+                copy(self, "*.txt", source_folder, self.export_sources_folder)
+                copy(self, "*.cmake", source_folder, self.export_sources_folder)
+
+            def source(self):
+                cmake = load(self, "CMakeLists.txt")
+                self.output.info("MYCMAKE-SRC: {}".format(cmake))
+
+            def build(self):
+                path = os.path.join(self.source_folder, "CMakeLists.txt")
+                cmake = load(self, path)
+                self.output.info("MYCMAKE-BUILD: {}".format(cmake))
+
+                path = os.path.join(self.export_sources_folder, "common", "myutils.cmake")
+                cmake = load(self, path)
+                self.output.info("MYUTILS-BUILD: {}".format(cmake))
+            """)
+    c.save({"pkg/conanfile.py": conanfile,
+            "pkg/CMakeLists.txt": "mycmake!",
+            "common/myutils.cmake": "myutils!"})
+    c.run("create pkg")
+    assert "pkg/0.1: MYCMAKE-SRC: mycmake!" in c.out
+    assert "pkg/0.1: MYCMAKE-BUILD: mycmake!" in c.out
+    assert "pkg/0.1: MYUTILS-BUILD: myutils!" in c.out
+
+    # Local flow
+    c.run("install pkg")
+    # SOURCE NOT CALLED! It doesnt make sense (will fail due to local exports)
+    c.run("build pkg")
+    assert "conanfile.py (pkg/0.1): MYCMAKE-BUILD: mycmake!" in c.out
+    assert "conanfile.py (pkg/0.1): MYUTILS-BUILD: myutils!" in c.out
+
+
+@pytest.mark.tool_cmake
+def test_exports_sources_common_code_layout():
+    """ Equal to the previous test, but actually building and using cmake_layout
+    """
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        import os
+        from conan import ConanFile
+        from conan.tools.cmake import cmake_layout, CMake
+        from conan.tools.files import load, copy, save
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "os", "compiler", "build_type", "arch"
+            generators = "CMakeToolchain"
+
+            def layout(self):
+                self.folders.root = ".."
+                self.folders.subproject = "pkg"
+                cmake_layout(self)
+
+            def export_sources(self):
+                source_folder = os.path.join(self.recipe_folder, "..")
+                copy(self, "*", source_folder, self.export_sources_folder)
+
+            def build(self):
+                cmake = CMake(self)
+                cmake.configure()
+                cmake.build()
+                self.run(os.path.join(self.cpp.build.bindirs[0], "myapp"))
+            """)
+    cmake_include = "include(${CMAKE_CURRENT_LIST_DIR}/../common/myutils.cmake)"
+    c.save({"pkg/conanfile.py": conanfile,
+            "pkg/app.cpp": gen_function_cpp(name="main", includes=["../common/myheader"],
+                                            preprocessor=["MYDEFINE"]),
+            "pkg/CMakeLists.txt": gen_cmakelists(appsources=["app.cpp"],
+                                                 custom_content=cmake_include),
+            "common/myutils.cmake": 'message(STATUS "MYUTILS.CMAKE!")',
+            "common/myheader.h": '#define MYDEFINE "MYDEFINEVALUE"'})
+    c.run("create pkg")
+    assert "MYUTILS.CMAKE!" in c.out
+    assert "main: Release!" in c.out
+    assert "MYDEFINE: MYDEFINEVALUE" in c.out
+
+    # Local flow
+    c.run("install pkg")
+    c.run("build pkg")
+    assert "MYUTILS.CMAKE!" in c.out
+    assert "main: Release!" in c.out
+    assert "MYDEFINE: MYDEFINEVALUE" in c.out
+
+    c.run("install pkg -s build_type=Debug")
+    c.run("build pkg")
+    assert "MYUTILS.CMAKE!" in c.out
+    assert "main: Debug!" in c.out
+    assert "MYDEFINE: MYDEFINEVALUE" in c.out
diff --git a/conans/test/functional/subsystems_build_test.py b/conans/test/functional/subsystems_build_test.py
index d8c6ac4ee..4faa08d36 100644
--- a/conans/test/functional/subsystems_build_test.py
+++ b/conans/test/functional/subsystems_build_test.py
@@ -1,11 +1,13 @@
 import platform
+import tempfile
 
 import pytest
 import textwrap
 
+from conans.client.tools import environment_append
 from conans.test.assets.autotools import gen_makefile
 from conans.test.assets.sources import gen_function_cpp
-from conans.test.functional.utils import check_exe_run
+from conans.test.functional.utils import check_exe_run, check_vs_runtime
 from conans.test.utils.tools import TestClient
 
 
@@ -14,12 +16,24 @@ class TestSubsystems:
 
     @pytest.mark.tool_msys2
     def test_msys2_available(self):
+        """
+        Msys2 needs to be installed:
+        - Go to https://www.msys2.org/, download the exe installer and run it
+        - Follow instructions in https://www.msys2.org/ to update the package DB
+        - Install msys2 autotools "pacman -S autotools"
+        - Make sure the entry in conftest_user.py of msys2 points to the right location
+        """
         client = TestClient()
         client.run_command('uname')
         assert "MSYS" in client.out
 
     @pytest.mark.tool_cygwin
     def test_cygwin_available(self):
+        """ Cygwin is necessary
+        - Install from https://www.cygwin.com/install.html, use the default packages
+        - Install automake 1.16, gcc-g++, make and binutils packages (will add autoconf and more)
+        - Make sure that the path in conftest_user.py is pointing to cygwin "bin" folder
+        """
         client = TestClient()
         client.run_command('uname')
         assert "CYGWIN" in client.out
@@ -27,13 +41,36 @@ class TestSubsystems:
     @pytest.mark.tool_msys2
     @pytest.mark.tool_mingw32
     def test_mingw32_available(self):
+        """ Mingw32 needs to be installed. We use msys2, don't know if others work
+        - Inside msys2, install pacman -S mingw-w64-i686-toolchain (all pkgs)
+        """
         client = TestClient()
         client.run_command('uname')
         assert "MINGW32_NT" in client.out
 
+    @pytest.mark.tool_msys2
+    @pytest.mark.tool_ucrt64
+    def test_ucrt64_available(self):
+        """ ucrt64 needs to be installed. We use msys2, don't know if others work
+        - Inside msys2, install pacman -S mingw-w64-ucrt-x86_64-toolchain (all pkgs)
+        """
+        client = TestClient()
+        client.run_command('uname')
+        assert "MINGW64_NT" in client.out
+
+    @pytest.mark.tool_msys2
+    @pytest.mark.tool_msys2_clang64
+    def test_clang64_available(self):
+        client = TestClient()
+        client.run_command('uname')
+        assert "MINGW64_NT" in client.out
+
     @pytest.mark.tool_msys2
     @pytest.mark.tool_mingw64
     def test_mingw64_available(self):
+        """ Mingw64 needs to be installed. We use msys2, don't know if others work
+        - Inside msys2, install pacman -S mingw-w64-x86_64-toolchain (all pkgs)
+        """
         client = TestClient()
         client.run_command('uname')
         assert "MINGW64_NT" in client.out
@@ -48,77 +85,136 @@ class TestSubsystems:
 class TestSubsystemsBuild:
 
     @staticmethod
-    def _build(client):
-        makefile = gen_makefile(apps=["app"])
+    def _build(client, static_runtime=None):
+        makefile = gen_makefile(apps=["app"], static_runtime=static_runtime)
         main_cpp = gen_function_cpp(name="main")
         client.save({"Makefile": makefile,
                      "app.cpp": main_cpp})
         client.run_command("make")
         client.run_command("app")
 
+    @pytest.mark.parametrize("static", [True, False])
     @pytest.mark.tool_msys2
-    def test_msys(self):
+    def test_msys2(self, static):
         """
         native MSYS environment, binaries depend on MSYS runtime (msys-2.0.dll)
+        Install:
+        - pacman -S gcc
         posix-compatible, intended to be run only in MSYS environment (not in pure Windows)
         """
         client = TestClient()
-        # pacman -S gcc
-        self._build(client)
-
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
+        self._build(client, static_runtime=static)
 
-        assert "__MINGW32__" not in client.out
-        assert "__MINGW64__" not in client.out
-        assert "__MSYS__" in client.out
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="msys2")
+        assert "_M_X64" not in client.out
+        # TODO: Do not hardcode the visual version
+        check_vs_runtime("app.exe", client, "15", "Debug", static_runtime=static,
+                         subsystem="msys2")
 
+    @pytest.mark.parametrize("static", [True, False])
     @pytest.mark.tool_msys2
     @pytest.mark.tool_mingw64
-    def test_mingw64(self):
+    def test_mingw64(self, static):
         """
-        64-bit GCC, binaries for generic Windows (no dependency on MSYS runtime)
+        This will work if you installed the Mingw toolchain inside msys2 as TestSubystems above
+        64-bit GCC, binaries
         """
         client = TestClient()
         # pacman -S mingw-w64-x86_64-gcc
-        self._build(client)
+        self._build(client, static_runtime=static)
+
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="mingw64")
+        # it also defines the VS 64 bits macro
+        assert "main _M_X64 defined" in client.out
+        check_vs_runtime("app.exe", client, "15", "Debug", static_runtime=static,
+                         subsystem="mingw64")
 
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
+    @pytest.mark.parametrize("static", [True, False])
+    @pytest.mark.tool_msys2
+    @pytest.mark.tool_msys2_clang64
+    def test_msys2_clang64(self, static):
+        """
+        in msys2
+        $ pacman -S mingw-w64-x86_64-clang (NO, this is the mingw variant in ming64)
+        $ pacman -S mingw-w64-clang-x86_64-toolchain
+        """
+        client = TestClient()
+        self._build(client, static_runtime=static)
 
-        assert "__MINGW64__" in client.out
-        assert "__CYGWIN__" not in client.out
-        assert "__MSYS__" not in client.out
+        check_exe_run(client.out, "main", "clang", None, "Debug", "x86_64", None,
+                      subsystem="mingw64")
+        # it also defines the VS 64 bits macro
+        assert "main _M_X64 defined" in client.out
+        check_vs_runtime("app.exe", client, "15", "Debug", static_runtime=static,
+                         subsystem="clang64")
 
+    @pytest.mark.tool_msys2
+    @pytest.mark.tool_msys2_mingw64_clang64
+    def test_msys2_mingw64_clang64(self):
+        """
+        in msys2
+        $ pacman -S mingw-w64-x86_64-clang
+        $ pacman -S mingw-w64-clang-x86_64-toolchain (NO, this is the clang)
+        """
+        client = TestClient()
+        static = False  # This variant needs --static-glibc -static-libstdc++ (weird) to link static
+        # Need to redefine CXX otherwise is gcc
+        with environment_append({"CXX": "clang++"}):
+            self._build(client, static_runtime=static)
+
+        check_exe_run(client.out, "main", "clang", None, "Debug", "x86_64", None,
+                      subsystem="mingw64")
+        # it also defines the VS 64 bits macro
+        assert "main _M_X64 defined" in client.out
+        check_vs_runtime("app.exe", client, "15", "Debug", static_runtime=static,
+                         subsystem="mingw64")
+
+    @pytest.mark.parametrize("static", [True, False])
     @pytest.mark.tool_msys2
     @pytest.mark.tool_mingw32
-    def test_mingw32(self):
+    def test_mingw32(self, static):
         """
+        This will work if you installed the Mingw toolchain inside msys2 as TestSubystems above
         32-bit GCC, binaries for generic Windows (no dependency on MSYS runtime)
         """
         client = TestClient()
         # pacman -S mingw-w64-i686-gcc
-        self._build(client)
+        self._build(client, static_runtime=static)
+
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86", None, subsystem="mingw32")
+        # It also defines the VS flag
+        assert "main _M_IX86 defined" in client.out
+        check_vs_runtime("app.exe", client, "15", "Debug", static_runtime=static,
+                         subsystem="mingw32")
 
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86", None)
+    @pytest.mark.parametrize("static", [True, False])
+    @pytest.mark.tool_msys2
+    @pytest.mark.tool_ucrt64
+    def test_ucrt64(self, static):
+        """
+        This will work if you installed the Mingw toolchain inside msys2 as TestSubystems above
+        """
+        client = TestClient()
 
-        assert "__MINGW32__" in client.out
-        assert "__CYGWIN__" not in client.out
-        assert "__MSYS__" not in client.out
+        self._build(client, static_runtime=static)
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="mingw32")
+        # it also defines the VS macro
+        assert "main _M_X64 defined" in client.out
+        check_vs_runtime("app.exe", client, "15", "Debug", static_runtime=static,
+                         subsystem="ucrt64")
 
+    @pytest.mark.parametrize("static", [True, False])
     @pytest.mark.tool_cygwin
-    def test_cygwin(self):
+    def test_cygwin(self, static):
         """
         Cygwin environment, binaries depend on Cygwin runtime (cygwin1.dll)
         posix-compatible, intended to be run only in Cygwin environment (not in pure Windows)
         """
         client = TestClient()
-        # install "gcc-c++" and "make" packages
-        self._build(client)
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
-
-        assert "__CYGWIN__" in client.out
-        assert "__MINGW32__" not in client.out
-        assert "__MINGW64__" not in client.out
-        assert "__MSYS__" not in client.out
+        self._build(client, static_runtime=static)
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="cygwin")
+        check_vs_runtime("app.exe", client, "15", "Debug", static_runtime=static,
+                         subsystem="cygwin")
 
 
 @pytest.mark.skipif(platform.system() != "Windows", reason="Tests Windows Subsystems")
@@ -157,12 +253,8 @@ class TestSubsystemsAutotoolsBuild:
         client = TestClient()
         # pacman -S gcc
         self._build(client)
-
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
-
-        assert "__MINGW32__" not in client.out
-        assert "__MINGW64__" not in client.out
-        assert "__MSYS__" in client.out
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="msys2")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="msys2")
 
     @pytest.mark.tool_msys2
     @pytest.mark.tool_mingw64
@@ -173,12 +265,8 @@ class TestSubsystemsAutotoolsBuild:
         client = TestClient()
         # pacman -S mingw-w64-x86_64-gcc
         self._build(client)
-
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
-
-        assert "__MINGW64__" in client.out
-        assert "__CYGWIN__" not in client.out
-        assert "__MSYS__" not in client.out
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="mingw64")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="mingw64")
 
     @pytest.mark.tool_msys2
     @pytest.mark.tool_mingw32
@@ -189,110 +277,164 @@ class TestSubsystemsAutotoolsBuild:
         client = TestClient()
         # pacman -S mingw-w64-i686-gcc
         self._build(client)
-
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86", None)
-
-        assert "__MINGW32__" in client.out
-        assert "__CYGWIN__" not in client.out
-        assert "__MSYS__" not in client.out
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86", None, subsystem="mingw32")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="mingw32")
 
     @pytest.mark.tool_cygwin
     def test_cygwin(self):
         """
         Cygwin environment, binaries depend on Cygwin runtime (cygwin1.dll)
         posix-compatible, intended to be run only in Cygwin environment (not in pure Windows)
+        # install autotools, autoconf, libtool, "gcc-c++" and "make" packages
         """
         client = TestClient()
-        # install "gcc-c++" and "make" packages
         self._build(client)
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
-
-        assert "__CYGWIN__" in client.out
-        assert "__MINGW32__" not in client.out
-        assert "__MINGW64__" not in client.out
-        assert "__MSYS__" not in client.out
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="cygwin")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="cygwin")
 
 
 @pytest.mark.skipif(platform.system() != "Windows", reason="Tests Windows Subsystems")
 class TestSubsystemsCMakeBuild:
+    """ These tests are running the CMake INSIDE THE subsystem, not the Windows native one
+    The results are basically the same if CMake is outside the subsystem, but it is NOT
+    enough to define CMAKE_CXX_COMPILER full path to the compiler, but it must be in the path
+
+    """
     cmakelists = textwrap.dedent("""
-        cmake_minimum_required(VERSION 2.8)
-        project(app)
+        cmake_minimum_required(VERSION 3.15)
+        project(app CXX)
+        message(STATUS "MYCMAKE VERSION=${CMAKE_VERSION}")
         add_executable(app main.cpp)
         """)
 
-    def _build(self, client, generator="Unix Makefiles"):
+    def _build(self, client, generator="Unix Makefiles", compiler=None, toolset=None):
         main_cpp = gen_function_cpp(name="main")
         client.save({"CMakeLists.txt": self.cmakelists,
                      "main.cpp": main_cpp})
 
-        client.run_command("cmake "
-                           " -DCMAKE_C_FLAGS=\"-Wl,-verbose\""
-                           " -DCMAKE_CXX_FLAGS=\"-Wl,-verbose\""
-                           " -DCMAKE_SH=\"CMAKE_SH-NOTFOUND\" -G \"%s\" ." % generator)
+        cmake_compiler = ""
+        if compiler:
+            cmake_compiler += " -DCMAKE_C_COMPILER={}".format(compiler)
+            compilerpp = "clang++" if compiler == "clang" else "g++"
+            cmake_compiler += " -DCMAKE_CXX_COMPILER={}".format(compilerpp)
+            cmake_compiler += " -DCMAKE_RC_COMPILER={}".format(compiler)
+        toolset = "-T {}".format(toolset) if toolset else ""
+        client.run_command("cmake {} {}"
+                           " -DCMAKE_SH=\"CMAKE_SH-NOTFOUND\" -G \"{}\" .".format(cmake_compiler,
+                                                                                  toolset,
+                                                                                  generator))
+        build_out = client.out
         client.run_command("cmake --build .")
-        client.run_command("app")
+        app = "app" if "Visual" not in generator else r"Debug\app"
+        client.run_command(app)
+        return build_out
 
     @pytest.mark.tool_msys2
     def test_msys(self):
         """
-        native MSYS environment, binaries depend on MSYS runtime (msys-2.0.dll)
-        posix-compatible, intended to be run only in MSYS environment (not in pure Windows)
+        pacman -S cmake
         """
         client = TestClient()
-        # pacman -S gcc
         self._build(client)
-
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
-
-        assert "__MINGW32__" not in client.out
-        assert "__MINGW64__" not in client.out
-        assert "__MSYS__" in client.out
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="msys2")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="msys2")
 
     @pytest.mark.tool_msys2
     @pytest.mark.tool_mingw64
     def test_mingw64(self):
         """
-        64-bit GCC, binaries for generic Windows (no dependency on MSYS runtime)
+        $ pacman -S mingw-w64-x86_64-cmake
         """
         client = TestClient()
-        # pacman -S mingw-w64-x86_64-gcc
         self._build(client, generator="MinGW Makefiles")
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="mingw64")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="mingw64")
+
+    @pytest.mark.tool_msys2
+    @pytest.mark.tool_msys2_clang64
+    @pytest.mark.skip(reason="This doesn't work, seems CMake issue")
+    def test_msys2_clang64(self):
+        """
+        FAILS WITH:
+        System is unknown to cmake, create:
+        Platform/MINGW64_NT-10.0-19044 to use this system,
+        """
+        client = TestClient()
+        self._build(client, generator="Unix Makefiles")
+        check_exe_run(client.out, "main", "clang", None, "Debug", "x86_64", None,
+                      subsystem="mingw64")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="clang64")
 
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
+    @pytest.mark.tool_msys2
+    @pytest.mark.tool_msys2_clang64
+    @pytest.mark.tool_cmake(version="3.19")
+    def test_msys2_clang64_external(self):
+        """
+        Exactly the same as the previous tests, but with a native cmake 3.19 (higher priority)
+        """
+        client = TestClient()
+        build_out = self._build(client)
+        assert "MYCMAKE VERSION=3.19" in build_out
+        check_exe_run(client.out, "main", "clang", None, "Debug", "x86_64", None,
+                      subsystem="mingw64")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="clang64")
 
-        assert "__MINGW64__" in client.out
-        assert "__CYGWIN__" not in client.out
-        assert "__MSYS__" not in client.out
+    @pytest.mark.tool_msys2
+    @pytest.mark.tool_msys2_mingw64_clang64
+    def test_msys2_mingw64_clang64(self):
+        """
+        """
+        client = TestClient()
+        # IMPORTANT: Need to redefine the CXX, otherwise CMake will use GCC by default
+        with environment_append({"CXX": "clang++"}):
+            self._build(client, generator="MinGW Makefiles")
+        check_exe_run(client.out, "main", "clang", None, "Debug", "x86_64", None,
+                      subsystem="mingw64")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="mingw64")
 
     @pytest.mark.tool_msys2
     @pytest.mark.tool_mingw32
     def test_mingw32(self):
         """
-        32-bit GCC, binaries for generic Windows (no dependency on MSYS runtime)
+        $ pacman -S mingw-w64-i686-cmake
         """
         client = TestClient()
-        # pacman -S mingw-w64-i686-gcc
         self._build(client, generator="MinGW Makefiles")
-
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86", None)
-
-        assert "__MINGW32__" in client.out
-        assert "__CYGWIN__" not in client.out
-        assert "__MSYS__" not in client.out
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86", None, subsystem="mingw32")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="mingw32")
 
     @pytest.mark.tool_cygwin
     def test_cygwin(self):
         """
-        Cygwin environment, binaries depend on Cygwin runtime (cygwin1.dll)
-        posix-compatible, intended to be run only in Cygwin environment (not in pure Windows)
+        Needs to install cmake from the cygwin setup.exe
         """
         client = TestClient()
         # install "gcc-c++" and "make" packages
         self._build(client)
-        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None)
+        check_exe_run(client.out, "main", "gcc", None, "Debug", "x86_64", None, subsystem="cygwin")
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem="cygwin")
+
+    @pytest.mark.tool_clang
+    def test_clang(self):
+        """
+        native, LLVM/Clang compiler
+        Installing the binary from LLVM site
+        https://github.com/llvm/llvm-project/releases/tag/llvmorg-14.0.6
+        """
+        client = TestClient()
+        self._build(client, generator="Ninja", compiler="clang")
+        check_exe_run(client.out, "main", "clang", None, "Debug", "x86_64", None, subsystem=None)
+        check_vs_runtime("app.exe", client, "15", "Debug", subsystem=None)
 
-        assert "__CYGWIN__" in client.out
-        assert "__MINGW32__" not in client.out
-        assert "__MINGW64__" not in client.out
-        assert "__MSYS__" not in client.out
+    @pytest.mark.tool_cmake(version="3.23")
+    @pytest.mark.tool_visual_studio(version="17")
+    def test_vs_clang(self):
+        """
+        native, LLVM/Clang compiler installed with VS 2022 -T ClangCL
+        """
+        # IMPORTANT: VS CLang not found if in another unit
+        folder = tempfile.mkdtemp(suffix='conans')
+        client = TestClient(current_folder=folder)
+        self._build(client, generator="Visual Studio 17 2022", toolset="ClangCL")
+        check_exe_run(client.out, "main", "clang", None, "Debug", "x86_64", None, subsystem=None)
+        check_vs_runtime("Debug/app.exe", client, "15", "Debug", subsystem=None)
diff --git a/conans/test/functional/toolchains/apple/test_xcodedeps_components.py b/conans/test/functional/toolchains/apple/test_xcodedeps_components.py
index 4ccd40f28..d4898bff1 100644
--- a/conans/test/functional/toolchains/apple/test_xcodedeps_components.py
+++ b/conans/test/functional/toolchains/apple/test_xcodedeps_components.py
@@ -9,8 +9,6 @@ from conans.test.utils.tools import TestClient
 
 @pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
 @pytest.mark.tool_cmake
-@pytest.mark.tool_xcodebuild
-@pytest.mark.tool_xcodegen
 def test_xcodedeps_components():
     """
     tcp/1.0 is a lib without components
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
index aa5193d7d..3566bfade 100644
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
@@ -6,8 +6,7 @@ from conans.test.utils.tools import TestClient
 
 
 @pytest.mark.tool_cmake
-@pytest.mark.parametrize("use_components", [False, True])
-def test_build_modules_alias_target(use_components):
+def test_build_modules_alias_target():
     client = TestClient()
     conanfile = textwrap.dedent("""
         import os
@@ -24,21 +23,13 @@ def test_build_modules_alias_target(use_components):
 
             def package_info(self):
                 module = os.path.join("share", "cmake", "target-alias.cmake")
-                {}
+                self.cpp_info.set_property("cmake_build_modules", [module])
         """)
-    if use_components:
-        info = """
-        self.cpp_info.components["comp"].set_property("cmake_build_modules", [module])
-        """
-    else:
-        info = """
-        self.cpp_info.set_property("cmake_build_modules", [module])
-        """
+
     target_alias = textwrap.dedent("""
         add_library(otherhello INTERFACE IMPORTED)
-        target_link_libraries(otherhello INTERFACE {target_name})
-        """).format(target_name="namespace::comp" if use_components else "hello::hello")
-    conanfile = conanfile.format(info)
+        target_link_libraries(otherhello INTERFACE hello::hello)
+        """)
     client.save({"conanfile.py": conanfile, "target-alias.cmake": target_alias})
     client.run("create .")
 
@@ -66,20 +57,13 @@ def test_build_modules_alias_target(use_components):
         """)
     client.save({"conanfile.py": consumer, "CMakeLists.txt": cmakelists})
     client.run("create .")
-    if use_components:
-        assert "otherhello link libraries: namespace::comp" in client.out
-    else:
-        assert "otherhello link libraries: hello::hello" in client.out
+    assert "otherhello link libraries: hello::hello" in client.out
 
 
 @pytest.mark.tool_cmake
-def test_build_modules_components_selection_is_not_possible():
+def test_build_modules_components_is_not_possible():
     """
-    If openssl declares different cmake_build_modules on ssl and crypto, in the consumer both
-    are included even if the cpp_info of the consumer declares:
-        def package_info(self):
-            self.cpp_info.requires = ["openssl::crypto"]
-    Because that information is defined later, not at "generate" time (building time).
+    The "cmake_build_module" property declared in the components is useless
     """
     client = TestClient()
     conanfile = textwrap.dedent("""
@@ -90,15 +74,12 @@ def test_build_modules_components_selection_is_not_possible():
             name = "openssl"
             version = "1.0"
             settings = "os", "arch", "compiler", "build_type"
-            exports_sources = ["ssl.cmake", "crypto.cmake", "root.cmake"]
+            exports_sources = ["crypto.cmake", "root.cmake"]
 
             def package(self):
                 self.copy("*.cmake", dst="share/cmake")
 
             def package_info(self):
-                ssl_module = os.path.join("share", "cmake", "ssl.cmake")
-                self.cpp_info.components["ssl"].set_property("cmake_build_modules", [ssl_module])
-
                 crypto_module = os.path.join("share", "cmake", "crypto.cmake")
                 self.cpp_info.components["crypto"].set_property("cmake_build_modules", [crypto_module])
 
@@ -106,11 +87,6 @@ def test_build_modules_components_selection_is_not_possible():
                 self.cpp_info.set_property("cmake_build_modules", [root_module])
         """)
 
-    ssl_cmake = textwrap.dedent("""
-        function(ssl_message MESSAGE_OUTPUT)
-            message("SSL MESSAGE:${ARGV${0}}")
-        endfunction()
-        """)
     crypto_cmake = textwrap.dedent("""
         function(crypto_message MESSAGE_OUTPUT)
             message("CRYPTO MESSAGE:${ARGV${0}}")
@@ -122,7 +98,6 @@ def test_build_modules_components_selection_is_not_possible():
         endfunction()
         """)
     client.save({"conanfile.py": conanfile,
-                 "ssl.cmake": ssl_cmake,
                  "crypto.cmake": crypto_cmake,
                  "root.cmake": root_cmake})
     client.run("create .")
@@ -151,14 +126,15 @@ def test_build_modules_components_selection_is_not_possible():
             project(test)
             find_package(openssl CONFIG)
             crypto_message("hello!")
-            ssl_message("hello!")
             root_message("hello!")
             """)
     client.save({"conanfile.py": consumer, "CMakeLists.txt": cmakelists})
     # As we are requiring only "crypto" but it doesn't matter, it is not possible to include
     # only crypto build_modules
-    client.run("create .")
-    assert "SSL MESSAGE:hello!" in client.out
-    assert "CRYPTO MESSAGE:hello!" in client.out
-    assert "ROOT MESSAGE:hello!" in client.out
+    client.run("create .", assert_error=True)
+    assert 'Unknown CMake command "crypto_message"' in client.out
+
+    # Comment the function call
+    client.save({"CMakeLists.txt": cmakelists.replace("crypto", "#crypto")})
+    assert "ROOT MESSAGE:hello!" not in client.out
 
diff --git a/conans/test/functional/toolchains/cmake/test_cmake.py b/conans/test/functional/toolchains/cmake/test_cmake.py
index 0c38395fb..e84fc0981 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake.py
@@ -350,7 +350,7 @@ class WinTest(Base):
                        "MYVAR_CONFIG": "MYVAR_{}".format(build_type.upper()),
                        "MYDEFINE": "MYDEF_VALUE",
                        "MYDEFINE_CONFIG": "MYDEF_{}".format(build_type.upper())
-                       })
+                       }, subsystem="mingw64")
 
         self._modify_code()
         time.sleep(2)
diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
index c7101504c..c4b25b272 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
@@ -76,7 +76,8 @@ def test_cmake_toolchain_custom_toolchain():
                     reason="Single config test, Linux CI still without 3.23")
 @pytest.mark.tool_cmake(version="3.23")
 @pytest.mark.parametrize("existing_user_presets", [None, "user_provided", "conan_generated"])
-def test_cmake_user_presets_load(existing_user_presets):
+@pytest.mark.parametrize("schema2", [True, False])
+def test_cmake_user_presets_load(existing_user_presets, schema2):
     """
     Test if the CMakeUserPresets.cmake is generated and use CMake to use it to verify the right
     syntax of generated CMakeUserPresets.cmake and CMakePresets.cmake. If the user already provided
@@ -813,6 +814,48 @@ def test_cmake_presets_multiple_settings_multi_config():
     assert "MSVC_LANG2017" in client.out
 
 
+@pytest.mark.tool_cmake(version="3.23")
+def test_user_presets_version2():
+    client = TestClient(path_with_spaces=False)
+    client.run("new hello/0.1 --template=cmake_exe")
+    configs = ["-c tools.cmake.cmaketoolchain.presets:max_schema_version=2 ",
+               "-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'"]
+    client.run("install . {} -s compiler.cppstd=14".format(" ".join(configs)))
+    client.run("install . {} -s compiler.cppstd=17".format(" ".join(configs)))
+    client.run("install . {} -s compiler.cppstd=20".format(" ".join(configs)))
+
+    if platform.system() == "Windows":
+        client.run_command("cmake . --preset 14")
+        client.run_command("cmake --build --preset 14-release")
+        client.run_command(r"build\14\Release\hello.exe")
+    else:
+        client.run_command("cmake . --preset 14-release")
+        client.run_command("cmake --build --preset 14-release")
+        client.run_command("./build/14/Release/hello")
+
+    assert "Hello World Release!" in client.out
+
+    if platform.system() != "Windows":
+        assert "__cplusplus2014" in client.out
+    else:
+        assert "MSVC_LANG2014" in client.out
+
+    if platform.system() == "Windows":
+        client.run_command("cmake . --preset 17")
+        client.run_command("cmake --build --preset 17-release")
+        client.run_command(r"build\17\Release\hello.exe")
+    else:
+        client.run_command("cmake . --preset 17-release")
+        client.run_command("cmake --build --preset 17-release")
+        client.run_command("./build/17/Release/hello")
+
+    assert "Hello World Release!" in client.out
+    if platform.system() != "Windows":
+        assert "__cplusplus2017" in client.out
+    else:
+        assert "MSVC_LANG2017" in client.out
+
+
 @pytest.mark.tool_cmake
 def test_cmaketoolchain_sysroot():
     client = TestClient(path_with_spaces=False)
@@ -918,3 +961,94 @@ def test_cmake_presets_forbidden_build_type():
     client.run("install . {}".format(settings_layout), assert_error=True)
     assert "Error, don't include 'settings.build_type' in the " \
            "'tools.cmake.cmake_layout:build_folder_vars' conf" in client.out
+
+
+def test_resdirs_cmake_install():
+    """If resdirs is declared, the CMAKE_INSTALL_DATAROOTDIR folder is set"""
+
+    client = TestClient(path_with_spaces=False)
+
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout
+
+            class AppConan(ConanFile):
+                settings = "os", "compiler", "build_type", "arch"
+                exports_sources = "CMakeLists.txt", "my_license"
+                name = "foo"
+                version = "1.0"
+
+                def generate(self):
+                    tc = CMakeToolchain(self)
+                    tc.generate()
+
+                def layout(self):
+                    self.cpp.package.resdirs = ["res"]
+
+                def build(self):
+                    cmake = CMake(self)
+                    cmake.configure()
+                    cmake.build()
+
+                def package(self):
+                    cmake = CMake(self)
+                    cmake.install()
+            """)
+
+    cmake = """
+    cmake_minimum_required(VERSION 3.15)
+    set(CMAKE_CXX_COMPILER_WORKS 1)
+    project(foo)
+    if(NOT CMAKE_INSTALL_DATAROOTDIR)
+        message(FATAL_ERROR "Cannot install stuff")
+    endif()
+    install(FILES my_license DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses)
+    """
+
+    client.save({"conanfile.py": conanfile, "CMakeLists.txt": cmake, "my_license": "MIT"})
+    client.run("create .")
+    assert "/res/licenses/my_license" in client.out
+    assert "Packaged 1 file: my_license" in client.out
+
+
+def test_resdirs_none_cmake_install():
+    """If no resdirs are declared, the CMAKE_INSTALL_DATAROOTDIR folder is not set"""
+
+    client = TestClient(path_with_spaces=False)
+
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout
+
+            class AppConan(ConanFile):
+                settings = "os", "compiler", "build_type", "arch"
+                exports_sources = "CMakeLists.txt", "my_license"
+                name = "foo"
+                version = "1.0"
+
+                def generate(self):
+                    tc = CMakeToolchain(self)
+                    tc.generate()
+
+                def build(self):
+                    cmake = CMake(self)
+                    cmake.configure()
+                    cmake.build()
+
+                def package(self):
+                    cmake = CMake(self)
+                    cmake.install()
+            """)
+
+    cmake = """
+    cmake_minimum_required(VERSION 3.15)
+    set(CMAKE_CXX_COMPILER_WORKS 1)
+    project(foo)
+    if(NOT CMAKE_INSTALL_DATAROOTDIR)
+        message(FATAL_ERROR "Cannot install stuff")
+    endif()
+    """
+
+    client.save({"conanfile.py": conanfile, "CMakeLists.txt": cmake, "my_license": "MIT"})
+    client.run("create .", assert_error=True)
+    assert "Cannot install stuff" in client.out
diff --git a/conans/test/functional/toolchains/cmake/test_ninja.py b/conans/test/functional/toolchains/cmake/test_ninja.py
index fbd7df03f..0a15f7d9e 100644
--- a/conans/test/functional/toolchains/cmake/test_ninja.py
+++ b/conans/test/functional/toolchains/cmake/test_ninja.py
@@ -171,7 +171,8 @@ def test_locally_build_gcc(build_type, shared, client):
 
     client.run_command("myapp.exe")
     # TODO: Need full gcc version check
-    check_exe_run(client.out, ["main", "hello"], "gcc", None, build_type, "x86_64", cppstd=None)
+    check_exe_run(client.out, ["main", "hello"], "gcc", None, build_type, "x86_64", cppstd=None,
+                  subsystem="mingw64")
 
 
 @pytest.mark.skipif(platform.system() != "Darwin", reason="Requires apple-clang")
diff --git a/conans/test/functional/toolchains/gnu/autotools/test_basic.py b/conans/test/functional/toolchains/gnu/autotools/test_basic.py
index 3d4a41f96..b7c507c21 100644
--- a/conans/test/functional/toolchains/gnu/autotools/test_basic.py
+++ b/conans/test/functional/toolchains/gnu/autotools/test_basic.py
@@ -53,11 +53,12 @@ def test_autotools():
     client.run("build .")
     client.run_command("./main")
     cxx11_abi = 0 if platform.system() == "Linux" else None
-    check_exe_run(client.out, "main", "gcc", None, "Release", "x86_64", None, cxx11_abi=cxx11_abi)
+    compiler = "gcc" if platform.system() == "Linux" else "clang"
+    check_exe_run(client.out, "main", compiler, None, "Release", "x86_64", None, cxx11_abi=cxx11_abi)
     assert "hello/0.1: Hello World Release!" in client.out
 
 
-def build_windows_subsystem(profile, make_program):
+def build_windows_subsystem(profile, make_program, subsystem):
     """ The AutotoolsDeps can be used also in pure Makefiles, if the makefiles follow
     the Autotools conventions
     """
@@ -99,7 +100,7 @@ def build_windows_subsystem(profile, make_program):
     client.run_command(cmd)
     client.run_command("app")
     # TODO: fill compiler version when ready
-    check_exe_run(client.out, "main", "gcc", None, "Release", "x86_64", None)
+    check_exe_run(client.out, "main", "gcc", None, "Release", "x86_64", None, subsystem=subsystem)
     assert "hello/0.1: Hello World Release!" in client.out
 
     client.save({"app.cpp": gen_function_cpp(name="main", msg="main2",
@@ -111,7 +112,8 @@ def build_windows_subsystem(profile, make_program):
     client.run("build .")
     client.run_command("app")
     # TODO: fill compiler version when ready
-    check_exe_run(client.out, "main2", "gcc", None, "Release", "x86_64", None, cxx11_abi=0)
+    check_exe_run(client.out, "main2", "gcc", None, "Release", "x86_64", None, cxx11_abi=0,
+                  subsystem=subsystem)
     assert "hello/0.1: Hello World Release!" in client.out
     return client.out
 
@@ -129,10 +131,7 @@ def test_autotoolsdeps_cygwin():
         arch=x86_64
         build_type=Release
         """)
-    out = build_windows_subsystem(gcc, make_program="make")
-    assert "__MSYS__" not in out
-    assert "MINGW" not in out
-    assert "main2 __CYGWIN__1" in out
+    build_windows_subsystem(gcc, make_program="make", subsystem="cygwin")
 
 
 @pytest.mark.tool_mingw64
@@ -147,13 +146,13 @@ def test_autotoolsdeps_mingw_msys():
         arch=x86_64
         build_type=Release
         """)
-    out = build_windows_subsystem(gcc, make_program="mingw32-make")
-    assert "__MSYS__" not in out
-    assert "main2 __MINGW64__1" in out
+    build_windows_subsystem(gcc, make_program="mingw32-make", subsystem="mingw64")
 
 
 @pytest.mark.tool_msys2
 @pytest.mark.skipif(platform.system() != "Windows", reason="Needs windows")
+# If we use the cmake inside msys2, it fails, so better force our own cmake
+@pytest.mark.tool_cmake
 def test_autotoolsdeps_msys():
     gcc = textwrap.dedent("""
         [settings]
@@ -165,11 +164,7 @@ def test_autotoolsdeps_msys():
         arch=x86_64
         build_type=Release
         """)
-    out = build_windows_subsystem(gcc, make_program="make")
-    # Msys2 is a rewrite of Msys, using Cygwin
-    assert "MINGW" not in out
-    assert "main2 __MSYS__1" in out
-    assert "main2 __CYGWIN__1" in out
+    build_windows_subsystem(gcc, make_program="make", subsystem="msys2")
 
 
 @pytest.mark.skipif(platform.system() not in ["Linux", "Darwin"], reason="Requires Autotools")
diff --git a/conans/test/functional/toolchains/meson/test_install.py b/conans/test/functional/toolchains/meson/test_install.py
index b41167146..e61f75adc 100644
--- a/conans/test/functional/toolchains/meson/test_install.py
+++ b/conans/test/functional/toolchains/meson/test_install.py
@@ -30,8 +30,6 @@ class MesonInstall(TestMesonBase):
 
             def generate(self):
                 tc = MesonToolchain(self)
-                # https://mesonbuild.com/Release-notes-for-0-50-0.html#libdir-defaults-to-lib-when-cross-compiling
-                tc.project_options["libdir"] = "lib"
                 tc.generate()
 
             def build(self):
diff --git a/conans/test/functional/toolchains/meson/test_meson.py b/conans/test/functional/toolchains/meson/test_meson.py
index 70818c934..6ee637ad7 100644
--- a/conans/test/functional/toolchains/meson/test_meson.py
+++ b/conans/test/functional/toolchains/meson/test_meson.py
@@ -1,6 +1,8 @@
 import os
+import platform
 import textwrap
 
+from conans.model.ref import ConanFileReference
 from conans.test.assets.sources import gen_function_cpp, gen_function_h
 from conans.test.functional.toolchains.meson._base import TestMesonBase
 
@@ -58,7 +60,7 @@ class MesonToolchainTest(TestMesonBase):
     executable('demo', 'main.cpp', link_with: hello)
     """)
 
-    def test_build(self):
+    def test_definition_of_global_options(self):
         hello_h = gen_function_h(name="hello")
         hello_cpp = gen_function_cpp(name="hello", preprocessor=["STRING_DEFINITION"])
         app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"])
@@ -94,3 +96,74 @@ class MesonToolchainTest(TestMesonBase):
         self.assertNotIn("needs_exe_wrapper", content)
 
         self._check_binary()
+
+    def test_meson_default_dirs(self):
+        self.t.run("new hello/1.0 -m meson_exe")
+        # self.t.run("new meson_exe -d name=hello -d version=1.0 -m meson_exe")
+
+        meson_build = textwrap.dedent("""
+        project('tutorial', 'cpp')
+        # Creating specific library
+        hello = library('hello', 'src/hello.cpp', install: true)
+        # Creating specific executable
+        executable('demo', 'src/main.cpp', link_with: hello, install: true)
+        # Creating specific data in src/ (they're going to be exported)
+        install_data(['src/file1.txt', 'src/file2.txt'])
+        """)
+        conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.meson import Meson
+        class HelloConan(ConanFile):
+            name = "hello"
+            version = "1.0"
+            settings = "os", "compiler", "build_type", "arch"
+            exports_sources = "meson.build", "src/*"
+            generators = "MesonToolchain"
+
+            def layout(self):
+                self.folders.build = "build"
+                # Only adding "res" to resdirs
+                self.cpp.package.resdirs = ["res"]
+
+            def build(self):
+                meson = Meson(self)
+                meson.configure()
+                meson.build()
+
+            def package(self):
+                meson = Meson(self)
+                meson.install()
+        """)
+        test_conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.build import cross_building
+        class HelloTestConan(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            generators = "VirtualRunEnv"
+            apply_env = False
+
+            def test(self):
+                if not cross_building(self):
+                    self.run("demo", env="conanrun")
+        """)
+        # Replace meson.build, conanfile.py and test_package/conanfile.py
+        self.t.save({"meson.build": meson_build,
+                     "conanfile.py": conanfile,
+                     "test_package/conanfile.py": test_conanfile,
+                     "src/file1.txt": "", "src/file2.txt": ""})
+        self.t.run("create .")
+        # Check if all the files are in the final directories
+        ref = ConanFileReference.loads("hello/1.0")
+        cache_package_folder = self.t.cache.package_layout(ref).packages()
+        package_folder = os.path.join(cache_package_folder, os.listdir(cache_package_folder)[0])
+        if platform.system() == "Windows":
+            assert os.path.exists(os.path.join(package_folder, "lib", "hello.lib"))
+            assert os.path.exists(os.path.join(package_folder, "bin", "hello.dll"))
+            assert os.path.exists(os.path.join(package_folder, "bin", "demo.exe"))
+        else:
+            ext = "dylib" if platform.system() == "Darwin" else "so"
+            assert os.path.exists(os.path.join(package_folder, "bin", "demo"))
+            assert os.path.exists(os.path.join(package_folder, "lib", "libhello." + ext))
+        # res/tutorial -> tutorial is being added automatically by Meson
+        assert os.path.exists(os.path.join(package_folder, "res", "tutorial", "file1.txt"))
+        assert os.path.exists(os.path.join(package_folder, "res", "tutorial", "file2.txt"))
diff --git a/conans/test/functional/toolchains/meson/test_meson_and_gnu_deps_flags.py b/conans/test/functional/toolchains/meson/test_meson_and_gnu_deps_flags.py
new file mode 100644
index 000000000..8c3d0c018
--- /dev/null
+++ b/conans/test/functional/toolchains/meson/test_meson_and_gnu_deps_flags.py
@@ -0,0 +1,146 @@
+import os
+import platform
+import textwrap
+
+from conan.tools.files import load
+from conans.test.assets.sources import gen_function_cpp
+from conans.test.functional.toolchains.meson._base import TestMesonBase
+from conans.test.utils.tools import TestClient
+
+
+class TestMesonToolchainAndGnuFlags(TestMesonBase):
+
+    def test_mesondeps(self):
+        client = TestClient(path_with_spaces=False)
+        client.run("new hello/0.1 -s")
+        client.run("create . hello/0.1@ %s" % self._settings_str)
+        app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"])
+
+        conanfile_py = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.meson import Meson
+
+        class App(ConanFile):
+            settings = "os", "arch", "compiler", "build_type"
+            requires = "hello/0.1"
+            generators = "MesonDeps", "MesonToolchain"
+
+            def layout(self):
+                self.folders.build = "build"
+
+            def build(self):
+                meson = Meson(self)
+                meson.configure()
+                meson.build()
+        """)
+
+        meson_build = textwrap.dedent("""
+        project('tutorial', 'cpp')
+        cxx = meson.get_compiler('cpp')
+        hello = cxx.find_library('hello', required: true)
+        executable('demo', 'main.cpp', dependencies: hello)
+        """)
+
+        client.save({"conanfile.py": conanfile_py,
+                     "meson.build": meson_build,
+                     "main.cpp": app},
+                    clean_first=True)
+
+        client.run("install . %s" % self._settings_str)
+        client.run("build .")
+        assert "[2/2] Linking target demo" in client.out
+
+    def test_mesondeps_flags_are_being_appended_and_not_replacing_toolchain_ones(self):
+        """
+        Test MesonDeps and MesonToolchain are keeping all the flags/definitions defined
+        from both generators and nothing is being messed up.
+        """
+        client = TestClient(path_with_spaces=False)
+        if platform.system() == "Windows":
+            deps_flags = '"/GA", "/analyze:quiet"'
+            flags = '"/Wall", "/W4"'
+        else:
+            deps_flags = '"-Wpedantic", "-Werror"'
+            flags = '"-Wall", "-finline-functions"'
+        # Dependency - hello/0.1
+        conanfile_py = textwrap.dedent("""
+        from conan import ConanFile
+
+        class HelloConan(ConanFile):
+            name = "hello"
+            version = "0.1"
+
+            def package_info(self):
+                self.cpp_info.libs = ["hello"]
+                self.cpp_info.cxxflags = [{}]
+                self.cpp_info.defines = ['DEF1=one_string', 'DEF2=other_string']
+        """.format(deps_flags))
+        client.save({"conanfile.py": conanfile_py})
+        client.run("create . %s" % self._settings_str)
+        # Dependency - other/0.1
+        conanfile_py = textwrap.dedent("""
+        from conan import ConanFile
+
+        class OtherConan(ConanFile):
+            name = "other"
+            version = "0.1"
+
+            def package_info(self):
+                self.cpp_info.libs = ["other"]
+                self.cpp_info.defines = ['DEF3=simple_string']
+        """)
+        client.save({"conanfile.py": conanfile_py}, clean_first=True)
+        client.run("create . %s" % self._settings_str)
+
+        # Consumer using MesonDeps and MesonToolchain
+        conanfile_py = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.meson import Meson, MesonDeps, MesonToolchain
+
+        class App(ConanFile):
+            settings = "os", "arch", "compiler", "build_type"
+            requires = "hello/0.1", "other/0.1"
+
+            def layout(self):
+                self.folders.build = "build"
+
+            def generate(self):
+                tc = MesonDeps(self)
+                tc.generate()
+                tc = MesonToolchain(self)
+                tc.preprocessor_definitions["VAR"] = "VALUE"
+                tc.preprocessor_definitions["VAR2"] = "VALUE2"
+                tc.generate()
+
+            def build(self):
+                meson = Meson(self)
+                meson.configure()
+                meson.build()
+        """)
+
+        meson_build = textwrap.dedent("""
+            project('tutorial', 'cpp')
+            cxx = meson.get_compiler('cpp')
+            # It's not needed to declare "hello/0.1" as a dependency, only interested in flags
+            executable('demo', 'main.cpp')
+        """)
+        client.save({"conanfile.py": conanfile_py,
+                     "meson.build": meson_build,
+                     "main.cpp": "int main()\n{return 0;}\n"},
+                    clean_first=True)
+
+        client.run("install . %s -c 'tools.build:cxxflags=[%s]'" % (self._settings_str, flags))
+        client.run("build .")
+        deps_flags = deps_flags.replace('"', "").replace(",", "")
+        flags = flags.replace('"', "").replace(",", "")
+        meson_log_path = os.path.join(client.current_folder, "build", "meson-logs", "meson-log.txt")
+        meson_log = load(None, meson_log_path)
+        meson_log = meson_log.replace("\\", "/")
+        assert "Build Options: " \
+               "'--native-file {folder}/conan_meson_native.ini' " \
+               "'--native-file {folder}/conan_meson_deps_flags.ini'" \
+               "".format(folder=client.current_folder.replace("\\", "/")) in meson_log
+        # Flags/Defines from deps and consumer are appearing in meson-log.txt as part
+        # of the command-line
+        assert '%s -DVAR="VALUE" -DVAR2="VALUE2" %s' % (flags, deps_flags) in meson_log
+        assert '-DDEF3=simple_string -DDEF1=one_string -DDEF2=other_string' in meson_log
diff --git a/conans/test/functional/toolchains/meson/test_meson_and_objc.py b/conans/test/functional/toolchains/meson/test_meson_and_objc.py
new file mode 100644
index 000000000..6f657a87b
--- /dev/null
+++ b/conans/test/functional/toolchains/meson/test_meson_and_objc.py
@@ -0,0 +1,141 @@
+import os
+import platform
+import sys
+import textwrap
+
+import pytest
+
+from conans.client.tools.apple import XCRun, to_apple_arch
+from conans.test.utils.tools import TestClient
+
+_conanfile_py = textwrap.dedent("""
+from conan import ConanFile
+from conan.tools.meson import Meson, MesonToolchain
+
+
+class App(ConanFile):
+    settings = "os", "arch", "compiler", "build_type"
+    options = {"shared": [True, False], "fPIC": [True, False]}
+    default_options = {"shared": False, "fPIC": True}
+
+    def layout(self):
+        self.folders.build = "build"
+
+    def config_options(self):
+        if self.settings.os == "Windows":
+            del self.options.fPIC
+
+    def generate(self):
+        tc = MesonToolchain(self)
+        tc.generate()
+
+    def build(self):
+        meson = Meson(self)
+        meson.configure()
+        meson.build()
+""")
+
+_meson_build_objc = textwrap.dedent("""
+project('tutorial', 'objc')
+executable('demo', 'main.m', link_args: ['-framework', 'Foundation'])
+""")
+
+
+@pytest.mark.tool_meson
+@pytest.mark.skipif(sys.version_info.major == 2, reason="Meson not supported in Py2")
+@pytest.mark.skipif(platform.system() != "Darwin", reason="requires Xcode")
+def test_apple_meson_toolchain_native_compilation_objective_c():
+    profile = textwrap.dedent("""
+    [settings]
+    os = Macos
+    arch = x86_64
+    compiler = apple-clang
+    compiler.version = 12.0
+    compiler.libcxx = libc++
+    """)
+    app = textwrap.dedent("""
+    #import <Foundation/Foundation.h>
+
+    int main(int argc, const char * argv[]) {
+        @autoreleasepool {
+            // insert code here...
+            NSLog(@"Hello, World!");
+        }
+        return 0;
+    }
+    """)
+    t = TestClient()
+    t.save({"conanfile.py": _conanfile_py,
+            "meson.build": _meson_build_objc,
+            "main.m": app,
+            "macos_pr": profile})
+
+    t.run("install . -pr macos_pr")
+    t.run("build .")
+    t.run_command("./demo", cwd=os.path.join(t.current_folder, "build"))
+    assert "Hello, World!" in t.out
+
+
+@pytest.mark.parametrize("arch, os_, os_version, sdk", [
+    ('armv8', 'iOS', '10.0', 'iphoneos'),
+    ('armv7', 'iOS', '10.0', 'iphoneos'),
+    ('x86', 'iOS', '10.0', 'iphonesimulator'),
+    ('x86_64', 'iOS', '10.0', 'iphonesimulator'),
+    ('armv8', 'Macos', None, None)  # MacOS M1
+])
+@pytest.mark.tool_meson
+@pytest.mark.skipif(sys.version_info.major == 2, reason="Meson not supported in Py2")
+@pytest.mark.skipif(platform.system() != "Darwin", reason="requires Xcode")
+def test_apple_meson_toolchain_cross_compiling_and_objective_c(arch, os_, os_version, sdk):
+    profile = textwrap.dedent("""
+    include(default)
+
+    [settings]
+    os = {os}
+    os.version = {os_version}
+    os.sdk = {os_sdk}
+    arch = {arch}
+    compiler = apple-clang
+    compiler.version = 12.0
+    compiler.libcxx = libc++
+
+    [conf]
+    tools.apple:sdk_path={sdk_path}
+    """)
+
+    xcrun = XCRun(None, sdk)
+    sdk_path = xcrun.sdk_path
+    app = textwrap.dedent("""
+    #import <Foundation/Foundation.h>
+
+    int main(int argc, const char * argv[]) {
+        @autoreleasepool {
+            // insert code here...
+            NSLog(@"Hello, World!");
+        }
+        return 0;
+    }
+    """)
+    profile = profile.format(
+        os=os_,
+        os_version=os_version,
+        os_sdk=sdk,
+        arch=arch,
+        sdk_path=sdk_path)
+
+    t = TestClient()
+    t.save({"conanfile.py": _conanfile_py,
+            "meson.build": _meson_build_objc,
+            "main.m": app,
+            "profile_host": profile})
+
+    t.run("install . --profile:build=default --profile:host=profile_host")
+    t.run("build .")
+    assert "Objective-C compiler for the host machine: clang" in t.out
+
+    demo = os.path.join(t.current_folder, "build", "demo")
+    assert os.path.isfile(demo) is True
+
+    lipo = xcrun.find('lipo')
+    t.run_command('"%s" -info "%s"' % (lipo, demo))
+    assert "architecture: %s" % to_apple_arch(arch) in t.out
diff --git a/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py b/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
index 4c78b57d0..e950df38e 100644
--- a/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
+++ b/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
@@ -1004,6 +1004,7 @@ def test_build_requires_transitives():
     c.run("create tool")
     c.run("install consumer -g MSBuildDeps")
     tool = c.load("conan_tool_build_release_x64.props")
-    assert "conan_dep" not in tool
+    assert "conan_dep_build.props" in tool
+    assert "conan_dep.props" not in tool
     tool_vars = c.load("conan_tool_build_vars_release_x64.props")
-    assert "<Conantool_buildDependencies></Conantool_buildDependencies>" in tool_vars
+    assert "<Conantool_buildDependencies>dep_build</Conantool_buildDependencies>" in tool_vars
diff --git a/conans/test/functional/toolchains/microsoft/test_msbuilddeps_components.py b/conans/test/functional/toolchains/microsoft/test_msbuilddeps_components.py
new file mode 100644
index 000000000..ae62297b9
--- /dev/null
+++ b/conans/test/functional/toolchains/microsoft/test_msbuilddeps_components.py
@@ -0,0 +1,172 @@
+import platform
+import textwrap
+
+import pytest
+
+from conans.test.assets.sources import gen_function_cpp
+from conans.test.utils.tools import TestClient
+
+
+@pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows")
+def test_msbuild_deps_components():
+    # TODO: Duplicated from xcodedeps_components
+    client = TestClient()
+
+    client.run("new tcp/1.0 -m=cmake_lib")
+    client.run("create . -tf=None")
+
+    header = textwrap.dedent("""
+        #pragma once
+        void {name}();
+        """)
+
+    source = textwrap.dedent("""
+        #include <iostream>
+        #include "{name}.h"
+        {include}
+
+        void {name}(){{
+            {call}
+            #ifdef NDEBUG
+            std::cout << "{name}/1.0: Hello World Release!" << std::endl;
+            #else
+            std::cout << "{name}/1.0: Hello World Debug!" << std::endl;
+            #endif
+        }}
+        """)
+
+    cmakelists = textwrap.dedent("""
+        cmake_minimum_required(VERSION 3.15)
+        project(myproject CXX)
+
+        find_package(tcp REQUIRED CONFIG)
+
+        add_library(core src/core.cpp include/core.h)
+        add_library(client src/client.cpp include/client.h)
+        add_library(server src/server.cpp include/server.h)
+
+        target_include_directories(core PUBLIC include)
+        target_include_directories(client PUBLIC include)
+        target_include_directories(server PUBLIC include)
+
+        set_target_properties(core PROPERTIES PUBLIC_HEADER "include/core.h")
+        set_target_properties(client PROPERTIES PUBLIC_HEADER "include/client.h")
+        set_target_properties(server PROPERTIES PUBLIC_HEADER "include/server.h")
+
+        target_link_libraries(client core tcp::tcp)
+        target_link_libraries(server core tcp::tcp)
+
+        install(TARGETS core client server)
+        """)
+
+    conanfile_py = textwrap.dedent("""
+        import os
+
+        from conan import ConanFile
+        from conan.tools.cmake import CMake, cmake_layout
+
+
+        class LibConan(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            exports_sources = "CMakeLists.txt", "src/*", "include/*"
+            {requires}
+            generators = "CMakeToolchain", "CMakeDeps"
+
+            def layout(self):
+                cmake_layout(self)
+
+            def build(self):
+                cmake = CMake(self)
+                cmake.configure()
+                cmake.build()
+
+            def package(self):
+                cmake = CMake(self)
+                cmake.install()
+            {package_info}
+        """)
+
+    network_pi = """
+    def package_info(self):
+        self.cpp_info.components["core"].libs = ["core"]
+        self.cpp_info.components["core"].includedirs.append("include")
+        self.cpp_info.components["core"].libdirs.append("lib")
+
+        self.cpp_info.components["client"].libs = ["client"]
+        self.cpp_info.components["client"].includedirs.append("include")
+        self.cpp_info.components["client"].libdirs.append("lib")
+        self.cpp_info.components["client"].requires.extend(["core", "tcp::tcp"])
+
+        self.cpp_info.components["server"].libs = ["server"]
+        self.cpp_info.components["server"].includedirs.append("include")
+        self.cpp_info.components["server"].libdirs.append("lib")
+        self.cpp_info.components["server"].requires.extend(["core", "tcp::tcp"])
+    """
+
+    client.save({
+        "include/core.h": header.format(name="core"),
+        "include/server.h": header.format(name="server"),
+        "include/client.h": header.format(name="client"),
+        "src/core.cpp": source.format(name="core", include="", call=""),
+        "src/server.cpp": source.format(name="server",
+                                        include='#include "core.h"\n#include "tcp.h"',
+                                        call="core(); tcp();"),
+        "src/client.cpp": source.format(name="client", include='#include "core.h"\n#include "tcp.h"',
+                                        call="core(); tcp();"),
+        "conanfile.py": conanfile_py.format(requires='requires= "tcp/1.0"', package_info=network_pi),
+        "CMakeLists.txt": cmakelists,
+    }, clean_first=True)
+
+    client.run("create . network/1.0@")
+
+    chat_pi = """
+    def package_info(self):
+        self.cpp_info.libs = ["chat"]
+        self.cpp_info.includedirs.append("include")
+        self.cpp_info.libdirs.append("lib")
+        self.cpp_info.requires.append("network::client")
+    """
+
+    cmakelists_chat = textwrap.dedent("""
+        cmake_minimum_required(VERSION 3.15)
+        project(chat CXX)
+        find_package(network REQUIRED CONFIG)
+        add_library(chat src/chat.cpp include/chat.h)
+        target_include_directories(chat PUBLIC include)
+        set_target_properties(chat PROPERTIES PUBLIC_HEADER "include/chat.h")
+        target_link_libraries(chat network::client)
+        install(TARGETS chat)
+        """)
+
+    client.save({
+        "include/chat.h": header.format(name="chat"),
+        "src/chat.cpp": source.format(name="chat", include='#include "client.h"', call="client();"),
+        "conanfile.py": conanfile_py.format(requires='requires= "network/1.0"',
+                                            package_info=chat_pi),
+        "CMakeLists.txt": cmakelists_chat,
+    }, clean_first=True)
+
+    client.run("create . chat/1.0@")
+
+    client.run("new greet/0.1 --template=msbuild_exe")
+    conanfile = client.load("conanfile.py").replace("settings = ",
+                                                    'requires="chat/1.0"\n'
+                                                    '    generators = "MSBuildDeps"\n'
+                                                    '    settings = ')
+    vcproj = client.load("greet.vcxproj")
+    vcproj2 = vcproj.replace(r'<Import Project="conan\\conantoolchain.props" />',
+                             r"""<Import Project="conan\\conantoolchain.props" />
+                               <Import Project="conan\\conandeps.props" />
+                             """)
+    assert vcproj2 != vcproj
+    client.save({"conanfile.py": conanfile,
+                 "src/greet.cpp": gen_function_cpp(name="main", includes=["chat"],
+                                                   calls=["chat"]),
+                 "greet.vcxproj": vcproj2})
+    client.run("create .")
+    assert "main: Release!" in client.out
+    assert "core/1.0: Hello World Release!" in client.out
+    assert "tcp/1.0: Hello World Release!" in client.out
+    assert "client/1.0: Hello World Release!" in client.out
+    assert "chat/1.0: Hello World Release!" in client.out
+    assert "server/1.0" not in client.out
diff --git a/conans/test/functional/utils.py b/conans/test/functional/utils.py
index 9fe753eab..b4d121735 100644
--- a/conans/test/functional/utils.py
+++ b/conans/test/functional/utils.py
@@ -2,18 +2,64 @@ from conan.tools.microsoft.visual import vcvars_command
 
 
 def check_vs_runtime(artifact, client, vs_version, build_type, architecture="amd64",
-                     static_runtime=False):
+                     static_runtime=False, subsystem=None):
     vcvars = vcvars_command(version=vs_version, architecture=architecture)
     normalized_path = artifact.replace("/", "\\")
     static = artifact.endswith(".a") or artifact.endswith(".lib")
     if not static:
         cmd = ('%s && dumpbin /nologo /dependents "%s"' % (vcvars, normalized_path))
         client.run_command(cmd)
-        if static_runtime:
+        if subsystem:
+            assert "KERNEL32.dll" in client.out
+            if subsystem in ("mingw32", "mingw64"):
+                assert "msvcrt.dll" in client.out
+                if static_runtime:
+                    assert "libstdc++-6.dll" not in client.out
+                else:
+                    assert "libstdc++-6.dll" in client.out
+                if subsystem == "mingw32":
+                    if static_runtime:
+                        assert "libgcc_s_dw2-1.dll" not in client.out
+                    else:
+                        assert "libgcc_s_dw2-1.dll" in client.out
+            elif subsystem == "msys2":
+                assert "msys-2.0.dll" in client.out
+                if static_runtime:
+                    assert "msys-stdc++-6.dll" not in client.out
+                else:
+                    assert "msys-stdc++-6.dll" in client.out
+            elif subsystem == "cygwin":
+                assert "cygwin1.dll" in client.out
+                if static_runtime:
+                    assert "cygstdc++-6.dll" not in client.out
+                else:
+                    assert "cygstdc++-6.dll" in client.out
+            elif subsystem == "ucrt64":
+                assert "api-ms-win-crt-" in client.out
+                if static_runtime:
+                    assert "libstdc++-6.dll" not in client.out
+                else:
+                    assert "libstdc++-6.dll" in client.out
+            elif subsystem == "clang64":
+                assert "api-ms-win-crt-" in client.out
+                if static_runtime:
+                    assert "libunwind.dll" not in client.out
+                    assert "libc++.dll" not in client.out
+                else:
+                    assert "libunwind.dll" in client.out
+                    assert "libc++.dll" in client.out
+            else:
+                raise Exception("unknown {}".format(subsystem))
+        elif static_runtime:
             assert "KERNEL32.dll" in client.out
             assert "MSVC" not in client.out
             assert "VCRUNTIME" not in client.out
         else:
+            assert "KERNEL32.dll" in client.out
+            if build_type == "Debug":
+                assert "ucrtbased" in client.out
+            else:
+                assert "api-ms-win-crt-" in client.out
             if vs_version in ["15", "16", "17"]:  # UCRT
                 debug = "D" if build_type == "Debug" else ""
                 assert "MSVCP140{}.dll".format(debug) in client.out
@@ -29,7 +75,7 @@ def check_vs_runtime(artifact, client, vs_version, build_type, architecture="amd
 
 
 def check_exe_run(output, names, compiler, version, build_type, arch, cppstd, definitions=None,
-                  cxx11_abi=None):
+                  cxx11_abi=None, subsystem=None):
     output = str(output)
     names = names if isinstance(names, list) else [names]
 
@@ -51,12 +97,13 @@ def check_exe_run(output, names, compiler, version, build_type, arch, cppstd, de
         elif compiler in ["gcc", "clang", "apple-clang"]:
             if compiler == "gcc":
                 assert "{} __GNUC__".format(name) in output
+                assert "clang" not in output
                 if version:  # FIXME: At the moment, the GCC version is not controlled, will change
                     major, minor = version.split(".")[0:2]
                     assert "{} __GNUC__{}".format(name, major) in output
                     assert "{} __GNUC_MINOR__{}".format(name, minor) in output
             elif compiler == "clang":
-                assert "{} __clang__".format(name) in output
+                assert "{} __clang_".format(name) in output
                 if version:
                     major, minor = version.split(".")[0:2]
                     assert "{} __clang_major__{}".format(name, major) in output
@@ -88,3 +135,28 @@ def check_exe_run(output, names, compiler, version, build_type, arch, cppstd, de
         if definitions:
             for k, v in definitions.items():
                 assert "{}: {}".format(k, v) in output
+
+        if subsystem:
+            if subsystem == "msys2":
+                assert "__MSYS__" in output
+                assert "__CYGWIN__" in output
+                assert "MINGW" not in output
+            elif subsystem in ("mingw32", "mingw64"):
+                assert "__MINGW32__" in output
+                assert "__CYGWIN__" not in output
+                assert "__MSYS__" not in output
+                if subsystem == "mingw64":
+                    assert "__MINGW64__" in output
+                else:
+                    assert "MING64" not in output
+            elif subsystem == "cygwin":
+                assert "__CYGWIN__" in output
+                assert "__MINGW32__" not in output
+                assert "__MINGW64__" not in output
+                assert "__MSYS__" not in output
+            else:
+                raise Exception("unknown subsystem {}".format(subsystem))
+        else:
+            assert "CYGWIN" not in output
+            assert "MINGW" not in output
+            assert "MSYS" not in output
diff --git a/conans/test/integration/conanfile/folders_access_test.py b/conans/test/integration/conanfile/folders_access_test.py
index 3a6a635f8..741643aa6 100644
--- a/conans/test/integration/conanfile/folders_access_test.py
+++ b/conans/test/integration/conanfile/folders_access_test.py
@@ -22,6 +22,7 @@ class parentLib(ConanFile):
 
 conanfile = """
 import os
+from pathlib import Path
 from conans import ConanFile
 
 class AConan(ConanFile):
@@ -45,6 +46,8 @@ class AConan(ConanFile):
 
     def source(self):
         assert(self.source_folder == os.getcwd())
+        assert(isinstance(self.source_path, Path))
+        assert(str(self.source_path) == self.source_folder)
         self.assert_in_local_cache()
 
         # Prevented to use them, it's dangerous, because the source is run only for the first
@@ -65,6 +68,8 @@ class AConan(ConanFile):
 
     def build(self):
         assert(self.build_folder == os.getcwd())
+        assert(isinstance(self.build_path, Path))
+        assert(str(self.build_path) == self.build_folder)
 
         self.assert_in_local_cache()
         self.assert_deps_infos()
@@ -77,11 +82,15 @@ class AConan(ConanFile):
             self.install_folder
 
         assert(self.package_folder is not None)
+        assert(isinstance(self.package_path, Path))
+        assert(str(self.package_path) == self.package_folder)
         self.copy_build_folder = self.build_folder
 
     def package(self):
         assert(self.install_folder is not None)
         assert(self.build_folder == os.getcwd())
+        assert(isinstance(self.build_path, Path))
+        assert(str(self.build_path) == self.build_folder)
         self.assert_in_local_cache()
         self.assert_deps_infos()
 
@@ -97,6 +106,8 @@ class AConan(ConanFile):
 
     def package_info(self):
         assert(self.package_folder == os.getcwd())
+        assert(isinstance(self.package_path, Path))
+        assert(str(self.package_path) == self.package_folder)
         assert(self.in_local_cache == True)
 
         assert(self.source_folder is None)
diff --git a/conans/test/integration/graph/test_validate_build.py b/conans/test/integration/graph/test_validate_build.py
new file mode 100644
index 000000000..65ab33011
--- /dev/null
+++ b/conans/test/integration/graph/test_validate_build.py
@@ -0,0 +1,83 @@
+import json
+import textwrap
+
+from conans.test.assets.genconanfile import GenConanfile
+from conans.test.utils.tools import TestClient
+
+
+def test_basic_validate_build_test():
+
+    t = TestClient()
+    conanfile = textwrap.dedent("""
+    from conan import ConanFile
+    from conans.errors import ConanInvalidConfiguration
+
+    class myConan(ConanFile):
+        name = "foo"
+        version = "1.0"
+        settings = "os", "arch", "compiler"
+
+        def validate_build(self):
+            if self.settings.compiler == "gcc":
+                raise ConanInvalidConfiguration("This doesn't build in GCC")
+
+        def package_id(self):
+            del self.info.settings.compiler
+    """)
+
+    settings_gcc = "-s compiler=gcc -s compiler.libcxx=libstdc++11 -s compiler.version=11"
+    settings_clang = "-s compiler=clang -s compiler.libcxx=libc++ -s compiler.version=8"
+
+    t.save({"conanfile.py": conanfile})
+    t.run(f"create . {settings_gcc}", assert_error=True)
+
+    assert "foo/1.0: Cannot build for this configuration: This doesn't build in GCC" in t.out
+
+    t.run(f"create . {settings_clang}")
+
+    # Now with GCC again, but now we have the binary, we don't need to build, so it doesn't fail
+    t.run(f"create . {settings_gcc} --build missing")
+    assert "foo/1.0: Already installed!" in t.out
+
+    # But if I force the build... it will fail
+    t.run(f"create . {settings_gcc} ", assert_error=True)
+    assert "foo/1.0: Cannot build for this configuration: This doesn't build in GCC" in t.out
+
+    # What happens with a conan info?
+    t.run(f"info foo/1.0@ {settings_gcc} --json=myjson")
+    myjson = json.loads(t.load("myjson"))
+    assert myjson[0]["invalid_build"] is True
+    assert myjson[0]["invalid_build_reason"] == "This doesn't build in GCC"
+
+    t.run(f"info foo/1.0@ {settings_clang} --json=myjson")
+    myjson = json.loads(t.load("myjson"))
+    assert myjson[0]["invalid_build"] is False
+    assert "invalid_build_reason" not in myjson[0]
+
+
+def test_with_options_validate_build_test():
+    t = TestClient()
+    conanfile = textwrap.dedent("""
+    from conan import ConanFile
+    from conans.errors import ConanInvalidConfiguration
+
+    class myConan(ConanFile):
+        name = "foo"
+        version = "1.0"
+        options = {"my_option": [True, False]}
+        default_options = {"my_option": True}
+
+        def validate_build(self):
+            if not self.options.my_option:
+                raise ConanInvalidConfiguration("This doesn't build with False option")
+
+    """)
+    t.save({"conanfile.py": conanfile})
+    t.run("export .")
+    consumer = GenConanfile().with_require("foo/1.0").with_name("consumer").with_version("1.0")
+    t.save({"consumer.py": consumer})
+    t.run("create consumer.py --build missing -o foo/*:my_option=False", assert_error=True)
+    assert "foo/1.0: Cannot build for this configuration: This doesn't build " \
+           "with False option" in t.out
+
+    t.run("create consumer.py --build missing -o foo/*:my_option=True")
diff --git a/conans/test/integration/layout/__init__.py b/conans/test/integration/layout/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/conans/test/integration/py_requires/python_requires_test.py b/conans/test/integration/py_requires/python_requires_test.py
index be3aa71db..c2d5bab40 100644
--- a/conans/test/integration/py_requires/python_requires_test.py
+++ b/conans/test/integration/py_requires/python_requires_test.py
@@ -969,3 +969,54 @@ def test_transitive_diamond_python_requires():
            client.out
     assert "consumer/1.0@user/channel: Calling package()\nconsumer/1.0@user/channel: 222, 234" in \
            client.out
+
+
+def test_multiple_reuse():
+    """ test how to enable the multiple code reuse for custom user generators
+        # https://github.com/conan-io/conan/issues/11589
+    """
+
+    c = TestClient()
+    common = textwrap.dedent("""
+        from conan import ConanFile
+        def mycommon():
+            return 42
+        class Common(ConanFile):
+            name = "common"
+            version = "0.1"
+        """)
+    tool = textwrap.dedent("""
+        from conan import ConanFile
+
+        class MyGenerator:
+            common = None
+            def __init__(self, conanfile):
+                self.conanfile = conanfile
+            def generate(self):
+                self.conanfile.output.info("VALUE TOOL: {}!!!".format(MyGenerator.common.mycommon()))
+
+        class Tool(ConanFile):
+            name = "tool"
+            version = "0.1"
+            python_requires = "common/0.1"
+            def init(self):
+                MyGenerator.common = self.python_requires["common"].module
+        """)
+    consumer = textwrap.dedent("""
+        from conan import ConanFile
+        class Consumer(ConanFile):
+            python_requires = "tool/0.1", "common/0.1"
+            def generate(self):
+                mycommon = self.python_requires["common"].module.mycommon
+                self.output.info("VALUE COMMON: {}!!!".format(mycommon()))
+                mygenerator = self.python_requires["tool"].module.MyGenerator(self)
+                mygenerator.generate()
+        """)
+    c.save({"common/conanfile.py": common,
+            "tool/conanfile.py": tool,
+            "consumer/conanfile.py": consumer})
+    c.run("export common")
+    c.run("export tool")
+    c.run("install consumer")
+    assert "VALUE COMMON: 42!!!" in c.out
+    assert "VALUE TOOL: 42!!!" in c.out
diff --git a/conans/test/integration/toolchains/apple/test_xcodedeps.py b/conans/test/integration/toolchains/apple/test_xcodedeps.py
index 1a5ddb5f4..3467b7da2 100644
--- a/conans/test/integration/toolchains/apple/test_xcodedeps.py
+++ b/conans/test/integration/toolchains/apple/test_xcodedeps.py
@@ -1,5 +1,6 @@
 import os
 import platform
+import textwrap
 
 import pytest
 
@@ -85,3 +86,197 @@ def test_generator_files():
         assert '#include "conandeps.xcconfig"' in conan_config
 
         check_contents(client, ["hello", "goodbye"], build_type, "x86_64", "macosx", "12.1")
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+def test_xcodedeps_aggregate_components():
+    client = TestClient()
+
+    conanfile_py = textwrap.dedent("""
+        from conan import ConanFile
+        class LibConan(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            def package_info(self):
+                self.cpp_info.includedirs = ["liba_include"]
+        """)
+
+    client.save({"conanfile.py": conanfile_py})
+
+    client.run("create . liba/1.0@")
+
+    r""""
+        1   a
+       / \ /
+      2   3
+       \ /
+        4   5  6
+        |   |  /
+         \ / /
+           7
+    """
+
+    conanfile_py = textwrap.dedent("""
+        from conan import ConanFile
+        class LibConan(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            requires = "liba/1.0"
+            def package_info(self):
+                self.cpp_info.components["libb_comp1"].includedirs = ["libb_comp1"]
+                self.cpp_info.components["libb_comp1"].libdirs = ["mylibdir"]
+                self.cpp_info.components["libb_comp2"].includedirs = ["libb_comp2"]
+                self.cpp_info.components["libb_comp2"].libdirs = ["mylibdir"]
+                self.cpp_info.components["libb_comp2"].requires = ["libb_comp1"]
+                self.cpp_info.components["libb_comp3"].includedirs = ["libb_comp3"]
+                self.cpp_info.components["libb_comp3"].libdirs = ["mylibdir"]
+                self.cpp_info.components["libb_comp3"].requires = ["libb_comp1", "liba::liba"]
+                self.cpp_info.components["libb_comp4"].includedirs = ["libb_comp4"]
+                self.cpp_info.components["libb_comp4"].libdirs = ["mylibdir"]
+                self.cpp_info.components["libb_comp4"].requires = ["libb_comp2", "libb_comp3"]
+                self.cpp_info.components["libb_comp5"].includedirs = ["libb_comp5"]
+                self.cpp_info.components["libb_comp5"].libdirs = ["mylibdir"]
+                self.cpp_info.components["libb_comp6"].includedirs = ["libb_comp6"]
+                self.cpp_info.components["libb_comp6"].libdirs = ["mylibdir"]
+                self.cpp_info.components["libb_comp7"].includedirs = ["libb_comp7"]
+                self.cpp_info.components["libb_comp7"].libdirs = ["mylibdir"]
+                self.cpp_info.components["libb_comp7"].requires = ["libb_comp4", "libb_comp5", "libb_comp6"]
+        """)
+
+    client.save({"conanfile.py": conanfile_py})
+
+    client.run("create . libb/1.0@")
+
+    client.run("install libb/1.0@ -g XcodeDeps")
+
+    lib_entry = client.load("conan_libb.xcconfig")
+
+    for index in range(1, 8):
+        assert f"conan_libb_libb_comp{index}.xcconfig" in lib_entry
+
+    component7_entry = client.load("conan_libb_libb_comp7.xcconfig")
+    assert '#include "conan_liba_liba.xcconfig"' in component7_entry
+
+    component7_vars = client.load("conan_libb_libb_comp7_release_x86_64.xcconfig")
+
+    # all of the transitive required components and the component itself are added
+    for index in range(1, 8):
+        assert f"libb_comp{index}" in component7_vars
+
+    assert "mylibdir" in component7_vars
+
+    component4_vars = client.load("conan_libb_libb_comp4_release_x86_64.xcconfig")
+
+    # all of the transitive required components and the component itself are added
+    for index in range(1, 5):
+        assert f"libb_comp{index}" in component4_vars
+
+    for index in range(5, 8):
+        assert f"libb_comp{index}" not in component4_vars
+
+    # folders are aggregated
+    assert "mylibdir" in component4_vars
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+def test_xcodedeps_frameworkdirs():
+    client = TestClient()
+
+    conanfile_py = textwrap.dedent("""
+        from conan import ConanFile
+        class LibConan(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            def package_info(self):
+                self.cpp_info.frameworkdirs = ["lib_a_frameworkdir"]
+        """)
+
+    client.save({"conanfile.py": conanfile_py})
+    client.run("create conanfile.py lib_a/1.0@")
+
+    client.run("install lib_a/1.0@ -g XcodeDeps")
+
+    lib_a_xcconfig = client.load("conan_lib_a_lib_a_release_x86_64.xcconfig")
+
+    assert "lib_a_frameworkdir" in lib_a_xcconfig
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+def test_xcodedeps_cppinfo_requires():
+
+    """
+    lib_a: has four components cmp1, cmp2, cmp3, cmp4
+    lib_b --> uses libA cmp1 so cpp_info.requires = ["lib_a::cmp1"]
+    lib_c --> uses libA cmp2 so cpp_info.requires = ["lib_a::cmp2"]
+    consumer --> libB, libC
+    """
+    client = TestClient()
+    lib_a = textwrap.dedent("""
+        from conan import ConanFile
+        class lib_aConan(ConanFile):
+            name = "lib_a"
+            version = "1.0"
+            settings = "os", "compiler", "build_type", "arch"
+            def package_info(self):
+                self.cpp_info.components["cmp1"].includedirs = ["include"]
+                self.cpp_info.components["cmp2"].includedirs = ["include"]
+                self.cpp_info.components["cmp3"].includedirs = ["include"]
+                self.cpp_info.components["cmp4"].includedirs = ["include"]
+        """)
+
+    lib = textwrap.dedent("""
+        from conan import ConanFile
+        class lib_{name}Conan(ConanFile):
+            name = "lib_{name}"
+            version = "1.0"
+            settings = "os", "compiler", "build_type", "arch"
+            def requirements(self):
+                self.requires("lib_a/1.0")
+            def package_info(self):
+                self.cpp_info.requires = {cppinfo_comps}
+        """)
+
+    consumer = textwrap.dedent("""
+    from conan import ConanFile
+    class ConsumerConan(ConanFile):
+        name = "consumer"
+        version = "1.0"
+        settings = "os", "compiler", "build_type", "arch"
+        generators = "XcodeDeps"
+        def requirements(self):
+            self.requires("lib_b/1.0")
+            self.requires("lib_c/1.0")
+    """)
+
+    client.save({
+        'lib_a/conanfile.py': lib_a,
+        'lib_b/conanfile.py': lib.format(name="b", cppinfo_comps='["lib_a::cmp1"]'),
+        'lib_c/conanfile.py': lib.format(name="c", cppinfo_comps='["lib_a::cmp2"]'),
+        'consumer/conanfile.py': consumer,
+    })
+
+    client.run("create lib_a")
+
+    client.run("create lib_b")
+
+    client.run("create lib_c")
+
+    client.run("install consumer")
+
+    """
+    Check that the generated lib_b and lib_c xcconfig only use the cmp1 and cmp2 components
+    So we will only link against the components specified in the cpp_info.requires of lib_b and lib_c
+    """
+
+    lib_b = client.load("conan_lib_b_lib_b.xcconfig")
+
+    # check that nothing from other components than the specified in the cpp_info.requires
+    # from lib_b and lib_c exist in the xcconfig that adds the includes from components
+    assert "cmp1" in lib_b
+    assert "cmp2" not in lib_b
+    assert "cmp3" not in lib_b
+    assert "cmp4" not in lib_b
+
+    lib_c = client.load("conan_lib_c_lib_c.xcconfig")
+
+    assert "cmp1" not in lib_c
+    assert "cmp2" in lib_c
+    assert "cmp3" not in lib_c
+    assert "cmp4" not in lib_c
diff --git a/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py b/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py
index bd1aa44a1..a94672945 100644
--- a/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py
+++ b/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py
@@ -107,15 +107,22 @@ def test_cpp_info_component_objects():
         assert """set_property(TARGET hello::say PROPERTY INTERFACE_LINK_LIBRARIES
              $<$<CONFIG:Release>:${hello_hello_say_OBJECTS_RELEASE}
              ${hello_hello_say_LINK_LIBS_RELEASE}> APPEND)""" in content
+        # If there are componets, there is not a global cpp so this is not generated
         assert """set_property(TARGET hello::hello
              PROPERTY INTERFACE_LINK_LIBRARIES
              $<$<CONFIG:Release>:${hello_OBJECTS_RELEASE}
-             ${hello_LIBRARIES_TARGETS_RELEASE}> APPEND)""" in content
+             ${hello_LIBRARIES_TARGETS_RELEASE}> APPEND)""" not in content
+        # But the global target is linked with the targets from the components
+        assert "target_link_libraries(hello::hello INTERFACE hello::say)" in content
 
     with open(os.path.join(client.current_folder, "hello-release-x86_64-data.cmake")) as f:
         content = f.read()
-        assert 'set(hello_OBJECTS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/mycomponent.o")' in content
-        assert 'set(hello_hello_say_OBJECTS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/mycomponent.o")' in content
+        # Not global variables
+        assert 'set(hello_OBJECTS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/mycomponent.o")' \
+               not in content
+        # But component variables
+        assert 'set(hello_hello_say_OBJECTS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/' \
+               'mycomponent.o")' in content
 
 
 def test_cpp_info_component_error_aggregate():
diff --git a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
index 967329a5d..1bb64565e 100644
--- a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
+++ b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
@@ -9,6 +9,7 @@ from mock import mock
 from conan.tools.cmake.presets import load_cmake_presets
 from conans.test.assets.genconanfile import GenConanfile
 from conans.test.utils.tools import TestClient
+from conans.util.files import rmdir
 
 
 def test_cross_build():
@@ -384,7 +385,8 @@ def test_cmake_presets_multiconfig():
     assert presets["buildPresets"][0]["configuration"] == "Release"
     assert presets["buildPresets"][1]["configuration"] == "Debug"
 
-    client.run("install mylib/1.0@ -g CMakeToolchain -s build_type=RelWithDebInfo --profile:h=profile")
+    client.run("install mylib/1.0@ -g CMakeToolchain -s build_type=RelWithDebInfo "
+               "--profile:h=profile")
     client.run("install mylib/1.0@ -g CMakeToolchain -s build_type=MinSizeRel --profile:h=profile")
     presets = json.loads(client.load("CMakePresets.json"))
     assert len(presets["buildPresets"]) == 4
@@ -473,3 +475,215 @@ def test_toolchain_cache_variables():
     assert cache_variables["CMAKE_SH"] == "THIS VALUE HAS PRIORITY"
     assert cache_variables["CMAKE_POLICY_DEFAULT_CMP0091"] == "THIS VALUE HAS PRIORITY"
     assert cache_variables["CMAKE_MAKE_PROGRAM"] == "MyMake"
+
+
+def test_android_c_library():
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+
+        class Conan(ConanFile):
+            settings = "os", "arch", "compiler", "build_type"
+            generators = "CMakeToolchain"
+
+            def configure(self):
+                del self.settings.compiler.libcxx
+
+        """)
+    client.save({"conanfile.py": conanfile})
+    client.run("create . foo/1.0@ -s os=Android -s os.api_level=23 -c tools.android:ndk_path=/foo")
+
+
+def test_user_presets_version2():
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+                from conan import ConanFile
+                from conan.tools.cmake import cmake_layout
+
+                class Conan(ConanFile):
+                    name = "foo"
+                    version = "1.0"
+                    settings = "os", "arch", "compiler", "build_type"
+                    generators = "CMakeToolchain"
+
+                    def layout(self):
+                        cmake_layout(self)
+
+            """)
+    client.save({"conanfile.py": conanfile, "CMakeLists.txt": "foo"})
+    configs = ["-c tools.cmake.cmaketoolchain.presets:max_schema_version=2 ",
+               "-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'"]
+    client.run("install . {} -s compiler.cppstd=14".format(" ".join(configs)))
+    client.run("install . {} -s compiler.cppstd=17".format(" ".join(configs)))
+
+    presets = json.loads(client.load("CMakeUserPresets.json"))
+    assert len(presets["configurePresets"]) == 2
+    assert presets["version"] == 2
+    assert "build/14/generators/conan_toolchain.cmake" \
+           in presets["configurePresets"][0]["cacheVariables"]["CMAKE_TOOLCHAIN_FILE"].replace("\\",
+                                                                                               "/")
+    assert "build/17/generators/conan_toolchain.cmake" \
+           in presets["configurePresets"][1]["cacheVariables"]["CMAKE_TOOLCHAIN_FILE"].replace("\\",
+                                                                                               "/")
+
+
+def test_user_presets_version2_no_overwrite_user():
+
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.cmake import cmake_layout
+
+            class Conan(ConanFile):
+                name = "foo"
+                version = "1.0"
+                settings = "os", "arch", "compiler", "build_type"
+                generators = "CMakeToolchain"
+
+                def layout(self):
+                    cmake_layout(self)
+
+            """)
+    client.save({"conanfile.py": conanfile, "CMakeLists.txt": "foo",
+                 "CMakeUserPresets.json": '{"from_user": 1}'})
+    configs = ["-c tools.cmake.cmaketoolchain.presets:max_schema_version=2 ",
+               "-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'"]
+    client.run("install . {} -s compiler.cppstd=14".format(" ".join(configs)))
+
+    presets = json.loads(client.load("CMakeUserPresets.json"))
+    assert presets == {"from_user": 1}
+
+
+@pytest.mark.skipif(platform.system() != "Windows", reason="Only Windows")
+def test_presets_paths_correct():
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.cmake import cmake_layout
+
+            class Conan(ConanFile):
+                settings = "os", "arch", "compiler", "build_type"
+                generators = "CMakeToolchain"
+
+                def layout(self):
+                    cmake_layout(self)
+            """)
+    client.save({"conanfile.py": conanfile, "CMakeLists.txt": "foo"})
+    configs = ["-c tools.cmake.cmaketoolchain.presets:max_schema_version=2 ",
+               "-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'"]
+    client.run("install . {} -s compiler.cppstd=14".format(" ".join(configs)))
+    client.run("install . {} -s compiler.cppstd=17".format(" ".join(configs)))
+
+    presets = json.loads(client.load("CMakeUserPresets.json"))
+    assert len(presets["configurePresets"]) == 2
+    assert presets["version"] == 2
+    assert "build/14/generators/conan_toolchain.cmake" \
+           in presets["configurePresets"][0]["cacheVariables"]["CMAKE_TOOLCHAIN_FILE"].replace("\\",
+                                                                                               "/")
+    assert "build/17/generators/conan_toolchain.cmake" \
+           in presets["configurePresets"][1]["cacheVariables"]["CMAKE_TOOLCHAIN_FILE"].replace("\\",
+                                                                                               "/")
+
+
+def test_presets_updated():
+    """If a preset file is generated more than once, the values are always added and, in case the
+    configurePreset or buildPreset already exist, the new preset is updated """
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.cmake import cmake_layout
+
+            class Conan(ConanFile):
+                settings = "os", "arch", "compiler", "build_type"
+                generators = "CMakeToolchain"
+
+                def layout(self):
+                    cmake_layout(self)
+            """)
+    client.save({"conanfile.py": conanfile, "CMakeLists.txt": "foo"})
+    configs = ["-c tools.cmake.cmaketoolchain.presets:max_schema_version=2 ",
+               "-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'"]
+    client.run("install . {} -s compiler.cppstd=14".format(" ".join(configs)))
+    client.run("install . {} -s compiler.cppstd=17".format(" ".join(configs)))
+
+    presets = json.loads(client.load("CMakeUserPresets.json"))
+    assert len(presets["configurePresets"]) == 2
+    assert "FOO" not in presets["configurePresets"][0]["cacheVariables"]
+
+    # Now introduce a cache_variable FOO to see if we get it in the CMakeUserPresets.json (that
+    # at the same time, it will come from the build/xxxx/CMakePreset.json that is also updated)
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.cmake import cmake_layout, CMakeToolchain
+
+            class Conan(ConanFile):
+                settings = "os", "arch", "compiler", "build_type"
+
+                def generate(self):
+                    tc = CMakeToolchain(self)
+                    tc.cache_variables["FOO"] = "var"
+                    tc.generate()
+
+                def layout(self):
+                    cmake_layout(self)
+            """)
+    client.save({"conanfile.py": conanfile})
+    client.run("install . {} -s compiler.cppstd=14".format(" ".join(configs)))
+    presets = json.loads(client.load("CMakeUserPresets.json"))
+    assert len(presets["configurePresets"]) == 2
+    assert "FOO" in presets["configurePresets"][0]["cacheVariables"]
+
+
+@pytest.mark.parametrize("arch, arch_toolset", [("x86", "x86_64"), ("x86_64", "x86_64")])
+def test_presets_ninja_msvc(arch, arch_toolset):
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.cmake import cmake_layout
+
+            class Conan(ConanFile):
+                settings = "os", "arch", "compiler", "build_type"
+                generators = "CMakeToolchain"
+
+                def layout(self):
+                    cmake_layout(self)
+            """)
+    client.save({"conanfile.py": conanfile, "CMakeLists.txt": "foo"})
+    configs = ["-c tools.cmake.cmaketoolchain:toolset_arch={}".format(arch_toolset),
+               "-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'",
+               "-c tools.cmake.cmaketoolchain:generator=Ninja"]
+    msvc = " -s compiler=msvc -s compiler.version=191 -s compiler.runtime=static " \
+           "-s compiler.runtime_type=Release"
+    client.run("install . {} -s compiler.cppstd=14 {} -s arch={}".format(" ".join(configs), msvc, arch))
+
+    presets = json.loads(client.load("build/14/generators/CMakePresets.json"))
+
+    toolset_value = {"x86_64": "host=x86_64", "x86": "x86"}.get(arch_toolset)
+    arch_value = {"x86_64": "x64", "x86": "x86"}.get(arch)
+
+    assert presets["configurePresets"][0]["architecture"]["value"] == arch_value
+    assert presets["configurePresets"][0]["architecture"]["strategy"] == "external"
+    assert presets["configurePresets"][0]["toolset"]["value"] == toolset_value
+    assert presets["configurePresets"][0]["toolset"]["strategy"] == "external"
+
+    # Only for Ninja, no ninja, no values
+    rmdir(os.path.join(client.current_folder, "build"))
+    configs = ["-c tools.cmake.cmaketoolchain:toolset_arch={}".format(arch_toolset),
+               "-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'"]
+    client.run(
+        "install . {} -s compiler.cppstd=14 {} -s arch={}".format(" ".join(configs), msvc, arch))
+
+    presets = json.loads(client.load("build/14/generators/CMakePresets.json"))
+    assert "architecture" not in presets["configurePresets"][0]
+    assert "toolset" not in presets["configurePresets"][0]
+
+    # No toolset defined in conf, no value
+    rmdir(os.path.join(client.current_folder, "build"))
+    configs = ["-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'",
+               "-c tools.cmake.cmaketoolchain:generator=Ninja"]
+
+    client.run(
+        "install . {} -s compiler.cppstd=14 {} -s arch={}".format(" ".join(configs), msvc, arch))
+    presets = json.loads(client.load("build/14/generators/CMakePresets.json"))
+    assert "architecture" in presets["configurePresets"][0]
+    assert "toolset" not in presets["configurePresets"][0]
diff --git a/conans/test/integration/toolchains/gnu/test_autotoolstoolchain.py b/conans/test/integration/toolchains/gnu/test_autotoolstoolchain.py
index 7a20a0260..36ede715b 100644
--- a/conans/test/integration/toolchains/gnu/test_autotoolstoolchain.py
+++ b/conans/test/integration/toolchains/gnu/test_autotoolstoolchain.py
@@ -42,3 +42,28 @@ def test_extra_flags_via_conf():
         assert 'export CXXFLAGS="$CXXFLAGS -O3 -s --flag1 --flag2"' in toolchain
         assert 'export CFLAGS="$CFLAGS -O3 -s --flag3 --flag4"' in toolchain
         assert 'export LDFLAGS="$LDFLAGS --flag5 --flag6"' in toolchain
+
+
+def test_not_none_values():
+
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.gnu import AutotoolsToolchain
+
+        class Foo(ConanFile):
+            name = "foo"
+            version = "1.0"
+
+            def generate(self):
+                tc = AutotoolsToolchain(self)
+                assert None not in tc.defines
+                assert None not in tc.cxxflags
+                assert None not in tc.cflags
+                assert None not in tc.ldflags
+
+    """)
+
+    client = TestClient()
+    client.save({"conanfile.py": conanfile})
+    client.run("install .")
+
diff --git a/conans/test/integration/toolchains/gnu/test_basic_layout.py b/conans/test/integration/toolchains/gnu/test_basic_layout.py
new file mode 100644
index 000000000..19cd9ebb6
--- /dev/null
+++ b/conans/test/integration/toolchains/gnu/test_basic_layout.py
@@ -0,0 +1,25 @@
+import os
+import platform
+import textwrap
+
+from conans.test.utils.tools import TestClient
+
+
+def test_basic_layout_subproject():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.layout import basic_layout
+        class Pkg(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            generators = "AutotoolsToolchain"
+            def layout(self):
+                self.folders.root = ".."
+                self.folders.subproject = "pkg"
+                basic_layout(self)
+        """)
+    c.save({"pkg/conanfile.py": conanfile})
+    c.run("install pkg")
+    ext = "sh" if platform.system() != "Windows" else "bat"
+    assert os.path.isfile(os.path.join(c.current_folder, "pkg", "build-release", "conan",
+                                       "conanautotoolstoolchain.{}".format(ext)))
diff --git a/conans/test/integration/toolchains/microsoft/test_vs_layout.py b/conans/test/integration/toolchains/microsoft/test_vs_layout.py
new file mode 100644
index 000000000..5a446da73
--- /dev/null
+++ b/conans/test/integration/toolchains/microsoft/test_vs_layout.py
@@ -0,0 +1,22 @@
+import os
+import textwrap
+
+from conans.test.utils.tools import TestClient
+
+
+def test_vs_layout_subproject():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.microsoft import vs_layout
+        class Pkg(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            generators = "MSBuildToolchain"
+            def layout(self):
+                self.folders.root = ".."
+                self.folders.subproject = "pkg"
+                vs_layout(self)
+        """)
+    c.save({"pkg/conanfile.py": conanfile})
+    c.run("install pkg")
+    assert os.path.isfile(os.path.join(c.current_folder, "pkg", "conan", "conantoolchain.props"))
diff --git a/conans/test/integration/tools/system/package_manager_test.py b/conans/test/integration/tools/system/package_manager_test.py
index b5becec39..f63da31ec 100644
--- a/conans/test/integration/tools/system/package_manager_test.py
+++ b/conans/test/integration/tools/system/package_manager_test.py
@@ -1,4 +1,5 @@
 import platform
+from unittest.mock import MagicMock, patch
 
 import mock
 import pytest
@@ -51,6 +52,11 @@ def test_msys2():
     ("fedora", "dnf"),
     ("arch", "pacman"),
     ("opensuse", "zypper"),
+    ("sles", "zypper"),
+    ("opensuse", "zypper"),
+    ("opensuse-tumbleweed", "zypper"),
+    ("opensuse-leap", "zypper"),
+    ("opensuse-next_version", "zypper"),
     ("freebsd", "pkg"),
 ])
 @pytest.mark.skipif(platform.system() != "Linux", reason="Only linux")
@@ -111,7 +117,11 @@ def test_tools_install_mode_check(tool_class):
         context_mock.return_value = "host"
         tool = tool_class(conanfile)
         with pytest.raises(ConanException) as exc_info:
-            tool.install(["package1", "package2"])
+            def fake_check(*args, **kwargs):
+                return ["package1", "package2"]
+            from conan.tools.system.package_manager import _SystemPackageManagerTool
+            with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):
+                tool.install(["package1", "package2"])
         assert exc_info.value.args[0] == "System requirements: 'package1, package2' are missing but " \
                                          "can't install because tools.system.package_manager:mode is " \
                                          "'check'.Please update packages manually or set " \
@@ -120,28 +130,8 @@ def test_tools_install_mode_check(tool_class):
                                          "'-c tools.system.package_manager:mode=install'"
 
 
-@pytest.mark.parametrize("tool_class",
-                         [Apt, Yum, Dnf, Brew, Pkg, PkgUtil, Chocolatey, PacMan, Zypper])
-def test_tools_update_mode_check(tool_class):
-    conanfile = ConanFileMock()
-    conanfile.conf = Conf()
-    conanfile.settings = Settings()
-    conanfile.conf["tools.system.package_manager:tool"] = tool_class.tool_name
-    conanfile.conf["tools.system.package_manager:mode"] = "check"
-    with mock.patch('conans.ConanFile.context', new_callable=PropertyMock) as context_mock:
-        context_mock.return_value = "host"
-        tool = tool_class(conanfile)
-        with pytest.raises(ConanException) as exc_info:
-            tool.update()
-        assert exc_info.value.args[0] == "Can't update because tools.system.package_manager:mode is " \
-                                         "'check'.Please update packages manually or set " \
-                                         "'tools.system.package_manager:mode' to 'install' in the [conf] " \
-                                         "section of the profile, or in the command line using " \
-                                         "'-c tools.system.package_manager:mode=install'"
-
-
-
-@pytest.mark.parametrize("tool_class, result", [
+@pytest.mark.parametrize("tool_class, result",
+[
     (Apt, "apt-get update"),
     (Yum, "yum check-update -y"),
     (Dnf, "dnf check-update -y"),
@@ -153,6 +143,29 @@ def test_tools_update_mode_check(tool_class):
     (Zypper, "zypper --non-interactive ref"),
 ])
 def test_tools_update_mode_install(tool_class, result):
+    conanfile = ConanFileMock()
+    conanfile.conf = Conf()
+    conanfile.settings = Settings()
+    conanfile.conf["tools.system.package_manager:tool"] = tool_class.tool_name
+    for mode in ["check", "install"]:
+        conanfile.conf["tools.system.package_manager:mode"] = mode
+        with mock.patch('conans.ConanFile.context', new_callable=PropertyMock) as context_mock:
+            context_mock.return_value = "host"
+            tool = tool_class(conanfile)
+            tool.update()
+            if mode == "install":
+                assert tool._conanfile.command == result
+            else:
+                # does not run the update when mode check
+                assert tool._conanfile.command is None
+
+
+@pytest.mark.parametrize("tool_class, result", [
+    (Yum, "yum check-update -y"),
+    (Dnf, "dnf check-update -y"),
+])
+def test_dnf_yum_return_code_100(tool_class, result):
+    # https://github.com/conan-io/conan/issues/11661
     conanfile = ConanFileMock()
     conanfile.conf = Conf()
     conanfile.settings = Settings()
@@ -161,8 +174,26 @@ def test_tools_update_mode_install(tool_class, result):
     with mock.patch('conans.ConanFile.context', new_callable=PropertyMock) as context_mock:
         context_mock.return_value = "host"
         tool = tool_class(conanfile)
+
+        def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False):
+            assert command == result
+            return 100 if "check-update" in command else 0
+
+        conanfile.run = fake_run
         tool.update()
-    assert tool._conanfile.command == result
+
+    #check that some random return code fails
+    with mock.patch('conans.ConanFile.context', new_callable=PropertyMock) as context_mock:
+        context_mock.return_value = "host"
+        tool = tool_class(conanfile)
+
+        def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False):
+            return 55 if "check-update" in command else 0
+
+        conanfile.run = fake_run
+        with pytest.raises(ConanException) as exc_info:
+            tool.update()
+        assert f"Command '{result}' failed" == str(exc_info.value)
 
 
 @pytest.mark.parametrize("tool_class, result", [
@@ -185,8 +216,12 @@ def test_tools_install_mode_install(tool_class, result):
     with mock.patch('conans.ConanFile.context', new_callable=PropertyMock) as context_mock:
         context_mock.return_value = "host"
         tool = tool_class(conanfile)
-        tool.install(["package1", "package2"])
-    assert tool._conanfile.command == result
+
+        def fake_check(*args, **kwargs):
+            return ["package1", "package2"]
+        from conan.tools.system.package_manager import _SystemPackageManagerTool
+        with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):
+            tool.install(["package1", "package2"])
 
 
 @pytest.mark.parametrize("tool_class, result", [
@@ -209,4 +244,3 @@ def test_tools_check(tool_class, result):
         context_mock.return_value = "host"
         tool = tool_class(conanfile)
         tool.check(["package"])
-    assert tool._conanfile.command == result
diff --git a/conans/test/unittests/client/generators/cmake_test.py b/conans/test/unittests/client/generators/cmake_test.py
index 74e9111b7..9c3bef9be 100644
--- a/conans/test/unittests/client/generators/cmake_test.py
+++ b/conans/test/unittests/client/generators/cmake_test.py
@@ -371,7 +371,7 @@ endmacro()""", macro)
 
         generator = CMakeGenerator(conanfile)
         content = generator.content
-        self.assertIn('find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAME ${_FRAMEWORK} PATHS'
+        self.assertIn('find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAMES ${_FRAMEWORK} PATHS'
                       ' ${CONAN_FRAMEWORK_DIRS${SUFFIX}} CMAKE_FIND_ROOT_PATH_BOTH)', content)
         self.assertIn('set(CONAN_FRAMEWORK_DIRS "dummy_root_folder1/Frameworks"\n'
                       '\t\t\t"dummy_root_folder1/path/to/Frameworks1"\n'
diff --git a/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py b/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
index a9232a1e6..fb9ba0231 100644
--- a/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
+++ b/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
@@ -364,7 +364,12 @@ def test_custom_defines():
          "os.version": "14",
          "arch": "armv8"})
     be = AutotoolsToolchain(conanfile)
-    be.defines = ["MyDefine1", "MyDefine2"]
+    be.extra_defines = ["MyDefine1", "MyDefine2"]
+
+    assert "MyDefine1" in be.defines
+    assert "MyDefine2" in be.defines
+    assert "NDEBUG" in be.defines
+
     env = be.vars()
     assert "-DMyDefine1" in env["CPPFLAGS"]
     assert "-DMyDefine2" in env["CPPFLAGS"]
@@ -380,7 +385,14 @@ def test_custom_cxxflags():
          "os.version": "14",
          "arch": "armv8"})
     be = AutotoolsToolchain(conanfile)
-    be.cxxflags = ["MyFlag1", "MyFlag2"]
+    be.extra_cxxflags = ["MyFlag1", "MyFlag2"]
+
+    assert "MyFlag1" in be.cxxflags
+    assert "MyFlag2" in be.cxxflags
+    assert "-mios-version-min=14" in be.cxxflags
+    assert "MyFlag" not in be.cflags
+    assert "MyFlag" not in be.ldflags
+
     env = be.vars()
     assert "MyFlag1" in env["CXXFLAGS"]
     assert "MyFlag2" in env["CXXFLAGS"]
@@ -399,7 +411,14 @@ def test_custom_cflags():
          "os.version": "14",
          "arch": "armv8"})
     be = AutotoolsToolchain(conanfile)
-    be.cflags = ["MyFlag1", "MyFlag2"]
+    be.extra_cflags = ["MyFlag1", "MyFlag2"]
+
+    assert "MyFlag1" in be.cflags
+    assert "MyFlag2" in be.cflags
+    assert "-mios-version-min=14" in be.cflags
+    assert "MyFlag" not in be.cxxflags
+    assert "MyFlag" not in be.ldflags
+
     env = be.vars()
     assert "MyFlag1" in env["CFLAGS"]
     assert "MyFlag2" in env["CFLAGS"]
@@ -418,7 +437,14 @@ def test_custom_ldflags():
          "os.version": "14",
          "arch": "armv8"})
     be = AutotoolsToolchain(conanfile)
-    be.ldflags = ["MyFlag1", "MyFlag2"]
+    be.extra_ldflags = ["MyFlag1", "MyFlag2"]
+
+    assert "MyFlag1" in be.ldflags
+    assert "MyFlag2" in be.ldflags
+    assert "-mios-version-min=14" in be.ldflags
+    assert "MyFlag" not in be.cxxflags
+    assert "MyFlag" not in be.cflags
+
     env = be.vars()
     assert "MyFlag1" in env["LDFLAGS"]
     assert "MyFlag2" in env["LDFLAGS"]
diff --git a/conans/test/unittests/tools/cmake/test_cmake_test.py b/conans/test/unittests/tools/cmake/test_cmake_test.py
new file mode 100644
index 000000000..3e852b10d
--- /dev/null
+++ b/conans/test/unittests/tools/cmake/test_cmake_test.py
@@ -0,0 +1,45 @@
+import platform
+import pytest
+
+from conan.tools.cmake import CMake
+from conan.tools.cmake.presets import write_cmake_presets
+from conans.client.conf import get_default_settings_yml
+from conans.model.conf import Conf
+from conans.model.settings import Settings
+from conans.test.utils.mocks import ConanFileMock
+from conans.test.utils.test_files import temp_folder
+
+
+@pytest.mark.parametrize("generator,target", [
+    ("NMake Makefiles", "test"),
+    ("Ninja Makefiles", "test"),
+    ("Ninja Multi-Config", "test"),
+    ("Unix Makefiles", "test"),
+    ("Visual Studio 14 2015", "RUN_TESTS"),
+    ("Xcode", "RUN_TESTS"),
+])
+def test_run_tests(generator, target):
+    """
+    Testing that the proper test target is picked for different generators, especially multi-config ones.
+    Issue related: https://github.com/conan-io/conan/issues/11405
+    """
+    settings = Settings.loads(get_default_settings_yml())
+    settings.os = "Windows"
+    settings.arch = "x86"
+    settings.build_type = "Release"
+    settings.compiler = "Visual Studio"
+    settings.compiler.runtime = "MDd"
+    settings.compiler.version = "14"
+
+    conanfile = ConanFileMock()
+    conanfile.conf = Conf()
+    conanfile.folders.generators = "."
+    conanfile.folders.set_base_generators(temp_folder())
+    conanfile.settings = settings
+
+    write_cmake_presets(conanfile, "toolchain", generator, {})
+    cmake = CMake(conanfile)
+    cmake.test()
+
+    search_pattern = "--target {}" if platform.system() == "Windows" else "'--target' '{}'"
+    assert search_pattern.format(target) in conanfile.command
diff --git a/conans/test/unittests/tools/cmake/test_cmakedeps.py b/conans/test/unittests/tools/cmake/test_cmakedeps.py
index ec25884ec..8be95874d 100644
--- a/conans/test/unittests/tools/cmake/test_cmakedeps.py
+++ b/conans/test/unittests/tools/cmake/test_cmakedeps.py
@@ -61,8 +61,8 @@ def test_cpp_info_name_cmakedeps_components():
     conanfile.settings.arch = "x64"
 
     cpp_info = CppInfo("mypkg", "dummy_root_folder1")
-    cpp_info.set_property("cmake_target_name", "GlobakPkgName1::GlobakPkgName1")
-    cpp_info.components["mycomp"].set_property("cmake_target_name", "GlobakPkgName1::MySuperPkg1")
+    cpp_info.set_property("cmake_target_name", "GlobalPkgName1::GlobalPkgName1")
+    cpp_info.components["mycomp"].set_property("cmake_target_name", "GlobalPkgName1::MySuperPkg1")
     cpp_info.set_property("cmake_file_name", "ComplexFileName1")
 
     conanfile_dep = ConanFile(Mock(), None)
@@ -81,11 +81,13 @@ def test_cpp_info_name_cmakedeps_components():
 
         cmakedeps = CMakeDeps(conanfile)
         files = cmakedeps.content
-        assert "TARGET GlobakPkgName1::MySuperPkg1" in files["ComplexFileName1-Target-debug.cmake"]
+        assert "TARGET GlobalPkgName1::MySuperPkg1" in files["ComplexFileName1-Target-debug.cmake"]
+        # No global variables for the packages
         assert 'set(OriginalDepName_INCLUDE_DIRS_DEBUG ' \
                '"${OriginalDepName_PACKAGE_FOLDER_DEBUG}/include")' \
-               in files["ComplexFileName1-debug-x64-data.cmake"]
-        assert 'set(OriginalDepName_GlobakPkgName1_MySuperPkg1_INCLUDE_DIRS_DEBUG ' \
+               not in files["ComplexFileName1-debug-x64-data.cmake"]
+        # But components
+        assert 'set(OriginalDepName_GlobalPkgName1_MySuperPkg1_INCLUDE_DIRS_DEBUG ' \
                '"${OriginalDepName_PACKAGE_FOLDER_DEBUG}/include")' \
                in files["ComplexFileName1-debug-x64-data.cmake"]
 
diff --git a/conans/test/unittests/tools/files/collect_lib_test.py b/conans/test/unittests/tools/files/collect_lib_test.py
index e862ce75b..854ea3747 100644
--- a/conans/test/unittests/tools/files/collect_lib_test.py
+++ b/conans/test/unittests/tools/files/collect_lib_test.py
@@ -1,4 +1,7 @@
 import os
+import platform
+
+import pytest
 
 from conan.tools.files import check_md5, check_sha1, check_sha256, collect_libs
 from conans.model.build_info import CppInfo
@@ -43,7 +46,7 @@ def test_collect_libs():
     result = collect_libs(conanfile, folder="custom_folder")
     assert ["customlib"] == result
 
-    # Warn same lib different folders
+    # Unicity of lib names
     conanfile = ConanFileMock()
     conanfile.folders.set_base_package(temp_folder())
     conanfile.cpp_info = CppInfo(conanfile.name, "")
@@ -54,9 +57,6 @@ def test_collect_libs():
     conanfile.cpp_info.libdirs = ["lib", "custom_folder"]
     result = collect_libs(conanfile)
     assert ["mylib"] == result
-    assert "Library 'mylib' was either already found in a previous "\
-           "'conanfile.cpp_info.libdirs' folder or appears several times with a "\
-           "different file extension" in conanfile.output
 
     # Warn lib folder does not exist with correct result
     conanfile = ConanFileMock()
@@ -70,3 +70,23 @@ def test_collect_libs():
     assert ["mylib"] == result
     assert "WARN: Lib folder doesn't exist, can't collect libraries: %s" % no_folder_path \
            in conanfile.output
+
+@pytest.mark.skipif(platform.system() == "Windows", reason="Needs symlinks support")
+def test_collect_libs_symlinks():
+    # Keep only the shortest lib name per group of symlinks
+    conanfile = ConanFileMock()
+    conanfile.folders.set_base_package(temp_folder())
+    conanfile.cpp_info = CppInfo(conanfile.name, "")
+    version_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.1.0.0.dylib")
+    soversion_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.1.dylib")
+    lib_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.dylib")
+    lib_mylib2_path = os.path.join(conanfile.package_folder, "lib", "libmylib.2.dylib")
+    lib_mylib3_path = os.path.join(conanfile.package_folder, "custom_folder", "libmylib.3.dylib")
+    save(version_mylib_path, "")
+    os.symlink(version_mylib_path, soversion_mylib_path)
+    os.symlink(soversion_mylib_path, lib_mylib_path)
+    save(lib_mylib2_path, "")
+    save(lib_mylib3_path, "")
+    conanfile.cpp_info.libdirs = ["lib", "custom_folder"]
+    result = collect_libs(conanfile)
+    assert ["mylib", "mylib.2", "mylib.3"] == result
diff --git a/conans/test/unittests/tools/files/test_downloads.py b/conans/test/unittests/tools/files/test_downloads.py
index 30675c976..cf0064d22 100644
--- a/conans/test/unittests/tools/files/test_downloads.py
+++ b/conans/test/unittests/tools/files/test_downloads.py
@@ -1,4 +1,5 @@
 import os
+import platform
 
 import pytest
 import requests
@@ -157,6 +158,32 @@ class TestDownload:
         assert "Waiting" not in str(conanfile.output)
         assert "retry" not in str(conanfile.output)
 
+    def test_download_localfile(self):
+        conanfile = ConanFileMock()
+        conanfile._conan_requester = requests
+
+        file_location =  os.path.join(temp_folder(), "file.txt")
+        save(file_location, "this is some content")
+
+        file_url = f"file:///{file_location}"
+        file_md5 = "736db904ad222bf88ee6b8d103fceb8e"
+
+        dest = os.path.join(temp_folder(), "downloaded_file.txt")
+        download(conanfile, file_url, dest, md5=file_md5)
+        content = load(dest)
+        assert "this is some content" == content
+
+    def test_download_localfile_notfound(self):
+        conanfile = ConanFileMock()
+        conanfile._conan_requester = requests
+
+        file_url = "file:///path/to/missing/file.txt"
+        dest = os.path.join(temp_folder(), "file.txt")
+
+        with pytest.raises(FileNotFoundError) as exc:
+            download(conanfile, file_url, dest)
+
+        assert "No such file" in str(exc.value)
 
 @pytest.fixture()
 def bottle_server_zip():
diff --git a/conans/test/unittests/tools/google/test_bazeldeps.py b/conans/test/unittests/tools/google/test_bazeldeps.py
index acef3622e..be8a7a71e 100644
--- a/conans/test/unittests/tools/google/test_bazeldeps.py
+++ b/conans/test/unittests/tools/google/test_bazeldeps.py
@@ -58,7 +58,7 @@ def test_bazeldeps_dependency_buildfiles():
                 assert 'linkopts = ["/DEFAULTLIB:system_lib1"]' in dependency_content
             else:
                 assert 'linkopts = ["-lsystem_lib1"],' in dependency_content
-            assert 'deps = [\n    \n    ":lib1_precompiled",' in dependency_content
+            assert """deps = [\n        # do not sort\n    \n    ":lib1_precompiled",""" in dependency_content
 
 
 def test_bazeldeps_get_lib_file_path_by_basename():
@@ -93,7 +93,7 @@ def test_bazeldeps_get_lib_file_path_by_basename():
                 assert 'linkopts = ["/DEFAULTLIB:system_lib1"]' in dependency_content
             else:
                 assert 'linkopts = ["-lsystem_lib1"],' in dependency_content
-            assert 'deps = [\n    \n    ":liblib1.a_precompiled",' in dependency_content
+            assert 'deps = [\n        # do not sort\n    \n    ":liblib1.a_precompiled",' in dependency_content
 
 
 def test_bazeldeps_dependency_transitive():
@@ -148,7 +148,7 @@ def test_bazeldeps_dependency_transitive():
 
         # Ensure that transitive dependency is referenced by the 'deps' attribute of the direct
         # dependency
-        assert re.search(r'deps =\s*\[\s*":lib1_precompiled",\s*"@TransitiveDepName"',
+        assert re.search(r'deps =\s*\[\s*# do not sort\s*":lib1_precompiled",\s*"@TransitiveDepName"',
                          dependency_content)
 
 
@@ -220,6 +220,7 @@ cc_library(
     includes=["include"],
     visibility=["//visibility:public"],
     deps = [
+        # do not sort
         ":lib1_precompiled",
     ],
 )
diff --git a/conans/test/unittests/util/tools_test.py b/conans/test/unittests/util/tools_test.py
index 2be7e00e8..cc4c9bcd0 100644
--- a/conans/test/unittests/util/tools_test.py
+++ b/conans/test/unittests/util/tools_test.py
@@ -817,7 +817,7 @@ class CollectLibTestCase(unittest.TestCase):
         result = tools.collect_libs(conanfile, folder="custom_folder")
         self.assertEqual(["customlib"], result)
 
-        # Warn same lib different folders
+        # Unicity of lib names
         conanfile = ConanFileMock()
         conanfile.folders.set_base_package(temp_folder())
         conanfile.cpp_info = CppInfo(conanfile.name, "")
@@ -828,9 +828,6 @@ class CollectLibTestCase(unittest.TestCase):
         conanfile.cpp_info.libdirs = ["lib", "custom_folder"]
         result = tools.collect_libs(conanfile)
         self.assertEqual(["mylib"], result)
-        self.assertIn("Library 'mylib' was either already found in a previous "
-                      "'conanfile.cpp_info.libdirs' folder or appears several times with a "
-                      "different file extension", conanfile.output)
 
         # Warn lib folder does not exist with correct result
         conanfile = ConanFileMock()
@@ -845,6 +842,26 @@ class CollectLibTestCase(unittest.TestCase):
         self.assertIn("WARN: Lib folder doesn't exist, can't collect libraries: %s"
                       % no_folder_path, conanfile.output)
 
+    @pytest.mark.skipif(platform.system() == "Windows", reason="Needs symlinks support")
+    def test_collect_libs_symlinks(self):
+        # Keep only the shortest lib name per group of symlinks
+        conanfile = ConanFileMock()
+        conanfile.folders.set_base_package(temp_folder())
+        conanfile.cpp_info = CppInfo(conanfile.name, "")
+        version_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.1.0.0.dylib")
+        soversion_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.1.dylib")
+        lib_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.dylib")
+        lib_mylib2_path = os.path.join(conanfile.package_folder, "lib", "libmylib.2.dylib")
+        lib_mylib3_path = os.path.join(conanfile.package_folder, "custom_folder", "libmylib.3.dylib")
+        save(version_mylib_path, "")
+        os.symlink(version_mylib_path, soversion_mylib_path)
+        os.symlink(soversion_mylib_path, lib_mylib_path)
+        save(lib_mylib2_path, "")
+        save(lib_mylib3_path, "")
+        conanfile.cpp_info.libdirs = ["lib", "custom_folder"]
+        result = tools.collect_libs(conanfile)
+        self.assertEqual(["mylib", "mylib.2", "mylib.3"], result)
+
     def test_self_collect_libs(self):
         conanfile = ConanFileMock()
         # Without package_folder
@@ -880,7 +897,7 @@ class CollectLibTestCase(unittest.TestCase):
         result = conanfile.collect_libs(folder="custom_folder")
         self.assertEqual(["customlib"], result)
 
-        # Warn same lib different folders
+        # Unicity of lib names
         conanfile = ConanFileMock()
         conanfile.folders.set_base_package(temp_folder())
         conanfile.cpp_info = CppInfo("", "")
@@ -891,9 +908,6 @@ class CollectLibTestCase(unittest.TestCase):
         conanfile.cpp_info.libdirs = ["lib", "custom_folder"]
         result = conanfile.collect_libs()
         self.assertEqual(["mylib"], result)
-        self.assertIn("Library 'mylib' was either already found in a previous "
-                      "'conanfile.cpp_info.libdirs' folder or appears several times with a "
-                      "different file extension", conanfile.output)
 
         # Warn lib folder does not exist with correct result
         conanfile = ConanFileMock()
@@ -907,3 +921,23 @@ class CollectLibTestCase(unittest.TestCase):
         self.assertEqual(["mylib"], result)
         self.assertIn("WARN: Lib folder doesn't exist, can't collect libraries: %s"
                       % no_folder_path, conanfile.output)
+
+    @pytest.mark.skipif(platform.system() == "Windows", reason="Needs symlinks support")
+    def test_self_collect_libs_symlinks(self):
+        # Keep only the shortest lib name per group of symlinks
+        conanfile = ConanFileMock()
+        conanfile.folders.set_base_package(temp_folder())
+        conanfile.cpp_info = CppInfo("", "")
+        version_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.1.0.0.dylib")
+        soversion_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.1.dylib")
+        lib_mylib_path = os.path.join(conanfile.package_folder, "lib", "libmylib.dylib")
+        lib_mylib2_path = os.path.join(conanfile.package_folder, "lib", "libmylib.2.dylib")
+        lib_mylib3_path = os.path.join(conanfile.package_folder, "custom_folder", "libmylib.3.dylib")
+        save(version_mylib_path, "")
+        os.symlink(version_mylib_path, soversion_mylib_path)
+        os.symlink(soversion_mylib_path, lib_mylib_path)
+        save(lib_mylib2_path, "")
+        save(lib_mylib3_path, "")
+        conanfile.cpp_info.libdirs = ["lib", "custom_folder"]
+        result = conanfile.collect_libs()
+        self.assertEqual(["mylib", "mylib.2", "mylib.3"], result)
diff --git a/conans/test/utils/mocks.py b/conans/test/utils/mocks.py
index 4103bc4f3..08ae59928 100644
--- a/conans/test/utils/mocks.py
+++ b/conans/test/utils/mocks.py
@@ -197,6 +197,7 @@ class ConanFileMock(ConanFile):
         self.command = command
         self.path = os.environ["PATH"]
         self.captured_env = {key: value for key, value in os.environ.items()}
+        return 0
 
 
 MockOptions = MockSettings