Repository: conan-io/conan
Pull request #12319 (2022-10-17 11:06:15)

Use settings_target in xcrun instead of settings
Changelog: Fix: Use settings_target in XCRun instead of settings as default and provide argument `use_settings_target ` to select using the active context settings.
Docs: omit

`use_settings_target` is `False` by default because because of the use of this tool in ConanCenter, for example _openssl_ builds with _AutoTools_ so needs the **sysroot** (uses _XCRun.sdk_) and is a require by _CMake_ so in the **build context** it needs the `settings_build`, not the `settings_target`

To discuss: `use_settings_target ` default and name.

TODO: Check other tools that may need this fix too

Closes: https://github.com/conan-io/conan/issues/12260





Patch:
diff --git a/README.rst b/README.rst
index fb5ea23ce..91b3c398c 100644
--- a/README.rst
+++ b/README.rst
@@ -8,7 +8,7 @@ Decentralized, open-source (MIT), C/C++ package manager.
 - Homepage: https://conan.io/
 - Github: https://github.com/conan-io/conan
 - Docs: https://docs.conan.io/en/latest/
-- Slack: https://cpplang-inviter.cppalliance.org/ (#conan channel)
+- Slack: https://cppalliance.org/slack/ (#conan channel)
 - Twitter: https://twitter.com/conan_io
 
 
diff --git a/conan/tools/apple/apple.py b/conan/tools/apple/apple.py
index a68b5d355..b2efefd48 100644
--- a/conan/tools/apple/apple.py
+++ b/conan/tools/apple/apple.py
@@ -4,6 +4,7 @@ import os
 
 from conans.util.runners import check_output_runner
 from conans.client.tools.apple import to_apple_arch as _to_apple_arch
+from conans.errors import ConanException
 
 
 def is_apple_os(conanfile):
@@ -79,11 +80,18 @@ def apple_sdk_path(conanfile):
 
 class XCRun(object):
 
-    def __init__(self, conanfile, sdk=None):
+    def __init__(self, conanfile, sdk=None, use_settings_target=False):
         """sdk=False will skip the flag
-           sdk=None will try to adjust it automatically"""
-        if sdk is None and conanfile.settings:
-            sdk = apple_sdk_name(conanfile.settings)
+           sdk=None will try to adjust it automatically
+           target_settings=True try to use settings_target in case they exist"""
+
+        # FIXME: 2.0: remove "hasattr()" condition
+        settings = conanfile.settings
+        if use_settings_target and hasattr(conanfile, "settings_target") and conanfile.settings_target is not None:
+            settings = conanfile.settings_target
+
+        if sdk is None and settings:
+            sdk = apple_sdk_name(settings)
         self.sdk = sdk
 
     def _invoke(self, args):
@@ -158,8 +166,8 @@ def fix_apple_shared_install_name(conanfile):
         install_name = check_output_runner(command).strip().split(":")[1].strip()
         return install_name
 
-    def _osx_collect_dylibs(lib_folder):
-        return [os.path.join(full_folder, f) for f in os.listdir(lib_folder) if f.endswith(".dylib")
+    def _darwin_collect_dylibs(lib_folder):
+        return [os.path.join(lib_folder, f) for f in os.listdir(lib_folder) if f.endswith(".dylib")
                 and not os.path.islink(os.path.join(lib_folder, f))]
 
     def _fix_install_name(dylib_path, new_name):
@@ -170,16 +178,48 @@ def fix_apple_shared_install_name(conanfile):
         command = f"install_name_tool {dylib_path} -change {old_name} {new_name}"
         conanfile.run(command)
 
-    substitutions = {}
-
-    if is_apple_os(conanfile) and conanfile.options.get_safe("shared", False):
+    def _darwin_collect_executables(bin_folder):
+        ret = []
+        for f in os.listdir(bin_folder):
+            full_path = os.path.join(bin_folder, f)
+
+            # Run "otool -hv" to verify it is an executable
+            check_bin = "otool -hv {}".format(full_path)
+            if "EXECUTE" in check_output_runner(check_bin):
+                ret.append(full_path)
+        return ret
+
+    def _get_rpath_entries(binary_file):
+        entries = []
+        command = "otool -l {}".format(binary_file)
+        otool_output = check_output_runner(command).splitlines()
+        for count, text in enumerate(otool_output):
+            pass
+            if "LC_RPATH" in text:
+                rpath_entry = otool_output[count+2].split("path ")[1].split(" ")[0]
+                entries.append(rpath_entry)
+        return entries
+
+    def _get_shared_dependencies(binary_file):
+        command = "otool -L {}".format(binary_file)
+        all_shared = check_output_runner(command).strip().split(":")[1].strip()
+        ret = [s.split("(")[0].strip() for s in all_shared.splitlines()]
+        return ret
+
+    def _fix_dylib_files(conanfile):
+        substitutions = {}
         libdirs = getattr(conanfile.cpp.package, "libdirs")
         for libdir in libdirs:
             full_folder = os.path.join(conanfile.package_folder, libdir)
-            shared_libs = _osx_collect_dylibs(full_folder)
+            if not os.path.exists(full_folder):
+                raise ConanException(f"Trying to locate shared libraries, but `{libdir}` "
+                                     f" not found inside package folder {conanfile.package_folder}")
+            shared_libs = _darwin_collect_dylibs(full_folder)
             # fix LC_ID_DYLIB in first pass
             for shared_lib in shared_libs:
                 install_name = _get_install_name(shared_lib)
+                #TODO: we probably only want to fix the install the name if
+                # it starts with `/`.
                 rpath_name = f"@rpath/{os.path.basename(install_name)}"
                 _fix_install_name(shared_lib, rpath_name)
                 substitutions[install_name] = rpath_name
@@ -188,3 +228,45 @@ def fix_apple_shared_install_name(conanfile):
             for shared_lib in shared_libs:
                 for old, new in substitutions.items():
                     _fix_dep_name(shared_lib, old, new)
+
+        return substitutions
+
+    def _fix_executables(conanfile, substitutions):
+        # Fix the install name for executables inside the package
+        # that reference libraries we just patched
+        bindirs = getattr(conanfile.cpp.package, "bindirs")
+        for bindir in bindirs:
+            full_folder = os.path.join(conanfile.package_folder, bindir)
+            if not os.path.exists(full_folder):
+                # Skip if the folder does not exist inside the package
+                # (e.g. package does not contain executables but bindirs is defined)
+                continue
+            executables = _darwin_collect_executables(full_folder)
+            for executable in executables:
+
+                # Fix install names of libraries from within the same package
+                deps = _get_shared_dependencies(executable)
+                for dep in deps:
+                    dep_base = os.path.join(os.path.dirname(dep), os.path.basename(dep).split('.')[0])
+                    match = [k for k in substitutions.keys() if k.startswith(dep_base)]
+                    if match:
+                        _fix_dep_name(executable, dep, substitutions[match[0]])
+
+                # Add relative rpath to library directories, avoiding possible
+                # existing duplicates
+                libdirs = getattr(conanfile.cpp.package, "libdirs")
+                libdirs = [os.path.join(conanfile.package_folder, dir) for dir in libdirs]
+                rel_paths = [f"@executable_path/{os.path.relpath(dir, full_folder)}" for dir in libdirs]
+                existing_rpaths = _get_rpath_entries(executable)
+                rpaths_to_add = list(set(rel_paths) - set(existing_rpaths))
+                for entry in rpaths_to_add:
+                    command = f"install_name_tool {executable} -add_rpath {entry}"
+                    conanfile.run(command)
+
+    if is_apple_os(conanfile) and conanfile.options.get_safe("shared", False):
+        substitutions = _fix_dylib_files(conanfile)
+
+        # Only "fix" executables if dylib files were patched, otherwise 
+        # there is nothing to do.
+        if substitutions:
+            _fix_executables(conanfile, substitutions)
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index 0ad1e0bbd..eda75b0d6 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -153,7 +153,7 @@ class FPicBlock(Block):
     template = textwrap.dedent("""
         {% if fpic %}
         message(STATUS "Conan toolchain: Setting CMAKE_POSITION_INDEPENDENT_CODE={{ fpic }} (options.fPIC)")
-        set(CMAKE_POSITION_INDEPENDENT_CODE {{ fpic }})
+        set(CMAKE_POSITION_INDEPENDENT_CODE {{ fpic }} CACHE BOOL "Position independent code") 
         {% endif %}
         """)
 
@@ -239,7 +239,7 @@ class CppStdBlock(Block):
 class SharedLibBock(Block):
     template = textwrap.dedent("""
         message(STATUS "Conan toolchain: Setting BUILD_SHARED_LIBS = {{ shared_libs }}")
-        set(BUILD_SHARED_LIBS {{ shared_libs }})
+        set(BUILD_SHARED_LIBS {{ shared_libs }} CACHE BOOL "Build shared libraries")
         """)
 
     def context(self):
diff --git a/conan/tools/env/environment.py b/conan/tools/env/environment.py
index 18c5de0b7..4d43ed19a 100644
--- a/conan/tools/env/environment.py
+++ b/conan/tools/env/environment.py
@@ -350,7 +350,7 @@ class EnvVars:
         filepath, filename = os.path.split(file_location)
         deactivate_file = os.path.join(filepath, "deactivate_{}".format(filename))
         deactivate = textwrap.dedent("""\
-           echo "echo Restoring environment" >> "{deactivate_file}"
+           echo "echo Restoring environment" > "{deactivate_file}"
            for v in {vars}
            do
                is_defined="true"
diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py
index 7269fa2f7..7b0f735df 100644
--- a/conan/tools/gnu/autotoolstoolchain.py
+++ b/conan/tools/gnu/autotoolstoolchain.py
@@ -43,8 +43,8 @@ class AutotoolsToolchain:
         self.fpic = self._conanfile.options.get_safe("fPIC")
         self.msvc_runtime_flag = self._get_msvc_runtime_flag()
 
-        # Cross build
-        self._host = None
+        # Cross build triplets
+        self._host = self._conanfile.conf.get("tools.gnu:host_triplet")
         self._build = None
         self._target = None
 
@@ -56,7 +56,8 @@ class AutotoolsToolchain:
         if cross_building(self._conanfile):
             os_build, arch_build, os_host, arch_host = get_cross_building_settings(self._conanfile)
             compiler = self._conanfile.settings.get_safe("compiler")
-            self._host = _get_gnu_triplet(os_host, arch_host, compiler=compiler)
+            if not self._host:
+                self._host = _get_gnu_triplet(os_host, arch_host, compiler=compiler)
             self._build = _get_gnu_triplet(os_build, arch_build, compiler=compiler)
 
             # Apple Stuff
diff --git a/conan/tools/meson/toolchain.py b/conan/tools/meson/toolchain.py
index d97116943..b75fec4bd 100644
--- a/conan/tools/meson/toolchain.py
+++ b/conan/tools/meson/toolchain.py
@@ -317,6 +317,7 @@ class MesonToolchain(object):
 
         if self.libcxx:
             self.cpp_args.append(self.libcxx)
+            self.cpp_link_args.append(self.libcxx)
         if self.gcc_cxx11_abi:
             self.cpp_args.append("-D{}".format(self.gcc_cxx11_abi))
 
diff --git a/conan/tools/microsoft/msbuilddeps.py b/conan/tools/microsoft/msbuilddeps.py
index 52353f433..3c3d2739c 100644
--- a/conan/tools/microsoft/msbuilddeps.py
+++ b/conan/tools/microsoft/msbuilddeps.py
@@ -25,7 +25,6 @@ class MSBuildDeps(object):
           <PropertyGroup Label="ConanVariables">
             <Conan{{name}}RootFolder>{{root_folder}}</Conan{{name}}RootFolder>
             <Conan{{name}}BinaryDirectories>{{bin_dirs}}</Conan{{name}}BinaryDirectories>
-            <Conan{{name}}Dependencies>{{dependencies}}</Conan{{name}}Dependencies>
             {% if host_context %}
             <Conan{{name}}CompilerFlags>{{compiler_flags}}</Conan{{name}}CompilerFlags>
             <Conan{{name}}LinkerFlags>{{linker_flags}}</Conan{{name}}LinkerFlags>
@@ -134,7 +133,7 @@ class MSBuildDeps(object):
     def _get_valid_xml_format(name):
         return re.compile(r"[.+]").sub("_", name)
 
-    def _vars_props_file(self, dep, name, cpp_info, deps, build):
+    def _vars_props_file(self, dep, name, cpp_info, build):
         """
         content for conan_vars_poco_x86_release.props, containing the variables for 1 config
         This will be for 1 package or for one component of a package
@@ -180,7 +179,6 @@ class MSBuildDeps(object):
             'definitions': "".join("%s;" % d for d in cpp_info.defines),
             'compiler_flags': " ".join(cpp_info.cxxflags + cpp_info.cflags),
             'linker_flags': " ".join(cpp_info.sharedlinkflags + cpp_info.exelinkflags),
-            'dependencies': ";".join(deps),
             'host_context': not build
         }
         formatted_template = Template(self._vars_props, trim_blocks=True,
@@ -291,15 +289,16 @@ class MSBuildDeps(object):
                 comp_filename = "conan_%s.props" % full_comp_name
                 pkg_filename = "conan_%s.props" % dep_name
 
-                public_deps = []
+                public_deps = []  # To store the xml dependencies/file names
                 for r in comp_info.requires:
                     if "::" in r:  # Points to a component of a different package
                         pkg, cmp_name = r.split("::")
                         public_deps.append(pkg if pkg == cmp_name else "{}_{}".format(pkg, cmp_name))
                     else:  # Points to a component of same package
                         public_deps.append("{}_{}".format(dep_name, r))
+                public_deps = [self._get_valid_xml_format(d) for d in public_deps]
                 result[vars_filename] = self._vars_props_file(dep, full_comp_name, comp_info,
-                                                              public_deps, build=build)
+                                                              build=build)
                 result[activate_filename] = self._activate_props_file(full_comp_name, vars_filename,
                                                                       public_deps, build=build)
                 result[comp_filename] = self._dep_props_file(full_comp_name, comp_filename,
@@ -317,7 +316,7 @@ class MSBuildDeps(object):
             public_deps = [self._dep_name(d, build)
                            for r, d in dep.dependencies.direct_host.items() if r.visible]
             result[vars_filename] = self._vars_props_file(dep, dep_name, cpp_info,
-                                                          public_deps, build=build)
+                                                          build=build)
             result[activate_filename] = self._activate_props_file(dep_name, vars_filename,
                                                                   public_deps, build=build)
             result[pkg_filename] = self._dep_props_file(dep_name, pkg_filename, activate_filename,
diff --git a/conan/tools/system/package_manager.py b/conan/tools/system/package_manager.py
index ef281980f..927e8ecd1 100644
--- a/conan/tools/system/package_manager.py
+++ b/conan/tools/system/package_manager.py
@@ -1,5 +1,6 @@
 import platform
 
+from conan.tools.build import cross_building
 from conans.client.graph.graph import CONTEXT_BUILD
 from conans.errors import ConanException
 
@@ -57,7 +58,7 @@ class _SystemPackageManagerTool(object):
 
     def get_package_name(self, package):
         # TODO: should we only add the arch if cross-building?
-        if self._arch in self._arch_names:
+        if self._arch in self._arch_names and cross_building(self._conanfile):
             return "{}{}{}".format(package, self._arch_separator,
                                    self._arch_names.get(self._arch))
         return package
diff --git a/conans/client/cache/cache.py b/conans/client/cache/cache.py
index a35d2a406..b827edb16 100644
--- a/conans/client/cache/cache.py
+++ b/conans/client/cache/cache.py
@@ -170,7 +170,10 @@ class ClientCache(object):
             self._new_config = ConfDefinition()
             if os.path.exists(self.new_config_path):
                 text = load(self.new_config_path)
-                content = Template(text).render({"platform": platform, "os": os})
+                distro = None
+                if platform.system() in ["Linux", "FreeBSD"]:
+                    import distro
+                content = Template(text).render({"platform": platform, "os": os, "distro": distro})
                 self._new_config.loads(content)
         return self._new_config
 
diff --git a/conans/client/command.py b/conans/client/command.py
index 9c1469ac8..5b548b805 100644
--- a/conans/client/command.py
+++ b/conans/client/command.py
@@ -1575,7 +1575,7 @@ class Command(object):
         parser_add.add_argument('remote', help='Name of the remote')
         parser_add.add_argument('url', help='URL of the remote')
         parser_add.add_argument('verify_ssl', nargs="?", default="True",
-                                help='Verify SSL certificated. Default True')
+                                help='Verify SSL certificate. Defaulted to True')
         parser_add.add_argument("-i", "--insert", nargs="?", const=0, type=int, action=OnceArgument,
                                 help="insert remote at specific index")
         parser_add.add_argument("-f", "--force", default=False, action='store_true',
@@ -1587,7 +1587,7 @@ class Command(object):
 
         parser_upd.add_argument('url', help='URL')
         parser_upd.add_argument('verify_ssl', nargs="?", default="True",
-                                help='Verify SSL certificated. Default True')
+                                help='Verify SSL certificate. Defaulted to True')
         parser_upd.add_argument("-i", "--insert", nargs="?", const=0, type=int, action=OnceArgument,
                                 help="Insert remote at specific index")
         parser_rename = subparsers.add_parser('rename', help='Update the remote name')
diff --git a/conans/client/generators/__init__.py b/conans/client/generators/__init__.py
index 246af0a51..86d19ae10 100644
--- a/conans/client/generators/__init__.py
+++ b/conans/client/generators/__init__.py
@@ -254,6 +254,7 @@ def write_toolchain(conanfile, path, output):
 
     # tools.env.virtualenv:auto_use will be always True in Conan 2.0
     if conanfile.conf["tools.env.virtualenv:auto_use"]:
+        mkdir(path)
         with chdir(path):
             if conanfile.virtualbuildenv:
                 from conan.tools.env.virtualbuildenv import VirtualBuildEnv
diff --git a/conans/model/conf.py b/conans/model/conf.py
index 4df28790e..b7044625b 100644
--- a/conans/model/conf.py
+++ b/conans/model/conf.py
@@ -28,6 +28,7 @@ BUILT_IN_CONFS = {
     "tools.files.download:retry_wait": "Seconds to wait between download attempts",
     "tools.gnu:make_program": "Indicate path to make program",
     "tools.gnu:define_libcxx11_abi": "Force definition of GLIBCXX_USE_CXX11_ABI=1 for libstdc++11",
+    "tools.gnu:host_triplet": "Custom host triplet to pass to Autotools scripts",
     "tools.google.bazel:configs": "Define Bazel config file",
     "tools.google.bazel:bazelrc_path": "Defines Bazel rc-path",
     "tools.microsoft.msbuild:verbosity": "Verbosity level for MSBuild: 'Quiet', 'Minimal', 'Normal', 'Detailed', 'Diagnostic'",


Test patch:
diff --git a/conans/test/functional/layout/test_editables_layout.py b/conans/test/functional/layout/test_editables_layout.py
index d81dad552..277798608 100644
--- a/conans/test/functional/layout/test_editables_layout.py
+++ b/conans/test/functional/layout/test_editables_layout.py
@@ -253,3 +253,30 @@ def test_cpp_info_components_editable():
     assert "**VAR libs:['hello_var']**" in out
     assert "**VAR cxxflags:['my_cxx_flag_var']**" in out
     assert "**VAR cflags:['my_c_flag_var']**" in out
+
+
+def test_editable_package_folder():
+    """ This test checks the behavior that self.package_folder is NOT defined (i.e = None)
+    for editable packages, so it cannot be used in ``package_info()`` method
+    """
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        import os
+        from conan import ConanFile
+        from conan.tools.cmake import cmake_layout
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "os", "compiler", "arch", "build_type"
+
+            def package_info(self):
+                self.output.info("PKG FOLDER={}!!!".format(self.package_folder))
+
+            def layout(self):
+                cmake_layout(self)
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create .")
+    c.run("editable add . pkg/0.1")
+    c.run("install pkg/0.1@")
+    assert "pkg/0.1: PKG FOLDER=None!!!"
diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
index 01453c25b..42046cd43 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
@@ -1061,3 +1061,71 @@ def test_resdirs_none_cmake_install():
     client.save({"conanfile.py": conanfile, "CMakeLists.txt": cmake, "my_license": "MIT"})
     client.run("create .", assert_error=True)
     assert "Cannot install stuff" in client.out
+
+
+def test_cmake_toolchain_vars_when_option_declared():
+    t = TestClient()
+
+    cmakelists = textwrap.dedent("""
+    cmake_minimum_required(VERSION 2.8) # <---- set this to an old version for old policies
+    cmake_policy(SET CMP0091 NEW) # <-- Needed on Windows
+    project(mylib CXX)
+
+    message("CMake version: ${CMAKE_VERSION}")
+
+    # Set the options AFTER the call to project, that is, after toolchain is loaded
+    option(BUILD_SHARED_LIBS "" ON)
+    option(CMAKE_POSITION_INDEPENDENT_CODE "" OFF)
+
+    add_library(mylib src/mylib.cpp)
+    target_include_directories(mylib PUBLIC include)
+
+    get_target_property(MYLIB_TARGET_TYPE mylib TYPE)
+    get_target_property(MYLIB_PIC mylib POSITION_INDEPENDENT_CODE)
+    message("mylib target type: ${MYLIB_TARGET_TYPE}")
+    message("MYLIB_PIC value: ${MYLIB_PIC}")
+    if(MYLIB_PIC)
+        #Note: the value is "True"/"False" if set by cmake,
+        #       and "ON"/"OFF" if set by Conan
+        message("mylib position independent code: ON")
+    else()
+        message("mylib position independent code: OFF")
+    endif()
+
+    set_target_properties(mylib PROPERTIES PUBLIC_HEADER "include/mylib.h")
+    install(TARGETS mylib)
+    """)
+
+    t.run("new mylib/1.0 --template cmake_lib")
+    t.save({"CMakeLists.txt": cmakelists})
+    
+    # The generated toolchain should set `BUILD_SHARED_LIBS` to `OFF`,
+    # and `CMAKE_POSITION_INDEPENDENT_CODE` to `ON` and the calls to
+    # `option()` in the CMakeLists.txt should respect the existing values.
+    # Note: on *WINDOWS* `fPIC` is not an option for this recipe, so it's invalid
+    #       to pass it to Conan, in which case the value in CMakeLists.txt
+    #       takes precedence.
+    fpic_option = "-o mylib:fPIC=True" if platform.system() != "Windows" else ""
+    fpic_cmake_value = "ON" if platform.system() != "Windows" else "OFF"
+    t.run(f"create . -o mylib:shared=False {fpic_option} --test-folder=None")
+    assert "mylib target type: STATIC_LIBRARY" in t.out
+    assert f"mylib position independent code: {fpic_cmake_value}" in t.out
+
+    # When building manually, ensure the value passed by the toolchain overrides the ones in 
+    # the CMakeLists
+    fpic_option = "-o mylib:fPIC=False" if platform.system() != "Windows" else ""
+    t.run(f"install . -o mylib:shared=False {fpic_option}")
+    t.run_command("cmake -S . -B build/ -DCMAKE_TOOLCHAIN_FILE=build/generators/conan_toolchain.cmake")
+    assert "mylib target type: STATIC_LIBRARY" in t.out
+    assert f"mylib position independent code: OFF" in t.out
+
+    # Note: from this point forward, the CMakeCache is already initialised.
+    # When explicitly overriding `CMAKE_POSITION_INDEPENDENT_CODE` via command line, ensure
+    # this takes precedence to the value defined by the toolchain
+    t.run_command("cmake -S . -B build/ -DCMAKE_POSITION_INDEPENDENT_CODE=ON")
+    assert "mylib target type: STATIC_LIBRARY" in t.out
+    assert "mylib position independent code: ON" in t.out
+
+    t.run_command("cmake -S . -B build/ -DBUILD_SHARED_LIBS=ON")
+    assert "mylib target type: SHARED_LIBRARY" in t.out
+    assert "mylib position independent code: ON" in t.out
diff --git a/conans/test/functional/toolchains/gnu/autotools/test_crossbuild_triplet.py b/conans/test/functional/toolchains/gnu/autotools/test_crossbuild_triplet.py
new file mode 100644
index 000000000..d379b17b4
--- /dev/null
+++ b/conans/test/functional/toolchains/gnu/autotools/test_crossbuild_triplet.py
@@ -0,0 +1,53 @@
+import platform
+import pytest
+import textwrap
+
+from conans.test.utils.tools import TestClient
+
+@pytest.mark.skipif(platform.system() not in  ["Darwin", "Linux"], reason="Autotools on Linux or macOS")
+def test_crossbuild_triplet_from_conf():
+
+    settings_yml = textwrap.dedent("""
+        os:
+            Linux:
+            Windows:
+        arch: [x86_64, hexagon]
+        compiler:
+            gcc:
+                version: ["10", "11"]
+                libcxx: [libstdc++11]
+        build_type: [None, Debug, Release]
+        """)
+    
+    host_profile = textwrap.dedent("""
+        [settings]
+        os=Linux
+        arch=hexagon
+        compiler=gcc
+        compiler.version=10
+        compiler.libcxx=libstdc++11
+        build_type=Release
+        [conf]
+        tools.gnu:host_triplet=hexagon-acme-linux-gnu
+    """)
+
+    build_profile = textwrap.dedent("""
+        [settings]
+        os=Linux
+        arch=x86_64
+        compiler=gcc
+        compiler.version=11
+        compiler.libcxx=libstdc++11
+        build_type=Release   
+    """)
+
+    client = TestClient(path_with_spaces=False)
+    client.save({client.cache.settings_path: settings_yml})
+    client.save({"host_profile": host_profile})
+    client.save({"build_profile": build_profile})
+
+    client.run("new hello/0.1 --template=autotools_lib")
+    client.run("create . --profile:build=build_profile --profile:host=host_profile -tf None")
+
+    assert "--host=hexagon-acme-linux-gnu" in client.out
+    assert "checking host system type... hexagon-acme-linux-gnu" in client.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 81685594a..240f3213b 100644
--- a/conans/test/functional/toolchains/gnu/test_v2_autotools_template.py
+++ b/conans/test/functional/toolchains/gnu/test_v2_autotools_template.py
@@ -26,6 +26,23 @@ def test_autotools_lib_template():
     package_folder = client.cache.package_layout(pref.ref).package(pref)
     assert os.path.exists(os.path.join(package_folder, "include", "hello.h"))
 
+    # Local flow for shared library works
+    client.save({}, clean_first=True)
+    client.run("new hello/0.1 --template=autotools_lib")
+    client.run("install . -if install_shared -o hello:shared=True")
+    client.run("build . -if=install_shared")
+    client.run("export-pkg . hello/0.1@ -if=install_shared -o hello:shared=True")
+    package_id = re.search(r"Packaging to (\S+)", str(client.out)).group(1)
+    pref = PackageReference(ConanFileReference.loads("hello/0.1"), package_id)
+    package_folder = client.cache.package_layout(pref.ref).package(pref)
+
+    if platform.system() == "Darwin":
+        # Ensure that install name of dylib is patched
+        client.run_command(f"otool -L {package_folder}/lib/libhello.0.dylib")
+        assert "@rpath/libhello.0.dylib" in client.out
+    elif platform.system() == "Linux":
+        assert os.path.exists(os.path.join(package_folder, "lib", "libhello.so.0"))
+
     # Create works
     client.run("create .")
     assert "hello/0.1: Hello World Release!" in client.out
@@ -269,6 +286,10 @@ def test_autotools_fix_shared_libs():
         libbye_la_HEADERS = bye.h
         libbye_ladir = $(includedir)
         libbye_la_LIBADD = libhello.la
+
+        bin_PROGRAMS = main
+        main_SOURCES = main.cpp
+        main_LDADD = libhello.la libbye.la
     """)
 
     test_src = textwrap.dedent("""
@@ -280,6 +301,7 @@ def test_autotools_fix_shared_libs():
         "src/makefile.am": makefile_am,
         "src/bye.cpp": bye_cpp,
         "src/bye.h": bye_h,
+        "src/main.cpp": test_src,
         "test_package/main.cpp": test_src,
         "conanfile.py": conanfile,
     })
@@ -304,5 +326,13 @@ def test_autotools_fix_shared_libs():
     assert "@rpath/libhello.dylib (compatibility version 1.0.0, current version 1.0.0)" in client.out
     assert "@rpath/libbye.dylib (compatibility version 1.0.0, current version 1.0.0)" in client.out
 
+    # app rpath fixed in executable
+    exe_path = os.path.join(package_folder, "bin", "main")
+    client.run_command("otool -L {}".format(exe_path))
+    assert "@rpath/libhello.dylib" in client.out
+    client.run_command(exe_path)
+    assert "Bye, bye!" in client.out
+
+    # Running the test-package also works
     client.run("test test_package hello/0.1@ -o hello:shared=True")
     assert "Bye, bye!" in client.out
diff --git a/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py b/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
index 9c6a9120b..f36d3bede 100644
--- a/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
+++ b/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
@@ -1008,4 +1008,4 @@ def test_build_requires_transitives():
     assert "conan_dep_build.props" in tool
     assert "conan_dep.props" not in tool
     tool_vars = c.load("conan_tool_build_vars_release_x64.props")
-    assert "<Conantool_buildDependencies>dep_build</Conantool_buildDependencies>" in tool_vars
+    assert "<Conantool_buildRootFolder>" in tool_vars
diff --git a/conans/test/functional/tools/system/package_manager_test.py b/conans/test/functional/tools/system/package_manager_test.py
index 210f6434d..89d27e705 100644
--- a/conans/test/functional/tools/system/package_manager_test.py
+++ b/conans/test/functional/tools/system/package_manager_test.py
@@ -50,11 +50,10 @@ def test_apt_install_substitutes():
     client.save({"conanfile.py": conanfile_py.format(installs)})
     client.run("create . test/1.0@ -c tools.system.package_manager:mode=install "
                "-c tools.system.package_manager:sudo=True", assert_error=True)
-
-    assert "dpkg-query: no packages found matching non-existing1:amd64" in client.out
-    assert "dpkg-query: no packages found matching non-existing2:amd64" in client.out
-    assert "dpkg-query: no packages found matching non-existing3:amd64" in client.out
-    assert "dpkg-query: no packages found matching non-existing4:amd64" in client.out
+    assert "dpkg-query: no packages found matching non-existing1" in client.out
+    assert "dpkg-query: no packages found matching non-existing2" in client.out
+    assert "dpkg-query: no packages found matching non-existing3" in client.out
+    assert "dpkg-query: no packages found matching non-existing4" in client.out
     assert "ERROR: while executing system_requirements(): " \
            "None of the installs for the package substitutes succeeded." in client.out
 
@@ -88,8 +87,8 @@ def test_build_require():
             tool_requires = "tool_require/1.0"
         """)})
     client.run("create consumer.py consumer/1.0@ -s:b arch=armv8 -s:h arch=x86 --build=missing")
-    assert "dpkg-query: no packages found matching non-existing1:arm64" in client.out
-    assert "dpkg-query: no packages found matching non-existing2:arm64" in client.out
+    assert "dpkg-query: no packages found matching non-existing1" in client.out
+    assert "dpkg-query: no packages found matching non-existing2" in client.out
     assert "missing: ['non-existing1', 'non-existing2']" in client.out
 
 
diff --git a/conans/test/functional/tools/test_apple_tools.py b/conans/test/functional/tools/test_apple_tools.py
index 15fba0bcf..cfb351a67 100644
--- a/conans/test/functional/tools/test_apple_tools.py
+++ b/conans/test/functional/tools/test_apple_tools.py
@@ -3,6 +3,7 @@ import textwrap
 
 import pytest
 
+from conans.test.assets.genconanfile import GenConanfile
 from conans.test.utils.tools import TestClient
 
 
@@ -24,3 +25,96 @@ def test_xcrun():
     client.save({"conanfile.py": conanfile}, clean_first=True)
     client.run("create .")
     assert "Xcode.app/Contents/Developer/Platforms/MacOSX.platform" in client.out
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Requires Xcode")
+def test_xcrun_in_tool_requires():
+    # https://github.com/conan-io/conan/issues/12260
+    client = TestClient()
+    tool = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.apple import XCRun
+        class Pkg(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+
+            def package_info(self):
+                xcrun = XCRun(self{})
+                self.output.info("sdk: %s" % xcrun.sdk)
+        """)
+    client.save({"br.py": tool.format(", use_settings_target=True")})
+    client.run("export br.py br/0.1@")
+
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        class Pkg(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            tool_requires = "br/0.1"
+        """)
+
+    profile_ios = textwrap.dedent("""
+        include(default)
+        [settings]
+        os=iOS
+        os.version=15.4
+        os.sdk=iphoneos
+        os.sdk_version=15.0
+        arch=armv8
+    """)
+
+    client.save({"conanfile.py": conanfile, "profile_ios": profile_ios})
+    client.run("create . pkg/1.0@ -pr:h=./profile_ios -pr:b=default --build")
+    assert "br/0.1: sdk: iphoneos15.0" in client.out
+    assert "br/0.1: sdk: macosx" not in client.out
+
+    client.save({"br.py": tool.format("")})
+    client.run("export br.py br/0.1@")
+    client.run("create . pkg/1.0@ -pr:h=./profile_ios -pr:b=default --build")
+    assert "br/0.1: sdk: iphoneos15.0" not in client.out
+    assert "br/0.1: sdk: macosx" in client.out
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Requires Xcode")
+def test_xcrun_in_required_by_tool_requires():
+    """
+    ConanCenter case, most typical, openssl builds with autotools so needs the sysroot
+    and is a require by cmake so in the build context it needs the settings_build, not
+    the settings_target, that's why the use_settings_target default is False
+    """
+    client = TestClient()
+
+    openssl = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.apple import XCRun
+        class Pkg(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            def build(self):
+                xcrun = XCRun(self)
+                self.output.info("sdk for building openssl: %s" % xcrun.sdk)
+        """)
+
+    consumer = textwrap.dedent("""
+        from conan import ConanFile
+        class Pkg(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+            tool_requires = "cmake/1.0"
+        """)
+
+    profile_ios = textwrap.dedent("""
+        include(default)
+        [settings]
+        os=iOS
+        os.version=15.4
+        os.sdk=iphoneos
+        os.sdk_version=15.0
+        arch=armv8
+    """)
+
+    client.save({"cmake.py": GenConanfile("cmake", "1.0").with_requires("openssl/1.0"),
+                 "openssl.py": openssl,
+                 "consumer.py": consumer,
+                 "profile_ios": profile_ios})
+
+    client.run("export openssl.py openssl/1.0@")
+    client.run("export cmake.py")
+    client.run("create consumer.py consumer/1.0@ -pr:h=./profile_ios -pr:b=default --build")
+    assert "sdk for building openssl: macosx" in client.out
diff --git a/conans/test/integration/configuration/conf/test_conf.py b/conans/test/integration/configuration/conf/test_conf.py
index 5bdeb5477..9310a156b 100644
--- a/conans/test/integration/configuration/conf/test_conf.py
+++ b/conans/test/integration/configuration/conf/test_conf.py
@@ -177,10 +177,15 @@ def test_composition_conan_conf_different_data_types_by_cli_arg(client):
     assert "tools.microsoft.msbuildtoolchain:compile_options${'ExceptionHandling': 'Async'}" in client.out
 
 
-@pytest.mark.skipif(six.PY2, reason="only Py3")
 def test_jinja_global_conf(client):
     save(client.cache.new_config_path, "user.mycompany:parallel = {{os.cpu_count()/2}}\n"
-                                       "user.mycompany:other = {{platform.system()}}\n")
+                                       "user.mycompany:other = {{platform.system()}}\n"
+                                       "user.mycompany:dist = {{distro.id() if distro else '42'}}\n")
     client.run("install .")
     assert "user.mycompany:parallel={}".format(os.cpu_count()/2) in client.out
     assert "user.mycompany:other={}".format(platform.system()) in client.out
+    if platform.system() == "Linux":
+        import distro
+        assert "user.mycompany:dist={}".format(distro.id()) in client.out
+    else:
+        assert "user.mycompany:dist=42" in client.out
diff --git a/conans/test/integration/environment/test_env.py b/conans/test/integration/environment/test_env.py
index d81f55ef7..334936ae8 100644
--- a/conans/test/integration/environment/test_env.py
+++ b/conans/test/integration/environment/test_env.py
@@ -483,18 +483,19 @@ def test_multiple_deactivate():
     os.chmod(os.path.join(client.current_folder, "display.sh"), 0o777)
     client.run("install .")
 
-    if platform.system() == "Windows":
-        cmd = "conanbuild.bat && display.bat && deactivate_conanbuild.bat && display.bat"
-    else:
-        cmd = '. ./conanbuild.sh && ./display.sh && . ./deactivate_conanbuild.sh && ./display.sh'
-    out, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
-                              shell=True, cwd=client.current_folder).communicate()
-    out = out.decode()
-    assert "VAR1=Value1!!" in out
-    assert "VAR2=Value2!!" in out
-    assert 2 == str(out).count("Restoring environment")
-    assert "VAR1=!!" in out
-    assert "VAR2=!!" in out
+    for _ in range(2):  # Just repeat it, so we can check things keep working
+        if platform.system() == "Windows":
+            cmd = "conanbuild.bat && display.bat && deactivate_conanbuild.bat && display.bat"
+        else:
+            cmd = '. ./conanbuild.sh && ./display.sh && . ./deactivate_conanbuild.sh && ./display.sh'
+        out, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+                                  shell=True, cwd=client.current_folder).communicate()
+        out = out.decode()
+        assert "VAR1=Value1!!" in out
+        assert "VAR2=Value2!!" in out
+        assert 2 == str(out).count("Restoring environment")
+        assert "VAR1=!!" in out
+        assert "VAR2=!!" in out
 
 
 @pytest.mark.skipif(platform.system() != "Windows", reason="Path problem in Windows only")
diff --git a/conans/test/integration/toolchains/gnu/test_basic_layout.py b/conans/test/integration/toolchains/gnu/test_basic_layout.py
index 19cd9ebb6..968596115 100644
--- a/conans/test/integration/toolchains/gnu/test_basic_layout.py
+++ b/conans/test/integration/toolchains/gnu/test_basic_layout.py
@@ -23,3 +23,25 @@ def test_basic_layout_subproject():
     ext = "sh" if platform.system() != "Windows" else "bat"
     assert os.path.isfile(os.path.join(c.current_folder, "pkg", "build-release", "conan",
                                        "conanautotoolstoolchain.{}".format(ext)))
+
+
+# TODO: Remove this test in 2.0
+def test_basic_layout_no_generators():
+    """ test that conan doesn't crash for auto_use=True
+    because generator folder doesn't exist
+    # https://github.com/conan-io/conan/issues/12383
+    """
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.layout import basic_layout
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "0.1"
+            settings = "os", "compiler", "build_type", "arch"
+            def layout(self):
+                basic_layout(self)
+        """)
+    c.save({"conanfile.py": conanfile})
+    c.run("create . -c tools.env.virtualenv:auto_use=True")
+    # It used to fail, if it doesn't crash, it is good
diff --git a/conans/test/integration/toolchains/meson/test_mesontoolchain.py b/conans/test/integration/toolchains/meson/test_mesontoolchain.py
index 1f9a933c7..c5b273ada 100644
--- a/conans/test/integration/toolchains/meson/test_mesontoolchain.py
+++ b/conans/test/integration/toolchains/meson/test_mesontoolchain.py
@@ -58,8 +58,8 @@ def test_apple_meson_keep_user_custom_flags():
     content = t.load(MesonToolchain.cross_filename)
     assert "c_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7']" in content
     assert "c_link_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7']" in content
-    assert "cpp_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7']" in content
-    assert "cpp_link_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7']" in content
+    assert "cpp_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7', '-stdlib=libc++']" in content
+    assert "cpp_link_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7', '-stdlib=libc++']" in content
 
 
 @pytest.mark.skipif(sys.version_info.major == 2, reason="Meson not supported in Py2")
@@ -71,7 +71,7 @@ def test_extra_flags_via_conf():
         compiler=gcc
         compiler.version=9
         compiler.cppstd=17
-        compiler.libcxx=libstdc++11
+        compiler.libcxx=libstdc++
         build_type=Release
 
         [buildenv]
@@ -91,7 +91,7 @@ def test_extra_flags_via_conf():
 
     t.run("install . -pr=profile")
     content = t.load(MesonToolchain.native_filename)
-    assert "cpp_args = ['-flag0', '-other=val', '-flag1', '-flag2']" in content
+    assert "cpp_args = ['-flag0', '-other=val', '-flag1', '-flag2', '-D_GLIBCXX_USE_CXX11_ABI=0']" in content
     assert "c_args = ['-flag0', '-other=val', '-flag3', '-flag4']" in content
     assert "c_link_args = ['-flag0', '-other=val', '-flag5', '-flag6']" in content
     assert "cpp_link_args = ['-flag0', '-other=val', '-flag5', '-flag6']" in content
diff --git a/conans/test/integration/toolchains/microsoft/test_msbuilddeps.py b/conans/test/integration/toolchains/microsoft/test_msbuilddeps.py
index 0422276c3..32f40c7c2 100644
--- a/conans/test/integration/toolchains/microsoft/test_msbuilddeps.py
+++ b/conans/test/integration/toolchains/microsoft/test_msbuilddeps.py
@@ -45,6 +45,19 @@ def test_msbuilddeps_format_names():
     c.run("install pkg.name-more+/1.0@ -g MSBuildDeps -s build_type=Release -s arch=x86_64")
     # Checking that MSBuildDeps builds correctly the XML file
     # loading all .props and xml parse them to check no errors
+    pkg_more = c.load("conan_pkg_name-more_.props")
+    assert "$(conan_pkg_name-more__libmpdecimal___props_imported)" in pkg_more
+    assert "$(conan_pkg_name-more__mycomp_some-comp__props_imported)" in pkg_more
+
+    some_comp = c.load("conan_pkg_name-more__mycomp_some-comp_.props")
+    assert "<conan_pkg_name-more__mycomp_some-comp__props_imported>" in some_comp
+
+    libmpdecimal = c.load("conan_pkg_name-more__libmpdecimal__.props")
+    assert "<conan_pkg_name-more__libmpdecimal___props_imported>" in libmpdecimal
+
+    libmpdecimal_release = c.load("conan_pkg_name-more__libmpdecimal___release_x64.props")
+    assert "$(conan_pkg_name-more__mycomp_some-comp__props_imported)" in libmpdecimal_release
+
     counter = 0
     for f in os.listdir(c.current_folder):
         if f.endswith(".props"):
diff --git a/conans/test/integration/tools/system/package_manager_test.py b/conans/test/integration/tools/system/package_manager_test.py
index f63da31ec..dbac4cf19 100644
--- a/conans/test/integration/tools/system/package_manager_test.py
+++ b/conans/test/integration/tools/system/package_manager_test.py
@@ -10,7 +10,7 @@ from conan.tools.system.package_manager import Apt, Dnf, Yum, Brew, Pkg, PkgUtil
 from conans import Settings
 from conans.errors import ConanException
 from conans.model.conf import Conf
-from conans.test.utils.mocks import ConanFileMock
+from conans.test.utils.mocks import ConanFileMock, MockSettings
 
 
 @pytest.mark.parametrize("platform, tool", [
@@ -196,26 +196,66 @@ def test_dnf_yum_return_code_100(tool_class, result):
         assert f"Command '{result}' failed" == str(exc_info.value)
 
 
+@pytest.mark.parametrize("tool_class, arch_host, result", [
+    # not cross-compile -> do not add host architecture
+    (Apt, 'x86_64', 'apt-get install -y --no-install-recommends package1 package2'),
+    (Yum, 'x86_64', 'yum install -y package1 package2'),
+    (Dnf, 'x86_64', 'dnf install -y package1 package2'),
+    (Brew, 'x86_64', 'brew install package1 package2'),
+    (Pkg, 'x86_64', 'pkg install -y package1 package2'),
+    (PkgUtil, 'x86_64', 'pkgutil --install --yes package1 package2'),
+    (Chocolatey, 'x86_64', 'choco install --yes package1 package2'),
+    (PacMan, 'x86_64', 'pacman -S --noconfirm package1 package2'),
+    (Zypper, 'x86_64', 'zypper --non-interactive in package1 package2'),
+    # cross-compile -> add host architecture https://github.com/conan-io/conan/issues/12320
+    (Apt, 'x86', 'apt-get install -y --no-install-recommends package1:i386 package2:i386'),
+    (Yum, 'x86', 'yum install -y package1.i?86 package2.i?86'),
+    (Dnf, 'x86', 'dnf install -y package1.i?86 package2.i?86'),
+    (Brew, 'x86', 'brew install package1 package2'),
+    (Pkg, 'x86', 'pkg install -y package1 package2'),
+    (PkgUtil, 'x86', 'pkgutil --install --yes package1 package2'),
+    (Chocolatey, 'x86', 'choco install --yes package1 package2'),
+    (PacMan, 'x86', 'pacman -S --noconfirm package1-lib32 package2-lib32'),
+    (Zypper, 'x86', 'zypper --non-interactive in package1 package2'),
+])
+def test_tools_install_mode_install_different_archs(tool_class, arch_host, result):
+    conanfile = ConanFileMock()
+    conanfile.conf = Conf()
+    conanfile.settings = MockSettings({"arch": f"{arch_host}"})
+    conanfile.settings_build = MockSettings({"arch": "x86_64"})
+    conanfile.conf["tools.system.package_manager:tool"] = tool_class.tool_name
+    conanfile.conf["tools.system.package_manager:mode"] = "install"
+    with mock.patch('conans.ConanFile.context', new_callable=PropertyMock) as context_mock:
+        context_mock.return_value = "host"
+        tool = tool_class(conanfile)
+
+        def fake_check(*args, **kwargs):
+            return ["package1", "package2"]
+        from conan.tools.system.package_manager import _SystemPackageManagerTool
+        with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):
+            tool.install(["package1", "package2"])
+
+    assert tool._conanfile.command == result
+
+
 @pytest.mark.parametrize("tool_class, result", [
+    # cross-compile but arch_names=None -> do not add host architecture
+    # https://github.com/conan-io/conan/issues/12320 because the package is archless
     (Apt, 'apt-get install -y --no-install-recommends package1 package2'),
     (Yum, 'yum install -y package1 package2'),
     (Dnf, 'dnf install -y package1 package2'),
-    (Brew, 'brew install package1 package2'),
-    (Pkg, 'pkg install -y package1 package2'),
-    (PkgUtil, 'pkgutil --install --yes package1 package2'),
-    (Chocolatey, 'choco --install --yes package1 package2'),
     (PacMan, 'pacman -S --noconfirm package1 package2'),
-    (Zypper, 'zypper --non-interactive in package1 package2'),
 ])
-def test_tools_install_mode_install(tool_class, result):
+def test_tools_install_archless(tool_class, result):
     conanfile = ConanFileMock()
     conanfile.conf = Conf()
-    conanfile.settings = Settings()
+    conanfile.settings = MockSettings({"arch": "x86"})
+    conanfile.settings_build = MockSettings({"arch": "x86_64"})
     conanfile.conf["tools.system.package_manager:tool"] = tool_class.tool_name
     conanfile.conf["tools.system.package_manager:mode"] = "install"
     with mock.patch('conans.ConanFile.context', new_callable=PropertyMock) as context_mock:
         context_mock.return_value = "host"
-        tool = tool_class(conanfile)
+        tool = tool_class(conanfile, arch_names={})
 
         def fake_check(*args, **kwargs):
             return ["package1", "package2"]
@@ -223,6 +263,8 @@ def test_tools_install_mode_install(tool_class, result):
         with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):
             tool.install(["package1", "package2"])
 
+    assert tool._conanfile.command == result
+
 
 @pytest.mark.parametrize("tool_class, result", [
     (Apt, 'dpkg-query -W -f=\'${Status}\' package | grep -q "ok installed"'),
@@ -244,3 +286,5 @@ def test_tools_check(tool_class, result):
         context_mock.return_value = "host"
         tool = tool_class(conanfile)
         tool.check(["package"])
+
+    assert tool._conanfile.command == result
diff --git a/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py b/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
index acbe860bb..aedd2fdf9 100644
--- a/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
+++ b/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
@@ -58,6 +58,15 @@ def test_invalid_target_triple():
     assert "Unknown 'UNKNOWN_ARCH' machine, Conan doesn't know how " \
            "to translate it to the GNU triplet," in str(excinfo)
 
+def test_custom_host_triple():
+    conanfile = ConanFileMock()
+    conanfile.settings = MockSettings({"os": "Linux", "arch": "x86"})
+    conanfile.settings_build = MockSettings({"os": "Linux", "arch": "x86_64"})
+    conanfile.conf.define("tools.gnu:host_triplet", "i686-pc-linux-gnu")
+    tc = AutotoolsToolchain(conanfile)
+    tc.generate_args()
+    obj = load_toolchain_args()
+    assert "--host=i686-pc-linux-gnu" in obj["configure_args"]
 
 def test_cppstd():
     # Using "cppstd" is discarded
diff --git a/conans/test/unittests/tools/apple/test_apple_tools.py b/conans/test/unittests/tools/apple/test_apple_tools.py
index 4146d0e50..6331c1dab 100644
--- a/conans/test/unittests/tools/apple/test_apple_tools.py
+++ b/conans/test/unittests/tools/apple/test_apple_tools.py
@@ -1,5 +1,8 @@
+import pytest
+
 from conans.test.utils.mocks import ConanFileMock, MockSettings
-from conan.tools.apple import is_apple_os, to_apple_arch
+from conans.test.utils.test_files import temp_folder
+from conan.tools.apple import is_apple_os, to_apple_arch, fix_apple_shared_install_name
 
 def test_tools_apple_is_apple_os():
     conanfile = ConanFileMock()
@@ -22,3 +25,14 @@ def test_tools_apple_to_apple_arch():
 
     conanfile.settings = MockSettings({"arch": "x86_64"})
     assert to_apple_arch(conanfile) == "x86_64"
+
+def test_fix_shared_install_name_no_libraries():
+    conanfile = ConanFileMock(
+        options="""{"shared": [True, False]}""",
+        options_values={"shared": True})
+    conanfile.settings = MockSettings({"os": "Macos"})
+    conanfile.folders.set_base_package(temp_folder())
+
+    with pytest.raises(Exception) as e:
+        fix_apple_shared_install_name(conanfile)
+        assert "not found inside package folder" in str(e.value)
diff --git a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
index 2fac1acfd..2d30b9eb1 100644
--- a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
+++ b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
@@ -302,7 +302,7 @@ def test_fpic_when_shared_true(conanfile_linux_shared, fPIC):
     toolchain = CMakeToolchain(conanfile_linux_shared)
     cmake_value = 'ON' if fPIC else 'OFF'
     content = toolchain.content
-    assert 'set(CMAKE_POSITION_INDEPENDENT_CODE {})'.format(cmake_value) in content
+    assert 'set(CMAKE_POSITION_INDEPENDENT_CODE {} CACHE BOOL'.format(cmake_value) in content
 
 
 def test_fpic_when_not_shared(conanfile_linux_shared):