Repository: conan-io/conan
Pull request #12446 (2022-11-02 13:48:45)

fix default_cppstd
Changelog: Bugfix: Fix ``default_cppstd()`` import error
Docs: Omit

Close https://github.com/conan-io/conan/issues/12298


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 0feb41eec..b2efefd48 100644
--- a/conan/tools/apple/apple.py
+++ b/conan/tools/apple/apple.py
@@ -80,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):
diff --git a/conan/tools/build/cppstd.py b/conan/tools/build/cppstd.py
index cd2296c4b..c2f06b10c 100644
--- a/conan/tools/build/cppstd.py
+++ b/conan/tools/build/cppstd.py
@@ -70,12 +70,26 @@ def default_cppstd(conanfile, compiler=None, compiler_version=None):
     :param compiler_version: Version of the compiler e.g. 12
     :return: The default ``compiler.cppstd`` for the specified compiler
     """
-    from conans.client.conf.detect import _cppstd_default
     compiler = compiler or conanfile.settings.get_safe("compiler")
     compiler_version = compiler_version or conanfile.settings.get_safe("compiler.version")
     if not compiler or not compiler_version:
         raise ConanException("Called default_cppstd with no compiler or no compiler.version")
-    return _cppstd_default(compiler, Version(compiler_version))
+    from conans.client.build.cppstd_flags import _gcc_cppstd_default
+    from conans.client.build.cppstd_flags import _clang_cppstd_default
+    from conans.client.build.cppstd_flags import _visual_cppstd_default
+    from conans.client.build.cppstd_flags import _mcst_lcc_cppstd_default
+    def _msvc_cppstd_default(compiler_version):
+        if Version(compiler_version) >= "190":  # VS 2015 update 3 only
+            return "14"
+        return None
+    default = {"gcc": _gcc_cppstd_default(compiler_version),
+               "clang": _clang_cppstd_default(compiler_version),
+               "apple-clang": "gnu98",
+               # Confirmed in apple-clang 9.1 with a simple "auto i=1;"; 14.0 still the same
+               "Visual Studio": _visual_cppstd_default(compiler_version),
+               "msvc": _msvc_cppstd_default(compiler_version),
+               "mcst-lcc": _mcst_lcc_cppstd_default(compiler_version)}.get(str(compiler), None)
+    return default
 
 
 def supported_cppstd(conanfile, compiler=None, compiler_version=None):
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/gnu/autotools.py b/conan/tools/gnu/autotools.py
index 0db4bd302..e99735e98 100644
--- a/conan/tools/gnu/autotools.py
+++ b/conan/tools/gnu/autotools.py
@@ -6,7 +6,6 @@ from conans.client.subsystems import subsystem_path, deduce_subsystem
 from conans.client.build import join_arguments
 from conans.tools import args_to_string
 from conan.tools.files import chdir
-from conans.util.runners import check_output_runner
 
 
 class Autotools(object):
diff --git a/conan/tools/microsoft/subsystems.py b/conan/tools/microsoft/subsystems.py
index 651b9cb69..55789e8ea 100644
--- a/conan/tools/microsoft/subsystems.py
+++ b/conan/tools/microsoft/subsystems.py
@@ -1,8 +1,6 @@
 from conans.client.subsystems import deduce_subsystem, subsystem_path
 
 
-def unix_path(conanfile, path):
-    if not conanfile.win_bash:
-        return path
-    subsystem = deduce_subsystem(conanfile, scope="build")
+def unix_path(conanfile, path, scope="build"):
+    subsystem = deduce_subsystem(conanfile, scope=scope)
     return subsystem_path(subsystem, path)
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/manager.py b/conans/client/manager.py
index ae53663c7..aae89735e 100644
--- a/conans/client/manager.py
+++ b/conans/client/manager.py
@@ -84,6 +84,7 @@ def deps_install(app, ref_or_path, install_folder, base_folder, graph_info, remo
         conanfile.folders.set_base_imports(install_folder)
         conanfile.folders.set_base_generators(base_folder)
         conanfile.folders.set_base_source(base_folder)
+        conanfile.folders.set_base_build(base_folder)
 
     if hasattr(conanfile, "layout") and test:
         install_folder = conanfile.generators_folder
diff --git a/conans/client/subsystems.py b/conans/client/subsystems.py
index 30cf824b1..7b961d815 100644
--- a/conans/client/subsystems.py
+++ b/conans/client/subsystems.py
@@ -34,10 +34,27 @@ WSL = 'wsl'  # Windows Subsystem for Linux
 SFU = 'sfu'  # Windows Services for UNIX
 
 
-def command_env_wrapper(conanfile, command, envfiles, envfiles_folder):
+def command_env_wrapper(conanfile, command, envfiles, envfiles_folder, scope="build"):
     from conan.tools.env.environment import environment_wrap_command
-    if platform.system() == "Windows" and conanfile.win_bash:  # New, Conan 2.0
-        wrapped_cmd = _windows_bash_wrapper(conanfile, command, envfiles, envfiles_folder)
+    if getattr(conanfile, "conf", None) is None:
+        # TODO: No conf, no profile defined!! This happens at ``export()`` time
+        #  Is it possible to run a self.run() in export() in bash?
+        #  Is it necessary? Shouldn't be
+        return command
+
+    active = conanfile.conf.get("tools.microsoft.bash:active", check_type=bool)
+    subsystem = conanfile.conf.get("tools.microsoft.bash:subsystem")
+
+    if platform.system() == "Windows" and (
+            (conanfile.win_bash and scope == "build") or
+            (conanfile.win_bash_run and scope == "run")):
+        if subsystem is None:
+            raise ConanException("win_bash/win_bash_run defined but no "
+                                 "tools.microsoft.bash:subsystem")
+        if active:
+            wrapped_cmd = environment_wrap_command(envfiles, envfiles_folder, command)
+        else:
+            wrapped_cmd = _windows_bash_wrapper(conanfile, command, envfiles, envfiles_folder)
     else:
         wrapped_cmd = environment_wrap_command(envfiles, envfiles_folder, command)
     return wrapped_cmd
@@ -50,9 +67,8 @@ def _windows_bash_wrapper(conanfile, command, env, envfiles_folder):
 
     subsystem = conanfile.conf.get("tools.microsoft.bash:subsystem")
     shell_path = conanfile.conf.get("tools.microsoft.bash:path")
-    if not subsystem or not shell_path:
-        raise ConanException("The config 'tools.microsoft.bash:subsystem' and "
-                             "'tools.microsoft.bash:path' are "
+    if not shell_path:
+        raise ConanException("The config 'tools.microsoft.bash:path' is "
                              "needed to run commands in a Windows subsystem")
     env = env or []
     if subsystem == MSYS2:
@@ -102,29 +118,35 @@ def deduce_subsystem(conanfile, scope):
     if scope.startswith("build"):
         if hasattr(conanfile, "settings_build"):
             the_os = conanfile.settings_build.get_safe("os")
-            subsystem = conanfile.settings_build.get_safe("os.subsystem")
         else:
             the_os = platform.system()  # FIXME: Temporary fallback until 2.0
-            subsystem = None
     else:
         the_os = conanfile.settings.get_safe("os")
-        subsystem = conanfile.settings.get_safe("os.subsystem")
 
     if not str(the_os).startswith("Windows"):
         return None
 
-    if subsystem is None and not scope.startswith("build"):  # "run" scope do not follow win_bash
+    subsystem = conanfile.conf.get("tools.microsoft.bash:subsystem")
+    if not subsystem:
+        if conanfile.win_bash:
+            raise ConanException("win_bash=True but tools.microsoft.bash:subsystem "
+                                 "configuration not defined")
+        if conanfile.win_bash_run:
+            raise ConanException("win_bash_run=True but tools.microsoft.bash:subsystem "
+                                 "configuration not defined")
         return WINDOWS
-
-    if subsystem is None:  # Not defined by settings, so native windows
-        if not conanfile.win_bash:
-            return WINDOWS
-
-        subsystem = conanfile.conf.get("tools.microsoft.bash:subsystem")
-        if not subsystem:
-            raise ConanException("The config 'tools.microsoft.bash:subsystem' is "
-                                 "needed to run commands in a Windows subsystem")
-    return subsystem
+    active = conanfile.conf.get("tools.microsoft.bash:active", check_type=bool)
+    if active:
+        return subsystem
+
+    if scope.startswith("build"):  # "run" scope do not follow win_bash
+        if conanfile.win_bash:
+            return subsystem
+    elif scope.startswith("run"):
+        if conanfile.win_bash_run:
+            return subsystem
+
+    return WINDOWS
 
 
 def subsystem_path(subsystem, path):
diff --git a/conans/model/conan_file.py b/conans/model/conan_file.py
index d3dcae176..b3737b516 100644
--- a/conans/model/conan_file.py
+++ b/conans/model/conan_file.py
@@ -144,6 +144,7 @@ class ConanFile(object):
 
     # Run in windows bash
     win_bash = None
+    win_bash_run = None  # For run scope
     tested_reference_str = None
 
     def __init__(self, output, runner, display_name="", user=None, channel=None):
@@ -423,9 +424,13 @@ class ConanFile(object):
         """
 
     def run(self, command, output=True, cwd=None, win_bash=False, subsystem=None, msys_mingw=True,
-            ignore_errors=False, run_environment=False, with_login=True, env="conanbuild"):
+            ignore_errors=False, run_environment=False, with_login=True, env="", scope="build"):
         # NOTE: "self.win_bash" is the new parameter "win_bash" for Conan 2.0
 
+        if env == "":  # This default allows not breaking for users with ``env=None`` indicating
+            # they don't want any env-file applied
+            env = "conanbuild" if scope == "build" else "conanrun"
+
         def _run(cmd, _env):
             # FIXME: run in windows bash is not using output
             if platform.system() == "Windows":
@@ -434,7 +439,8 @@ class ConanFile(object):
                                                      msys_mingw=msys_mingw, with_login=with_login)
             envfiles_folder = self.generators_folder or os.getcwd()
             _env = [_env] if _env and isinstance(_env, str) else []
-            wrapped_cmd = command_env_wrapper(self, cmd, _env, envfiles_folder=envfiles_folder)
+            wrapped_cmd = command_env_wrapper(self, cmd, _env, envfiles_folder=envfiles_folder,
+                                              scope=scope)
             return self._conan_runner(wrapped_cmd, output, os.path.abspath(RUN_LOG_NAME), cwd)
 
         if run_environment:


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..4e1e9593f 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
@@ -69,7 +69,8 @@ def test_cmake_toolchain_custom_toolchain():
     assert not os.path.exists(os.path.join(client.current_folder, "conan_toolchain.cmake"))
     presets = load_cmake_presets(client.current_folder)
     assert "mytoolchain.cmake" in presets["configurePresets"][0]["toolchainFile"]
-    assert "binaryDir" not in presets["configurePresets"][0]
+    # Now that we define the build_folder even if not layout() binaryDir is defined
+    assert "binaryDir" in presets["configurePresets"][0]
 
 
 @pytest.mark.skipif(platform.system() != "Darwin",
@@ -1061,3 +1062,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/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/layout/test_layout_generate.py b/conans/test/integration/layout/test_layout_generate.py
index ebe3cf106..7548f0788 100644
--- a/conans/test/integration/layout/test_layout_generate.py
+++ b/conans/test/integration/layout/test_layout_generate.py
@@ -96,3 +96,32 @@ def test_generate_source_folder_test_package():
             "test_package/conanfile.py": conanfile})
     c.run("create .")
     assert "PKG_CONFIG_PATH True!" in c.out
+
+
+def test_generate_build_folder_test_package():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        import os
+        from conan import ConanFile
+        from conan.tools.cmake import cmake_layout
+
+        class Pkg(ConanFile):
+            settings = "os", "compiler", "build_type", "arch"
+
+            def requirements(self):
+                self.requires(self.tested_reference_str)
+
+            def layout(self):
+                cmake_layout(self)
+
+            def generate(self):
+                self.output.info(f"build_folder in test_package: {bool(self.build_folder)}")
+
+            def test(self):
+                pass
+        """)
+
+    c.save({"conanfile.py": GenConanfile("pkg", "1.0"),
+            "test_package/conanfile.py": conanfile})
+    c.run("create .")
+    assert f"build_folder in test_package: True" in c.out
diff --git a/conans/test/integration/toolchains/env/test_virtualenv_winbash.py b/conans/test/integration/toolchains/env/test_virtualenv_winbash.py
index dc231f5d8..c7f2ebcaf 100644
--- a/conans/test/integration/toolchains/env/test_virtualenv_winbash.py
+++ b/conans/test/integration/toolchains/env/test_virtualenv_winbash.py
@@ -67,60 +67,12 @@ def test_virtualenv_deactivated(client, win_bash):
 
 
 @pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows")
-def test_nowinbash_virtual_msys(client):
-    # Make sure the "tools.microsoft.bash:subsystem=msys2" is ignored if not win_bash
-    conanfile = str(GenConanfile().with_settings("os")
-                    .with_generator("VirtualBuildEnv").with_generator("VirtualRunEnv")
-                    .with_require("foo/1.0"))
-
-    client.save({"conanfile.py": conanfile})
-    client.run("install . -s:b os=Windows -s:h os=Windows")
-    assert not os.path.exists(os.path.join(client.current_folder, "conanbuildenv.sh"))
-    build_contents = client.load("conanbuildenv.bat")
-    assert 'set "AR=c:/path/to/ar"' in build_contents
-    assert 'set "PATH=%PATH%;c:/path/to/something"' in build_contents
-    assert not os.path.exists(os.path.join(client.current_folder, "conanrunenv.sh"))
-    run_contents = client.load("conanrunenv.bat")
-    assert 'set "RUNTIME_VAR=c:/path/to/exe"' in run_contents
-
-    # BUILD subsystem=msys2 HOST subsystem=None
-    client.save({"conanfile.py": conanfile}, clean_first=True)
-    client.run("install . -s:b os=Windows -s:b os.subsystem=msys2 -s:h os=Windows")
-    assert not os.path.exists(os.path.join(client.current_folder, "conanbuildenv.bat"))
-    build_contents = client.load("conanbuildenv.sh")
-    assert 'export AR="/c/path/to/ar"' in build_contents
-    assert 'export PATH="$PATH:/c/path/to/something"' in build_contents
-    assert not os.path.exists(os.path.join(client.current_folder, "conanrunenv.sh"))
-    run_contents = client.load("conanrunenv.bat")
-    assert 'set "RUNTIME_VAR=c:/path/to/exe"' in run_contents
-
-    # BUILD subsystem=None HOST subsystem=msys2
-    client.save({"conanfile.py": conanfile}, clean_first=True)
-    client.run("install . -s:b os=Windows  -s:h os=Windows -s:h os.subsystem=msys2")
-    assert not os.path.exists(os.path.join(client.current_folder, "conanbuildenv.sh"))
-    build_contents = client.load("conanbuildenv.bat")
-    assert 'set "AR=c:/path/to/ar"' in build_contents
-    assert 'set "PATH=%PATH%;c:/path/to/something"' in build_contents
-    assert not os.path.exists(os.path.join(client.current_folder, "conanrunenv.bat"))
-    run_contents = client.load("conanrunenv.sh")
-    assert 'export RUNTIME_VAR="/c/path/to/exe"' in run_contents
-
-    # BUILD subsystem=msys2 HOST subsystem=msys2
-    client.save({"conanfile.py": conanfile}, clean_first=True)
-    client.run("install . -s:b os=Windows -s:b os.subsystem=msys2 "
-               "-s:h os=Windows -s:h os.subsystem=msys2")
-    assert not os.path.exists(os.path.join(client.current_folder, "conanbuildenv.bat"))
-    build_contents = client.load("conanbuildenv.sh")
-    assert 'export AR="/c/path/to/ar"' in build_contents
-    assert 'export PATH="$PATH:/c/path/to/something"' in build_contents
-    assert not os.path.exists(os.path.join(client.current_folder, "conanrunenv.bat"))
-    run_contents = client.load("conanrunenv.sh")
-    assert 'export RUNTIME_VAR="/c/path/to/exe"' in run_contents
-
-
-@pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows")
-def test_nowinbash_virtual_cygwin(client):
-    # Make sure the "tools.microsoft.bash:subsystem=cygwin" is ignored if not win_bash
+def test_nowinbash(client):
+    """ whe the recipe doesn't define win_bash=True 2 things can happen:
+    - No need to run in bash, things will run in normal command, with .bat
+    - You run directly in a subsytem terminal a recipe that was not aware of that, still the
+       files need to follow the subsystem
+    """
     conanfile = str(GenConanfile().with_settings("os")
                     .with_generator("VirtualBuildEnv").with_generator("VirtualRunEnv")
                     .with_require("foo/1.0"))
@@ -135,39 +87,29 @@ def test_nowinbash_virtual_cygwin(client):
     run_contents = client.load("conanrunenv.bat")
     assert 'set "RUNTIME_VAR=c:/path/to/exe"' in run_contents
 
-    # BUILD subsystem=cygwin HOST subsystem=None
+    # Running it inside a cygwin subsystem
     client.save({"conanfile.py": conanfile}, clean_first=True)
-    client.run("install . -s:b os=Windows -s:b os.subsystem=cygwin -s:h os=Windows")
+    client.run("install . -s:b os=Windows -s:h os=Windows "
+               "-c:h tools.microsoft.bash:active=True")
     assert not os.path.exists(os.path.join(client.current_folder, "conanbuildenv.bat"))
     build_contents = client.load("conanbuildenv.sh")
     assert 'export AR="/cygdrive/c/path/to/ar"' in build_contents
     assert 'export PATH="$PATH:/cygdrive/c/path/to/something"' in build_contents
-    assert not os.path.exists(os.path.join(client.current_folder, "conanrunenv.sh"))
-    run_contents = client.load("conanrunenv.bat")
-    assert 'set "RUNTIME_VAR=c:/path/to/exe"' in run_contents
-
-    # BUILD subsystem=None HOST subsystem=cygwin
-    client.save({"conanfile.py": conanfile}, clean_first=True)
-    client.run("install . -s:b os=Windows  -s:h os=Windows -s:h os.subsystem=cygwin")
-    assert not os.path.exists(os.path.join(client.current_folder, "conanbuildenv.sh"))
-    build_contents = client.load("conanbuildenv.bat")
-    assert 'set "AR=c:/path/to/ar"' in build_contents
-    assert 'set "PATH=%PATH%;c:/path/to/something"' in build_contents
     assert not os.path.exists(os.path.join(client.current_folder, "conanrunenv.bat"))
     run_contents = client.load("conanrunenv.sh")
     assert 'export RUNTIME_VAR="/cygdrive/c/path/to/exe"' in run_contents
 
-    # BUILD subsystem=cygwin HOST subsystem=cygwin
+    # Running it inside a msys2 subsystem, test tat it overrides
     client.save({"conanfile.py": conanfile}, clean_first=True)
-    client.run("install . -s:b os=Windows -s:b os.subsystem=cygwin "
-               "-s:h os=Windows -s:h os.subsystem=cygwin")
+    client.run("install . -s:b os=Windows -s:h os=Windows "
+               "-c tools.microsoft.bash:subsystem=msys2 -c:h tools.microsoft.bash:active=True")
     assert not os.path.exists(os.path.join(client.current_folder, "conanbuildenv.bat"))
     build_contents = client.load("conanbuildenv.sh")
-    assert 'export AR="/cygdrive/c/path/to/ar"' in build_contents
-    assert 'export PATH="$PATH:/cygdrive/c/path/to/something"' in build_contents
+    assert 'export AR="/c/path/to/ar"' in build_contents
+    assert 'export PATH="$PATH:/c/path/to/something"' in build_contents
     assert not os.path.exists(os.path.join(client.current_folder, "conanrunenv.bat"))
     run_contents = client.load("conanrunenv.sh")
-    assert 'export RUNTIME_VAR="/cygdrive/c/path/to/exe"' in run_contents
+    assert 'export RUNTIME_VAR="/c/path/to/exe"' in run_contents
 
 
 @pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows")
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/tools/apple/__init__.py b/conans/test/unittests/tools/apple/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/conans/test/unittests/tools/build/test_cppstd.py b/conans/test/unittests/tools/build/test_cppstd.py
index 4b915ff9e..4035966ac 100644
--- a/conans/test/unittests/tools/build/test_cppstd.py
+++ b/conans/test/unittests/tools/build/test_cppstd.py
@@ -1,6 +1,6 @@
 import pytest
 
-from conan.tools.build import supported_cppstd, check_min_cppstd, valid_min_cppstd
+from conan.tools.build import supported_cppstd, check_min_cppstd, valid_min_cppstd, default_cppstd
 from conans.errors import ConanException, ConanInvalidConfiguration
 from conans.test.utils.mocks import MockSettings, MockConanfile
 
@@ -104,6 +104,21 @@ def test_supported_cppstd_mcst(compiler, compiler_version, values):
     assert sot == values
 
 
+@pytest.mark.parametrize("compiler,compiler_version,result", [
+    ("gcc", "5", 'gnu98'),
+    ("gcc", "8", "gnu14"),
+    ("Visual Studio", "14", "14"),
+    ("msvc", "190", "14"),
+    ("apple-clang", "12.0", "gnu98"),
+    ("clang", "6", "gnu14"),
+])
+def test_default_cppstd_gcc(compiler, compiler_version, result):
+    settings = MockSettings({"compiler": compiler, "compiler.version": compiler_version})
+    conanfile = MockConanfile(settings)
+    sot = default_cppstd(conanfile)
+    assert sot == result
+
+
 def test_check_cppstd_type():
     """ cppstd must be a number
     """
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):
diff --git a/conans/test/unittests/tools/microsoft/test_subsystem.py b/conans/test/unittests/tools/microsoft/test_subsystem.py
index 07a43d329..65e5423e8 100644
--- a/conans/test/unittests/tools/microsoft/test_subsystem.py
+++ b/conans/test/unittests/tools/microsoft/test_subsystem.py
@@ -18,6 +18,7 @@ def test_unix_path(subsystem, expected_path):
     c = ConfDefinition()
     c.loads(textwrap.dedent("""\
         tools.microsoft.bash:subsystem={}
+        tools.microsoft.bash:active=True
     """.format(subsystem)))
 
     settings = MockSettings({"os": "Windows"})
@@ -25,7 +26,6 @@ def test_unix_path(subsystem, expected_path):
     conanfile.conf = c.get_conanfile_conf(None)
     conanfile.settings = settings
     conanfile.settings_build = settings
-    conanfile.win_bash = True
 
     path = unix_path(conanfile, "c:/path/to/stuff")
     assert expected_path == path