Repository: conan-io/conan
Pull request #11557 (2022-06-30 14:04:03)

[POC] MesonToolchain and GNU flags coming from dependencies
Changelog: Feature: Added `MesonDeps` as a new generator to create an extra file with all the GNU flags from all the dependencies. `Meson` build-helper will add that one (if exists) to complement the created one by `MesonToolchain`.
Docs: XXXXXX
Closes: https://github.com/conan-io/conan/issues/10683 https://github.com/conan-io/conan/issues/11397 https://github.com/conan-io/conan/issues/11398


Motivation: Dependencies which are defining only GNU flags, MesonToolchain will never get anything from their build environments because it needs those flags to initialize its own instance, so right now, it's possible to work-around it but it's a bit hard. This PR is proposing that alternative but, for sure, it's open to being discussed.


franramirez688: > moved to a MesonDeps generator that is based on the AutotoolsDeps?

Yeah, I think I'm going to try a `MesonDeps` instead of this. I think it's going to be much cleaner.
Thanks for the feedback!

SSE4: 
> Yeah, I think I'm going to try a `MesonDeps` instead of this. I think it's going to be much cleaner. Thanks for the feedback!

I can't find anything about `MesonDeps`, neither in the codebase, nor in the documentation. do you have a link?

franramirez688: > I can't find anything about `MesonDeps`, neither in the codebase, nor in the documentation. do you have a link?

Sure you cannot because that's a new generator. It's not created yet. I'm going to study if it's feasible or not and then, update the PR.


Patch:
diff --git a/conan/tools/cmake/cmake.py b/conan/tools/cmake/cmake.py
index b3d6535a5..0805f7092 100644
--- a/conan/tools/cmake/cmake.py
+++ b/conan/tools/cmake/cmake.py
@@ -153,7 +153,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/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index fca65c2fc..1f0d0a198 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:
diff --git a/conan/tools/files/files.py b/conan/tools/files/files.py
index 7eca6af89..3f69573b9 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):
     """
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/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..1b467ba35 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)
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..f095c8679 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() -%}
@@ -52,10 +57,10 @@ 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}}
+    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 pkg_config_path %}pkg_config_path = '{{pkg_config_path}}'{% endif %}
 
     {% for context, values in cross_build.items() %}
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/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/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


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/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/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_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_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/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/toolchains/cmake/test_cmaketoolchain.py b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
index 967329a5d..a4f7f09c6 100644
--- a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
+++ b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
@@ -473,3 +473,20 @@ 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")
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/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():