Repository: conan-io/conan
Pull request #15413 (2024-01-08 15:23:53)

test to cover test_requires potential loop
Changelog: Omit
Docs: Omit

Close https://github.com/conan-io/conan/issues/15412



Patch:
diff --git a/conan/api/subapi/cache.py b/conan/api/subapi/cache.py
index 0875f6fb2..1fcb49219 100644
--- a/conan/api/subapi/cache.py
+++ b/conan/api/subapi/cache.py
@@ -155,6 +155,8 @@ class CacheAPI:
             tgz.close()
 
     def restore(self, path):
+        if not os.path.isfile(path):
+            raise ConanException(f"Restore archive doesn't exist in {path}")
         with open(path, mode='rb') as file_handler:
             the_tar = tarfile.open(fileobj=file_handler)
             fileobj = the_tar.extractfile("pkglist.json")
diff --git a/conan/api/subapi/local.py b/conan/api/subapi/local.py
index eaaa3a170..88ae8a8fe 100644
--- a/conan/api/subapi/local.py
+++ b/conan/api/subapi/local.py
@@ -1,5 +1,6 @@
 import os
 
+from conan.api.output import ConanOutput
 from conan.cli import make_abs_path
 from conan.internal.conan_app import ConanApp
 from conans.client.cache.editable import EditablePackages
@@ -60,7 +61,8 @@ class LocalAPI:
 
     def editable_remove(self, path=None, requires=None, cwd=None):
         if path:
-            path = self._conan_api.local.get_conanfile_path(path, cwd, py=True)
+            path = make_abs_path(path, cwd)
+            path = os.path.join(path, "conanfile.py")
         return self.editable_packages.remove(path, requires)
 
     def editable_list(self):
diff --git a/conan/api/subapi/remotes.py b/conan/api/subapi/remotes.py
index 74162fd91..da6520695 100644
--- a/conan/api/subapi/remotes.py
+++ b/conan/api/subapi/remotes.py
@@ -257,7 +257,10 @@ def _load(remotes_file):
         _save(remotes_file, [remote])
         return [remote]
 
-    data = json.loads(load(remotes_file))
+    try:
+        data = json.loads(load(remotes_file))
+    except Exception as e:
+        raise ConanException(f"Error loading JSON remotes file '{remotes_file}': {e}")
     result = []
     for r in data.get("remotes", []):
         remote = Remote(r["name"], r["url"], r["verify_ssl"], r.get("disabled", False),
diff --git a/conan/cli/commands/graph.py b/conan/cli/commands/graph.py
index 3f4f8ada7..bf591c461 100644
--- a/conan/cli/commands/graph.py
+++ b/conan/cli/commands/graph.py
@@ -14,9 +14,8 @@ from conan.errors import ConanException
 from conan.internal.deploy import do_deploys
 from conans.client.graph.graph import BINARY_MISSING
 from conans.client.graph.install_graph import InstallGraph
-from conans.errors import ConanConnectionError, NotFoundException
+from conans.errors import NotFoundException
 from conans.model.recipe_ref import ref_matches, RecipeReference
-from conans.model.version_range import VersionRange
 
 
 def explain_formatter_text(data):
@@ -214,10 +213,7 @@ def graph_info(conan_api, parser, subparser, *args):
                                                          remotes, args.update,
                                                          check_updates=args.check_updates)
     print_graph_basic(deps_graph)
-    if deps_graph.error:
-        ConanOutput().info("Graph error", Color.BRIGHT_RED)
-        ConanOutput().info("    {}".format(deps_graph.error), Color.BRIGHT_RED)
-    else:
+    if not deps_graph.error:
         conan_api.graph.analyze_binaries(deps_graph, args.build, remotes=remotes, update=args.update,
                                          lockfile=lockfile)
         print_graph_packages(deps_graph)
diff --git a/conan/cli/commands/new.py b/conan/cli/commands/new.py
index 1e93fe7fe..f09ebd275 100644
--- a/conan/cli/commands/new.py
+++ b/conan/cli/commands/new.py
@@ -18,7 +18,7 @@ def new(conan_api, parser, *args):
                         "either a predefined built-in or a user-provided one. "
                         "Available built-in templates: basic, cmake_lib, cmake_exe, "
                         "meson_lib, meson_exe, msbuild_lib, msbuild_exe, bazel_lib, bazel_exe, "
-                        "autotools_lib, autotools_exe, local_recipes_index"
+                        "autotools_lib, autotools_exe, local_recipes_index. "
                         "E.g. 'conan new cmake_lib -d name=hello -d version=0.1'. "
                         "You can define your own templates too by inputting an absolute path "
                         "as your template, or a path relative to your conan home folder."
diff --git a/conan/cli/commands/version.py b/conan/cli/commands/version.py
index 507f0f7d1..b2509afef 100644
--- a/conan/cli/commands/version.py
+++ b/conan/cli/commands/version.py
@@ -12,10 +12,22 @@ def version(conan_api, parser, *args):
     Give information about the Conan client version.
     """
 
-    return {'version': str(conan_version),
+    return {
+            'version': str(conan_version),
+            'conan_path': sys.argv[0],
             'python': {
                 'version': platform.python_version().replace('\n', ''),
                 'sys_version': sys.version.replace('\n', ''),
+                'sys_executable': sys.executable,
+                'is_frozen': getattr(sys, 'frozen', False),
+                'architecture': platform.machine(),
+                },
+            'system': {
+                'version': platform.version(),
+                'platform': platform.platform(),
+                'system': platform.system(),
+                'release': platform.release(),
+                'cpu': platform.processor(),
                 }
             }
 
diff --git a/conan/cli/formatters/graph/info_graph_html.py b/conan/cli/formatters/graph/info_graph_html.py
index dc5aabe95..417969850 100644
--- a/conan/cli/formatters/graph/info_graph_html.py
+++ b/conan/cli/formatters/graph/info_graph_html.py
@@ -44,7 +44,10 @@ graph_info_html = r"""
                     <label for="show_package_type">Show package type</label>
                 </div>
                  <div>
-                    <input type="search" placeholder="Search package..." oninput="searchPackage(this)">
+                    <input type="search" placeholder="Search packages..." oninput="searchPackages(this)">
+                </div>
+                 <div>
+                    <input type="search" placeholder="Exclude packages..." title="Add a comma to exclude an additional package" oninput="excludePackages(this)">
                 </div>
                 <div>
                     <input type="checkbox" onchange="showhideclass('controls')" id="show_controls"/>
@@ -60,7 +63,8 @@ graph_info_html = r"""
             const graph_data = {{ deps_graph | tojson }};
             let hide_build = false;
             let hide_test = false;
-            let search_pkg = null;
+            let search_pkgs = null;
+            let excluded_pkgs = null;
             let collapse_packages = false;
             let show_package_type = false;
             let color_map = {Cache: "SkyBlue",
@@ -101,6 +105,15 @@ graph_info_html = r"""
                         if (existing) continue;
                         collapsed_packages[label] = node_id;
                     }
+                    if (excluded_pkgs) {
+                        let patterns = excluded_pkgs.split(',')
+                            .map(pattern => pattern.trim())
+                            .filter(pattern => pattern.length > 0)
+                            .map(pattern => pattern.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
+                        if (patterns.some(pattern => label.match(pattern))) {
+                            continue;
+                        }
+                    }
                     if (show_package_type) {
                          label = "<b>" + label + "\n" + "<i>" + node.package_type + "</i>";
                     }
@@ -114,9 +127,15 @@ graph_info_html = r"""
                         color = "Black";
                         shape = "circle";
                     }
-                    if (search_pkg && label.match(search_pkg)) {
-                        borderWidth = 3;
-                        borderColor = "Magenta";
+                    if (search_pkgs) {
+                        let patterns = search_pkgs.split(',')
+                            .map(pattern => pattern.trim())
+                            .filter(pattern => pattern.length > 0)
+                            .map(pattern => pattern.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
+                        if (patterns.some(pattern => label.match(pattern))) {
+                            borderWidth = 3;
+                            borderColor = "Magenta";
+                        }
                     }
                     if (node.test) {
                         font.background = "lightgrey";
@@ -293,8 +312,12 @@ graph_info_html = r"""
                 collapse_packages = !collapse_packages;
                 draw();
             }
-            function searchPackage(e) {
-                search_pkg = e.value;
+            function searchPackages(e) {
+                search_pkgs = e.value;
+                draw();
+            }
+            function excludePackages(e) {
+                excluded_pkgs = e.value;
                 draw();
             }
             function showPackageType(e) {
diff --git a/conan/internal/api/detect_api.py b/conan/internal/api/detect_api.py
index 2682ea375..8bdd5843e 100644
--- a/conan/internal/api/detect_api.py
+++ b/conan/internal/api/detect_api.py
@@ -167,7 +167,6 @@ def _detect_musl_libc(ldd="/usr/bin/ldd"):
     d = tempfile.mkdtemp()
     tmp_file = os.path.join(d, "err")
     try:
-        ldd_output = None
         with open(tmp_file, 'w') as stderr:
             check_output_runner(f"{ldd}", stderr=stderr, ignore_error=True)
         ldd_output = load(tmp_file)
@@ -362,48 +361,49 @@ def detect_default_compiler():
         output.info("CC and CXX: %s, %s " % (cc or "None", cxx or "None"))
         command = cc or cxx
         if "clang" in command.lower():
-            return _clang_compiler(command)
+            return detect_clang_compiler(command)
         if "gnu-cc" in command or "gcc" in command or "g++" in command or "c++" in command:
-            gcc, gcc_version, compiler_exe = _gcc_compiler(command)
+            gcc, gcc_version, compiler_exe = detect_gcc_compiler(command)
             if platform.system() == "Darwin" and gcc is None:
                 output.error("%s detected as a frontend using apple-clang. "
                              "Compiler not supported" % command)
             return gcc, gcc_version, compiler_exe
         if "icpx" in command or "icx" in command:
-            intel, intel_version, compiler_exe = _intel_compiler(command)
+            intel, intel_version, compiler_exe = detect_intel_compiler(command)
             return intel, intel_version, compiler_exe
         if platform.system() == "SunOS" and command.lower() == "cc":
-            return _sun_cc_compiler(command)
+            return detect_suncc_compiler(command)
         if (platform.system() == "Windows" and command.rstrip('"').endswith(("cl", "cl.exe"))
-            and "clang" not in command):
-            return _msvc_cl_compiler(command)
+                and "clang" not in command):
+            return detect_cl_compiler(command)
 
         # I am not able to find its version
         output.error("Not able to automatically detect '%s' version" % command)
         return None, None, None
 
     if platform.system() == "Windows":
-        version = _detect_vs_ide_version()
-        version = {"17": "193", "16": "192", "15": "191"}.get(str(version))  # Map to compiler
-        if version:
-            return 'msvc', Version(version), None
+        compiler, version, compiler_exe = detect_msvc_compiler()
+        if compiler:
+            return compiler, version, compiler_exe
 
     if platform.system() == "SunOS":
-        sun_cc, sun_cc_version, compiler_exe = _sun_cc_compiler()
+        sun_cc, sun_cc_version, compiler_exe = detect_suncc_compiler()
         if sun_cc:
             return sun_cc, sun_cc_version, compiler_exe
 
     if platform.system() in ["Darwin", "FreeBSD"]:
-        clang, clang_version, compiler_exe = _clang_compiler()  # prioritize clang
+        clang, clang_version, compiler_exe = detect_clang_compiler()  # prioritize clang
         if clang:
             return clang, clang_version, compiler_exe
         return None, None, None
-    else:
-        gcc, gcc_version, compiler_exe = _gcc_compiler()
+    else:  # linux like system
+        compiler, compiler_version, compiler_exe = _cc_compiler()
+        if compiler:
+            return compiler, compiler_version, compiler_exe
+        gcc, gcc_version, compiler_exe = detect_gcc_compiler()
         if gcc:
             return gcc, gcc_version, compiler_exe
-        return _clang_compiler()
-    return None, None, None
+        return detect_clang_compiler()
 
 
 def default_msvc_ide_version(version):
@@ -424,7 +424,23 @@ def _detect_vs_ide_version():
     return None
 
 
-def _gcc_compiler(compiler_exe="gcc"):
+def _cc_compiler():
+    # Try to detect the "cc" linux system "alternative". It could point to gcc or clang
+    try:
+        compiler_exe = "cc"
+        ret, out = detect_runner('%s --version' % compiler_exe)
+        if ret != 0:
+            return None, None, None
+        compiler = "clang" if "clang" in out else "gcc"
+        installed_version = re.search(r"([0-9]+(\.[0-9])?)", out).group()
+        if installed_version:
+            ConanOutput(scope="detect_api").info("Found cc=%s-%s" % (compiler, installed_version))
+            return compiler, Version(installed_version), compiler_exe
+    except (Exception,):  # to disable broad-except
+        return None, None, None
+
+
+def detect_gcc_compiler(compiler_exe="gcc"):
     try:
         if platform.system() == "Darwin":
             # In Mac OS X check if gcc is a fronted using apple-clang
@@ -453,7 +469,8 @@ def detect_compiler():
     compiler, version, _ = detect_default_compiler()
     return compiler, version
 
-def _intel_compiler(compiler_exe="icx"):
+
+def detect_intel_compiler(compiler_exe="icx"):
     try:
         ret, out = detect_runner("%s --version" % compiler_exe)
         if ret != 0:
@@ -466,7 +483,8 @@ def _intel_compiler(compiler_exe="icx"):
     except (Exception,):  # to disable broad-except
         return None, None, None
 
-def _sun_cc_compiler(compiler_exe="cc"):
+
+def detect_suncc_compiler(compiler_exe="cc"):
     try:
         _, out = detect_runner('%s -V' % compiler_exe)
         compiler = "sun-cc"
@@ -482,7 +500,7 @@ def _sun_cc_compiler(compiler_exe="cc"):
         return None, None, None
 
 
-def _clang_compiler(compiler_exe="clang"):
+def detect_clang_compiler(compiler_exe="clang"):
     try:
         ret, out = detect_runner('%s --version' % compiler_exe)
         if ret != 0:
@@ -501,7 +519,15 @@ def _clang_compiler(compiler_exe="clang"):
         return None, None, None
 
 
-def _msvc_cl_compiler(compiler_exe="cl"):
+def detect_msvc_compiler():
+    version = _detect_vs_ide_version()
+    version = {"17": "193", "16": "192", "15": "191"}.get(str(version))  # Map to compiler
+    if version:
+        return 'msvc', Version(version), None
+    return None, None, None
+
+
+def detect_cl_compiler(compiler_exe="cl"):
     """ only if CC/CXX env-vars are defined pointing to cl.exe, and the VS environment must
     be active to have them in the path
     """
diff --git a/conan/internal/api/new/autoools_exe.py b/conan/internal/api/new/autoools_exe.py
index 68e4a9a77..c2394fc6d 100644
--- a/conan/internal/api/new/autoools_exe.py
+++ b/conan/internal/api/new/autoools_exe.py
@@ -14,6 +14,7 @@ class {{package_name}}Conan(ConanFile):
     name = "{{name}}"
     version = "{{version}}"
     package_type = "application"
+    win_bash = True
 
     # Optional metadata
     license = "<Put the package license here>"
diff --git a/conan/internal/api/new/autotools_lib.py b/conan/internal/api/new/autotools_lib.py
index 8c0103d38..7eb5d11f8 100644
--- a/conan/internal/api/new/autotools_lib.py
+++ b/conan/internal/api/new/autotools_lib.py
@@ -14,6 +14,7 @@ class {{package_name}}Conan(ConanFile):
     name = "{{name}}"
     version = "{{version}}"
     package_type = "library"
+    win_bash = True
 
     # Optional metadata
     license = "<Put the package license here>"
@@ -92,6 +93,7 @@ from conan.tools.build import can_run
 class {{package_name}}TestConan(ConanFile):
     settings = "os", "compiler", "build_type", "arch"
     generators = "AutotoolsDeps", "AutotoolsToolchain"
+    win_bash = True
 
     def requirements(self):
         self.requires(self.tested_reference_str)
diff --git a/conan/internal/cache/db/packages_table.py b/conan/internal/cache/db/packages_table.py
index 7d093197b..a5ec13b7a 100644
--- a/conan/internal/cache/db/packages_table.py
+++ b/conan/internal/cache/db/packages_table.py
@@ -39,7 +39,7 @@ class PackagesDBTable(BaseDbTable):
             self.columns.prev: pref.revision,
         }
         where_expr = ' AND '.join(
-            [f'{k}="{v}" ' if v is not None else f'{k} IS NULL' for k, v in where_dict.items()])
+            [f"{k}='{v}' " if v is not None else f'{k} IS NULL' for k, v in where_dict.items()])
         return where_expr
 
     def _set_clause(self, pref: PkgReference, path=None, build_id=None):
@@ -52,7 +52,7 @@ class PackagesDBTable(BaseDbTable):
             self.columns.timestamp: pref.timestamp,
             self.columns.build_id: build_id,
         }
-        set_expr = ', '.join([f'{k} = "{v}"' for k, v in set_dict.items() if v is not None])
+        set_expr = ', '.join([f"{k} = '{v}'" for k, v in set_dict.items() if v is not None])
         return set_expr
 
     def get(self, pref: PkgReference):
@@ -107,7 +107,7 @@ class PackagesDBTable(BaseDbTable):
         where_clause = self._where_clause(pref)
         lru = timestamp_now()
         query = f"UPDATE {self.table_name} " \
-                f'SET {self.columns.lru} = "{lru}" ' \
+                f"SET {self.columns.lru} = '{lru}' " \
                 f"WHERE {where_clause};"
         with self.db_connection() as conn:
             conn.execute(query)
@@ -115,7 +115,7 @@ class PackagesDBTable(BaseDbTable):
     def remove_build_id(self, pref):
         where_clause = self._where_clause(pref)
         query = f"UPDATE {self.table_name} " \
-                f'SET {self.columns.build_id} = "null" ' \
+                f"SET {self.columns.build_id} = 'null' " \
                 f"WHERE {where_clause};"
         with self.db_connection() as conn:
             try:
@@ -126,8 +126,8 @@ class PackagesDBTable(BaseDbTable):
     def remove_recipe(self, ref: RecipeReference):
         # can't use the _where_clause, because that is an exact match on the package_id, etc
         query = f"DELETE FROM {self.table_name} " \
-                f'WHERE {self.columns.reference} = "{str(ref)}" ' \
-                f'AND {self.columns.rrev} = "{ref.revision}" '
+                f"WHERE {self.columns.reference} = '{str(ref)}' " \
+                f"AND {self.columns.rrev} = '{ref.revision}' "
         with self.db_connection() as conn:
             conn.execute(query)
 
@@ -141,7 +141,7 @@ class PackagesDBTable(BaseDbTable):
     def get_package_revisions_references(self, pref: PkgReference, only_latest_prev=False):
         assert pref.ref.revision, "To search package revisions you must provide a recipe revision."
         assert pref.package_id, "To search package revisions you must provide a package id."
-        check_prev = f'AND {self.columns.prev} = "{pref.revision}" ' if pref.revision else ''
+        check_prev = f"AND {self.columns.prev} = '{pref.revision}' " if pref.revision else ""
         if only_latest_prev:
             query = f'SELECT {self.columns.reference}, ' \
                     f'{self.columns.rrev}, ' \
@@ -152,17 +152,17 @@ class PackagesDBTable(BaseDbTable):
                     f'{self.columns.build_id}, ' \
                     f'{self.columns.lru} ' \
                     f'FROM {self.table_name} ' \
-                    f'WHERE {self.columns.rrev} = "{pref.ref.revision}" ' \
-                    f'AND {self.columns.reference} = "{str(pref.ref)}" ' \
-                    f'AND {self.columns.pkgid} = "{pref.package_id}" ' \
+                    f"WHERE {self.columns.rrev} = '{pref.ref.revision}' " \
+                    f"AND {self.columns.reference} = '{str(pref.ref)}' " \
+                    f"AND {self.columns.pkgid} = '{pref.package_id}' " \
                     f'{check_prev} ' \
                     f'AND {self.columns.prev} IS NOT NULL ' \
                     f'GROUP BY {self.columns.pkgid} '
         else:
             query = f'SELECT * FROM {self.table_name} ' \
-                    f'WHERE {self.columns.rrev} = "{pref.ref.revision}" ' \
-                    f'AND {self.columns.reference} = "{str(pref.ref)}" ' \
-                    f'AND {self.columns.pkgid} = "{pref.package_id}" ' \
+                    f"WHERE {self.columns.rrev} = '{pref.ref.revision}' " \
+                    f"AND {self.columns.reference} = '{str(pref.ref)}' " \
+                    f"AND {self.columns.pkgid} = '{pref.package_id}' " \
                     f'{check_prev} ' \
                     f'AND {self.columns.prev} IS NOT NULL ' \
                     f'ORDER BY {self.columns.timestamp} DESC'
@@ -185,13 +185,13 @@ class PackagesDBTable(BaseDbTable):
                     f'{self.columns.build_id}, ' \
                     f'{self.columns.lru} ' \
                     f'FROM {self.table_name} ' \
-                    f'WHERE {self.columns.rrev} = "{ref.revision}" ' \
-                    f'AND {self.columns.reference} = "{str(ref)}" ' \
+                    f"WHERE {self.columns.rrev} = '{ref.revision}' " \
+                    f"AND {self.columns.reference} = '{str(ref)}' " \
                     f'GROUP BY {self.columns.pkgid} '
         else:
             query = f'SELECT * FROM {self.table_name} ' \
-                    f'WHERE {self.columns.rrev} = "{ref.revision}" ' \
-                    f'AND {self.columns.reference} = "{str(ref)}" ' \
+                    f"WHERE {self.columns.rrev} = '{ref.revision}' " \
+                    f"AND {self.columns.reference} = '{str(ref)}' " \
                     f'AND {self.columns.prev} IS NOT NULL ' \
                     f'ORDER BY {self.columns.timestamp} DESC'
         with self.db_connection() as conn:
diff --git a/conan/internal/cache/db/recipes_table.py b/conan/internal/cache/db/recipes_table.py
index 38bbb3d2d..fe40ab567 100644
--- a/conan/internal/cache/db/recipes_table.py
+++ b/conan/internal/cache/db/recipes_table.py
@@ -33,7 +33,7 @@ class RecipesDBTable(BaseDbTable):
             self.columns.rrev: ref.revision,
         }
         where_expr = ' AND '.join(
-            [f'{k}="{v}" ' if v is not None else f'{k} IS NULL' for k, v in where_dict.items()])
+            [f"{k}='{v}' " if v is not None else f'{k} IS NULL' for k, v in where_dict.items()])
         return where_expr
 
     def create(self, path, ref: RecipeReference):
@@ -54,9 +54,9 @@ class RecipesDBTable(BaseDbTable):
         assert ref.revision is not None
         assert ref.timestamp is not None
         query = f"UPDATE {self.table_name} " \
-                f'SET {self.columns.timestamp} = "{ref.timestamp}" ' \
-                f'WHERE {self.columns.reference}="{str(ref)}" ' \
-                f'AND {self.columns.rrev} = "{ref.revision}" '
+                f"SET {self.columns.timestamp} = '{ref.timestamp}' " \
+                f"WHERE {self.columns.reference}='{str(ref)}' " \
+                f"AND {self.columns.rrev} = '{ref.revision}' "
         with self.db_connection() as conn:
             conn.execute(query)
 
@@ -66,7 +66,7 @@ class RecipesDBTable(BaseDbTable):
         where_clause = self._where_clause(ref)
         lru = timestamp_now()
         query = f"UPDATE {self.table_name} " \
-                f'SET {self.columns.lru} = "{lru}" ' \
+                f"SET {self.columns.lru} = '{lru}' " \
                 f"WHERE {where_clause};"
         with self.db_connection() as conn:
             conn.execute(query)
@@ -95,8 +95,8 @@ class RecipesDBTable(BaseDbTable):
 
     def get_recipe(self, ref: RecipeReference):
         query = f'SELECT * FROM {self.table_name} ' \
-                f'WHERE {self.columns.reference}="{str(ref)}" ' \
-                f'AND {self.columns.rrev} = "{ref.revision}" '
+                f"WHERE {self.columns.reference}='{str(ref)}' " \
+                f"AND {self.columns.rrev} = '{ref.revision}' "
         with self.db_connection() as conn:
             r = conn.execute(query)
             row = r.fetchone()
@@ -112,7 +112,7 @@ class RecipesDBTable(BaseDbTable):
                 f'MAX({self.columns.timestamp}), ' \
                 f'{self.columns.lru} ' \
                 f'FROM {self.table_name} ' \
-                f'WHERE {self.columns.reference} = "{str(ref)}" ' \
+                f"WHERE {self.columns.reference} = '{str(ref)}' " \
                 f'GROUP BY {self.columns.reference} '  # OTHERWISE IT FAILS THE MAX()
 
         with self.db_connection() as conn:
@@ -126,7 +126,7 @@ class RecipesDBTable(BaseDbTable):
     def get_recipe_revisions_references(self, ref: RecipeReference):
         assert ref.revision is None
         query = f'SELECT * FROM {self.table_name} ' \
-                f'WHERE {self.columns.reference} = "{str(ref)}" ' \
+                f"WHERE {self.columns.reference} = '{str(ref)}' " \
                 f'ORDER BY {self.columns.timestamp} DESC'
 
         with self.db_connection() as conn:
diff --git a/conan/tools/cmake/cmake.py b/conan/tools/cmake/cmake.py
index 3ac9760fb..02a80b39c 100644
--- a/conan/tools/cmake/cmake.py
+++ b/conan/tools/cmake/cmake.py
@@ -95,11 +95,8 @@ class CMake(object):
         if self._generator:
             arg_list.append('-G "{}"'.format(self._generator))
         if self._toolchain_file:
-            if os.path.isabs(self._toolchain_file):
-                toolpath = self._toolchain_file
-            else:
-                toolpath = os.path.join(generator_folder, self._toolchain_file)
-            arg_list.append('-DCMAKE_TOOLCHAIN_FILE="{}"'.format(toolpath.replace("\\", "/")))
+            toolpath = self._toolchain_file.replace("\\", "/")
+            arg_list.append('-DCMAKE_TOOLCHAIN_FILE="{}"'.format(toolpath))
         if self._conanfile.package_folder:
             pkg_folder = self._conanfile.package_folder.replace("\\", "/")
             arg_list.append('-DCMAKE_INSTALL_PREFIX="{}"'.format(pkg_folder))
diff --git a/conan/tools/cmake/presets.py b/conan/tools/cmake/presets.py
index c6fd71bd8..d50bfdea2 100644
--- a/conan/tools/cmake/presets.py
+++ b/conan/tools/cmake/presets.py
@@ -1,8 +1,9 @@
 import json
 import os
 import platform
+import textwrap
 
-from conan.api.output import ConanOutput
+from conan.api.output import ConanOutput, Color
 from conan.tools.cmake.layout import get_build_folder_custom_vars
 from conan.tools.cmake.toolchain.blocks import GenericSystemBlock
 from conan.tools.cmake.utils import is_multi_configuration
@@ -28,6 +29,11 @@ class _CMakePresets:
     @staticmethod
     def generate(conanfile, toolchain_file, generator, cache_variables, preset_prefix, buildenv, runenv,
                  cmake_executable):
+        toolchain_file = os.path.abspath(os.path.join(conanfile.generators_folder, toolchain_file))
+        try:  # Make it relative to the build dir if possible
+            toolchain_file = os.path.relpath(toolchain_file, conanfile.build_folder)
+        except ValueError:
+            pass
         cache_variables = cache_variables or {}
         if platform.system() == "Windows" and generator == "MinGW Makefiles":
             if "CMAKE_SH" not in cache_variables:
@@ -74,7 +80,7 @@ class _CMakePresets:
 
         preset_content = json.dumps(data, indent=4)
         save(preset_path, preset_content)
-        ConanOutput(str(conanfile)).info("CMakeToolchain generated: CMakePresets.json")
+        ConanOutput(str(conanfile)).info(f"CMakeToolchain generated: {preset_path}")
         return preset_path, data
 
     @staticmethod
@@ -172,13 +178,11 @@ class _CMakePresets:
         except:
             is_consumer = False
         if is_consumer:
-            conanfile.output.info(
-                f"Preset '{name}' added to CMakePresets.json. Invoke it manually using "
-                f"'cmake --preset {name}' if using CMake>=3.23")
-            conanfile.output.info(f"If your CMake version is not compatible with "
-                                  f"CMakePresets (<3.23) call cmake like: 'cmake <path> "
-                                  f"-G {_format_val(generator)} {add_toolchain_cache}"
-                                  f"{cache_variables_info}'")
+            msg = textwrap.dedent(f"""\
+                CMakeToolchain: Preset '{name}' added to CMakePresets.json.
+                    (cmake>=3.23) cmake --preset {name}
+                    (cmake<3.23) cmake <path> -G {_format_val(generator)} {add_toolchain_cache} {cache_variables_info}""")
+            conanfile.output.info(msg, fg=Color.CYAN)
         return ret
 
     @staticmethod
@@ -283,14 +287,15 @@ class _IncludingPresets:
 
         if inherited_user:
             _IncludingPresets._clean_user_inherits(data, preset_data)
-        data = _IncludingPresets._append_user_preset_path(data, preset_path)
+
+        try:  # Make it relative to the CMakeUserPresets.json if possible
+            preset_path = os.path.relpath(preset_path, output_dir)
+        except ValueError:
+            pass
+        data = _IncludingPresets._append_user_preset_path(data, preset_path, output_dir)
 
         data = json.dumps(data, indent=4)
-        try:
-            presets_path = os.path.relpath(user_presets_path, conanfile.generators_folder)
-        except ValueError:  # in Windows this fails if in another drive
-            presets_path = user_presets_path
-        ConanOutput(str(conanfile)).info(f"CMakeToolchain generated: {presets_path}")
+        ConanOutput(str(conanfile)).info(f"CMakeToolchain generated: {user_presets_path}")
         save(user_presets_path, data)
 
     @staticmethod
@@ -326,7 +331,7 @@ class _IncludingPresets:
             other[:] = [p for p in other if p["name"] not in presets_names]
 
     @staticmethod
-    def _append_user_preset_path(data, preset_path):
+    def _append_user_preset_path(data, preset_path, output_dir):
         """ - 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.
@@ -334,7 +339,8 @@ class _IncludingPresets:
         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)]
+        data["include"] = [i for i in data.get("include", [])
+                           if os.path.exists(os.path.join(output_dir, i))]
         if preset_path not in data["include"]:
             data["include"].append(preset_path)
         return data
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index 27a9c2260..adb338e5b 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -398,13 +398,13 @@ class AppleSystemBlock(Block):
         if not is_apple_os(self._conanfile):
             return None
 
-        def to_apple_archs(conanfile, default=None):
+        def to_apple_archs(conanfile):
             f"""converts conan-style architectures into Apple-style archs
             to be used by CMake also supports multiple architectures
             separated by '{universal_arch_separator}'"""
             arch_ = conanfile.settings.get_safe("arch") if conanfile else None
             if arch_ is not None:
-                return ";".join([_to_apple_arch(arch, default) for arch in
+                return ";".join([_to_apple_arch(arch, default=arch) for arch in
                                  arch_.split(universal_arch_separator)])
 
         # check valid combinations of architecture - os ?
diff --git a/conan/tools/cmake/toolchain/toolchain.py b/conan/tools/cmake/toolchain/toolchain.py
index 8391f9379..22e8c3801 100644
--- a/conan/tools/cmake/toolchain/toolchain.py
+++ b/conan/tools/cmake/toolchain/toolchain.py
@@ -227,16 +227,16 @@ class CMakeToolchain(object):
         check_duplicated_generator(self, self._conanfile)
         toolchain_file = self._conanfile.conf.get("tools.cmake.cmaketoolchain:toolchain_file")
         if toolchain_file is None:  # The main toolchain file generated only if user dont define
-            save(os.path.join(self._conanfile.generators_folder, self.filename), self.content)
-            ConanOutput(str(self._conanfile)).info(f"CMakeToolchain generated: {self.filename}")
+            toolchain_file = self.filename
+            save(os.path.join(self._conanfile.generators_folder, toolchain_file), self.content)
+            ConanOutput(str(self._conanfile)).info(f"CMakeToolchain generated: {toolchain_file}")
         # If we're using Intel oneAPI, we need to generate the environment file and run it
         if self._conanfile.settings.get_safe("compiler") == "intel-cc":
             IntelCC(self._conanfile).generate()
         # 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.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):
@@ -266,7 +266,7 @@ class CMakeToolchain(object):
 
             cmake_executable = self._conanfile.conf.get("tools.cmake:cmake_program", None) or self._find_cmake_exe()
 
-        write_cmake_presets(self._conanfile, toolchain, self.generator, cache_variables,
+        write_cmake_presets(self._conanfile, toolchain_file, self.generator, cache_variables,
                             self.user_presets_path, self.presets_prefix, buildenv, runenv,
                             cmake_executable)
 
diff --git a/conan/tools/gnu/__init__.py b/conan/tools/gnu/__init__.py
index 9c413ed21..cb51b0360 100644
--- a/conan/tools/gnu/__init__.py
+++ b/conan/tools/gnu/__init__.py
@@ -1,5 +1,6 @@
 from conan.tools.gnu.autotools import Autotools
 from conan.tools.gnu.autotoolstoolchain import AutotoolsToolchain
+from conan.tools.gnu.gnutoolchain import GnuToolchain
 from conan.tools.gnu.autotoolsdeps import AutotoolsDeps
 from conan.tools.gnu.pkgconfig import PkgConfig
 from conan.tools.gnu.pkgconfigdeps import PkgConfigDeps
diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py
index c81e70abe..6f961e442 100644
--- a/conan/tools/gnu/autotoolstoolchain.py
+++ b/conan/tools/gnu/autotoolstoolchain.py
@@ -1,21 +1,22 @@
+from conan.errors import ConanException
 from conan.internal import check_duplicated_generator
 from conan.internal.internal_tools import raise_on_universal_arch
-from conan.tools.apple.apple import apple_min_version_flag, is_apple_os, to_apple_arch, \
-    apple_sdk_path, resolve_apple_flags
+from conan.tools.apple.apple import is_apple_os, resolve_apple_flags
 from conan.tools.build import cmd_args_to_string, save_toolchain_args
 from conan.tools.build.cross_building import cross_building
-from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, build_type_link_flags, libcxx_flags
+from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, \
+    build_type_link_flags, \
+    libcxx_flags
 from conan.tools.env import Environment
 from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
 from conan.tools.microsoft import VCVars, msvc_runtime_flag, unix_path, check_min_vs, is_msvc
-from conan.errors import ConanException
 from conans.model.pkg_type import PackageType
 
 
 class AutotoolsToolchain:
+
     def __init__(self, conanfile, namespace=None, prefix="/"):
         """
-
         :param conanfile: The current recipe object. Always use ``self``.
         :param namespace: This argument avoids collisions when you have multiple toolchain calls in
                the same recipe. By setting this argument, the *conanbuild.conf* file used to pass
@@ -68,10 +69,10 @@ class AutotoolsToolchain:
 
             compiler = self._conanfile.settings.get_safe("compiler")
             if not self._host:
-                self._host = _get_gnu_triplet(os_host, arch_host, compiler=compiler)
+                self._host = _get_gnu_triplet(os_host, arch_host, compiler=compiler)["triplet"]
             # Build triplet
             if not self._build:
-                self._build = _get_gnu_triplet(os_build, arch_build, compiler=compiler)
+                self._build = _get_gnu_triplet(os_build, arch_build, compiler=compiler)["triplet"]
 
         sysroot = self._conanfile.conf.get("tools.build:sysroot")
         sysroot = sysroot.replace("\\", "/") if sysroot is not None else None
diff --git a/conan/tools/gnu/get_gnu_triplet.py b/conan/tools/gnu/get_gnu_triplet.py
index 5e230218b..dc7e3b68d 100644
--- a/conan/tools/gnu/get_gnu_triplet.py
+++ b/conan/tools/gnu/get_gnu_triplet.py
@@ -1,19 +1,7 @@
 from conan.errors import ConanException
 
 
-def _get_gnu_triplet(os_, arch, compiler=None):
-    """
-    Returns string with <machine>-<vendor>-<op_system> triplet (<vendor> can be omitted in practice)
-
-    :param os_: os to be used to create the triplet
-    :param arch: arch to be used to create the triplet
-    :param compiler: compiler used to create the triplet (only needed fo windows)
-    """
-
-    if os_ == "Windows" and compiler is None:
-        raise ConanException("'compiler' parameter for 'get_gnu_triplet()' is not specified and "
-                             "needed for os=Windows")
-
+def _get_gnu_arch(os_, arch):
     # Calculate the arch
     machine = {"x86": "i686",
                "x86_64": "x86_64",
@@ -67,7 +55,10 @@ def _get_gnu_triplet(os_, arch, compiler=None):
         raise ConanException("Unknown '%s' machine, Conan doesn't know how to "
                              "translate it to the GNU triplet, please report at "
                              " https://github.com/conan-io/conan/issues" % arch)
+    return machine
 
+
+def _get_gnu_os(os_, arch, compiler=None):
     # Calculate the OS
     if compiler == "gcc":
         windows_op = "w64-mingw32"
@@ -98,5 +89,24 @@ def _get_gnu_triplet(os_, arch, compiler=None):
 
         if arch == "armv8_32" and os_ == "Linux":
             op_system += "_ilp32"  # https://wiki.linaro.org/Platform/arm64-ilp32
+    return op_system
+
 
-    return "%s-%s" % (machine, op_system)
+def _get_gnu_triplet(os_, arch, compiler=None):
+    """
+    Returns string with <machine>-<vendor>-<op_system> triplet (<vendor> can be omitted in practice)
+
+    :param os_: os to be used to create the triplet
+    :param arch: arch to be used to create the triplet
+    :param compiler: compiler used to create the triplet (only needed fo windows)
+    """
+    if os_ == "Windows" and compiler is None:
+        raise ConanException("'compiler' parameter for 'get_gnu_triplet()' is not specified and "
+                             "needed for os=Windows")
+    machine = _get_gnu_arch(os_, arch)
+    op_system = _get_gnu_os(os_, arch, compiler=compiler)
+    return {
+        'machine': machine,
+        'system': op_system,
+        'triplet': f"{machine}-{op_system}"
+    }
diff --git a/conan/tools/gnu/gnutoolchain.py b/conan/tools/gnu/gnutoolchain.py
new file mode 100644
index 000000000..95c32129e
--- /dev/null
+++ b/conan/tools/gnu/gnutoolchain.py
@@ -0,0 +1,265 @@
+from conan.internal import check_duplicated_generator
+from conan.internal.internal_tools import raise_on_universal_arch
+from conan.tools.apple.apple import is_apple_os, resolve_apple_flags
+from conan.tools.build import cmd_args_to_string, save_toolchain_args
+from conan.tools.build.cross_building import cross_building
+from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, \
+    build_type_link_flags, \
+    libcxx_flags
+from conan.tools.env import Environment
+from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
+from conan.tools.microsoft import VCVars, msvc_runtime_flag, unix_path, check_min_vs, is_msvc
+from conans.model.pkg_type import PackageType
+
+
+class GnuToolchain:
+    """
+    GnuToolchain generator.
+
+    Note: it's based on legacy AutotoolsToolchain but with a more modern and usable UX
+    """
+    def __init__(self, conanfile, namespace=None, prefix="/"):
+        """
+        :param conanfile: The current recipe object. Always use ``self``.
+        :param namespace: This argument avoids collisions when you have multiple toolchain calls in
+               the same recipe. By setting this argument, the *conanbuild.conf* file used to pass
+               information to the build helper will be named as *<namespace>_conanbuild.conf*. The default
+               value is ``None`` meaning that the name of the generated file is *conanbuild.conf*. This
+               namespace must be also set with the same value in the constructor of the Autotools build
+               helper so that it reads the information from the proper file.
+        :param prefix: Folder to use for ``--prefix`` argument ("/" by default).
+        """
+        raise_on_universal_arch(conanfile)
+        self._conanfile = conanfile
+        self._namespace = namespace
+        self._is_apple_system = is_apple_os(self._conanfile)
+        self._prefix = prefix
+        # Extra flags
+        self.extra_cxxflags = []
+        self.extra_cflags = []
+        self.extra_ldflags = []
+        self.extra_defines = []
+        # Extra environment definitions
+        self.extra_env = Environment()
+        # Defines
+        self.ndebug = None
+        build_type = self._conanfile.settings.get_safe("build_type")
+        if build_type in ['Release', 'RelWithDebInfo', 'MinSizeRel']:
+            self.ndebug = "NDEBUG"
+
+        # TODO: This is also covering compilers like Visual Studio, necessary to test it (&remove?)
+        self.build_type_flags = build_type_flags(self._conanfile.settings)
+        self.build_type_link_flags = build_type_link_flags(self._conanfile.settings)
+
+        self.cppstd = cppstd_flag(self._conanfile)
+        self.arch_flag = architecture_flag(self._conanfile.settings)
+        self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile)
+        self.fpic = self._conanfile.options.get_safe("fPIC")
+        self.msvc_runtime_flag = self._get_msvc_runtime_flag()
+        self.msvc_extra_flags = self._msvc_extra_flags()
+
+        # Host/Build triplets
+        self.triplets_info = {
+            "host": {"triplet": self._conanfile.conf.get("tools.gnu:host_triplet")},
+            "build": {"triplet": self._conanfile.conf.get("tools.gnu:build_triplet")}
+        }
+        is_cross_building = cross_building(self._conanfile)
+        if is_cross_building:
+            compiler = self._conanfile.settings.get_safe("compiler")
+            # Host triplet
+            if not self.triplets_info["host"]["triplet"]:
+                os_host = conanfile.settings.get_safe("os")
+                arch_host = conanfile.settings.get_safe("arch")
+                self.triplets_info["host"] = _get_gnu_triplet(os_host, arch_host, compiler=compiler)
+            # Build triplet
+            if not self.triplets_info["build"]["triplet"]:
+                os_build = conanfile.settings_build.get_safe('os')
+                arch_build = conanfile.settings_build.get_safe('arch')
+                self.triplets_info["build"] = _get_gnu_triplet(os_build, arch_build, compiler=compiler)
+
+        sysroot = self._conanfile.conf.get("tools.build:sysroot")
+        sysroot = sysroot.replace("\\", "/") if sysroot is not None else None
+        self.sysroot_flag = "--sysroot {}".format(sysroot) if sysroot else None
+        self.configure_args = {}
+        self.autoreconf_args = {"--force": None, "--install": None}
+        self.make_args = {}
+        # Initializing configure arguments: triplets, shared flags, dirs flags, etc.
+        self.configure_args.update(self._get_default_configure_shared_flags())
+        self.configure_args.update(self._get_default_configure_install_flags())
+        self.configure_args.update(self._get_default_triplets())
+        # Apple stuff
+        is_cross_building_osx = (is_cross_building
+                                 and conanfile.settings_build.get_safe('os') == "Macos"
+                                 and is_apple_os(conanfile))
+        min_flag, arch_flag, isysroot_flag = (
+            resolve_apple_flags(conanfile, is_cross_building=is_cross_building_osx)
+        )
+        # https://man.archlinux.org/man/clang.1.en#Target_Selection_Options
+        self.apple_arch_flag = arch_flag
+        # -isysroot makes all includes for your library relative to the build directory
+        self.apple_isysroot_flag = isysroot_flag
+        self.apple_min_version_flag = min_flag
+        # MSVC common stuff
+        self._initialize_default_extra_env()
+
+    def yes_no(self, option_name, default=None, negated=False):
+        """
+        Simple wrapper to return "yes" or "no" depending on whether option_name is
+        evaluated as True or False.
+
+        :param option_name: option name.
+        :param default: Default value to return.
+        :param negated: Negates the option value if True.
+        :return: "yes" or "no" depending on whether option_name is True or False.
+        """
+        option_value = bool(self._conanfile.options.get_safe(option_name, default=default))
+        option_value = not option_value if negated else option_value
+        return "yes" if option_value else "no"
+
+    def _initialize_default_extra_env(self):
+        """Initialize the default environment variables."""
+        extra_env_vars = dict()
+        # Normally, these are the most common default flags used by MSVC in Windows
+        if is_msvc(self._conanfile):
+            extra_env_vars = {"CC": "cl -nologo",
+                              "CXX": "cl -nologo",
+                              "LD": "link -nologo",
+                              "AR": "lib",
+                              "NM": "dumpbin -symbols",
+                              "OBJDUMP": ":",
+                              "RANLIB": ":",
+                              "STRIP": ":"}
+        # Configuration map
+        compilers_mapping = {"c": "CC", "cpp": "CXX", "cuda": "NVCC", "fortran": "FC",
+                             "rc": "RC", "ld": "LD", "ar": "AR", "nm": "NM", "ranlib": "RANLIB",
+                             "objdump": "OBJDUMP", "strip": "STRIP"}
+        # Compiler definitions by conf
+        compilers_by_conf = self._conanfile.conf.get("tools.build:compiler_executables", default={},
+                                                     check_type=dict)
+        if compilers_by_conf:
+            for comp, env_var in compilers_mapping.items():
+                if comp in compilers_by_conf:
+                    compiler = compilers_by_conf[comp]
+                    # https://github.com/conan-io/conan/issues/13780
+                    compiler = unix_path(self._conanfile, compiler)
+                    extra_env_vars[env_var] = compiler  # User/tools ones have precedence
+        # Update the extra_env attribute with all the compiler values
+        for env_var, env_value in extra_env_vars.items():
+            self.extra_env.define(env_var, env_value)
+
+    def _get_msvc_runtime_flag(self):
+        flag = msvc_runtime_flag(self._conanfile)
+        return f"-{flag}" if flag else ""
+
+    def _msvc_extra_flags(self):
+        if is_msvc(self._conanfile) and check_min_vs(self._conanfile, "180", raise_invalid=False):
+            return ["-FS"]
+        return []
+
+    def _add_msvc_flags(self, flags):
+        # This is to avoid potential duplicate with users recipes -FS (alreday some in ConanCenter)
+        return [f for f in self.msvc_extra_flags if f not in flags]
+
+    @staticmethod
+    def _filter_list_empty_fields(v):
+        return list(filter(bool, v))
+
+    @staticmethod
+    def _dict_to_list(flags):
+        return [f"{k}={v}" if v else k for k, v in flags.items()]
+
+    @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)
+        vs_flag = self._add_msvc_flags(self.extra_cxxflags)
+        ret = ret + self.build_type_flags + apple_flags + self.extra_cxxflags + vs_flag + conf_flags
+        return self._filter_list_empty_fields(ret)
+
+    @property
+    def cflags(self):
+        fpic = "-fPIC" if self.fpic else None
+        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)
+        vs_flag = self._add_msvc_flags(self.extra_cflags)
+        ret = ret + self.build_type_flags + apple_flags + self.extra_cflags + vs_flag + conf_flags
+        return self._filter_list_empty_fields(ret)
+
+    @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))
+        linker_scripts = self._conanfile.conf.get("tools.build:linker_scripts", default=[],
+                                                  check_type=list)
+        conf_flags.extend(["-T'" + linker_script + "'" for linker_script in linker_scripts])
+        ret = ret + self.build_type_link_flags + apple_flags + self.extra_ldflags + conf_flags
+        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] + self.extra_defines + conf_flags
+        return self._filter_list_empty_fields(ret)
+
+    def _get_default_configure_shared_flags(self):
+        args = {}
+        # Just add these flags if there's a shared option defined (never add to exe's)
+        if self._conanfile.package_type is PackageType.SHARED:
+            args = {"--enable-shared": None, "--disable-static": None}
+        elif self._conanfile.package_type is PackageType.STATIC:
+            args = {"--disable-shared": None, "--enable-static": None}
+        return args
+
+    def _get_default_configure_install_flags(self):
+        configure_install_flags = {"--prefix": self._prefix}
+        # If someone want arguments but not the defaults can pass them in args manually
+        for flag_name, cppinfo_name in [("bindir", "bindirs"), ("sbindir", "bindirs"),
+                                        ("libdir", "libdirs"), ("includedir", "includedirs"),
+                                        ("oldincludedir", "includedirs"),
+                                        ("datarootdir", "resdirs")]:
+            elements = getattr(self._conanfile.cpp.package, cppinfo_name)
+            cppinfo_value = f"${{prefix}}/{elements[0]}" if elements else None
+            if cppinfo_value:
+                configure_install_flags[f"--{flag_name}"] = cppinfo_value
+        return configure_install_flags
+
+    def _get_default_triplets(self):
+        triplets = {}
+        for context, info in self.triplets_info.items():
+            if info.get("triplet") is not None:
+                triplets[f"--{context}"] = info["triplet"]
+        return triplets
+
+    @property
+    def _environment(self):
+        env = Environment()
+        # Flags and defines
+        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)
+        # Let's compose with user extra env variables defined (user ones have precedence)
+        return self.extra_env.compose_env(env)
+
+    def generate(self):
+        check_duplicated_generator(self, self._conanfile)
+        # Composing both environments. User extra_env definitions has precedence
+        env_vars = self._environment.vars(self._conanfile)
+        env_vars.save_script("conanautotoolstoolchain")
+        # Converts all the arguments into strings
+        args = {
+            "configure_args": cmd_args_to_string(self._dict_to_list(self.configure_args)),
+            "make_args": cmd_args_to_string(self._dict_to_list(self.make_args)),
+            "autoreconf_args": cmd_args_to_string(self._dict_to_list(self.autoreconf_args))
+        }
+        save_toolchain_args(args, namespace=self._namespace)
+        VCVars(self._conanfile).generate()
diff --git a/conans/client/cmd/uploader.py b/conans/client/cmd/uploader.py
index 65afb5150..424e100ff 100644
--- a/conans/client/cmd/uploader.py
+++ b/conans/client/cmd/uploader.py
@@ -9,7 +9,8 @@ from conans.errors import ConanException, NotFoundException
 from conans.paths import (CONAN_MANIFEST, CONANFILE, EXPORT_SOURCES_TGZ_NAME,
                           EXPORT_TGZ_NAME, PACKAGE_TGZ_NAME, CONANINFO)
 from conans.util.files import (clean_dirty, is_dirty, gather_files,
-                               gzopen_without_timestamps, set_dirty_context_manager, mkdir)
+                               gzopen_without_timestamps, set_dirty_context_manager, mkdir,
+                               human_size)
 
 UPLOAD_POLICY_FORCE = "force-upload"
 UPLOAD_POLICY_SKIP = "skip-upload"
@@ -220,10 +221,11 @@ class UploadExecutor:
 
     def upload_recipe(self, ref, bundle, remote):
         output = ConanOutput(scope=str(ref))
-        output.info(f"Uploading recipe '{ref.repr_notime()}'")
-        t1 = time.time()
         cache_files = bundle["files"]
 
+        output.info(f"Uploading recipe '{ref.repr_notime()}' ({_total_size(cache_files)})")
+
+        t1 = time.time()
         self._app.remote_manager.upload_recipe(ref, cache_files, remote)
 
         duration = time.time() - t1
@@ -232,11 +234,12 @@ class UploadExecutor:
 
     def upload_package(self, pref, prev_bundle, remote):
         output = ConanOutput(scope=str(pref.ref))
-        output.info(f"Uploading package '{pref.repr_notime()}'")
         cache_files = prev_bundle["files"]
         assert (pref.revision is not None), "Cannot upload a package without PREV"
         assert (pref.ref.revision is not None), "Cannot upload a package without RREV"
 
+        output.info(f"Uploading package '{pref.repr_notime()}' ({_total_size(cache_files)})")
+
         t1 = time.time()
         self._app.remote_manager.upload_package(pref, cache_files, remote)
         duration = time.time() - t1
@@ -259,3 +262,11 @@ def compress_files(files, name, dest_dir, compresslevel=None, ref=None):
     duration = time.time() - t1
     ConanOutput().debug(f"{name} compressed in {duration} time")
     return tgz_path
+
+
+def _total_size(cache_files):
+    total_size = 0
+    for file in cache_files.values():
+        stat = os.stat(file)
+        total_size += stat.st_size
+    return human_size(total_size)
diff --git a/conans/client/conf/config_installer.py b/conans/client/conf/config_installer.py
index fc4284fd9..82f39daa0 100644
--- a/conans/client/conf/config_installer.py
+++ b/conans/client/conf/config_installer.py
@@ -19,8 +19,8 @@ class _ConanIgnoreMatcher:
         if os.path.exists(conanignore_path):
             with open(conanignore_path, 'r') as conanignore:
                 for line in conanignore:
-                    line_content = line.strip()
-                    if line_content != "":
+                    line_content = line.split("#", maxsplit=1)[0].strip()
+                    if line_content:
                         self._ignored_entries.add(line_content)
         if ignore:
             self._ignored_entries.update(ignore)
diff --git a/conans/client/generators/__init__.py b/conans/client/generators/__init__.py
index 749e9ec2c..eeed8ddbb 100644
--- a/conans/client/generators/__init__.py
+++ b/conans/client/generators/__init__.py
@@ -8,19 +8,26 @@ from conans.client.subsystems import deduce_subsystem, subsystem_path
 from conans.errors import ConanException, conanfile_exception_formatter
 from conans.util.files import save, mkdir, chdir
 
-_generators = {"CMakeToolchain": "conan.tools.cmake", "CMakeDeps": "conan.tools.cmake",
+_generators = {"CMakeToolchain": "conan.tools.cmake",
+               "CMakeDeps": "conan.tools.cmake",
                "MesonToolchain": "conan.tools.meson",
-               "MSBuildDeps": "conan.tools.microsoft", "MSBuildToolchain": "conan.tools.microsoft",
-               "NMakeToolchain": "conan.tools.microsoft", "NMakeDeps": "conan.tools.microsoft",
+               "MSBuildDeps": "conan.tools.microsoft",
+               "MSBuildToolchain": "conan.tools.microsoft",
+               "NMakeToolchain": "conan.tools.microsoft",
+               "NMakeDeps": "conan.tools.microsoft",
                "VCVars": "conan.tools.microsoft",
                "QbsProfile": "conan.tools.qbs.qbsprofile",
                "VirtualRunEnv": "conan.tools.env.virtualrunenv",
                "VirtualBuildEnv": "conan.tools.env.virtualbuildenv",
-               "AutotoolsDeps": "conan.tools.gnu", "AutotoolsToolchain": "conan.tools.gnu",
+               "AutotoolsDeps": "conan.tools.gnu",
+               "AutotoolsToolchain": "conan.tools.gnu",
+               "GnuToolchain": "conan.tools.gnu",
                "PkgConfigDeps": "conan.tools.gnu",
-               "BazelDeps": "conan.tools.google", "BazelToolchain": "conan.tools.google",
+               "BazelDeps": "conan.tools.google",
+               "BazelToolchain": "conan.tools.google",
                "IntelCC": "conan.tools.intel",
-               "XcodeDeps": "conan.tools.apple", "XcodeToolchain": "conan.tools.apple",
+               "XcodeDeps": "conan.tools.apple",
+               "XcodeToolchain": "conan.tools.apple",
                "PremakeDeps": "conan.tools.premake",
                "MakeDeps": "conan.tools.gnu",
                "SConsDeps": "conan.tools.scons"
diff --git a/conans/client/graph/compute_pid.py b/conans/client/graph/compute_pid.py
index d86a146f6..60842cefa 100644
--- a/conans/client/graph/compute_pid.py
+++ b/conans/client/graph/compute_pid.py
@@ -57,11 +57,12 @@ def compute_package_id(node, new_config, config_version):
 
     if hasattr(conanfile, "validate_build"):
         with conanfile_exception_formatter(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)
+            with conanfile_remove_attr(conanfile, ['cpp_info'], "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)
 
     run_validate_package_id(conanfile)
 
diff --git a/conans/client/graph/graph_error.py b/conans/client/graph/graph_error.py
index b29e84fb2..cf2497e35 100644
--- a/conans/client/graph/graph_error.py
+++ b/conans/client/graph/graph_error.py
@@ -25,19 +25,15 @@ class GraphConflictError(GraphError):
                             "require": self.require.serialize()}}
 
     def __str__(self):
-        if self.node.ref is not None and self.base_previous.ref is not None:
-            return f"Version conflict: {self.node.ref}->{self.require.ref}, " \
-                   f"{self.base_previous.ref}->{self.prev_require.ref}."
-        else:
-            conflicting_node = self.node.ref or self.base_previous.ref
-            conflicting_node_msg = ""
-            if conflicting_node is not None:
-                conflicting_node_msg = f"\nConflict originates from {conflicting_node}\n"
-            return f"Version conflict: " \
-                   f"Conflict between {self.require.ref} and {self.prev_require.ref} in the graph." \
-                   f"{conflicting_node_msg}" \
-                   f"\nRun conan graph info with your recipe and add --format=html " \
-                   f"to inspect the graph errors in an easier to visualize way."
+        conflicting_node = self.node.ref or self.base_previous.ref
+        conflicting_node_msg = ""
+        if conflicting_node is not None:
+            conflicting_node_msg = f"\nConflict originates from {conflicting_node}\n"
+        return f"Version conflict: " \
+               f"Conflict between {self.require.ref} and {self.prev_require.ref} in the graph." \
+               f"{conflicting_node_msg}" \
+               f"\nRun 'conan graph info ... --format=html > graph.html' " \
+               f"and open 'graph.html' to inspect the conflict graphically."
 
 
 class GraphLoopError(GraphError):
diff --git a/conans/client/rest/conan_requester.py b/conans/client/rest/conan_requester.py
index 5c0e3f2cc..80d277054 100644
--- a/conans/client/rest/conan_requester.py
+++ b/conans/client/rest/conan_requester.py
@@ -32,9 +32,6 @@ class URLCredentials:
         creds_path = os.path.join(cache_folder, "source_credentials.json")
         if not os.path.exists(creds_path):
             return
-        template = Template(load(creds_path))
-        content = template.render({"platform": platform, "os": os})
-        content = json.loads(content)
 
         def _get_auth(credentials):
             result = {}
@@ -52,10 +49,13 @@ class URLCredentials:
                 raise ConanException(f"Unknown credentials method for '{credentials['url']}'")
 
         try:
+            template = Template(load(creds_path))
+            content = template.render({"platform": platform, "os": os})
+            content = json.loads(content)
             self._urls = {credentials["url"]: _get_auth(credentials)
                           for credentials in content["credentials"]}
-        except KeyError as e:
-            raise ConanException(f"Authentication error, wrong source_credentials.json layout: {e}")
+        except Exception as e:
+            raise ConanException(f"Error loading 'source_credentials.json' {creds_path}: {repr(e)}")
 
     def add_auth(self, url, kwargs):
         for u, creds in self._urls.items():
diff --git a/conans/client/rest/remote_credentials.py b/conans/client/rest/remote_credentials.py
index 5bed60785..33dbe638d 100644
--- a/conans/client/rest/remote_credentials.py
+++ b/conans/client/rest/remote_credentials.py
@@ -17,13 +17,16 @@ class RemoteCredentials:
         creds_path = os.path.join(cache_folder, "credentials.json")
         if not os.path.exists(creds_path):
             return
-        template = Template(load(creds_path))
-        content = template.render({"platform": platform, "os": os})
-        content = json.loads(content)
+        try:
+            template = Template(load(creds_path))
+            content = template.render({"platform": platform, "os": os})
+            content = json.loads(content)
 
-        self._urls = {credentials["remote"]: {"user": credentials["user"],
-                                              "password": credentials["password"]}
-                      for credentials in content["credentials"]}
+            self._urls = {credentials["remote"]: {"user": credentials["user"],
+                                                  "password": credentials["password"]}
+                          for credentials in content["credentials"]}
+        except Exception as e:
+            raise ConanException(f"Error loading 'credentials.json' {creds_path}: {repr(e)}")
 
     def auth(self, remote, user=None, password=None):
         if user is not None and password is not None:
diff --git a/conans/client/rest/rest_client_common.py b/conans/client/rest/rest_client_common.py
index b0956c2ce..9a3f76243 100644
--- a/conans/client/rest/rest_client_common.py
+++ b/conans/client/rest/rest_client_common.py
@@ -142,11 +142,14 @@ class RestCommonMethods(object):
             auth = self.auth
         ret = self.requester.get(url, auth=auth, headers=self.custom_headers, verify=self.verify_ssl)
 
-        server_capabilities = ret.headers.get('X-Conan-Server-Capabilities', "")
+        server_capabilities = ret.headers.get('X-Conan-Server-Capabilities')
         if not server_capabilities and not ret.ok:
             # Old Artifactory might return 401/403 without capabilities, we don't want
             # to cache them #5687, so raise the exception and force authentication
             raise get_exception_from_error(ret.status_code)(response_to_str(ret))
+        if server_capabilities is None:
+            # Some servers returning 200-ok, even if not valid repo
+            raise ConanException(f"Remote {self.remote_url} doesn't seem like a valid Conan remote")
 
         return [cap.strip() for cap in server_capabilities.split(",") if cap]
 
diff --git a/conans/client/store/localdb.py b/conans/client/store/localdb.py
index 9ae82f9eb..8525256b6 100644
--- a/conans/client/store/localdb.py
+++ b/conans/client/store/localdb.py
@@ -49,7 +49,7 @@ class LocalDB:
                 cursor = connection.cursor()
                 query = "DELETE FROM %s" % REMOTES_USER_TABLE
                 if remote_url:
-                    query += ' WHERE remote_url="{}"'.format(remote_url)
+                    query += " WHERE remote_url='{}'".format(remote_url)
                 cursor.execute(query)
                 try:
                     # https://github.com/ghaering/pysqlite/issues/109
@@ -74,7 +74,7 @@ class LocalDB:
         with self._connect() as connection:
             try:
                 statement = connection.cursor()
-                statement.execute('select user, token, refresh_token from %s where remote_url="%s"'
+                statement.execute("select user, token, refresh_token from %s where remote_url='%s'"
                                   % (REMOTES_USER_TABLE, remote_url))
                 rs = statement.fetchone()
                 if not rs:
diff --git a/conans/model/conf.py b/conans/model/conf.py
index f74ee2107..5098608e9 100644
--- a/conans/model/conf.py
+++ b/conans/model/conf.py
@@ -113,7 +113,7 @@ BUILT_IN_CONFS = {
     "tools.apple:enable_visibility": "(boolean) Enable/Disable Visibility Apple Clang flags",
     "tools.env.virtualenv:powershell": "If it is set to True it will generate powershell launchers if os=Windows",
     # Compilers/Flags configurations
-    "tools.build:compiler_executables": "Defines a Python dict-like with the compilers path to be used. Allowed keys {'c', 'cpp', 'cuda', 'objc', 'objcxx', 'rc', 'fortran', 'asm', 'hip', 'ispc'}",
+    "tools.build:compiler_executables": "Defines a Python dict-like with the compilers path to be used. Allowed keys {'c', 'cpp', 'cuda', 'objc', 'objcxx', 'rc', 'fortran', 'asm', 'hip', 'ispc', 'ld', 'ar'}",
     "tools.build:cxxflags": "List of extra CXX flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",
     "tools.build:cflags": "List of extra C flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",
     "tools.build:defines": "List of extra definition flags used by different toolchains like CMakeToolchain and AutotoolsToolchain",
diff --git a/conans/model/dependencies.py b/conans/model/dependencies.py
index 01f4afbcd..0f8640fc8 100644
--- a/conans/model/dependencies.py
+++ b/conans/model/dependencies.py
@@ -165,7 +165,9 @@ def get_transitive_requires(consumer, dependency):
     """ the transitive requires that we need are the consumer ones, not the current dependencey
     ones, so we get the current ones, then look for them in the consumer, and return those
     """
-    pkg_deps = dependency.dependencies.filter({"direct": True})
+    # The build dependencies cannot be transitive in generators like CMakeDeps,
+    # even if users make them visible
+    pkg_deps = dependency.dependencies.filter({"direct": True, "build": False})
     result = consumer.dependencies.transitive_requires(pkg_deps)
     result = result.filter({"skip": False})
     return result
diff --git a/conans/model/settings.py b/conans/model/settings.py
index 8ebe924b4..347ab40a5 100644
--- a/conans/model/settings.py
+++ b/conans/model/settings.py
@@ -205,7 +205,7 @@ class Settings(object):
 
     def get_safe(self, name, default=None):
         """
-        Get the setting value avoiding
+        Get the setting value avoiding throwing if it does not exist or has been removed
         :param name:
         :param default:
         :return:
@@ -232,7 +232,10 @@ class Settings(object):
             except KeyError:
                 pass
         else:
-            self._data.pop(name, None)
+            if name == "*":
+                self.clear()
+            else:
+                self._data.pop(name, None)
 
     def copy(self):
         """ deepcopy, recursive
diff --git a/conans/paths/__init__.py b/conans/paths/__init__.py
index dc17a7093..41e4dd953 100644
--- a/conans/paths/__init__.py
+++ b/conans/paths/__init__.py
@@ -3,6 +3,8 @@ import os
 import platform
 from pathlib import Path
 
+from conans.errors import ConanException
+
 if platform.system() == "Windows":
     from conans.util.windows import conan_expand_user
 else:
@@ -46,7 +48,7 @@ def get_conan_user_home():
     else:  # Do an expansion, just in case the user is using ~/something/here
         user_home = conan_expand_user(user_home)
     if not os.path.isabs(user_home):
-        raise Exception("Invalid CONAN_HOME value '%s', "
+        raise ConanException("Invalid CONAN_HOME value '%s', "
                         "please specify an absolute or path starting with ~/ "
                         "(relative to user home)" % user_home)
     return user_home
diff --git a/conans/util/windows.py b/conans/util/windows.py
index 53cc89c39..89c1a2752 100644
--- a/conans/util/windows.py
+++ b/conans/util/windows.py
@@ -9,8 +9,7 @@ def conan_expand_user(path):
     if path[:1] != '~':
         return path
     # In win these variables should exist and point to user directory, which
-    # must exist. Using context to avoid permanent modification of os.environ
-    old_env = dict(os.environ)
+    # must exist.
     try:
         home = os.environ.get("HOME")
         # Problematic cases of wrong HOME variable
@@ -22,6 +21,6 @@ def conan_expand_user(path):
             del os.environ["HOME"]
         result = os.path.expanduser(path)
     finally:
-        os.environ.clear()
-        os.environ.update(old_env)
+        if home is not None:
+            os.environ["HOME"] = home
     return result


Test patch:
diff --git a/conans/test/conftest.py b/conans/test/conftest.py
index 080b111b5..07b35c85b 100644
--- a/conans/test/conftest.py
+++ b/conans/test/conftest.py
@@ -52,7 +52,7 @@ tools_locations = {
     'visual_studio': {"default": "15",
                       "15": {},
                       "16": {"disabled": True},
-                      "17": {"disabled": True}},
+                      "17": {}},
     'pkg_config': {
         "exe": "pkg-config",
         "default": "0.28",
diff --git a/conans/test/functional/test_profile_detect_api.py b/conans/test/functional/test_profile_detect_api.py
index 8efa5e7a6..b33d1cb30 100644
--- a/conans/test/functional/test_profile_detect_api.py
+++ b/conans/test/functional/test_profile_detect_api.py
@@ -8,6 +8,7 @@ from conans.test.utils.tools import TestClient
 
 
 class TestProfileDetectAPI:
+    @pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows")
     @pytest.mark.tool("visual_studio", "17")
     def test_profile_detect_compiler(self):
 
@@ -45,12 +46,14 @@ class TestProfileDetectAPI:
 
     @pytest.mark.skipif(platform.system() != "Linux", reason="Only linux")
     def test_profile_detect_libc(self):
-
         client = TestClient()
         tpl1 = textwrap.dedent("""
+            {% set compiler, version, _ = detect_api.detect_gcc_compiler() %}
             {% set libc, libc_version = detect_api.detect_libc() %}
             [settings]
             os=Linux
+            compiler={{compiler}}
+            compiler.version={{version}}
             [conf]
             user.confvar:libc={{libc}}
             user.confvar:libc_version={{libc_version}}
@@ -61,9 +64,12 @@ class TestProfileDetectAPI:
         libc_name, libc_version = detect_api.detect_libc()
         assert libc_name is not None
         assert libc_version is not None
+        _, version, _ = detect_api.detect_gcc_compiler()
         expected = textwrap.dedent(f"""\
             Host profile:
             [settings]
+            compiler=gcc
+            compiler.version={version}
             os=Linux
             [conf]
             user.confvar:libc={libc_name}
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_build_context_transitive_build.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_build_context_transitive_build.py
index 51bf1019b..0436b0b1f 100644
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_build_context_transitive_build.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_build_context_transitive_build.py
@@ -135,3 +135,25 @@ def test_error_cmakedeps_transitive_build_requires():
     c.run("export tool")
     c.run("install consumer --build=missing -s:b build_type=Release -s:h build_type=Debug")
     assert "tool/0.1: Created package" in c.out
+
+
+def test_transitive_tool_requires_visible():
+    # https://github.com/conan-io/conan/issues/16058
+    # The "tool/0.1", even if visible doesn't generate any files in the "app" consumer side,
+    # even if the "app" declares it in build_context_activated, because it only works for direct
+    # dependencies. tool_requires(..., visible=True) only affects at the moment and version conflict
+    # detection
+    c = TestClient()
+    c.save({"tool/conanfile.py": GenConanfile("tool", "0.1").with_package_type("application"),
+            "pkgb/conanfile.py": GenConanfile("pkgb", "0.1").with_tool_requirement("tool/0.1",
+                                                                                   visible=True),
+            "app/conanfile.py": GenConanfile("app", "0.1").with_requires("pkgb/0.1")
+                                                          .with_settings("build_type")
+                                                          .with_generator("CMakeDeps")})
+
+    c.run("create tool")
+    c.run("create pkgb")
+    c.run("install app")
+    cmake = c.load("app/pkgb-release-data.cmake")
+    # pkgb doesn't deepnd on tool, because it is a tool-require and not build-context activated
+    assert "list(APPEND pkgb_FIND_DEPENDENCY_NAMES )" in cmake
diff --git a/conans/test/functional/toolchains/cmake/test_cmake.py b/conans/test/functional/toolchains/cmake/test_cmake.py
index d98610e4a..7743cc946 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake.py
@@ -216,13 +216,9 @@ class WinTest(Base):
                     }
         options = {"shared": shared}
         save(self.client.cache.new_config_path, "tools.build:jobs=1")
-        install_out = self._run_build(settings, options)
-
-        # FIXME: Hardcoded VS version and partial toolset check
-        toolchain_path = os.path.join(self.client.current_folder, "build",
-                                      "conan_toolchain.cmake").replace("\\", "/")
+        self._run_build(settings, options)
         self.assertIn('cmake -G "Visual Studio 15 2017" '
-                      '-DCMAKE_TOOLCHAIN_FILE="{}"'.format(toolchain_path), self.client.out)
+                      '-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"', self.client.out)
         if toolset == "v140":
             self.assertIn("Microsoft Visual Studio 14.0", self.client.out)
         else:
@@ -312,12 +308,10 @@ class WinTest(Base):
                     "build_type": build_type,
                     }
         options = {"shared": shared}
-        install_out = self._run_build(settings, options)
+        self._run_build(settings, options)
         self.assertIn("The C compiler identification is GNU", self.client.out)
-        toolchain_path = os.path.join(self.client.current_folder, "build",
-                                      "conan_toolchain.cmake").replace("\\", "/")
         self.assertIn('cmake -G "MinGW Makefiles" '
-                      '-DCMAKE_TOOLCHAIN_FILE="{}"'.format(toolchain_path), self.client.out)
+                      '-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"', self.client.out)
         assert '-DCMAKE_SH="CMAKE_SH-NOTFOUND"' in self.client.out
 
         def _verify_out(marker=">>"):
@@ -370,10 +364,8 @@ class LinuxTest(Base):
                     "arch": arch,
                     "build_type": build_type}
         self._run_build(settings, {"shared": shared})
-        toolchain_path = os.path.join(self.client.current_folder, "build",
-                                      "conan_toolchain.cmake").replace("\\", "/")
         self.assertIn('cmake -G "Unix Makefiles" '
-                      '-DCMAKE_TOOLCHAIN_FILE="{}"'.format(toolchain_path), self.client.out)
+                      '-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"', self.client.out)
 
         extensions_str = "ON" if "gnu" in cppstd else "OFF"
         arch_str = "-m32" if arch == "x86" else "-m64"
@@ -430,10 +422,8 @@ class AppleTest(Base):
                     "build_type": build_type}
         self._run_build(settings, {"shared": shared})
 
-        toolchain_path = os.path.join(self.client.current_folder, "build",
-                                      "conan_toolchain.cmake").replace("\\", "/")
         self.assertIn('cmake -G "Unix Makefiles" '
-                      '-DCMAKE_TOOLCHAIN_FILE="{}"'.format(toolchain_path), self.client.out)
+                      '-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"', self.client.out)
 
         extensions_str = "OFF" if cppstd else ""
         vals = {"CMAKE_CXX_STANDARD": cppstd,
diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
index 2463c2f97..17ded05c2 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
@@ -693,7 +693,7 @@ def test_cmake_presets_multiple_settings_single_config():
     assert os.path.exists(user_presets_path)
     user_presets = json.loads(load(user_presets_path))
     assert len(user_presets["include"]) == 1
-    presets = json.loads(load(user_presets["include"][0]))
+    presets = json.loads(client.load(user_presets["include"][0]))
     assert len(presets["configurePresets"]) == 1
     assert len(presets["buildPresets"]) == 1
     assert len(presets["testPresets"]) == 1
@@ -710,7 +710,7 @@ def test_cmake_presets_multiple_settings_single_config():
     assert os.path.exists(user_presets_path)
     user_presets = json.loads(load(user_presets_path))
     assert len(user_presets["include"]) == 2
-    presets = json.loads(load(user_presets["include"][0]))
+    presets = json.loads(client.load(user_presets["include"][0]))
     assert len(presets["configurePresets"]) == 1
     assert len(presets["buildPresets"]) == 1
     assert len(presets["testPresets"]) == 1
@@ -720,7 +720,7 @@ def test_cmake_presets_multiple_settings_single_config():
     assert presets["testPresets"][0]["name"] == "conan-apple-clang-12.0-gnu17-release"
     assert presets["testPresets"][0]["configurePreset"] == "conan-apple-clang-12.0-gnu17-release"
 
-    presets = json.loads(load(user_presets["include"][1]))
+    presets = json.loads(client.load(user_presets["include"][1]))
     assert len(presets["configurePresets"]) == 1
     assert len(presets["buildPresets"]) == 1
     assert len(presets["testPresets"]) == 1
@@ -741,7 +741,7 @@ def test_cmake_presets_multiple_settings_single_config():
     user_presets = json.loads(load(user_presets_path))
     # The [0] is the apple-clang 12 the [1] is the apple-clang 13
     assert len(user_presets["include"]) == 3
-    presets = json.loads(load(user_presets["include"][2]))
+    presets = json.loads(client.load(user_presets["include"][2]))
     assert len(presets["configurePresets"]) == 1
     assert len(presets["buildPresets"]) == 1
     assert len(presets["testPresets"]) == 1
@@ -887,7 +887,7 @@ def test_cmake_presets_multiple_settings_multi_config():
     assert os.path.exists(user_presets_path)
     user_presets = json.loads(load(user_presets_path))
     assert len(user_presets["include"]) == 1
-    presets = json.loads(load(user_presets["include"][0]))
+    presets = json.loads(client.load(user_presets["include"][0]))
     assert len(presets["configurePresets"]) == 1
     assert len(presets["buildPresets"]) == 1
     assert len(presets["testPresets"]) == 1
@@ -904,7 +904,7 @@ def test_cmake_presets_multiple_settings_multi_config():
     assert os.path.exists(user_presets_path)
     user_presets = json.loads(load(user_presets_path))
     assert len(user_presets["include"]) == 1
-    presets = json.loads(load(user_presets["include"][0]))
+    presets = json.loads(client.load(user_presets["include"][0]))
     assert len(presets["configurePresets"]) == 1
     assert len(presets["buildPresets"]) == 2
     assert len(presets["testPresets"]) == 2
@@ -928,7 +928,7 @@ def test_cmake_presets_multiple_settings_multi_config():
     user_presets = json.loads(load(user_presets_path))
     # The [0] is the msvc dynamic/14 the [1] is the static/17
     assert len(user_presets["include"]) == 2
-    presets = json.loads(load(user_presets["include"][1]))
+    presets = json.loads(client.load(user_presets["include"][1]))
     assert len(presets["configurePresets"]) == 1
     assert len(presets["buildPresets"]) == 1
     assert len(presets["testPresets"]) == 1
diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain_win_clang.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain_win_clang.py
index c2fcd265e..2b0a03695 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain_win_clang.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain_win_clang.py
@@ -9,7 +9,6 @@ from conans.test.assets.cmake import gen_cmakelists
 from conans.test.assets.sources import gen_function_cpp, gen_function_c
 from conans.test.functional.utils import check_vs_runtime, check_exe_run
 from conans.test.utils.tools import TestClient
-from conans.util.env import environment_update
 
 
 @pytest.fixture
@@ -65,7 +64,7 @@ def client():
 
 
 @pytest.mark.tool("cmake")
-@pytest.mark.tool("clang", "13")
+@pytest.mark.tool("clang", "16")
 @pytest.mark.skipif(platform.system() != "Windows", reason="requires Win")
 class TestLLVMClang:
     """ External LLVM/clang, with different CMake generators
@@ -74,7 +73,7 @@ class TestLLVMClang:
 
     @pytest.mark.tool("mingw64")
     @pytest.mark.tool("visual_studio", "17")
-    @pytest.mark.tool("clang", "13")  # repeated, for priority over the mingw64 clang
+    @pytest.mark.tool("clang", "16")  # repeated, for priority over the mingw64 clang
     @pytest.mark.parametrize("runtime", ["static", "dynamic"])
     def test_clang_mingw(self, client, runtime):
         """ compiling with an LLVM-clang installed, which uses by default the
@@ -86,7 +85,7 @@ class TestLLVMClang:
         # clang compilations in Windows will use MinGW Makefiles by default
         assert 'cmake -G "MinGW Makefiles"' in client.out
         assert "GNU-like command-line" in client.out
-        assert "main __clang_major__13" in client.out
+        assert "main __clang_major__16" in client.out
         assert "main _MSC_VER193" in client.out
         assert "main _MSVC_LANG2014" in client.out
         assert "main _M_X64 defined" in client.out
@@ -107,7 +106,7 @@ class TestLLVMClang:
 
         assert 'cmake -G "{}"'.format(generator) in client.out
         assert "GNU-like command-line" in client.out
-        assert "main __clang_major__13" in client.out
+        assert "main __clang_major__16" in client.out
         assert "main _MSC_VER193" in client.out
         assert "main _MSVC_LANG2014" in client.out
         assert "main _M_X64 defined" in client.out
@@ -117,7 +116,7 @@ class TestLLVMClang:
         check_vs_runtime(cmd, client, "17", build_type="Release", static_runtime=False)
 
     @pytest.mark.tool("visual_studio", "16")
-    @pytest.mark.tool("clang", "13")  # repeated, for priority over the mingw64 clang
+    @pytest.mark.tool("clang", "16")  # repeated, for priority over the mingw64 clang
     def test_clang_cmake_runtime_version(self, client):
         generator = "Ninja"
         # Make sure that normal CMakeLists with verify=False works
@@ -129,7 +128,7 @@ class TestLLVMClang:
 
         assert 'cmake -G "{}"'.format(generator) in client.out
         assert "GNU-like command-line" in client.out
-        assert "main __clang_major__13" in client.out
+        assert "main __clang_major__16" in client.out
         # Check this! Clang compiler in Windows is reporting MSC_VER and MSVC_LANG!
         assert "main _MSC_VER192" in client.out
         assert "main _MSVC_LANG2017" in client.out
@@ -155,6 +154,7 @@ class TestVSClangCL:
                    '-c tools.cmake.cmaketoolchain:generator="{}"'.format(generator))
         assert 'cmake -G "{}"'.format(generator) in client.out
         assert "MSVC-like command-line" in client.out
+        # My local is 17, but CI ClangCL still 16
         assert "main __clang_major__16" in client.out
         # Check this! Clang compiler in Windows is reporting MSC_VER and MSVC_LANG!
         assert "main _MSC_VER193" in client.out
@@ -164,7 +164,7 @@ class TestVSClangCL:
         assert "-m64" not in client.out
         cmd = re.search(r"MYCMD=(.*)!", str(client.out)).group(1)
         cmd = cmd + ".exe"
-        check_vs_runtime(cmd, client, "16", build_type="Release", static_runtime=False)
+        check_vs_runtime(cmd, client, "17", build_type="Release", static_runtime=False)
 
 
 @pytest.mark.tool("cmake")
@@ -182,7 +182,7 @@ class TestMsysClang:
         # clang compilations in Windows will use MinGW Makefiles by default
         assert 'cmake -G "MinGW Makefiles"' in client.out
         # TODO: Version is still not controlled
-        assert "main __clang_major__14" in client.out
+        assert "main __clang_major__15" in client.out
         # Not using libstdc++
         assert "_GLIBCXX_USE_CXX11_ABI" not in client.out
         assert "main __cplusplus2014" in client.out
@@ -212,7 +212,7 @@ class TestMsysClang:
         # clang compilations in Windows will use MinGW Makefiles by default
         assert 'cmake -G "MinGW Makefiles"' in client.out
         # TODO: Version is still not controlled
-        assert "main __clang_major__14" in client.out
+        assert "main __clang_major__15" in client.out
         assert "main _GLIBCXX_USE_CXX11_ABI 0" in client.out
         assert "main __cplusplus2014" in client.out
         assert "main __GNUC__" in client.out
@@ -241,7 +241,7 @@ class TestMsysClang:
         client.run(f"create . --name=pkg --version=0.1 -pr=clang")
         # clang compilations in Windows will use MinGW Makefiles by default
         assert 'cmake -G "MinGW Makefiles"' in client.out
-        assert "main __clang_major__14" in client.out
+        assert "main __clang_major__15" in client.out
         assert "GLIBCXX" not in client.out
         assert "cplusplus" not in client.out
         assert "main __GNUC__" in client.out
@@ -260,27 +260,22 @@ class TestMsysClang:
 
 
 @pytest.mark.tool("cmake")
-@pytest.mark.tool("clang", "12")
+@pytest.mark.tool("ninja")
+@pytest.mark.tool("clang", "16")
 @pytest.mark.skipif(platform.system() != "Windows", reason="requires Win")
 def test_error_clang_cmake_ninja_custom_cxx(client):
-    with environment_update({"CXX": "/no/exist/clang++"}):
-        client.run("create . --name=pkg --version=0.1 -pr=clang -c tools.cmake.cmaketoolchain:generator=Ninja",
-                   assert_error=True)
-        assert 'Could not find compiler' in client.out
-        assert '/no/exist/clang++' in client.out
-
     clang_profile = textwrap.dedent("""
         [settings]
         os=Windows
         arch=x86_64
         build_type=Release
         compiler=clang
-        compiler.version=12
+        compiler.version=16
         [buildenv]
         CXX=/no/exist/clang++
         """)
     client.save({"clang":     clang_profile})
-    client.run("create . --name=pkg --version=0.1 -pr=clang -c tools.cmake.cmaketoolchain:generator=Ninja",
-               assert_error=True)
+    client.run("create . --name=pkg --version=0.1 -pr=clang "
+               "-c tools.cmake.cmaketoolchain:generator=Ninja", assert_error=True)
     assert 'Could not find compiler' in client.out
     assert '/no/exist/clang++' in client.out
diff --git a/conans/test/functional/toolchains/gnu/test_gnutoolchain_apple.py b/conans/test/functional/toolchains/gnu/test_gnutoolchain_apple.py
new file mode 100644
index 000000000..ce146db9c
--- /dev/null
+++ b/conans/test/functional/toolchains/gnu/test_gnutoolchain_apple.py
@@ -0,0 +1,81 @@
+import os
+import platform
+import textwrap
+
+import pytest
+
+from conan.tools.apple.apple import _to_apple_arch
+from conans.test.assets.autotools import gen_makefile
+from conans.test.assets.sources import gen_function_h, gen_function_cpp
+from conans.test.utils.tools import TestClient
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only OSX")
+@pytest.mark.parametrize("config", [("x86_64", "Macos", "10.14", None),
+                                    ("armv8", "iOS", "10.0", "iphoneos"),
+                                    ("armv7", "iOS", "10.0", "iphoneos"),
+                                    ("x86", "iOS", "10.0", "iphonesimulator"),
+                                    ("x86_64", "iOS", "10.0", "iphonesimulator"),
+                                    ("armv8", "Macos", "10.14", None)  # M1
+                                    ])
+def test_makefile_arch(config):
+    makefile = gen_makefile(apps=["app"], libs=["hello"])
+    conanfile_py = textwrap.dedent("""
+        from conan import ConanFile, tools
+        from conan.tools.gnu import Autotools
+
+        class App(ConanFile):
+            settings = "os", "arch", "compiler", "build_type"
+            options = {"shared": [True, False], "fPIC": [True, False]}
+            default_options = {"shared": False, "fPIC": True}
+            generators = "GnuToolchain"
+
+            def config_options(self):
+                if self.settings.os == "Windows":
+                    self.options.rm_safe("fPIC")
+
+            def configure(self):
+                if self.options.shared:
+                    self.options.rm_safe("fPIC")
+
+            def build(self):
+                env_build = Autotools(self)
+                env_build.make()
+    """)
+    arch, os_, os_version, os_sdk = config
+    profile = textwrap.dedent("""
+                include(default)
+                [settings]
+                os = {os}
+                {os_sdk}
+                os.version = {os_version}
+                arch = {arch}
+                """).format(os=os_, arch=arch,
+                            os_version=os_version, os_sdk="os.sdk = " + os_sdk if os_sdk else "")
+
+    t = TestClient()
+    hello_h = gen_function_h(name="hello")
+    hello_cpp = gen_function_cpp(name="hello")
+    main_cpp = gen_function_cpp(name="main", includes=["hello"], calls=["hello"])
+
+    t.save({"Makefile": makefile,
+            "hello.h": hello_h,
+            "hello.cpp": hello_cpp,
+            "app.cpp": main_cpp,
+            "conanfile.py": conanfile_py,
+            "profile": profile})
+
+    t.run("install . --profile:host=profile --profile:build=default")
+    t.run("build . --profile:host=profile --profile:build=default")
+
+    libhello = os.path.join(t.current_folder, "libhello.a")
+    app = os.path.join(t.current_folder, "app")
+    assert os.path.isfile(libhello)
+    assert os.path.isfile(app)
+
+    expected_arch = _to_apple_arch(arch)
+    t.run_command('lipo -info "%s"' % libhello)
+    assert "architecture: %s" % expected_arch in t.out
+
+    t.run_command('lipo -info "%s"' % app)
+    assert "architecture: %s" % expected_arch in t.out
diff --git a/conans/test/functional/toolchains/gnu/test_v2_autotools_template.py b/conans/test/functional/toolchains/gnu/test_v2_autotools_template.py
index 1e9b3685f..93c84e1f1 100644
--- a/conans/test/functional/toolchains/gnu/test_v2_autotools_template.py
+++ b/conans/test/functional/toolchains/gnu/test_v2_autotools_template.py
@@ -338,3 +338,39 @@ def test_autotools_fix_shared_libs():
     # Running the test-package also works
     client.run("test test_package hello/0.1@ -o hello/*:shared=True")
     assert "Bye, bye!" in client.out
+
+
+@pytest.mark.skip(reason="Test too slow, and needs fix to AutotoolsDeps")
+@pytest.mark.tool("msys2")
+class TestAutotoolsTemplateWindows:
+    def test_msys2_autotools_windows(self):
+        c = TestClient(path_with_spaces=False)
+        c.run("new autotools_lib -d name=hello -d version=1.0")
+        # TODO: Can we reduce the configuration? maybe path=bash can be defaulted?
+        msys2 = textwrap.dedent("""
+            include(default)
+            [conf]
+            tools.microsoft.bash:subsystem=msys2
+            tools.microsoft.bash:path=bash
+            tools.build:compiler_executables={"c": "cl", "cpp": "cl"}
+            """)
+        c.save({"msys2": msys2})
+        # FIXME: Need to deactivate test_package because AutotoolsDeps doesn't work in Win
+        c.run("create . -pr=msys2 -tf=")
+        # This will not crash
+        assert "conanvcvars.bat: Activating environment" in c.out
+        assert "hello/1.0: package(): Packaged 1 '.lib' file: hello.lib" in c.out
+
+    def test_msys2_autotools_exe_windows(self):
+        c = TestClient(path_with_spaces=False)
+        c.run("new autotools_exe -d name=hello -d version=1.0")
+        msys2 = textwrap.dedent("""
+            include(default)
+            [conf]
+            tools.microsoft.bash:subsystem=msys2
+            tools.microsoft.bash:path=bash
+            tools.build:compiler_executables={"c": "cl", "cpp": "cl"}
+            """)
+        c.save({"msys2": msys2})
+        c.run("create . -pr=msys2")
+        assert "hello/1.0: _MSC_VER19" in c.out
diff --git a/conans/test/functional/toolchains/microsoft/test_msbuild.py b/conans/test/functional/toolchains/microsoft/test_msbuild.py
index fd90b06d3..104813008 100644
--- a/conans/test/functional/toolchains/microsoft/test_msbuild.py
+++ b/conans/test/functional/toolchains/microsoft/test_msbuild.py
@@ -426,7 +426,7 @@ class TestWin:
     def test_toolchain_win_vs2017(self, compiler, version, runtime, cppstd):
         self.check_toolchain_win(compiler, version, runtime, cppstd, ide_version=15)
 
-    @pytest.mark.tool("cmake", "3.21")
+    @pytest.mark.tool("cmake", "3.23")
     @pytest.mark.tool("visual_studio", "17")
     @pytest.mark.parametrize("compiler,version,runtime,cppstd",
                              [("msvc", "193", "static", "17")])
diff --git a/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py b/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
index c71e536a5..5551f171c 100644
--- a/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
+++ b/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
@@ -713,7 +713,7 @@ def test_build_vs_project_with_a_vs2017():
 
 
 @pytest.mark.tool("visual_studio", "17")
-@pytest.mark.tool("cmake")
+@pytest.mark.tool("cmake", "3.23")
 @pytest.mark.skipif(platform.system() != "Windows", reason="Requires MSBuild")
 def test_build_vs_project_with_a_vs2022():
     check_build_vs_project_with_a("193")
@@ -782,10 +782,16 @@ def check_build_vs_project_with_a(vs_version):
     main_cpp = gen_function_cpp(name="main", includes=["hello"], calls=["hello"])
     files["MyProject/main.cpp"] = main_cpp
     files["conanfile.py"] = consumer
+    # INJECT PROPS FILES
     props = os.path.join(client.current_folder, "conandeps.props")
-    old = r'<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />'
-    new = old + '<Import Project="{props}" />'.format(props=props)
+    old = r'<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />'
+    new = old + f'<Import Project="{props}" />'
+    files["MyProject/MyProject.vcxproj"] = files["MyProject/MyProject.vcxproj"].replace(old, new)
+    old = r'<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />'
+    toolchain = os.path.join(client.current_folder, "conantoolchain.props")
+    new = f'<Import Project="{toolchain}" />' + old
     files["MyProject/MyProject.vcxproj"] = files["MyProject/MyProject.vcxproj"].replace(old, new)
+
     client.save(files, clean_first=True)
     client.run('build . -s compiler=msvc'
                ' -s compiler.version={vs_version}'.format(vs_version=vs_version))
@@ -803,7 +809,7 @@ def test_build_vs_project_with_test_requires_vs2017():
 
 
 @pytest.mark.tool("visual_studio", "17")
-@pytest.mark.tool("cmake")
+@pytest.mark.tool("cmake", "3.23")
 @pytest.mark.skipif(platform.system() != "Windows", reason="Requires MSBuild")
 def test_build_vs_project_with_test_requires_vs2022():
     check_build_vs_project_with_test_requires("193")
@@ -837,10 +843,17 @@ def check_build_vs_project_with_test_requires(vs_version):
     main_cpp = gen_function_cpp(name="main", includes=["mydep_pkg_team"], calls=["mydep_pkg_team"])
     files["MyProject/main.cpp"] = main_cpp
     files["conanfile.py"] = consumer
+
+    # INJECT PROPS FILES
     props = os.path.join(client.current_folder, "conandeps.props")
-    old = r'<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />'
-    new = old + '<Import Project="{props}" />'.format(props=props)
+    old = r'<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />'
+    new = old + f'<Import Project="{props}" />'
+    files["MyProject/MyProject.vcxproj"] = files["MyProject/MyProject.vcxproj"].replace(old, new)
+    old = r'<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />'
+    toolchain = os.path.join(client.current_folder, "conantoolchain.props")
+    new = f'<Import Project="{toolchain}" />' + old
     files["MyProject/MyProject.vcxproj"] = files["MyProject/MyProject.vcxproj"].replace(old, new)
+
     client.save(files, clean_first=True)
     client.run('build .  -s compiler.version={vs_version}'.format(vs_version=vs_version))
     client.run_command(r"x64\Release\MyProject.exe")
diff --git a/conans/test/functional/toolchains/test_basic.py b/conans/test/functional/toolchains/test_basic.py
index 54fad8c36..314b44e79 100644
--- a/conans/test/functional/toolchains/test_basic.py
+++ b/conans/test/functional/toolchains/test_basic.py
@@ -102,9 +102,7 @@ class BasicTest(unittest.TestCase):
         client = TestClient()
         client.save({"conanfile.py": conanfile})
         client.run("build .", assert_error=True)  # No CMakeLists.txt
-        toolchain_path = os.path.join(client.current_folder,
-                                      "conan_toolchain.cmake").replace("\\", "/")
-        self.assertIn('-DCMAKE_TOOLCHAIN_FILE="{}"'.format(toolchain_path),  client.out)
+        self.assertIn('-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"',  client.out)
         self.assertIn("ERROR: conanfile.py: Error in build() method", client.out)
 
     @pytest.mark.tool("visual_studio")
diff --git a/conans/test/functional/utils.py b/conans/test/functional/utils.py
index 611fb8bab..7d92a89d1 100644
--- a/conans/test/functional/utils.py
+++ b/conans/test/functional/utils.py
@@ -46,7 +46,8 @@ def check_vs_runtime(artifact, client, vs_version, build_type, architecture="amd
                     assert "libunwind.dll" not in client.out
                     assert "libc++.dll" not in client.out
                 else:
-                    assert "libunwind.dll" in client.out
+                    # Latest clangs from subsystems no longer depend on libunwind
+                    assert "libunwind.dll" not in client.out
                     assert "libc++.dll" in client.out
             else:
                 raise Exception("unknown {}".format(subsystem))
diff --git a/conans/test/integration/command/config_test.py b/conans/test/integration/command/config_test.py
index b47bf91ae..f35d1ea1d 100644
--- a/conans/test/integration/command/config_test.py
+++ b/conans/test/integration/command/config_test.py
@@ -65,9 +65,12 @@ def test_config_install():
 def test_config_install_conanignore():
     tc = TestClient()
     conanignore = textwrap.dedent("""
-    a/*
+    a/*  # This is a tests
     b/c/*
     d/*
+    tests/*
+    # Next line is commented out, so it should be ignored
+    # other_tests/*
     """)
     tc.save({
         'config_folder/.conanignore': conanignore,
@@ -78,7 +81,9 @@ def test_config_install_conanignore():
         'config_folder/b/c/helmet': '',
         'config_folder/d/prix': '',
         'config_folder/d/foo/bar': '',
-        'config_folder/foo': ''
+        'config_folder/foo': '',
+        'config_folder/tests/tester': '',
+        'config_folder/other_tests/tester2': ''
     })
     def _assert_config_exists(path):
         assert os.path.exists(os.path.join(tc.cache_folder, path))
@@ -107,6 +112,9 @@ def test_config_install_conanignore():
 
     _assert_config_exists("foo")
 
+    _assert_config_not_exists("tests/tester")
+    _assert_config_exists("other_tests/tester2")
+
     os.listdir(tc.current_folder)
 
 
diff --git a/conans/test/integration/command/info/test_graph_info_graphical.py b/conans/test/integration/command/info/test_graph_info_graphical.py
index 29dfe14b4..6637f2299 100644
--- a/conans/test/integration/command/info/test_graph_info_graphical.py
+++ b/conans/test/integration/command/info/test_graph_info_graphical.py
@@ -131,7 +131,7 @@ def test_graph_info_html_error_reporting_output():
 
     tc.run("graph info --requires=math/1.0 --requires=ui/1.0 --format=html", assert_error=True,
            redirect_stdout="graph.html")
-    assert "ERROR: Version conflict:" in tc.out # check that it doesn't crash
+    assert "ERROR: Version conflict:" in tc.out  # check that it doesn't crash
 
     # change order,  just in case
     tc.run("graph info --requires=ui/1.0 --requires=math/1.0 --format=html", assert_error=True,
@@ -144,3 +144,20 @@ def test_graph_info_html_error_reporting_output():
     assert "ERROR: Version conflict:" in tc.out  # check that it doesn't crash
     # Check manually
     # tc.run_command(f"{tc.current_folder}/graph.html")
+
+
+def test_graph_conflict_diamond():
+    c = TestClient()
+    c.save({"math/conanfile.py": GenConanfile("math"),
+            "engine/conanfile.py": GenConanfile("engine", "1.0").with_requires("math/1.0"),
+            "ai/conanfile.py": GenConanfile("ai", "1.0").with_requires("math/1.0.1"),
+            "game/conanfile.py": GenConanfile("game", "1.0").with_requires("engine/1.0", "ai/1.0"),
+            })
+    c.run("create math --version=1.0")
+    c.run("create math --version=1.0.1")
+    c.run("create math --version=1.0.2")
+    c.run("create engine")
+    c.run("create ai")
+    c.run("graph info game --format=html", assert_error=True, redirect_stdout="graph.html")
+    # check that it doesn't crash
+    assert "ERROR: Version conflict: Conflict between math/1.0.1 and math/1.0 in the graph." in c.out
diff --git a/conans/test/integration/command/remote_test.py b/conans/test/integration/command/remote_test.py
index b687fb592..96c66843c 100644
--- a/conans/test/integration/command/remote_test.py
+++ b/conans/test/integration/command/remote_test.py
@@ -344,6 +344,13 @@ def test_add_wrong_conancenter():
     assert "the correct remote API is https://center.conan.io" in c.out
 
 
+def test_wrong_remotes_json_file():
+    c = TestClient(light=True)
+    c.save_home({"remotes.json": ""})
+    c.run("remote list", assert_error=True)
+    assert "ERROR: Error loading JSON remotes file" in c.out
+
+
 def test_allowed_packages_remotes():
     tc = TestClient(light=True, default_server_user=True)
     tc.save({"conanfile.py": GenConanfile(),
diff --git a/conans/test/integration/command/source_test.py b/conans/test/integration/command/source_test.py
index d6e6a8393..57644154e 100644
--- a/conans/test/integration/command/source_test.py
+++ b/conans/test/integration/command/source_test.py
@@ -1,4 +1,5 @@
 import os
+import re
 import textwrap
 import unittest
 from collections import OrderedDict
@@ -156,6 +157,9 @@ class ConanLib(ConanFile):
         client.run("create . --name=hello --version=0.1")
         rrev = client.exported_recipe_revision()
         client.run("upload hello/0.1 -r server0")
+        # Ensure we uploaded it
+        assert re.search(r"Uploading recipe 'hello/0.1#.*' \(.*\)", client.out)
+        assert re.search(r"Uploading package 'hello/0.1#.*' \(.*\)", client.out)
         client.run("remove * -c")
 
         # install from server0 that has the sources, upload to server1 (does not have the package)
diff --git a/conans/test/integration/command/upload/upload_test.py b/conans/test/integration/command/upload/upload_test.py
index 7a17a61aa..eda0c0695 100644
--- a/conans/test/integration/command/upload/upload_test.py
+++ b/conans/test/integration/command/upload/upload_test.py
@@ -8,6 +8,7 @@ from collections import OrderedDict
 import pytest
 import requests
 from mock import patch
+from requests import Response
 
 from conans.errors import ConanException
 from conans.model.package_ref import PkgReference
@@ -485,6 +486,21 @@ class UploadTest(unittest.TestCase):
         client.run("upload hello0/1.2.1@user/testing -r default")
         assert "Uploading recipe 'hello0/1.2.1@user/testing" in client.out
 
+    def test_server_returns_200_ok(self):
+        # https://github.com/conan-io/conan/issues/16104
+        # If server returns 200 ok, without headers, it raises an error
+        class MyHttpRequester(TestRequester):
+            def get(self, _, **kwargs):
+                resp = Response()
+                resp.status_code = 200
+                return resp
+
+        client = TestClient(requester_class=MyHttpRequester, servers={"default": TestServer()})
+        client.save({"conanfile.py": GenConanfile("hello0", "1.2.1")})
+        client.run("create . ")
+        client.run("upload * -c -r default", assert_error=True)
+        assert "doesn't seem like a valid Conan remote" in client.out
+
 
 def test_upload_only_without_user_channel():
     """
diff --git a/conans/test/integration/command_v2/test_cache_save_restore.py b/conans/test/integration/command_v2/test_cache_save_restore.py
index 046e0fb0e..2d5301b60 100644
--- a/conans/test/integration/command_v2/test_cache_save_restore.py
+++ b/conans/test/integration/command_v2/test_cache_save_restore.py
@@ -211,3 +211,9 @@ def test_cache_save_subfolder():
     c.run("export .")
     c.run("cache save * --file=subfolder/cache.tgz")
     assert os.path.exists(os.path.join(c.current_folder, "subfolder", "cache.tgz"))
+
+
+def test_error_restore_not_existing():
+    c = TestClient()
+    c.run("cache restore potato.tgz", assert_error=True)
+    assert "ERROR: Restore archive doesn't exist in " in c.out
diff --git a/conans/test/integration/command_v2/test_version.py b/conans/test/integration/command_v2/test_version.py
index 6ddc7aff1..3f397d105 100644
--- a/conans/test/integration/command_v2/test_version.py
+++ b/conans/test/integration/command_v2/test_version.py
@@ -21,8 +21,17 @@ def test_version_json():
     t.run("version --format=json")
     js = json.loads(t.stdout)
     assert js["version"] == __version__
+    assert js["conan_path"] == sys.argv[0]
     assert js["python"]["version"] == _python_version()
     assert js["python"]["sys_version"] == _sys_version()
+    assert js["python"]["sys_executable"] == sys.executable
+    assert js["python"]["is_frozen"] == getattr(sys, 'frozen', False)
+    assert js["python"]["architecture"] == platform.machine()
+    assert js["system"]["version"] == platform.version()
+    assert js["system"]["platform"] == platform.platform()
+    assert js["system"]["system"] == platform.system()
+    assert js["system"]["release"] == platform.release()
+    assert js["system"]["cpu"] == platform.processor()
 
 
 def test_version_text():
@@ -47,6 +56,16 @@ def test_version_raw():
 def _validate_text_output(output):
     lines = output.splitlines()
     assert f'version: {__version__}' in lines
+    assert f'conan_path: {sys.argv[0]}' in lines
     assert 'python' in lines
     assert f'  version: {_python_version()}' in lines
     assert f'  sys_version: {_sys_version()}' in lines
+    assert f'  sys_executable: {sys.executable}' in lines
+    assert f'  is_frozen: {getattr(sys, "frozen", False)}' in lines
+    assert f'  architecture: {platform.machine()}' in lines
+    assert 'system' in lines
+    assert f'  version: {platform.version()}' in lines
+    assert f'  platform: {platform.platform()}' in lines
+    assert f'  system: {platform.system()}' in lines
+    assert f'  release: {platform.release()}' in lines
+    assert f'  cpu: {platform.processor()}' in lines
diff --git a/conans/test/integration/configuration/test_profile_jinja.py b/conans/test/integration/configuration/test_profile_jinja.py
index b8dd5d331..4972a5233 100644
--- a/conans/test/integration/configuration/test_profile_jinja.py
+++ b/conans/test/integration/configuration/test_profile_jinja.py
@@ -198,3 +198,10 @@ class TestProfileDetectAPI:
             os={the_os}
             """)
         assert expected in client.out
+
+
+def test_profile_jinja_error():
+    c = TestClient(light=True)
+    c.save({"profile1": "{% set kk = other() %}"})
+    c.run("profile show -pr=profile1", assert_error=True)
+    assert "ERROR: Error while rendering the profile template file" in c.out
diff --git a/conans/test/integration/editable/editable_remove_test.py b/conans/test/integration/editable/editable_remove_test.py
index e28164f68..837e17601 100644
--- a/conans/test/integration/editable/editable_remove_test.py
+++ b/conans/test/integration/editable/editable_remove_test.py
@@ -48,8 +48,9 @@ class TestRemoveEditablePackageTest:
         c.save({'pkg/conanfile.py': GenConanfile()})
         c.run('editable add pkg --name=lib --version=version')
         shutil.rmtree(os.path.join(c.current_folder, "pkg"))
-        c.run("editable remove pkg", assert_error=True)
-        c.run("editable remove --refs=lib/version")
+        # https://github.com/conan-io/conan/issues/16164
+        # Making it possible, repeated issue
+        c.run("editable remove pkg")
         assert "Removed editable 'lib/version'" in c.out
         c.run("editable list")
         assert "lib" not in c.out
diff --git a/conans/test/integration/export_sources_test.py b/conans/test/integration/export_sources_test.py
index 0b30d04e3..d68850b3b 100644
--- a/conans/test/integration/export_sources_test.py
+++ b/conans/test/integration/export_sources_test.py
@@ -17,7 +17,7 @@ def test_exports():
             version = "0.1"
             exports = "*.h"
         """)
-    c = TestClient()
+    c = TestClient(light=True)
     c.save({"conanfile.py": conanfile,
             "hello.h": "hello",
             "data.txt": "data"})
@@ -44,7 +44,7 @@ def test_exports_sources():
             version = "0.1"
             exports_sources = "*.h"
         """)
-    c = TestClient()
+    c = TestClient(light=True)
     c.save({"conanfile.py": conanfile,
             "hello.h": "hello",
             "data.txt": "data"})
@@ -64,9 +64,24 @@ def test_test_package_copied():
     """The exclusion of the test_package folder have been removed so now we test that indeed is
     exported"""
 
-    client = TestClient()
+    client = TestClient(light=True)
     conanfile = GenConanfile().with_exports("*").with_exports_sources("*")
     client.save({"conanfile.py": conanfile,
                  "test_package/foo.txt": "bar"})
     client.run("export . --name foo --version 1.0")
     assert "Copied 2 '.txt' file" in client.out
+
+
+def test_source_changes_generate_new_revisions():
+    tc = TestClient(light=True)
+    tc.save({"conanfile.py": GenConanfile("lib", "1.0").with_exports_sources("file.h"),
+             "file.h": "Hello World!"})
+
+    tc.run("export .")
+    exported_rev = tc.exported_recipe_revision()
+
+    tc.save({"file.h": "Bye World!"})
+    tc.run("export .")
+    exported_rev_new = tc.exported_recipe_revision()
+
+    assert exported_rev != exported_rev_new
diff --git a/conans/test/integration/graph/conflict_diamond_test.py b/conans/test/integration/graph/conflict_diamond_test.py
index f55336fda..462bfecdd 100644
--- a/conans/test/integration/graph/conflict_diamond_test.py
+++ b/conans/test/integration/graph/conflict_diamond_test.py
@@ -23,7 +23,7 @@ class TestConflictDiamondTest:
         c.run("create engine")
         c.run("create ai")
         c.run("install game", assert_error=True)
-        assert "Version conflict: ai/1.0->math/1.0.1, game/1.0->math/1.0" in c.out
+        assert "Version conflict: Conflict between math/1.0.1 and math/1.0 in the graph" in c.out
         # This shouldnt error, so we are able to diagnose our dependency graph
         # The UX still need to be improved, but this is start
         c.run("graph info game --filter=requires", assert_error=True)
diff --git a/conans/test/integration/graph/core/test_build_requires.py b/conans/test/integration/graph/core/test_build_requires.py
index 4e50e1185..73a3fcc75 100644
--- a/conans/test/integration/graph/core/test_build_requires.py
+++ b/conans/test/integration/graph/core/test_build_requires.py
@@ -405,6 +405,24 @@ class TestTestRequire(GraphManagerTest):
         _check_transitive(lib, [(gtest, True, True, False, False),
                                 (zlib, True, True, False, False, False)])
 
+    def test_test_require_loop(self):
+        # https://github.com/conan-io/conan/issues/15412
+        self._cache_recipe("gtest/1.11", GenConanfile())
+        self._cache_recipe("abseil/1.0", GenConanfile().with_test_requires("gtest/[>=1 <1.14]"))
+        self._cache_recipe("gtest/1.14", GenConanfile().with_requires("abseil/1.0"))
+        deps_graph = self.build_graph(GenConanfile("opencv", "1.0").with_test_requires("gtest/1.14"))
+
+        self.assertEqual(4, len(deps_graph.nodes))
+        opencv = deps_graph.root
+        gtest14 = opencv.dependencies[0].dst
+        abseil = gtest14.dependencies[0].dst
+        gtest11 = abseil.dependencies[0].dst
+
+        self._check_node(opencv, "opencv/1.0@", deps=[gtest14], dependents=[])
+        self._check_node(gtest14, "gtest/1.14#123", deps=[abseil], dependents=[opencv])
+        self._check_node(abseil, "abseil/1.0#123", deps=[gtest11], dependents=[gtest14])
+        self._check_node(gtest11, "gtest/1.11#123", deps=[], dependents=[abseil])
+
 
 class TestTestRequiresProblemsShared(GraphManagerTest):
 
diff --git a/conans/test/integration/lockfile/test_graph_overrides.py b/conans/test/integration/lockfile/test_graph_overrides.py
index bae9f6817..6c64ecb1a 100644
--- a/conans/test/integration/lockfile/test_graph_overrides.py
+++ b/conans/test/integration/lockfile/test_graph_overrides.py
@@ -315,7 +315,7 @@ def test_introduced_conflict(override, force):
             })
 
     c.run("graph info pkgd --lockfile=pkgd/conan.lock --lockfile-partial", assert_error=True)
-    assert "Version conflict: pkgc/0.1->pkga/[>=0.2 <0.3], pkgd/0.1->pkga/0.1" in c.out
+    assert "Version conflict: Conflict between pkga/[>=0.2 <0.3] and pkga/0.1 in the graph" in c.out
     # Resolve the conflict with an override or force
     c.save({"pkgd/conanfile.py": GenConanfile("pkgd", "0.1").with_requirement("pkgb/0.1")
                                                             .with_requirement("pkgc/0.1")
diff --git a/conans/test/integration/py_requires/python_requires_test.py b/conans/test/integration/py_requires/python_requires_test.py
index 6aadeab9d..68cb2d1ee 100644
--- a/conans/test/integration/py_requires/python_requires_test.py
+++ b/conans/test/integration/py_requires/python_requires_test.py
@@ -27,7 +27,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         client.run("export . --name=base --version=1.1 --user=user --channel=testing")
 
     def test_reuse(self):
-        client = TestClient(default_server_user=True)
+        client = TestClient(light=True, default_server_user=True)
         self._define_base(client)
         reuse = textwrap.dedent("""
             from conan import ConanFile
@@ -50,9 +50,22 @@ class PyRequiresExtendTest(unittest.TestCase):
         client.run("remove * -c")
         client.run("download pkg/0.1@user/testing#latest:* -r default")
         self.assertIn(f"pkg/0.1@user/testing: Package installed {package_id}", client.out)
+        # But it's broken with a single download
+        client.run("install --requires=pkg/0.1@user/testing -nr", assert_error=True)
+        assert "Cannot resolve python_requires 'base/1.1@user/testing'" in client.out
+        # If pyrequires are expected, then first graph info -f=json and then get recipes from pkglist
+        client.run("remove * -c")
+        client.run("graph info --requires=pkg/0.1@user/testing -f=json", redirect_stdout="graph_info.json")
+        # We can even remove from the cache now (The pyrequires is already downloaded in the above step)
+        client.run("remove * -c")
+        client.run("list --graph=graph_info.json --graph-recipes=* -f=json", redirect_stdout="pkglist.json")
+        client.run("download --list=pkglist.json -r default")
+        assert "Downloading recipe 'base/1.1@user/testing" in client.out
+        client.run("install --requires=pkg/0.1@user/testing -nr")
+        self.assertIn("pkg/0.1@user/testing: My cool package_info!", client.out)
 
     def test_reuse_super(self):
-        client = TestClient(default_server_user=True)
+        client = TestClient(light=True, default_server_user=True)
         self._define_base(client)
         reuse = textwrap.dedent("""
                from conan import ConanFile
@@ -70,7 +83,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         assert "conanfile.py (pkg/0.1): MY OWN SOURCE" in client.out
 
     def test_reuse_dot(self):
-        client = TestClient(default_server_user=True)
+        client = TestClient(light=True, default_server_user=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             class MyConanfileBase(ConanFile):
@@ -90,7 +103,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("pkg/0.1@user/testing: My cool build!", client.out)
 
     def test_with_alias(self):
-        client = TestClient()
+        client = TestClient(light=True)
         self._define_base(client)
         client.alias("base/latest@user/testing", "base/1.1@user/testing")
 
@@ -108,7 +121,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         assert "python-requires 'alias' are not supported in Conan 2.0" in client.out
 
     def test_reuse_version_ranges(self):
-        client = TestClient()
+        client = TestClient(light=True)
         self._define_base(client)
 
         reuse = textwrap.dedent("""
@@ -127,7 +140,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("pkg/0.1@user/testing: My cool package_info!", client.out)
 
     def test_multiple_reuse(self):
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             class SourceBuild(ConanFile):
@@ -165,7 +178,7 @@ class PyRequiresExtendTest(unittest.TestCase):
 
     @staticmethod
     def test_transitive_access():
-        client = TestClient()
+        client = TestClient(light=True)
         client.save({"conanfile.py": GenConanfile()})
         client.run("export . --name=base --version=1.0 --user=user --channel=channel")
 
@@ -199,7 +212,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         assert "pkg/0.1@user/channel: Created package" in client.out
 
     def test_multiple_requires_error(self):
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             myvar = 123
@@ -248,7 +261,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("consumer/0.1@user/testing: PKG2F : 234", client.out)
 
     def test_local_import(self):
-        client = TestClient(default_server_user=True)
+        client = TestClient(light=True, default_server_user=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             import mydata
@@ -296,7 +309,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn(f"pkg/0.1@user/testing: Package installed {package_id}", client.out)
 
     def test_reuse_class_members(self):
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             class MyConanfileBase(ConanFile):
@@ -343,7 +356,7 @@ class PyRequiresExtendTest(unittest.TestCase):
 
     def test_reuse_system_requirements(self):
         # https://github.com/conan-io/conan/issues/7718
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
            from conan import ConanFile
            class MyConanfileBase(ConanFile):
@@ -363,7 +376,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("pkg/0.1@user/testing: My system_requirements pkg being called!", client.out)
 
     def test_reuse_requirements(self):
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
                    from conan import ConanFile
                    class MyConanfileBase(ConanFile):
@@ -462,7 +475,7 @@ class PyRequiresExtendTest(unittest.TestCase):
 
     def test_transitive_imports_conflicts(self):
         # https://github.com/conan-io/conan/issues/3874
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             import myhelper
@@ -502,7 +515,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("pkg/0.1@user/testing: MyOtherHelperOutput!", client.out)
 
     def test_update(self):
-        client = TestClient(default_server_user=True)
+        client = TestClient(light=True, default_server_user=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             somevar = 42
@@ -513,7 +526,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         client.run("export . --name=base --version=1.1 --user=user --channel=testing")
         client.run("upload * --confirm -r default")
 
-        client2 = TestClient(servers=client.servers, inputs=["user", "password"])
+        client2 = TestClient(light=True, servers=client.servers, inputs=["user", "password"])
         reuse = textwrap.dedent("""
             from conan import ConanFile
             class PkgTest(ConanFile):
@@ -539,7 +552,7 @@ class PyRequiresExtendTest(unittest.TestCase):
     def test_update_ranges(self):
         # Same as the above, but using a version range, and no --update
         # https://github.com/conan-io/conan/issues/4650#issuecomment-497464305
-        client = TestClient(default_server_user=True)
+        client = TestClient(light=True, default_server_user=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             somevar = 42
@@ -550,7 +563,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         client.run("export . --name=base --version=1.1 --user=user --channel=testing")
         client.run("upload * --confirm -r default")
 
-        client2 = TestClient(servers=client.servers, inputs=["user", "password"])
+        client2 = TestClient(light=True, servers=client.servers, inputs=["user", "password"])
         reuse = textwrap.dedent("""
             from conan import ConanFile
             class PkgTest(ConanFile):
@@ -574,7 +587,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("conanfile.py: PYTHON REQUIRE VAR 143", client2.out)
 
     def test_duplicate_pyreq(self):
-        t = TestClient()
+        t = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             class PyReq(ConanFile):
@@ -596,7 +609,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("The python_require 'pyreq' already exists", t.out)
 
     def test_local_build(self):
-        client = TestClient()
+        client = TestClient(light=True)
         client.save({"conanfile.py": "var=42\n" + str(GenConanfile())})
         client.run("export . --name=tool --version=0.1 --user=user --channel=channel")
         conanfile = textwrap.dedent("""
@@ -619,7 +632,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         client.run("export-pkg . --name=pkg1 --version=0.1 --user=user --channel=testing")
 
     def test_reuse_name_version(self):
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             from conan.tools.files import load
@@ -660,7 +673,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("mypkg/myversion: Pkg1 package: mypkg:myversion", client.out)
 
     def test_reuse_export_sources(self):
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             class MyConanfileBase(ConanFile):
@@ -718,7 +731,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("conanfile.py: Build: tool other: otherheader", client.out)
 
     def test_reuse_editable_exports(self):
-        client = TestClient()
+        client = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             class MyConanfileBase(ConanFile):
@@ -749,7 +762,7 @@ class PyRequiresExtendTest(unittest.TestCase):
                     self.output.info("Build: tool other: %s" % load(self, other_h))
             """)
 
-        client2 = TestClient(cache_folder=client.cache_folder)
+        client2 = TestClient(light=True, cache_folder=client.cache_folder)
         client2.save({"conanfile.py": conanfile,
                       "name.txt": "MyPkg",
                       "version.txt": "MyVersion"})
@@ -764,7 +777,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("conanfile.py: Build: tool other: otherheader", client2.out)
 
     def test_build_id(self):
-        client = TestClient(default_server_user=True)
+        client = TestClient(light=True, default_server_user=True)
         self._define_base(client)
         reuse = textwrap.dedent("""
             from conan import ConanFile
@@ -782,7 +795,7 @@ class PyRequiresExtendTest(unittest.TestCase):
         self.assertIn("pkg/0.1@user/testing: My cool package_info!", client.out)
 
     def test_options_errors(self):
-        c = TestClient()
+        c = TestClient(light=True)
         base = textwrap.dedent("""
             from conan import ConanFile
             class BaseConan:
@@ -822,7 +835,7 @@ class PyRequiresExtendTest(unittest.TestCase):
 
 def test_transitive_python_requires():
     # https://github.com/conan-io/conan/issues/8546
-    client = TestClient()
+    client = TestClient(light=True)
     conanfile = textwrap.dedent("""
         from conan import ConanFile
         myvar = 123
@@ -865,7 +878,7 @@ def test_transitive_python_requires():
 
 
 def test_transitive_diamond_python_requires():
-    client = TestClient()
+    client = TestClient(light=True)
     conanfile = textwrap.dedent("""
         from conan import ConanFile
         myvar = 123
@@ -939,7 +952,7 @@ def test_transitive_diamond_python_requires():
 class TestConflictPyRequires:
     # https://github.com/conan-io/conan/issues/15016
     def test_diamond_conflict_fixed(self):
-        c = TestClient()
+        c = TestClient(light=True)
 
         c.save({"tool/conanfile.py": GenConanfile("tool"),
                 "sub1/conanfile.py": GenConanfile("sub1", "1.0").with_python_requires("tool/1.0"),
@@ -953,7 +966,7 @@ class TestConflictPyRequires:
         assert "Conflict in py_requires tool/1.0 - tool/1.1" in c.out
 
     def test_diamond_conflict_ranges(self):
-        c = TestClient()
+        c = TestClient(light=True)
 
         c.save({"tool/conanfile.py": GenConanfile("tool"),
                 "sub1/conanfile.py": GenConanfile("sub1", "1.0").with_python_requires("tool/[*]"),
@@ -972,7 +985,7 @@ def test_multiple_reuse():
         # https://github.com/conan-io/conan/issues/11589
     """
 
-    c = TestClient()
+    c = TestClient(light=True)
     common = textwrap.dedent("""
         from conan import ConanFile
         def mycommon():
@@ -1023,7 +1036,7 @@ class TestTestPackagePythonRequire:
         """ test how to test_package a python_require
         """
 
-        c = TestClient()
+        c = TestClient(light=True)
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             def mycommon():
@@ -1086,7 +1099,7 @@ class TestResolveRemote:
         """ a "conan export" command should work even when a python_requires
         is in the server
         """
-        c = TestClient(default_server_user=True)
+        c = TestClient(light=True, default_server_user=True)
         c.save({"common/conanfile.py": GenConanfile("tool", "0.1"),
                 "pkg/conanfile.py": GenConanfile("pkg", "0.1").with_python_requires("tool/0.1")})
         c.run("export common")
@@ -1110,7 +1123,7 @@ class TestResolveRemote:
     def test_missing_python_require_error(self):
         """ make sure the error is clear enough for users UX
         """
-        c = TestClient()
+        c = TestClient(light=True)
         c.save({"pkg/conanfile.py": GenConanfile("pkg", "0.1").with_python_requires("tool/0.1")})
         c.run("create pkg", assert_error=True)
         assert "Cannot resolve python_requires 'tool/0.1'" in c.out
@@ -1120,7 +1133,7 @@ class TestTransitiveExtend:
     # https://github.com/conan-io/conan/issues/10511
     # https://github.com/conan-io/conan/issues/10565
     def test_transitive_extend(self):
-        client = TestClient()
+        client = TestClient(light=True)
         company = textwrap.dedent("""
             from conan import ConanFile
             class CompanyConanFile(ConanFile):
@@ -1165,7 +1178,7 @@ class TestTransitiveExtend:
         assert "conanfile.py (consumer/1.0): Msg2:company!!!" in client.out
 
     def test_transitive_extend2(self):
-        client = TestClient()
+        client = TestClient(light=True)
         company = textwrap.dedent("""
             from conan import ConanFile
             class CompanyConanFile(ConanFile):
@@ -1220,7 +1233,7 @@ def test_multi_top_missing_from_remote():
     """
     https://github.com/conan-io/conan/issues/13656
     """
-    tc = TestClient(default_server_user=True)
+    tc = TestClient(light=True, default_server_user=True)
     tc.save({"conanfile.py": GenConanfile("base", "1.1")})
     tc.run("create . --user=user --channel=testing")
 
@@ -1248,7 +1261,7 @@ def test_transitive_range_not_found_in_cache():
     """
     https://github.com/conan-io/conan/issues/13761
     """
-    c = TestClient()
+    c = TestClient(light=True)
     c.save({"conanfile.py": GenConanfile("pr", "1.0")})
     c.run("create .")
 
@@ -1262,7 +1275,7 @@ def test_transitive_range_not_found_in_cache():
 
 
 def test_export_pkg():
-    c = TestClient()
+    c = TestClient(light=True)
     c.save({"conanfile.py": GenConanfile("pytool", "0.1").with_package_type("python-require")})
     c.run("export-pkg .", assert_error=True)
     assert "export-pkg can only be used for binaries, not for 'python-require'" in c.out
@@ -1273,7 +1286,7 @@ def test_export_pkg():
 
 
 def test_py_requires_override_method():
-    tc = TestClient()
+    tc = TestClient(light=True)
     pyreq = textwrap.dedent("""
         from conan import ConanFile
         class MyConanfileBase:
diff --git a/conans/test/integration/remote/multi_remote_test.py b/conans/test/integration/remote/multi_remote_test.py
index 0e40e9a59..515ad32dd 100644
--- a/conans/test/integration/remote/multi_remote_test.py
+++ b/conans/test/integration/remote/multi_remote_test.py
@@ -120,35 +120,37 @@ class MultiRemotesTest(unittest.TestCase):
         client = TestClient(servers=self.servers, inputs=2*["admin", "password"])
 
         self._create(client, "hello0", "0.0")
+        default_remote_rev = client.exported_recipe_revision()
         client.run("install --requires=hello0/0.0@lasote/stable --build missing")
+
         client.run("upload hello0/0.0@lasote/stable -r default")
         sleep(1)  # For timestamp and updates checks
         self._create(client, "hello0", "0.0", modifier=" ")
+        local_remote_rev = client.exported_recipe_revision()
         client.run("install --requires=hello0/0.0@lasote/stable --build missing")
+
         client.run("upload hello0/0.0@lasote/stable#latest -r local")
         client.run("remove '*' -c")
 
         client.run("install --requires=hello0/0.0@lasote/stable")
         # If we don't set a remote we find between all remotes and get the first match
-        self.assertIn("hello0/0.0@lasote/stable#20f1a1ed31481dfb59bdfd22f1aa1093 - Downloaded",
-                      client.out)
+        assert f"hello0/0.0@lasote/stable#{default_remote_rev} - Downloaded" in client.out
         client.run("install --requires=hello0/0.0@lasote/stable --update")
-        self.assertIn("hello0/0.0@lasote/stable#f49dd3f4009e57f521520364d8468757 - Updated",
-                      client.out)
+        assert f"hello0/0.0@lasote/stable#{local_remote_rev} - Updated" in client.out
 
         client.run("install --requires=hello0/0.0@lasote/stable --update -r default")
-        self.assertIn("hello0/0.0@lasote/stable#f49dd3f4009e57f521520364d8468757 - Newer",
+        self.assertIn(f"hello0/0.0@lasote/stable#{local_remote_rev} - Newer",
                       client.out)
 
         sleep(1)  # For timestamp and updates checks
         # Check that it really updates in case of newer package uploaded to the associated remote
         client_b = TestClient(servers=self.servers, inputs=3*["admin", "password"])
         self._create(client_b, "hello0", "0.0", modifier="  ")
+        new_local_remote_rev = client_b.exported_recipe_revision()
         client_b.run("install --requires=hello0/0.0@lasote/stable --build missing")
         client_b.run("upload hello0/0.0@lasote/stable -r local")
         client.run("install --requires=hello0/0.0@lasote/stable --update")
-        self.assertIn("hello0/0.0@lasote/stable#1169dcd60e44cc939d0b475693195bd4 - Updated",
-                      client.out)
+        assert f"hello0/0.0@lasote/stable#{new_local_remote_rev} - Updated" in client.out
 
 
 class MultiRemoteTest(unittest.TestCase):
diff --git a/conans/test/integration/remote/test_remote_file_credentials.py b/conans/test/integration/remote/test_remote_file_credentials.py
index 78e0a4ba1..f1d25ba74 100644
--- a/conans/test/integration/remote/test_remote_file_credentials.py
+++ b/conans/test/integration/remote/test_remote_file_credentials.py
@@ -42,3 +42,14 @@ def test_remote_file_credentials_error(client):
     save(os.path.join(c.cache_folder, "credentials.json"), json.dumps(content))
     c.run("upload * -r=default -c", assert_error=True)
     assert "ERROR: Wrong user or password" in c.out
+
+
+def test_remote_file_credentials_bad_file(client):
+    c = client
+    save(os.path.join(c.cache_folder, "credentials.json"), "")
+    c.run("upload * -r=default -c", assert_error=True)
+    assert "ERROR: Error loading 'credentials.json'" in c.out
+    content = {"credentials": [{"remote": "default"}]}
+    save(os.path.join(c.cache_folder, "credentials.json"), json.dumps(content))
+    c.run("upload * -r=default -c", assert_error=True)
+    assert "ERROR: Error loading 'credentials.json'" in c.out
diff --git a/conans/test/integration/settings/test_settings_user.py b/conans/test/integration/settings/test_settings_user.py
index eb24e909f..215aa794c 100644
--- a/conans/test/integration/settings/test_settings_user.py
+++ b/conans/test/integration/settings/test_settings_user.py
@@ -93,3 +93,17 @@ def test_settings_user_error():
     save(os.path.join(c.cache_folder, "settings_user.yml"), settings_user)
     c.run("profile show", assert_error=True)
     assert "ERROR: Definition of settings.yml 'settings.os.libc' cannot be null" in c.out
+
+
+def test_settings_user_breaking_universal_binaries():
+    # If you had a settings_user.yml with a custom architecture wit will error
+    # in the Apple block of CMakeToolchain
+    # https://github.com/conan-io/conan/issues/16086#issuecomment-2059118224
+    c = TestClient()
+    settings_user = textwrap.dedent("""\
+        arch: [universal]
+        """)
+    save(os.path.join(c.cache_folder, "settings_user.yml"), settings_user)
+    c.save({"conanfile.py": GenConanfile().with_settings("os").with_settings("arch").with_generator("CMakeToolchain")})
+    c.run('install . -s="arch=universal"')
+    assert "CMakeToolchain generated: conan_toolchain.cmake" in c.out
diff --git a/conans/test/integration/test_source_download_password.py b/conans/test/integration/test_source_download_password.py
index 691903e73..eac0ef4db 100644
--- a/conans/test/integration/test_source_download_password.py
+++ b/conans/test/integration/test_source_download_password.py
@@ -41,9 +41,10 @@ def test_source_download_password():
     c.run("source .")
     assert "Content: hello world!" in c.out
 
-    # Errors
-    for invalid in [{"token": "mytoken"},
-                    {"url": server_url, "token": "mytoken2"},  # Unauthorized
+    # Errors loading file
+    for invalid in ["",
+                    "potato",
+                    {"token": "mytoken"},
                     {},
                     {"url": server_url},
                     {"auth": {}},
@@ -51,4 +52,10 @@ def test_source_download_password():
         content = {"credentials": [invalid]}
         save(os.path.join(c.cache_folder, "source_credentials.json"), json.dumps(content))
         c.run("source .", assert_error=True)
-        assert "Authentication" in c.out or "Unknown credentials" in c.out
+        assert "Error loading 'source_credentials.json'" in c.out
+
+    content = {"credentials": [{"url": server_url, "token": "mytoken2"}]}
+    save(os.path.join(c.cache_folder, "source_credentials.json"), json.dumps(content))
+    c.run("source .", assert_error=True)
+    assert "ERROR: conanfile.py: Error in source() method, line 6" in c.out
+    assert "Authentication" in c.out
diff --git a/conans/test/integration/toolchains/gnu/test_gnutoolchain.py b/conans/test/integration/toolchains/gnu/test_gnutoolchain.py
new file mode 100644
index 000000000..0541e2381
--- /dev/null
+++ b/conans/test/integration/toolchains/gnu/test_gnutoolchain.py
@@ -0,0 +1,437 @@
+import os
+import platform
+import textwrap
+import re
+
+import pytest
+
+from conans.test.assets.genconanfile import GenConanfile
+from conans.test.utils.tools import TestClient
+from conans.util.files import save, load
+
+
+@pytest.mark.parametrize("os_", ["Macos", "Linux", "Windows"])
+def test_extra_flags_via_conf(os_):
+    os_sdk = "tools.apple:sdk_path=/my/sdk/path" if os_ == "Macos" else ""
+    profile = textwrap.dedent(f"""
+        [settings]
+        os={os_}
+        compiler=gcc
+        compiler.version=6
+        compiler.libcxx=libstdc++11
+        arch=armv8
+        build_type=Release
+
+        [conf]
+        tools.build:cxxflags=["--flag1", "--flag2"]
+        tools.build:cflags+=["--flag3", "--flag4"]
+        tools.build:sharedlinkflags+=["--flag5"]
+        tools.build:exelinkflags+=["--flag6"]
+        tools.build:defines+=["DEF1", "DEF2"]
+        {os_sdk}
+        """)
+    client = TestClient()
+    conanfile = GenConanfile().with_settings("os", "arch", "compiler", "build_type") \
+        .with_generator("GnuToolchain")
+    client.save({"conanfile.py": conanfile,
+                 "profile": profile})
+    client.run("install . --profile:build=profile --profile:host=profile")
+    toolchain = client.load(
+        "conanautotoolstoolchain{}".format('.bat' if os_ == "Windows" else '.sh'))
+    if os_ == "Windows":
+        assert 'set "CPPFLAGS=%CPPFLAGS% -DNDEBUG -DDEF1 -DDEF2"' in toolchain
+        assert 'set "CXXFLAGS=%CXXFLAGS% -O3 --flag1 --flag2"' in toolchain
+        assert 'set "CFLAGS=%CFLAGS% -O3 --flag3 --flag4"' in toolchain
+        assert 'set "LDFLAGS=%LDFLAGS% --flag5 --flag6"' in toolchain
+        assert f'set "PKG_CONFIG_PATH={client.current_folder};%PKG_CONFIG_PATH%"' in toolchain
+    elif os_ == "Linux":
+        assert 'export CPPFLAGS="$CPPFLAGS -DNDEBUG -DDEF1 -DDEF2"' in toolchain
+        assert 'export CXXFLAGS="$CXXFLAGS -O3 --flag1 --flag2"' in toolchain
+        assert 'export CFLAGS="$CFLAGS -O3 --flag3 --flag4"' in toolchain
+        assert 'export LDFLAGS="$LDFLAGS --flag5 --flag6"' in toolchain
+        assert f'export PKG_CONFIG_PATH="{client.current_folder}:$PKG_CONFIG_PATH"' in toolchain
+    else:  # macOS
+        assert 'export CPPFLAGS="$CPPFLAGS -DNDEBUG -DDEF1 -DDEF2"' in toolchain
+        assert 'export CXXFLAGS="$CXXFLAGS -O3 --flag1 --flag2"' in toolchain
+        assert 'export CFLAGS="$CFLAGS -O3 --flag3 --flag4"' in toolchain
+        assert 'export LDFLAGS="$LDFLAGS --flag5 --flag6"' in toolchain
+        assert f'export PKG_CONFIG_PATH="{client.current_folder}:$PKG_CONFIG_PATH"' in toolchain
+
+
+def test_extra_flags_order():
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.gnu import GnuToolchain
+
+        class Conan(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "os", "arch", "build_type"
+            def generate(self):
+                at = GnuToolchain(self)
+                at.extra_cxxflags = ["extra_cxxflags"]
+                at.extra_cflags = ["extra_cflags"]
+                at.extra_ldflags = ["extra_ldflags"]
+                at.extra_defines = ["extra_defines"]
+                at.generate()
+        """)
+    profile = textwrap.dedent("""
+        include(default)
+        [conf]
+        tools.build:cxxflags+=['cxxflags']
+        tools.build:cflags+=['cflags']
+        tools.build:sharedlinkflags+=['sharedlinkflags']
+        tools.build:exelinkflags+=['exelinkflags']
+        tools.build:defines+=['defines']
+        """)
+    client.save({"conanfile.py": conanfile, "profile": profile})
+    client.run('install . -pr=./profile')
+    toolchain = client.load(
+        "conanautotoolstoolchain{}".format('.bat' if platform.system() == "Windows" else '.sh'))
+
+    assert '-Dextra_defines -Ddefines' in toolchain
+    assert 'extra_cxxflags cxxflags' in toolchain
+    assert 'extra_cflags cflags' in toolchain
+    assert 'extra_ldflags sharedlinkflags exelinkflags' in toolchain
+
+
+def test_autotools_custom_environment():
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.gnu import GnuToolchain
+
+            class Conan(ConanFile):
+                settings = "os"
+                def generate(self):
+                    at = GnuToolchain(self)
+                    env = at.extra_env
+                    env.define("FOO", "BAR")
+                    at.generate()
+            """)
+
+    client.save({"conanfile.py": conanfile})
+    client.run("install . -s:b os=Linux -s:h os=Linux")
+    content = load(os.path.join(client.current_folder, "conanautotoolstoolchain.sh"))
+    assert 'export FOO="BAR"' in content
+
+
+@pytest.mark.parametrize("os_", ["Linux", "Windows"])
+def test_linker_scripts_via_conf(os_):
+    profile = textwrap.dedent("""
+        [settings]
+        os=%s
+        compiler=gcc
+        compiler.version=6
+        compiler.libcxx=libstdc++11
+        arch=armv8
+        build_type=Release
+
+        [conf]
+
+        tools.build:sharedlinkflags+=["--flag5"]
+        tools.build:exelinkflags+=["--flag6"]
+        tools.build:linker_scripts+=["/linker/scripts/flash.ld", "/linker/scripts/extra_data.ld"]
+        """ % os_)
+    client = TestClient()
+    conanfile = GenConanfile().with_settings("os", "arch", "compiler", "build_type") \
+        .with_generator("GnuToolchain")
+    client.save({"conanfile.py": conanfile,
+                 "profile": profile})
+    client.run("install . --profile:build=profile --profile:host=profile")
+    toolchain = client.load(
+        "conanautotoolstoolchain{}".format('.bat' if os_ == "Windows" else '.sh'))
+    if os_ == "Windows":
+        assert 'set "LDFLAGS=%LDFLAGS% --flag5 --flag6 -T\'/linker/scripts/flash.ld\' -T\'/linker/scripts/extra_data.ld\'"' in toolchain
+    else:
+        assert 'export LDFLAGS="$LDFLAGS --flag5 --flag6 -T\'/linker/scripts/flash.ld\' -T\'/linker/scripts/extra_data.ld\'"' in toolchain
+
+
+def test_not_none_values():
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.gnu import GnuToolchain
+
+        class Foo(ConanFile):
+            name = "foo"
+            version = "1.0"
+
+            def generate(self):
+                tc = GnuToolchain(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 .")
+
+
+def test_set_prefix():
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.gnu import GnuToolchain
+        from conan.tools.layout import basic_layout
+
+
+        class Foo(ConanFile):
+            name = "foo"
+            version = "1.0"
+            def layout(self):
+                basic_layout(self)
+            def generate(self):
+                at_toolchain = GnuToolchain(self, prefix="/somefolder")
+                at_toolchain.generate()
+    """)
+
+    client = TestClient()
+    client.save({"conanfile.py": conanfile})
+    client.run("install .")
+    conanbuild = client.load(
+        os.path.join(client.current_folder, "build", "conan", "conanbuild.conf"))
+    assert "--prefix=/somefolder" in conanbuild
+    assert conanbuild.count("--prefix") == 1
+
+
+def test_unknown_compiler():
+    client = TestClient()
+    settings = load(client.cache.settings_path)
+    settings = settings.replace("gcc:", "xlc:\n    gcc:", 1)
+    save(client.cache.settings_path, settings)
+    client.save({"conanfile.py": GenConanfile().with_settings("compiler", "build_type")
+                .with_generator("GnuToolchain")
+                 })
+    # this used to crash, because of build_type_flags in GnuToolchain returning empty string
+    client.run("install . -s compiler=xlc")
+    assert "conanfile.py: Generator 'GnuToolchain' calling 'generate()'" in client.out
+
+
+def test_toolchain_and_compilers_build_context():
+    """
+    Tests how GnuToolchain manages the build context profile if the build profile is
+    specifying another compiler path (using conf)
+
+    Issue related: https://github.com/conan-io/conan/issues/15878
+    """
+    host = textwrap.dedent("""
+    [settings]
+    arch=armv8
+    build_type=Release
+    compiler=gcc
+    compiler.cppstd=gnu17
+    compiler.libcxx=libstdc++11
+    compiler.version=11
+    os=Linux
+
+    [conf]
+    tools.build:compiler_executables={"c": "gcc", "cpp": "g++", "rc": "windres"}
+    """)
+    build = textwrap.dedent("""
+    [settings]
+    os=Linux
+    arch=x86_64
+    compiler=clang
+    compiler.version=12
+    compiler.libcxx=libc++
+    compiler.cppstd=11
+
+    [conf]
+    tools.build:compiler_executables={"c": "clang", "cpp": "clang++"}
+    """)
+    tool = textwrap.dedent("""
+    import os
+    from conan import ConanFile
+    from conan.tools.files import load
+
+    class toolRecipe(ConanFile):
+        name = "tool"
+        version = "1.0"
+        # Binary configuration
+        settings = "os", "compiler", "build_type", "arch"
+        generators = "GnuToolchain"
+
+        def build(self):
+            toolchain = os.path.join(self.generators_folder, "conanautotoolstoolchain.sh")
+            content = load(self, toolchain)
+            assert 'export CC="clang"' in content
+            assert 'export CXX="clang++"' in content
+    """)
+    consumer = textwrap.dedent("""
+    import os
+    from conan import ConanFile
+    from conan.tools.files import load
+
+    class consumerRecipe(ConanFile):
+        name = "consumer"
+        version = "1.0"
+        # Binary configuration
+        settings = "os", "compiler", "build_type", "arch"
+        generators = "GnuToolchain"
+        tool_requires = "tool/1.0"
+
+        def build(self):
+            toolchain = os.path.join(self.generators_folder, "conanautotoolstoolchain.sh")
+            content = load(self, toolchain)
+            assert 'export CC="gcc"' in content
+            assert 'export CXX="g++"' in content
+            assert 'export RC="windres"' in content
+    """)
+    client = TestClient()
+    client.save({
+        "host": host,
+        "build": build,
+        "tool/conanfile.py": tool,
+        "consumer/conanfile.py": consumer
+    })
+    client.run("export tool")
+    client.run("create consumer -pr:h host -pr:b build --build=missing")
+
+
+def test_autotools_crossbuild_ux():
+    client = TestClient()
+    profile_build = textwrap.dedent("""
+        [settings]
+        os = Macos
+        os.version=10.11
+        arch = armv7
+        compiler = apple-clang
+        compiler.version = 12.0
+        compiler.libcxx = libc++
+        """)
+    profile_host = textwrap.dedent("""
+        [settings]
+        arch=x86_64
+        build_type=Release
+        compiler=apple-clang
+        compiler.cppstd=gnu17
+        compiler.libcxx=libc++
+        compiler.version=15
+        os=Macos
+        [conf]
+        tools.apple:sdk_path=/my/sdk/path
+        """)
+    conanfile = textwrap.dedent("""
+    from conan import ConanFile
+    from conan.tools.gnu import GnuToolchain
+    from conan.tools.build import cross_building
+    class Pkg(ConanFile):
+        settings = "os", "arch", "compiler", "build_type"
+        def generate(self):
+            tc = GnuToolchain(self)
+            if cross_building(self):
+                host_arch = tc.triplets_info["host"]["machine"]
+                build_arch = tc.triplets_info["build"]["machine"]
+                if host_arch and build_arch:
+                    tc.configure_args["--host"] = f"{host_arch}-my-triplet-host"
+                    tc.configure_args["--build"] = f"{build_arch}-my-triplet-build"
+            tc.generate()
+            """)
+
+    client.save({"conanfile.py": conanfile,
+                 "profile_build": profile_build,
+                 "profile_host": profile_host})
+    client.run("install . --profile:build=profile_build --profile:host=profile_host")
+    conanbuild = client.load("conanbuild.conf")
+    host_flags = re.findall(r"--host=[\w-]*\b", conanbuild)
+    build_flags = re.findall(r"--build=[\w-]*\b", conanbuild)
+    assert len(host_flags) == 1
+    assert len(build_flags) == 1
+    assert host_flags[0] == '--host=x86_64-my-triplet-host'
+    assert build_flags[0] == '--build=arm-my-triplet-build'
+
+
+def test_msvc_profile_defaults():
+    """
+    Tests how GnuToolchain manages MSVC profile and its default env variables.
+    """
+    profile = textwrap.dedent("""\
+    [settings]
+    os=Windows
+    arch=x86_64
+    compiler=msvc
+    compiler.version=191
+    compiler.runtime=dynamic
+    build_type=Release
+
+    [conf]
+    tools.build:compiler_executables={"c": "clang", "cpp": "clang++"}
+    # Fake installation path
+    tools.microsoft.msbuild:installation_path={{os.getcwd()}}
+    """)
+    # Consumer with default values
+    consumer = textwrap.dedent("""\
+    import os
+    from conan import ConanFile
+    from conan.tools.files import load
+
+    class consumerRecipe(ConanFile):
+        name = "consumer"
+        version = "1.0"
+        # Binary configuration
+        settings = "os", "compiler", "build_type", "arch"
+        generators = "GnuToolchain"
+
+        def build(self):
+            toolchain = os.path.join(self.generators_folder, "conanautotoolstoolchain.bat")
+            content = load(self, toolchain)
+            # Default values and conf ones
+            assert r'set "CC=clang"' in content  # conf value has precedence
+            assert r'set "CXX=clang++"' in content  # conf value has precedence
+            assert 'set "LD=link -nologo"' in content
+            assert r'set "AR=lib"' in content
+            assert 'set "NM=dumpbin -symbols"' in content
+            assert 'set "OBJDUMP=:"' in content
+            assert 'set "RANLIB=:"' in content
+            assert 'set "STRIP=:"' in content
+    """)
+    client = TestClient()
+    client.save({
+        "profile": profile,
+        "consumer/conanfile.py": consumer
+    })
+    client.run("create consumer -pr:a profile --build=missing")
+    # Consumer changing default values
+    consumer = textwrap.dedent("""\
+    import os
+    from conan import ConanFile
+    from conan.tools.files import load
+    from conan.tools.gnu import GnuToolchain
+
+    class consumerRecipe(ConanFile):
+        name = "consumer"
+        version = "1.0"
+        # Binary configuration
+        settings = "os", "compiler", "build_type", "arch"
+
+        def generate(self):
+            tc = GnuToolchain(self)
+            # Prepending compiler wrappers
+            tc.extra_env.prepend("CC", "compile")
+            tc.extra_env.prepend("CXX", "compile")
+            tc.extra_env.prepend("AR", "ar-lib")
+            tc.extra_env.append("LD", "-fixed")
+            tc.extra_env.define("OBJDUMP", "other-value")
+            tc.extra_env.unset("RANLIB")
+            tc.generate()
+
+        def build(self):
+            toolchain = os.path.join(self.generators_folder, "conanautotoolstoolchain.bat")
+            content = load(self, toolchain)
+            # Default values
+            assert r'set "CC=compile clang"' in content
+            assert r'set "CXX=compile clang++"' in content
+            assert 'set "LD=link -nologo -fixed"' in content  # appended new value
+            assert r'set "AR=ar-lib lib"' in content
+            assert 'set "NM=dumpbin -symbols"' in content
+            assert 'set "OBJDUMP=other-value"' in content  # redefined
+            assert 'set "RANLIB=:"' not in content  # removed
+            assert 'set "STRIP=:"' in content
+    """)
+    client.save({
+        "consumer/conanfile.py": consumer
+    })
+    client.run("create consumer -pr:a profile --build=missing")
diff --git a/conans/test/unittests/client/conf/detect/test_gcc_compiler.py b/conans/test/unittests/client/conf/detect/test_gcc_compiler.py
index e88743832..dd8cc5e80 100644
--- a/conans/test/unittests/client/conf/detect/test_gcc_compiler.py
+++ b/conans/test/unittests/client/conf/detect/test_gcc_compiler.py
@@ -4,7 +4,7 @@ import mock
 from parameterized import parameterized
 
 
-from conan.internal.api.detect_api import _gcc_compiler
+from conan.internal.api.detect_api import detect_gcc_compiler
 
 
 class GCCCompilerTestCase(unittest.TestCase):
@@ -13,7 +13,7 @@ class GCCCompilerTestCase(unittest.TestCase):
     def test_detect_gcc_10(self, version):
         with mock.patch("platform.system", return_value="Linux"):
             with mock.patch("conan.internal.api.detect_api.detect_runner", return_value=(0, version)):
-                compiler, installed_version, compiler_exe = _gcc_compiler()
+                compiler, installed_version, compiler_exe = detect_gcc_compiler()
         self.assertEqual(compiler, 'gcc')
         self.assertEqual(installed_version, version)
         self.assertEqual(compiler_exe, 'gcc')
diff --git a/conans/test/unittests/model/settings_test.py b/conans/test/unittests/model/settings_test.py
index 94d4a4467..63960772d 100644
--- a/conans/test/unittests/model/settings_test.py
+++ b/conans/test/unittests/model/settings_test.py
@@ -465,6 +465,17 @@ def test_rm_safe():
     assert "'settings.compiler.libcxx' doesn't exist for 'clang'" in str(e.value)
 
 
+def test_rm_safe_wildcard():
+    settings = Settings.loads(default_settings_yml)
+    settings.compiler = "gcc"
+    settings.compiler.version = "4.8"
+    settings.compiler.libcxx = "libstdc++"
+    settings.rm_safe("compiler.*")
+    assert settings.compiler == "gcc"
+    assert settings.get_safe("compiler.version") is None
+    assert settings.get_safe("compiler.libcxx") is None
+
+
 def test_settings_intel_cppstd_03():
     settings = Settings.loads(default_settings_yml)
     settings.compiler = "intel-cc"
diff --git a/conans/test/unittests/model/version/test_version_range.py b/conans/test/unittests/model/version/test_version_range.py
index 256d4420e..7f82d625c 100644
--- a/conans/test/unittests/model/version/test_version_range.py
+++ b/conans/test/unittests/model/version/test_version_range.py
@@ -35,6 +35,7 @@ values = [
     ['>1- <2.0 || ^3.2 ',  [[['>', '1-'], ['<', '2.0-']], [['>=', '3.2-'], ['<', '4.0-']]],
                            ["1.0", "1.2", "3.3"],  ["1-pre.1", "1.5-a1", "3.3-a1"]],
     ['^1.1.2',  [[['>=', '1.1.2-'], ['<', '2.0.0-']]], ["1.2.3"],  ["1.2.0-alpha1", "2.0.0-alpha1"]],
+    ['^1.0.0, include_prerelease=True',  [[['>=', '1.0.0-'], ['<', '2.0.0-']]], ["1.2.3", "1.2.0-alpha1"],  ["2.0.0-alpha1"]],
     ['~1.1.2',  [[['>=', '1.1.2-'], ['<', '1.2.0-']]], ["1.1.3"],  ["1.1.3-alpha1", "1.2.0-alpha1"]],
     ['>=2.0-pre.0 <3', [[['>=', '2.0-pre.0'], ['<', '3-']]], ["2.1"], ["2.0-pre.1", "2.0-alpha.1"]],
     # Build metadata
diff --git a/conans/test/unittests/tools/gnu/test_gnutoolchain.py b/conans/test/unittests/tools/gnu/test_gnutoolchain.py
new file mode 100644
index 000000000..faaa43da4
--- /dev/null
+++ b/conans/test/unittests/tools/gnu/test_gnutoolchain.py
@@ -0,0 +1,196 @@
+from unittest.mock import patch
+
+import pytest
+
+from conan.tools.build import cmd_args_to_string
+from conan.tools.gnu import GnuToolchain
+from conans.errors import ConanException
+from conans.model.conf import Conf
+from conans.test.utils.mocks import ConanFileMock, MockSettings
+
+
+@pytest.fixture()
+def cross_building_conanfile():
+    settings_build = MockSettings({"os": "Linux",
+                                   "arch": "x86_64",
+                                   "compiler": "gcc",
+                                   "compiler.version": "11",
+                                   "compiler.libcxx": "libstdc++",
+                                   "build_type": "Release"})
+    settings_target = MockSettings({"os": "Android", "arch": "armv8"})
+    settings = MockSettings({"os": "Emscripten", "arch": "wasm"})
+    conanfile = ConanFileMock()
+    conanfile.settings = settings
+    conanfile.settings_build = settings_build
+    conanfile.settings_target = settings_target
+    return conanfile
+
+
+def test_get_gnu_triplet_for_cross_building():
+    """
+    Testing AutotoolsToolchainX and _get_gnu_triplet() function in case of
+    having os=Windows and cross compiling
+    """
+    # Issue: https://github.com/conan-io/conan/issues/10139
+    settings = MockSettings({"build_type": "Release",
+                             "compiler": "gcc",
+                             "compiler.version": "10.2",
+                             "os": "Windows",
+                             "arch": "x86_64"})
+    conanfile = ConanFileMock()
+    conanfile.settings = settings
+    conanfile.settings_build = MockSettings({"os": "Solaris", "arch": "x86"})
+    at = GnuToolchain(conanfile)
+    assert at.configure_args["--host"] == "x86_64-w64-mingw32"
+    assert at.configure_args["--build"] == "i686-solaris"
+
+
+def test_get_toolchain_cppstd():
+    settings = MockSettings({"build_type": "Release",
+                             "compiler": "gcc",
+                             "compiler.version": "10",
+                             "compiler.cppstd": "20",
+                             "os": "Linux",
+                             "arch": "x86_64"})
+    conanfile = ConanFileMock()
+    conanfile.settings = settings
+    conanfile.settings_build = settings
+    at = GnuToolchain(conanfile)
+    assert at.cppstd == "-std=c++2a"
+    settings.values["compiler.version"] = "12"
+    at = GnuToolchain(conanfile)
+    assert at.cppstd == "-std=c++20"
+
+
+@pytest.mark.parametrize("runtime, runtime_type, expected",
+                         [("static", "Debug", "MTd"),
+                          ("static", "Release", "MT"),
+                          ("dynamic", "Debug", "MDd"),
+                          ("dynamic", "Release", "MD")])
+def test_msvc_runtime(runtime, runtime_type, expected):
+    """
+    Testing AutotoolsToolchainX with the msvc compiler adjust the runtime
+    """
+    # Issue: https://github.com/conan-io/conan/issues/10139
+    settings = MockSettings({"build_type": "Release",
+                             "compiler": "msvc",
+                             "compiler.runtime": runtime,
+                             "compiler.runtime_type": runtime_type,
+                             "os": "Windows",
+                             "arch": "x86_64"})
+    conanfile = ConanFileMock()
+    conanfile.settings = settings
+    conanfile.settings_build = settings
+    at = GnuToolchain(conanfile)
+    expected_flag = "-{}".format(expected)
+    assert at.msvc_runtime_flag == expected_flag
+    env = at._environment.vars(conanfile)
+    assert expected_flag in env["CFLAGS"]
+    assert expected_flag in env["CXXFLAGS"]
+
+
+@pytest.mark.parametrize("runtime", ["MTd", "MT", "MDd", "MD"])
+def test_visual_runtime(runtime):
+    """
+    Testing AutotoolsToolchainX with the msvc compiler adjust the runtime
+    """
+    # Issue: https://github.com/conan-io/conan/issues/10139
+    settings = MockSettings({"build_type": "Release" if "d" not in runtime else "Debug",
+                             "compiler": "msvc",
+                             "compiler.runtime": "static" if "MT" in runtime else "dynamic",
+                             "compiler.runtime_type": "Release" if "d" not in runtime else "Debug",
+                             "os": "Windows",
+                             "arch": "x86_64"})
+    conanfile = ConanFileMock()
+    conanfile.settings = settings
+    conanfile.settings_build = settings
+    at = GnuToolchain(conanfile)
+    expected_flag = "-{}".format(runtime)
+    assert at.msvc_runtime_flag == expected_flag
+    env = at._environment.vars(conanfile)
+    assert expected_flag in env["CFLAGS"]
+    assert expected_flag in env["CXXFLAGS"]
+
+
+def test_get_gnu_triplet_for_cross_building_raise_error():
+    """
+    Testing AutotoolsToolchainX and _get_gnu_triplet() function raises an error in case of
+    having os=Windows, cross compiling and not defined any compiler
+    """
+    # Issue: https://github.com/conan-io/conan/issues/10139
+    settings = MockSettings({"build_type": "Release",
+                             "os": "Windows",
+                             "arch": "x86_64"})
+    conanfile = ConanFileMock()
+    conanfile.settings = settings
+    conanfile.settings_build = MockSettings({"os": "Solaris", "arch": "x86"})
+    with pytest.raises(ConanException) as conan_error:
+        GnuToolchain(conanfile)
+        msg = "'compiler' parameter for 'get_gnu_triplet()' is not specified and " \
+              "needed for os=Windows"
+        assert msg == str(conan_error.value)
+
+
+def test_compilers_mapping():
+    autotools_mapping = {"c": "CC", "cpp": "CXX", "cuda": "NVCC", "fortran": "FC"}
+    compilers = {"c": "path_to_c", "cpp": "path_to_cpp", "cuda": "path_to_cuda",
+                 "fortran": "path_to_fortran"}
+    settings = MockSettings({"build_type": "Release",
+                             "os": "Windows",
+                             "arch": "x86_64",
+                             "compiler": "gcc"})
+    conanfile = ConanFileMock()
+    conanfile.conf = Conf()
+    conanfile.conf.define("tools.build:compiler_executables", compilers)
+    conanfile.settings = settings
+    at = GnuToolchain(conanfile)
+    env = at._environment.vars(conanfile)
+    for compiler, env_var in autotools_mapping.items():
+        assert env[env_var] == f"path_to_{compiler}"
+
+
+def test_linker_scripts():
+    conanfile = ConanFileMock()
+    conanfile.conf = Conf()
+    conanfile.conf.define("tools.build:linker_scripts", ["path_to_first_linker_script", "path_to_second_linker_script"])
+    settings = MockSettings({"build_type": "Release",
+                             "os": "Windows",
+                             "compiler": "gcc",
+                             "arch": "x86_64"})
+    conanfile.settings = settings
+    at = GnuToolchain(conanfile)
+    env = at._environment.vars(conanfile)
+    assert "-T'path_to_first_linker_script'" in env["LDFLAGS"]
+    assert "-T'path_to_second_linker_script'" in env["LDFLAGS"]
+
+
+def test_update_or_prune_any_args(cross_building_conanfile):
+    # Issue: https://github.com/conan-io/conan/issues/12642
+    at = GnuToolchain(cross_building_conanfile)
+    at.configure_args.update({
+        "--with-cross-build": "my_path",
+        "--something-host": "my_host",
+        "--prefix": "/my/other/prefix"
+    })
+    new_configure_args = cmd_args_to_string(GnuToolchain._dict_to_list(at.configure_args))
+    assert "--build=x86_64-linux-gnu" in new_configure_args
+    assert "--host=wasm32-local-emscripten" in new_configure_args
+    assert "--with-cross-build=my_path" in new_configure_args
+    assert "--something-host=my_host" in new_configure_args
+    assert "--prefix=/my/other/prefix" in new_configure_args
+    # https://github.com/conan-io/conan/issues/12431
+    at.configure_args.pop("--build")
+    at.configure_args.pop("--host")
+    new_configure_args = cmd_args_to_string(GnuToolchain._dict_to_list(at.configure_args))
+    assert "--build=x86_64-linux-gnu" not in new_configure_args  # removed
+    assert "--host=wasm32-local-emscripten" not in new_configure_args  # removed
+    assert "--with-cross-build=my_path" in new_configure_args
+    assert "--something-host=my_host" in new_configure_args
+    # Update autoreconf_args
+    at.autoreconf_args.pop("--force")
+    new_autoreconf_args = cmd_args_to_string(GnuToolchain._dict_to_list(at.autoreconf_args))
+    assert "'--force" not in new_autoreconf_args
+    # Add new value to make_args
+    at.make_args.update({"--new-complex-flag": "new-value"})
+    new_make_args = cmd_args_to_string(GnuToolchain._dict_to_list(at.make_args))
+    assert "--new-complex-flag=new-value" in new_make_args
diff --git a/conans/test/unittests/tools/gnu/test_triplets.py b/conans/test/unittests/tools/gnu/test_triplets.py
index 481104ccd..be0719140 100644
--- a/conans/test/unittests/tools/gnu/test_triplets.py
+++ b/conans/test/unittests/tools/gnu/test_triplets.py
@@ -1,10 +1,10 @@
 import pytest
 
-from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
+from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet, _get_gnu_os, _get_gnu_arch
 from conans.errors import ConanException
 
 
-@pytest.mark.parametrize("os_, arch, compiler, expected_triplet", [
+@pytest.mark.parametrize("os_, arch, compiler, expected", [
     ["Linux", "x86", None, "i686-linux-gnu"],
     ["Linux", "x86_64", None, "x86_64-linux-gnu"],
     ["Linux", "armv6", None, "arm-linux-gnueabi"],
@@ -66,9 +66,11 @@ from conans.errors import ConanException
     ["Linux", "riscv32", None, "riscv32-linux-gnu"],
     ["Linux", "riscv64", None, "riscv64-linux-gnu"],
 ])
-def test_get_gnu_triplet(os_, arch, compiler, expected_triplet):
-    triplet = _get_gnu_triplet(os_, arch, compiler)
-    assert triplet == expected_triplet
+def test_get_gnu_triplet(os_, arch, compiler, expected):
+    info = _get_gnu_triplet(os_, arch, compiler)
+    assert info["triplet"] == expected
+    assert info["machine"] == _get_gnu_arch(os_, arch)
+    assert info["system"] == _get_gnu_os(os_, arch, compiler)
 
 
 def test_get_gnu_triplet_on_windows_without_compiler():
diff --git a/conans/test/unittests/util/detect_test.py b/conans/test/unittests/util/detect_test.py
index c86bff14e..c5272a005 100644
--- a/conans/test/unittests/util/detect_test.py
+++ b/conans/test/unittests/util/detect_test.py
@@ -48,7 +48,7 @@ class DetectTest(unittest.TestCase):
             result = dict(result)
             self.assertEqual(expected_arch, result['arch'])
 
-    @mock.patch("conan.internal.api.detect_api._clang_compiler",
+    @mock.patch("conan.internal.api.detect_api.detect_clang_compiler",
                 return_value=("clang", Version("9"), "clang"))
     def test_detect_clang_gcc_toolchain(self, _):
         output = RedirectedTestOutput()
diff --git a/conans/test/utils/tools.py b/conans/test/utils/tools.py
index 5e96c8550..f9d2efe9a 100644
--- a/conans/test/utils/tools.py
+++ b/conans/test/utils/tools.py
@@ -365,10 +365,12 @@ def redirect_input(target):
         sys.stdin = original_stdin
 
 
-class TestClient(object):
+class TestClient:
     """ Test wrap of the conans application to launch tests in the same way as
     in command line
     """
+    # Preventing Pytest collects any tests from here
+    __test__ = False
 
     def __init__(self, cache_folder=None, current_folder=None, servers=None, inputs=None,
                  requester_class=None, path_with_spaces=True,