Repository: conan-io/conan
Pull request #16196 (2024-05-03 05:31:20)

Feature: Enable bazel >= 7.1
Changelog: Feature: Add support for Bazel >= 7.1.
Docs: https://github.com/conan-io/docs/pull/3707
Closes: https://github.com/conan-io/conan/issues/15754
Closes: https://github.com/conan-io/conan/issues/15363
Example: https://github.com/conan-io/examples2/pull/147

This will **not** break older bazel versions, as just some additional files are generated.

I added some of those file based test-cases, and did some "real" integration tests [locally](https://github.com/conan-io/examples2/pull/147). If you know any better better way to put this into the conan test-environment, please let me know.

It's "only" supporting versions from 7.1 on, as there is a feature being used which is not available in 7.0. This is also documented in the code.

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop2/.github/CONTRIBUTING.md).
- [x] I've followed the PEP8 style guides for Python code.
- [x] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one.


Neeeflix: @memsharded would it also be possible to add a milestone for `1.X`
memsharded: > Would it also be possible to add a milestone for 1.X, as for us it will not be easy to go with 2.X in the near future.

This is not something that we can keep doing much longer, for new features like this one we'd strongly favor Conan 2 only. It was released more than 14 months ago, ConanCenter will soon stop updating packages for Conan 1.X too. We strongly recommend to  prioritize as much as possible the update to Conan 2.

In this case, if you'd like to get this in Conan 1, and you are willing to do the effort, then we might want to wait until we get @franramirez688 feedback about this. 
One of the aspects is that we should be 100% sure that it is not breaking Conan 1.X users, if there is any minimal risk (and I am a bit concerned about the proposed changes could no work for users using older versions of Bazel). @franramirez688 is more aware of the possible issues and efforts related to this.
Neeeflix: > This is not something that we can keep doing much longer, for new features like this one we'd strongly favor Conan 2 only. It was released more than 14 months ago, ConanCenter will soon stop updating packages for Conan 1.X too. We strongly recommend to prioritize as much as possible the update to Conan 2.

I understand the urgency and importance of updating to Conan 2, especially with the upcoming discontinuation of updates for Conan `1.X`. However, the process presents significant challenges, especially when depending on teams in different organizations, etc.

> One of the aspects is that we should be 100% sure that it is not breaking Conan 1.X users,

As mentioned in the PR description, the files which are generated for the older bazel version are not touched.
There are only two additional files being generated, there is no interference between those files at all.


franramirez688: Hi @Neeeflix 

Thanks a lot for this PR! 👏 
I was trying to test it locally but I got stuck with this error:
```shell
INFO: Starting clean (this may take a while). Consider using --async if the clean takes more than several minutes.

hello/0.1: RUN: bazel --bazelrc=/Users/franchuti/.conan2/p/b/hellodfdcbdac82faa/b/conan/conan_bzl.rc build --config=conan-config //main:hello
WARNING: --enable_bzlmod is set, but no MODULE.bazel file was found at the workspace root. Bazel will create an empty MODULE.bazel file. Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. For more details, please refer to https://github.com/bazelbuild/bazel/issues/18958.
ERROR: Error computing the main repository mapping: in module dependency chain <root> -> bazel_tools@_ -> rules_python@0.22.1: Error accessing registry https://bcr.bazel.build/: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Computing main repo mapping:

hello/0.1: ERROR:
Package '015c501fa3ba2da21e4c2e71becb7b76fa605a36' build failed
hello/0.1: WARN: Build folder /Users/franchuti/.conan2/p/b/hellodfdcbdac82faa/b
```
I do not know how to solve this. I just tried a couple of things that I found here:
* https://github.com/bazelbuild/bazel/issues/3915
* https://stackoverflow.com/questions/66638072/how-to-import-certificate-to-keystore-on-mac-os
* https://stackoverflow.com/questions/21076179/pkix-path-building-failed-and-unable-to-find-valid-certification-path-to-requ
* https://stackoverflow.com/questions/6908948/java-sun-security-provider-certpath-suncertpathbuilderexception-unable-to-find

Nothing worked 😭 Do you know how I can get it running OK locally?
Neeeflix: Hey @franramirez688, 
Thanks for looking into this

Regarding the your issue:
> ```shell
> INFO: Starting clean (this may take a while). Consider using --async if the clean takes more than several minutes.
> 
> hello/0.1: RUN: bazel --bazelrc=/Users/franchuti/.conan2/p/b/hellodfdcbdac82faa/b/conan/conan_bzl.rc build --config=conan-config //main:hello
> WARNING: --enable_bzlmod is set, but no MODULE.bazel file was found at the workspace root. Bazel will create an empty MODULE.bazel file. Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. For more details, please refer to https://github.com/bazelbuild/bazel/issues/18958.
> ERROR: Error computing the main repository mapping: in module dependency chain <root> -> bazel_tools@_ -> rules_python@0.22.1: Error accessing registry https://bcr.bazel.build/: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
> Computing main repo mapping:
> 
> hello/0.1: ERROR:
> Package '015c501fa3ba2da21e4c2e71becb7b76fa605a36' build failed
> hello/0.1: WARN: Build folder /Users/franchuti/.conan2/p/b/hellodfdcbdac82faa/b
> ```

Can you may give some more details about your setup. Which example did you use?
I also updated the example in: https://github.com/conan-io/examples2/pull/147, can you try that?
Also noticed that I only tested there for conan 1.X. Updated it, now also conan 2.X works for me.

Reproduction steps:
1. Install conan from this branch
2. CD to the example repo and checkout my branch.
3. In `examples/tools/google/bazel_7.1/testsuite` I run `conan build . -of conan`
4. ![image](https://github.com/conan-io/conan/assets/35348173/2b0fe3e2-c76d-416f-9009-07d039196844)


franramirez688: Hi @Neeeflix 

Thanks a lot for asking and for your help. Finally, after several hours of trying crazy things, I found the solution to my problem. I'm using Zscaler, so the solution came up with importing through `keytool` the Zscaler root certificate 👏 
Now, I can start reviewing everything 🥳 Sorry for the long delay in keeping my environment up-to-date.
franramirez688: UPDATE: CI is complaining about Linux and Bazel 7.x (not installed yet). Working on it 😁 

Patch:
diff --git a/.gitignore b/.gitignore
index cd3afe32d..87824d101 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@ venv/
 *.egg-info/
 .installed.cfg
 *.egg
+pip-wheel-metadata/
 
 # PyInstaller
 #  Usually these files are written by a python script from a template
diff --git a/conan/api/subapi/new.py b/conan/api/subapi/new.py
index 573ce75d4..468123718 100644
--- a/conan/api/subapi/new.py
+++ b/conan/api/subapi/new.py
@@ -26,9 +26,12 @@ class NewAPI:
         from conan.internal.api.new.msbuild_exe import msbuild_exe_files
         from conan.internal.api.new.bazel_lib import bazel_lib_files
         from conan.internal.api.new.bazel_exe import bazel_exe_files
+        from conan.internal.api.new.bazel_7_lib import bazel_lib_files_7
+        from conan.internal.api.new.bazel_7_exe import bazel_exe_files_7
         from conan.internal.api.new.autotools_lib import autotools_lib_files
         from conan.internal.api.new.autoools_exe import autotools_exe_files
         from conan.internal.api.new.local_recipes_index import local_recipes_index_files
+        from conan.internal.api.new.qbs_lib import qbs_lib_files
         new_templates = {"basic": basic_file,
                          "cmake_lib": cmake_lib_files,
                          "cmake_exe": cmake_exe_files,
@@ -36,12 +39,16 @@ class NewAPI:
                          "meson_exe": meson_exe_files,
                          "msbuild_lib": msbuild_lib_files,
                          "msbuild_exe": msbuild_exe_files,
+                         # TODO: Rename xxx_7 to xxx when dropped Bazel 6.x compatibility
                          "bazel_lib": bazel_lib_files,
                          "bazel_exe": bazel_exe_files,
+                         "bazel_7_lib": bazel_lib_files_7,
+                         "bazel_7_exe": bazel_exe_files_7,
                          "autotools_lib": autotools_lib_files,
                          "autotools_exe": autotools_exe_files,
                          "alias": alias_file,
-                         "local_recipes_index": local_recipes_index_files}
+                         "local_recipes_index": local_recipes_index_files,
+                         "qbs_lib": qbs_lib_files}
         template_files = new_templates.get(template_name)
         return template_files
 
diff --git a/conan/internal/api/detect_api.py b/conan/internal/api/detect_api.py
index e90894b29..04bb3ab16 100644
--- a/conan/internal/api/detect_api.py
+++ b/conan/internal/api/detect_api.py
@@ -438,8 +438,15 @@ def _cc_compiler(compiler_exe="cc"):
         if ret != 0:
             return None, None, None
         compiler = "clang" if "clang" in out else "gcc"
-        installed_version = re.search(r"([0-9]+(\.[0-9])?)", out).group()
-        if installed_version:
+        # clang and gcc have version after a space, first try to find that to skip extra numbers
+        # that might appear in the first line of the output before the version
+        installed_version = re.search(r" ([0-9]+(\.[0-9])+)", out)
+        # Try only major but with spaces next
+        installed_version = installed_version or re.search(r" ([0-9]+(\.[0-9])?)", out)
+        # Fallback to the first number we find optionally followed by other version fields
+        installed_version = installed_version or re.search(r"([0-9]+(\.[0-9])?)", out)
+        if installed_version and installed_version.group():
+            installed_version = installed_version.group()
             ConanOutput(scope="detect_api").info("Found cc=%s-%s" % (compiler, installed_version))
             return compiler, Version(installed_version), compiler_exe
     except (Exception,):  # to disable broad-except
@@ -581,3 +588,12 @@ def default_compiler_version(compiler, version):
     elif compiler == "intel-cc":
         return major
     return version
+
+
+def detect_sdk_version(sdk):
+    if platform.system() != "Darwin":
+        return
+    cmd = f'xcrun -sdk {sdk} --show-sdk-version'
+    result = check_output_runner(cmd)
+    result = result.strip()
+    return result
diff --git a/conan/internal/api/new/bazel_7_exe.py b/conan/internal/api/new/bazel_7_exe.py
new file mode 100644
index 000000000..570482a1d
--- /dev/null
+++ b/conan/internal/api/new/bazel_7_exe.py
@@ -0,0 +1,70 @@
+from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main
+
+
+conanfile_exe = """
+import os
+from conan import ConanFile
+from conan.tools.google import Bazel, bazel_layout
+from conan.tools.files import copy
+
+
+class {{package_name}}Recipe(ConanFile):
+    name = "{{name}}"
+    version = "{{version}}"
+    package_type = "application"
+
+    # Binary configuration
+    settings = "os", "compiler", "build_type", "arch"
+
+    # Sources are located in the same place as this recipe, copy them to the recipe
+    exports_sources = "main/*", "MODULE.bazel"
+
+    generators = "BazelToolchain"
+
+    def layout(self):
+        bazel_layout(self)
+
+    def build(self):
+        bazel = Bazel(self)
+        bazel.build(target="//main:{{name}}")
+
+    def package(self):
+        dest_bin = os.path.join(self.package_folder, "bin")
+        build = os.path.join(self.build_folder, "bazel-bin", "main")
+        copy(self, "{{name}}", build, dest_bin, keep_path=False)
+        copy(self, "{{name}}.exe", build, dest_bin, keep_path=False)
+        """
+
+test_conanfile_exe_v2 = """from conan import ConanFile
+from conan.tools.build import can_run
+
+
+class {{package_name}}Test(ConanFile):
+    settings = "os", "compiler", "build_type", "arch"
+
+    def requirements(self):
+        self.requires(self.tested_reference_str)
+
+    def test(self):
+        if can_run(self):
+            self.run("{{name}}", env="conanrun")
+"""
+
+_bazel_build_exe = """\
+cc_binary(
+    name = "{{name}}",
+    srcs = ["main.cpp", "{{name}}.cpp", "{{name}}.h"]
+)
+"""
+
+_bazel_workspace = " "  # Important not empty, so template doesn't discard it
+
+
+bazel_exe_files_7 = {"conanfile.py": conanfile_exe,
+                     "main/{{name}}.cpp": source_cpp,
+                     "main/{{name}}.h": source_h,
+                     "main/main.cpp": test_main,
+                     "main/BUILD": _bazel_build_exe,
+                     "MODULE.bazel": _bazel_workspace,
+                     "test_package/conanfile.py": test_conanfile_exe_v2
+                   }
diff --git a/conan/internal/api/new/bazel_7_lib.py b/conan/internal/api/new/bazel_7_lib.py
new file mode 100644
index 000000000..024a0f23e
--- /dev/null
+++ b/conan/internal/api/new/bazel_7_lib.py
@@ -0,0 +1,142 @@
+from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main
+
+conanfile_sources_v2 = """
+import os
+from conan import ConanFile
+from conan.tools.google import Bazel, bazel_layout
+from conan.tools.files import copy
+
+class {{package_name}}Recipe(ConanFile):
+    name = "{{name}}"
+    version = "{{version}}"
+    package_type = "library"
+
+    # Binary configuration
+    settings = "os", "compiler", "build_type", "arch"
+    options = {"shared": [True, False], "fPIC": [True, False]}
+    default_options = {"shared": False, "fPIC": True}
+
+    # Sources are located in the same place as this recipe, copy them to the recipe
+    exports_sources = "main/*", "MODULE.bazel"
+    generators = "BazelToolchain"
+
+    def config_options(self):
+        if self.settings.os == "Windows":
+            self.options.rm_safe("fPIC")
+
+    def configure(self):
+        if self.options.shared:
+            self.options.rm_safe("fPIC")
+
+    def layout(self):
+        bazel_layout(self)
+
+    def build(self):
+        bazel = Bazel(self)
+        # On Linux platforms, Bazel creates both shared and static libraries by default, and
+        # it is getting naming conflicts if we use the cc_shared_library rule
+        if self.options.shared and self.settings.os != "Linux":
+            # We need to add '--experimental_cc_shared_library' because the project uses
+            # cc_shared_library to create shared libraries
+            bazel.build(args=["--experimental_cc_shared_library"], target="//main:{{name}}_shared")
+        else:
+            bazel.build(target="//main:{{name}}")
+
+    def package(self):
+        dest_lib = os.path.join(self.package_folder, "lib")
+        dest_bin = os.path.join(self.package_folder, "bin")
+        build = os.path.join(self.build_folder, "bazel-bin", "main")
+        copy(self, "*.so", build, dest_lib, keep_path=False)
+        copy(self, "*.dll", build, dest_bin, keep_path=False)
+        copy(self, "*.dylib", build, dest_lib, keep_path=False)
+        copy(self, "*.a", build, dest_lib, keep_path=False)
+        copy(self, "*.lib", build, dest_lib, keep_path=False)
+        copy(self, "{{name}}.h", os.path.join(self.source_folder, "main"),
+             os.path.join(self.package_folder, "include"), keep_path=False)
+
+    def package_info(self):
+        if self.options.shared and self.settings.os != "Linux":
+            self.cpp_info.libs = ["{{name}}_shared"]
+        else:
+            self.cpp_info.libs = ["{{name}}"]
+"""
+
+
+test_conanfile_v2 = """import os
+from conan import ConanFile
+from conan.tools.google import Bazel, bazel_layout
+from conan.tools.build import can_run
+
+
+class {{package_name}}TestConan(ConanFile):
+    settings = "os", "compiler", "build_type", "arch"
+    generators = "BazelToolchain", "BazelDeps"
+
+    def requirements(self):
+        self.requires(self.tested_reference_str)
+
+    def build(self):
+        bazel = Bazel(self)
+        bazel.build(target="//main:example")
+
+    def layout(self):
+        bazel_layout(self)
+
+    def test(self):
+        if can_run(self):
+            cmd = os.path.join(self.cpp.build.bindir, "main", "example")
+            self.run(cmd, env="conanrun")
+"""
+
+
+_bazel_build_test = """\
+cc_binary(
+    name = "example",
+    srcs = ["example.cpp"],
+    deps = [
+        "@{{name}}//:{{name}}",
+    ],
+)
+"""
+
+_bazel_build = """\
+cc_library(
+    name = "{{name}}",
+    srcs = ["{{name}}.cpp"],
+    hdrs = ["{{name}}.h"],
+)
+"""
+
+_bazel_build_shared = """
+cc_shared_library(
+    name = "{{name}}_shared",
+    shared_lib_name = "lib{{name}}_shared.%s",
+    deps = [":{{name}}"],
+)
+"""
+
+_bazel_workspace = " "  # Important not empty, so template doesn't discard it
+_test_bazel_module_bazel = """\
+load_conan_dependencies = use_extension("//conan:conan_deps_module_extension.bzl", "conan_extension")
+use_repo(load_conan_dependencies, "{{name}}")
+"""
+
+
+def _get_bazel_build():
+    import platform
+    os_ = platform.system()
+    ret = _bazel_build
+    if os_ != "Linux":
+        ret += _bazel_build_shared % ("dylib" if os_ == "Darwin" else "dll")
+    return ret
+
+
+bazel_lib_files_7 = {"conanfile.py": conanfile_sources_v2,
+                     "main/{{name}}.cpp": source_cpp,
+                     "main/{{name}}.h": source_h,
+                     "main/BUILD": _get_bazel_build(),
+                     "MODULE.bazel": _bazel_workspace,
+                     "test_package/conanfile.py": test_conanfile_v2,
+                     "test_package/main/example.cpp": test_main,
+                     "test_package/main/BUILD": _bazel_build_test,
+                     "test_package/MODULE.bazel": _test_bazel_module_bazel}
diff --git a/conan/internal/api/new/bazel_exe.py b/conan/internal/api/new/bazel_exe.py
index e8e733110..a68271d85 100644
--- a/conan/internal/api/new/bazel_exe.py
+++ b/conan/internal/api/new/bazel_exe.py
@@ -18,13 +18,16 @@ class {{package_name}}Recipe(ConanFile):
 
     # Sources are located in the same place as this recipe, copy them to the recipe
     exports_sources = "main/*", "WORKSPACE"
-
     generators = "BazelToolchain"
 
     def layout(self):
         bazel_layout(self)
 
     def build(self):
+        from conan.api.output import ConanOutput
+        ConanOutput().warning("This is the template for Bazel 6.x version, "
+                              "but it will be overridden by the 'bazel_7_exe' template "
+                              "(Bazel >= 7.1 compatible).", warn_tag="deprecated")
         bazel = Bazel(self)
         bazel.build(target="//main:{{name}}")
 
@@ -51,8 +54,6 @@ class {{package_name}}Test(ConanFile):
 """
 
 _bazel_build_exe = """\
-load("@rules_cc//cc:defs.bzl", "cc_binary")
-
 cc_binary(
     name = "{{name}}",
     srcs = ["main.cpp", "{{name}}.cpp", "{{name}}.h"]
diff --git a/conan/internal/api/new/bazel_lib.py b/conan/internal/api/new/bazel_lib.py
index 222dba659..28328b20d 100644
--- a/conan/internal/api/new/bazel_lib.py
+++ b/conan/internal/api/new/bazel_lib.py
@@ -32,6 +32,10 @@ class {{package_name}}Recipe(ConanFile):
         bazel_layout(self)
 
     def build(self):
+        from conan.api.output import ConanOutput
+        ConanOutput().warning("This is the template for Bazel 6.x version, "
+                              "but it will be overridden by the 'bazel_7_lib' template "
+                              "(Bazel >= 7.1 compatible).", warn_tag="deprecated")
         bazel = Bazel(self)
         # On Linux platforms, Bazel creates both shared and static libraries by default, and
         # it is getting naming conflicts if we use the cc_shared_library rule
@@ -90,8 +94,6 @@ class {{package_name}}TestConan(ConanFile):
 
 
 _bazel_build_test = """\
-load("@rules_cc//cc:defs.bzl", "cc_binary")
-
 cc_binary(
     name = "example",
     srcs = ["example.cpp"],
@@ -102,8 +104,6 @@ cc_binary(
 """
 
 _bazel_build = """\
-load("@rules_cc//cc:defs.bzl", "cc_library")
-
 cc_library(
     name = "{{name}}",
     srcs = ["{{name}}.cpp"],
diff --git a/conan/internal/api/new/qbs_lib.py b/conan/internal/api/new/qbs_lib.py
new file mode 100644
index 000000000..2c71e8ff5
--- /dev/null
+++ b/conan/internal/api/new/qbs_lib.py
@@ -0,0 +1,103 @@
+from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main
+
+
+conanfile_sources = '''
+import os
+
+from conan import ConanFile
+from conan.tools.qbs import Qbs
+
+
+class {{package_name}}Recipe(ConanFile):
+    name = "{{name}}"
+    version = "{{version}}"
+
+    exports_sources = "*.cpp", "*.h", "*.qbs"
+    settings = "os", "compiler", "arch"
+    options = {"shared": [True, False]}
+    default_options = {"shared": False}
+
+    def build(self):
+        qbs = Qbs(self)
+        qbs.profile = ""
+        qbs_config = {"products.{{name}}.isShared": "true" if self.options.shared else "false"}
+        qbs.add_configuration("default", qbs_config)
+        qbs.build()
+
+    def package(self):
+        qbs = Qbs(self)
+        qbs.profile = ""
+        qbs.install()
+
+    def package_info(self):
+        self.cpp_info.libs = ["{{name}}"]
+'''
+
+qbs_lib_file = '''
+    Library {
+        property bool isShared: true
+        name: "{{name}}"
+        type: isShared ? "dynamiclibrary" : "staticlibrary"
+        files: [ "{{name}}.cpp" ]
+        Group {
+            name: "headers"
+            files: [ "{{name}}.h" ]
+            qbs.install: true
+            qbs.installDir: "include"
+        }
+        Depends { name: "cpp" }
+        Depends { name: "bundle" }
+        bundle.isBundle: false
+        install: true
+        qbs.installPrefix: ""
+    }
+'''
+
+test_conanfile_v2 = """import os
+
+from conan import ConanFile
+from conan.tools.build import can_run
+from conan.tools.qbs import Qbs
+from conan.tools.build import cmd_args_to_string
+
+class {{package_name}}TestConan(ConanFile):
+    settings = "os", "compiler", "build_type", "arch"
+    generators = "PkgConfigDeps"
+
+    def requirements(self):
+        self.requires(self.tested_reference_str)
+
+    def build(self):
+        qbs = Qbs(self)
+        qbs.profile = ""
+        qbs.build()
+        qbs.install()
+
+    def test(self):
+        if can_run(self):
+            cmd = os.path.join(self.package_folder, "bin", "example")
+            self.run(cmd_args_to_string([cmd]), env="conanrun")
+"""
+
+qbs_test_file = '''
+    Application {
+        name: "example"
+        consoleApplication: true
+        files: [ "example.cpp" ]
+        Depends { name: "cpp" }
+        install: true
+        qbs.installPrefix: ""
+        // external dependency via pkg-config
+        qbsModuleProviders: ["qbspkgconfig"]
+        moduleProviders.qbspkgconfig.libDirs: path
+        Depends { name: "{{name}}" }
+    }
+'''
+
+qbs_lib_files = {"conanfile.py": conanfile_sources,
+                 "{{name}}.qbs": qbs_lib_file,
+                 "{{name}}.cpp": source_cpp,
+                 "{{name}}.h": source_h,
+                 "test_package/conanfile.py": test_conanfile_v2,
+                 "test_package/example.cpp": test_main,
+                 "test_package/example.qbs": qbs_test_file}
diff --git a/conan/internal/runner/docker.py b/conan/internal/runner/docker.py
index 77aabaf0a..167e4ba4e 100644
--- a/conan/internal/runner/docker.py
+++ b/conan/internal/runner/docker.py
@@ -9,7 +9,6 @@ from conan.api.output import Color, ConanOutput
 from conan.api.conan_api import ConfigAPI
 from conan.cli import make_abs_path
 from conan.internal.runner import RunnerException
-from conans.client.profile_loader import ProfileLoader
 from conans.errors import ConanException
 from conans.model.version import Version
 
@@ -79,29 +78,6 @@ class DockerRunner:
         if args.format:
             raise ConanException("format argument is forbidden if running in a docker runner")
 
-        # Runner config
-        self.abs_runner_home_path = os.path.join(self.abs_host_path, '.conanrunner')
-        self.abs_docker_path = os.path.join('/root/conanrunner', os.path.basename(self.abs_host_path)).replace("\\","/")
-
-        # Update conan command and some paths to run inside the container
-        raw_args[raw_args.index(args.path)] = self.abs_docker_path
-        self.profiles = []
-        if self.args.profile_build and self.args.profile_host:
-            profile_list = set(self.args.profile_build + self.args.profile_host)
-        else:
-            profile_list = self.args.profile_host or self.args.profile_build
-
-        # Update the profile paths
-        for i, raw_arg in enumerate(raw_args):
-            for i, raw_profile in enumerate(profile_list):
-                _profile = ProfileLoader.get_profile_path(os.path.join(ConfigAPI(self.conan_api).home(), 'profiles'), raw_profile, os.getcwd())
-                _name = f'{os.path.basename(_profile)}_{i}'
-                if raw_profile in raw_arg:
-                    raw_args[raw_args.index(raw_arg)] = raw_arg.replace(raw_profile, os.path.join(self.abs_docker_path, '.conanrunner/profiles', _name))
-                self.profiles.append([_profile, os.path.join(self.abs_runner_home_path, 'profiles', _name)])
-
-        self.command = ' '.join([f'conan {command}'] + [f'"{raw_arg}"' if ' ' in raw_arg else raw_arg for raw_arg in raw_args] + ['-f json > create.json'])
-
         # Container config
         # https://containers.dev/implementors/json_reference/
         self.configfile = config_parser(host_profile.runner.get('configfile'))
@@ -116,6 +92,15 @@ class DockerRunner:
         self.cache = str(host_profile.runner.get('cache', 'clean'))
         self.container = None
 
+        # Runner config>
+        self.abs_runner_home_path = os.path.join(self.abs_host_path, '.conanrunner')
+        self.docker_user_name = self.configfile.run.user or 'root'
+        self.abs_docker_path = os.path.join(f'/{self.docker_user_name}/conanrunner', os.path.basename(self.abs_host_path)).replace("\\","/")
+
+        # Update conan command and some paths to run inside the container
+        raw_args[raw_args.index(args.path)] = self.abs_docker_path
+        self.command = ' '.join([f'conan {command}'] + [f'"{raw_arg}"' if ' ' in raw_arg else raw_arg for raw_arg in raw_args] + ['-f json > create.json'])
+
     def run(self):
         """
         run conan inside a Docker continer
@@ -194,10 +179,11 @@ class DockerRunner:
                         if stream:
                             ConanOutput().status(stream.strip())
 
-    def run_command(self, command, log=True):
+    def run_command(self, command, workdir=None, log=True):
+        workdir = workdir or self.abs_docker_path
         if log:
             _docker_info(f'Running in container: "{command}"')
-        exec_instance = self.docker_api.exec_create(self.container.id, f"/bin/bash -c '{command}'", tty=True)
+        exec_instance = self.docker_api.exec_create(self.container.id, f"/bin/bash -c '{command}'", workdir=workdir, tty=True)
         exec_output = self.docker_api.exec_start(exec_instance['Id'], tty=True, stream=True, demux=True,)
         stderr_log, stdout_log = '', ''
         try:
@@ -226,22 +212,22 @@ class DockerRunner:
         shutil.rmtree(self.abs_runner_home_path, ignore_errors=True)
         volumes = {self.abs_host_path: {'bind': self.abs_docker_path, 'mode': 'rw'}}
         environment = {'CONAN_RUNNER_ENVIRONMENT': '1'}
+
         if self.cache == 'shared':
-            volumes[ConfigAPI(self.conan_api).home()] = {'bind': '/root/.conan2', 'mode': 'rw'}
+            volumes[self.conan_api.home_folder] = {'bind': f'/{self.docker_user_name}/.conan2', 'mode': 'rw'}
+
         if self.cache in ['clean', 'copy']:
+            # Copy all conan profiles and config files to docker workspace
             os.mkdir(self.abs_runner_home_path)
-            os.mkdir(os.path.join(self.abs_runner_home_path, 'profiles'))
-
-            # Copy all conan config files to docker workspace
+            shutil.copytree(
+                os.path.join(self.conan_api.home_folder, 'profiles'),
+                os.path.join(self.abs_runner_home_path, 'profiles')
+            )
             for file_name in ['global.conf', 'settings.yml', 'remotes.json']:
-                src_file = os.path.join(ConfigAPI(self.conan_api).home(), file_name)
+                src_file = os.path.join(self.conan_api.home_folder, file_name)
                 if os.path.exists(src_file):
                     shutil.copy(src_file, os.path.join(self.abs_runner_home_path, file_name))
 
-            # Copy all profiles to docker workspace
-            for current_path, new_path in self.profiles:
-                shutil.copy(current_path, new_path)
-
             if self.cache == 'copy':
                 tgz_path = os.path.join(self.abs_runner_home_path, 'local_cache_save.tgz')
                 _docker_info(f'Save host cache in: {tgz_path}')
@@ -257,7 +243,6 @@ class DockerRunner:
             raise ConanException( f'conan version inside the container must be greater than {min_conan_version}')
         if self.cache != 'shared':
             self.run_command('mkdir -p ${HOME}/.conan2/profiles', log=False)
-            self.run_command('cp -r "'+self.abs_docker_path+'/.conanrunner/profiles/." ${HOME}/.conan2/profiles/.', log=False)
             for file_name in ['global.conf', 'settings.yml', 'remotes.json']:
                 if os.path.exists( os.path.join(self.abs_runner_home_path, file_name)):
                     self.run_command('cp "'+self.abs_docker_path+'/.conanrunner/'+file_name+'" ${HOME}/.conan2/'+file_name, log=False)
diff --git a/conan/tools/build/__init__.py b/conan/tools/build/__init__.py
index 9c77a3f4d..0ae8bc5f3 100644
--- a/conan/tools/build/__init__.py
+++ b/conan/tools/build/__init__.py
@@ -6,6 +6,8 @@ from shlex import quote
 from conan.tools.build.flags import cppstd_flag
 from conan.tools.build.cppstd import check_max_cppstd, check_min_cppstd, \
     valid_max_cppstd, valid_min_cppstd, default_cppstd, supported_cppstd
+from conan.tools.build.cstd import check_max_cstd, check_min_cstd, \
+    valid_max_cstd, valid_min_cstd, supported_cstd
 from conan.tools.build.cpu import build_jobs
 from conan.tools.build.cross_building import cross_building, can_run
 from conan.tools.build.stdcpp_library import stdcpp_library
diff --git a/conan/tools/build/cstd.py b/conan/tools/build/cstd.py
new file mode 100644
index 000000000..2d69eaba9
--- /dev/null
+++ b/conan/tools/build/cstd.py
@@ -0,0 +1,176 @@
+import operator
+
+from conan.errors import ConanInvalidConfiguration, ConanException
+from conans.model.version import Version
+
+
+def check_min_cstd(conanfile, cstd, gnu_extensions=False):
+    """ Check if current cstd fits the minimal version required.
+
+        In case the current cstd doesn't fit the minimal version required
+        by cstd, a ConanInvalidConfiguration exception will be raised.
+
+        1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare
+        2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the
+           default from cstd_default)
+        3. If not settings.compiler is present (not declared in settings) will raise because it
+           cannot compare.
+        4. If can not detect the default cstd for settings.compiler, a exception will be raised.
+
+    :param conanfile: The current recipe object. Always use ``self``.
+    :param cstd: Minimal cstd version required
+    :param gnu_extensions: GNU extension is required (e.g gnu17)
+    """
+    _check_cstd(conanfile, cstd, operator.lt, gnu_extensions)
+
+
+def check_max_cstd(conanfile, cstd, gnu_extensions=False):
+    """ Check if current cstd fits the maximum version required.
+
+        In case the current cstd doesn't fit the maximum version required
+        by cstd, a ConanInvalidConfiguration exception will be raised.
+
+        1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare
+        2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the
+           default from cstd_default)
+        3. If not settings.compiler is present (not declared in settings) will raise because it
+           cannot compare.
+        4. If can not detect the default cstd for settings.compiler, a exception will be raised.
+
+    :param conanfile: The current recipe object. Always use ``self``.
+    :param cstd: Maximum cstd version required
+    :param gnu_extensions: GNU extension is required (e.g gnu17)
+    """
+    _check_cstd(conanfile, cstd, operator.gt, gnu_extensions)
+
+
+def valid_min_cstd(conanfile, cstd, gnu_extensions=False):
+    """ Validate if current cstd fits the minimal version required.
+
+    :param conanfile: The current recipe object. Always use ``self``.
+    :param cstd: Minimal cstd version required
+    :param gnu_extensions: GNU extension is required (e.g gnu17). This option ONLY works on Linux.
+    :return: True, if current cstd matches the required cstd version. Otherwise, False.
+    """
+    try:
+        check_min_cstd(conanfile, cstd, gnu_extensions)
+    except ConanInvalidConfiguration:
+        return False
+    return True
+
+
+def valid_max_cstd(conanfile, cstd, gnu_extensions=False):
+    """ Validate if current cstd fits the maximum version required.
+
+    :param conanfile: The current recipe object. Always use ``self``.
+    :param cstd: Maximum cstd version required
+    :param gnu_extensions: GNU extension is required (e.g gnu17). This option ONLY works on Linux.
+    :return: True, if current cstd matches the required cstd version. Otherwise, False.
+    """
+    try:
+        check_max_cstd(conanfile, cstd, gnu_extensions)
+    except ConanInvalidConfiguration:
+        return False
+    return True
+
+
+def supported_cstd(conanfile, compiler=None, compiler_version=None):
+    """
+    Get a list of supported ``compiler.cstd`` for the "conanfile.settings.compiler" and
+    "conanfile.settings.compiler_version" or for the parameters "compiler" and "compiler_version"
+    if specified.
+
+    :param conanfile: The current recipe object. Always use ``self``.
+    :param compiler: Name of the compiler e.g: gcc
+    :param compiler_version: Version of the compiler e.g: 12
+    :return: a list of supported ``cstd`` values.
+    """
+    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 supported_cstd with no compiler or no compiler.version")
+
+    func = {"apple-clang": _apple_clang_supported_cstd,
+            "gcc": _gcc_supported_cstd,
+            "msvc": _msvc_supported_cstd,
+            "clang": _clang_supported_cstd,
+            }.get(compiler)
+    if func:
+        return func(Version(compiler_version))
+    return None
+
+
+def _check_cstd(conanfile, cstd, comparator, gnu_extensions):
+    """ Check if current cstd fits the version required according to a given comparator.
+
+        In case the current cstd doesn't fit the maximum version required
+        by cstd, a ConanInvalidConfiguration exception will be raised.
+
+        1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare
+        2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the
+           default from cstd_default)
+        3. If not settings.compiler is present (not declared in settings) will raise because it
+           cannot compare.
+        4. If can not detect the default cstd for settings.compiler, a exception will be raised.
+
+    :param conanfile: The current recipe object. Always use ``self``.
+    :param cstd: Required cstd version.
+    :param comparator: Operator to use to compare the detected and the required cstd versions.
+    :param gnu_extensions: GNU extension is required (e.g gnu17)
+    """
+    if not str(cstd).isdigit():
+        raise ConanException("cstd parameter must be a number")
+
+    def compare(lhs, rhs, comp):
+        def extract_cpp_version(_cstd):
+            return str(_cstd).replace("gnu", "")
+
+        def add_millennium(_cstd):
+            return "19%s" % _cstd if _cstd == "99" else "20%s" % _cstd
+
+        lhs = add_millennium(extract_cpp_version(lhs))
+        rhs = add_millennium(extract_cpp_version(rhs))
+        return not comp(lhs, rhs)
+
+    current_cstd = conanfile.settings.get_safe("compiler.cstd")
+    if current_cstd is None:
+        raise ConanInvalidConfiguration("The compiler.cstd is not defined for this configuration")
+
+    if gnu_extensions and "gnu" not in current_cstd:
+        raise ConanInvalidConfiguration("The cstd GNU extension is required")
+
+    if not compare(current_cstd, cstd, comparator):
+        raise ConanInvalidConfiguration(
+            "Current cstd ({}) is {} than the required C standard ({}).".format(
+                current_cstd, "higher" if comparator == operator.gt else "lower", cstd))
+
+
+def _apple_clang_supported_cstd(version):
+    # TODO: Per-version support
+    return ["99", "gnu99", "11", "gnu11", "17", "gnu17", "23", "gnu23"]
+
+
+def _gcc_supported_cstd(version):
+    if version < "4.7":
+        return ["99", "gnu99"]
+    if version < "8":
+        return ["99", "gnu99", "11", "gnu11"]
+    if version < "14":
+        return ["99", "gnu99", "11", "gnu11", "17", "gnu17"]
+    return ["99", "gnu99", "11", "gnu11", "17", "gnu17", "23", "gnu23"]
+
+
+def _msvc_supported_cstd(version):
+    if version < "192":
+        return []
+    return ["11", "17"]
+
+
+def _clang_supported_cstd(version):
+    if version < "3":
+        return ["99", "gnu99"]
+    if version < "6":
+        return ["99", "gnu99", "11", "gnu11"]
+    if version < "18":
+        return ["99", "gnu99", "11", "gnu11", "17", "gnu17"]
+    return ["99", "gnu99", "11", "gnu11", "17", "gnu17", "23", "gnu23"]
diff --git a/conan/tools/build/flags.py b/conan/tools/build/flags.py
index 7dbb1e06b..8b20fed3d 100644
--- a/conan/tools/build/flags.py
+++ b/conan/tools/build/flags.py
@@ -482,3 +482,76 @@ def _cppstd_intel_cc(_, cppstd):
             "20": v20, "gnu20": vgnu20,
             "23": v23, "gnu23": vgnu23}.get(cppstd)
     return f'-std={flag}' if flag else None
+
+
+def cstd_flag(conanfile) -> str:
+    """
+    Returns flags specific to the C+standard based on the ``conanfile.settings.compiler``,
+    ``conanfile.settings.compiler.version`` and ``conanfile.settings.compiler.cstd``.
+
+    It also considers when using GNU extension in ``settings.compiler.cstd``, reflecting it in the
+    compiler flag. Currently, it supports GCC, Clang, AppleClang, MSVC, Intel, MCST-LCC.
+
+    In case there is no ``settings.compiler`` or ``settings.cstd`` in the profile, the result will
+    be an **empty string**.
+
+    :param conanfile: The current recipe object. Always use ``self``.
+    :return: ``str`` with the standard C flag used by the compiler.
+    """
+    compiler = conanfile.settings.get_safe("compiler")
+    compiler_version = conanfile.settings.get_safe("compiler.version")
+    cstd = conanfile.settings.get_safe("compiler.cstd")
+
+    if not compiler or not compiler_version or not cstd:
+        return ""
+
+    func = {"gcc": _cstd_gcc,
+            "clang": _cstd_clang,
+            "apple-clang": _cstd_apple_clang,
+            "msvc": _cstd_msvc}.get(compiler)
+    flag = None
+    if func:
+        flag = func(Version(compiler_version), str(cstd))
+    return flag
+
+
+def _cstd_gcc(gcc_version, cstd):
+    # TODO: Verify flags per version
+    flag = {"99": "c99",
+            "11": "c11",
+            "17": "c17",
+            "23": "c23"}.get(cstd, cstd)
+    return f'-std={flag}' if flag else None
+
+
+def _cstd_clang(gcc_version, cstd):
+    # TODO: Verify flags per version
+    flag = {"99": "c99",
+            "11": "c11",
+            "17": "c17",
+            "23": "c23"}.get(cstd, cstd)
+    return f'-std={flag}' if flag else None
+
+
+def _cstd_apple_clang(gcc_version, cstd):
+    # TODO: Verify flags per version
+    flag = {"99": "c99",
+            "11": "c11",
+            "17": "c17",
+            "23": "c23"}.get(cstd, cstd)
+    return f'-std={flag}' if flag else None
+
+
+def cstd_msvc_flag(visual_version, cstd):
+    if cstd == "17":
+        if visual_version >= "192":
+            return "c17"
+    elif cstd == "11":
+        if visual_version >= "192":
+            return "c11"
+    return None
+
+
+def _cstd_msvc(visual_version, cstd):
+    flag = cstd_msvc_flag(visual_version, cstd)
+    return f'/std:{flag}' if flag else None
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index 575f520bf..34021ece8 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -249,24 +249,39 @@ class LinkerScriptsBlock(Block):
 
 class CppStdBlock(Block):
     template = textwrap.dedent("""
+        {% if cppstd %}
         message(STATUS "Conan toolchain: C++ Standard {{ cppstd }} with extensions {{ cppstd_extensions }}")
         set(CMAKE_CXX_STANDARD {{ cppstd }})
         set(CMAKE_CXX_EXTENSIONS {{ cppstd_extensions }})
         set(CMAKE_CXX_STANDARD_REQUIRED ON)
+        {% endif %}
+        {% if cstd %}
+        message(STATUS "Conan toolchain: C Standard {{ cstd }} with extensions {{ cstd_extensions }}")
+        set(CMAKE_C_STANDARD {{ cstd }})
+        set(CMAKE_C_EXTENSIONS {{ cstd_extensions }})
+        set(CMAKE_C_STANDARD_REQUIRED ON)
+        {% endif %}
         """)
 
     def context(self):
         compiler_cppstd = self._conanfile.settings.get_safe("compiler.cppstd")
-        if compiler_cppstd is None:
-            return None
-
-        if compiler_cppstd.startswith("gnu"):
-            cppstd = compiler_cppstd[3:]
-            cppstd_extensions = "ON"
-        else:
-            cppstd = compiler_cppstd
-            cppstd_extensions = "OFF"
-        return {"cppstd": cppstd, "cppstd_extensions": cppstd_extensions}
+        compiler_cstd = self._conanfile.settings.get_safe("compiler.cstd")
+        result = {}
+        if compiler_cppstd is not None:
+            if compiler_cppstd.startswith("gnu"):
+                result["cppstd"] = compiler_cppstd[3:]
+                result["cppstd_extensions"] = "ON"
+            else:
+                result["cppstd"] = compiler_cppstd
+                result["cppstd_extensions"] = "OFF"
+        if compiler_cstd is not None:
+            if compiler_cstd.startswith("gnu"):
+                result["cstd"] = compiler_cstd[3:]
+                result["cstd_extensions"] = "ON"
+            else:
+                result["cstd"] = compiler_cstd
+                result["cstd_extensions"] = "OFF"
+        return result or None
 
 
 class SharedLibBock(Block):
@@ -1048,6 +1063,46 @@ class GenericSystemBlock(Block):
                 "winsdk_version": winsdk_version,
                 "gen_platform_sdk_version": gen_platform_sdk_version}
 
+class ExtraVariablesBlock(Block):
+    template = textwrap.dedent(r"""
+        {% if extra_variables %}
+        {% for key, value in extra_variables.items() %}
+        set({{ key }} {{ value }})
+        {% endfor %}
+        {% endif %}
+    """)
+
+    CMAKE_CACHE_TYPES = ["BOOL","FILEPATH", "PATH", "STRING", "INTERNAL"]
+
+    def get_exact_type(self, key, value):
+        if isinstance(value, str):
+            return f"\"{value}\""
+        elif isinstance(value, (int, float)):
+            return value
+        elif isinstance(value, dict):
+            var_value = self.get_exact_type(key, value.get("value"))
+            is_cache = value.get("cache")
+            if is_cache:
+                if not isinstance(is_cache, bool):
+                    raise ConanException(f'tools.cmake.cmaketoolchain:extra_variables "cache" must be a boolean (True/False)')
+                var_type = value.get("type")
+                if not var_type:
+                    raise ConanException(f'tools.cmake.cmaketoolchain:extra_variables needs "type" defined for cache variable "{key}"')
+                if var_type not in self.CMAKE_CACHE_TYPES:
+                    raise ConanException(f'tools.cmake.cmaketoolchain:extra_variables invalid type "{var_type}" for cache variable "{key}". Possible types: {", ".join(self.CMAKE_CACHE_TYPES)}')
+                # Set docstring as variable name if not defined
+                docstring = value.get("docstring") or key
+                return f"{var_value} CACHE {var_type} \"{docstring}\""
+            else:
+                return var_value
+
+    def context(self):
+        # Reading configuration from "tools.cmake.cmaketoolchain:extra_variables"
+        extra_variables = self._conanfile.conf.get("tools.cmake.cmaketoolchain:extra_variables", default={}, check_type=dict)
+        parsed_extra_variables = {}
+        for key, value in extra_variables.items():
+            parsed_extra_variables[key] = self.get_exact_type(key, value)
+        return {"extra_variables": parsed_extra_variables}
 
 class OutputDirsBlock(Block):
 
diff --git a/conan/tools/cmake/toolchain/toolchain.py b/conan/tools/cmake/toolchain/toolchain.py
index 6924a1d9f..0692751eb 100644
--- a/conan/tools/cmake/toolchain/toolchain.py
+++ b/conan/tools/cmake/toolchain/toolchain.py
@@ -9,7 +9,7 @@ from conan.internal import check_duplicated_generator
 from conan.tools.build import use_win_mingw
 from conan.tools.cmake.presets import write_cmake_presets
 from conan.tools.cmake.toolchain import CONAN_TOOLCHAIN_FILENAME
-from conan.tools.cmake.toolchain.blocks import ToolchainBlocks, UserToolchain, GenericSystemBlock, \
+from conan.tools.cmake.toolchain.blocks import ExtraVariablesBlock, ToolchainBlocks, UserToolchain, GenericSystemBlock, \
     AndroidSystemBlock, AppleSystemBlock, FPicBlock, ArchitectureBlock, GLibCXXBlock, VSRuntimeBlock, \
     CppStdBlock, ParallelBlock, CMakeFlagsInitBlock, TryCompileBlock, FindFiles, PkgConfigBlock, \
     SkipRPath, SharedLibBock, OutputDirsBlock, ExtraFlagsBlock, CompilersBlock, LinkerScriptsBlock, \
@@ -165,6 +165,7 @@ class CMakeToolchain(object):
                                        ("parallel", ParallelBlock),
                                        ("extra_flags", ExtraFlagsBlock),
                                        ("cmake_flags_init", CMakeFlagsInitBlock),
+                                       ("extra_variables", ExtraVariablesBlock),
                                        ("try_compile", TryCompileBlock),
                                        ("find_paths", FindFiles),
                                        ("pkg_config", PkgConfigBlock),
diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py
index 6f961e442..f76edb7d1 100644
--- a/conan/tools/gnu/autotoolstoolchain.py
+++ b/conan/tools/gnu/autotoolstoolchain.py
@@ -5,8 +5,7 @@ from conan.tools.apple.apple import is_apple_os, resolve_apple_flags
 from conan.tools.build import cmd_args_to_string, save_toolchain_args
 from conan.tools.build.cross_building import cross_building
 from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, \
-    build_type_link_flags, \
-    libcxx_flags
+    build_type_link_flags, libcxx_flags, cstd_flag
 from conan.tools.env import Environment
 from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
 from conan.tools.microsoft import VCVars, msvc_runtime_flag, unix_path, check_min_vs, is_msvc
@@ -49,6 +48,7 @@ class AutotoolsToolchain:
         self.build_type_link_flags = build_type_link_flags(self._conanfile.settings)
 
         self.cppstd = cppstd_flag(self._conanfile)
+        self.cstd = cstd_flag(self._conanfile)
         self.arch_flag = architecture_flag(self._conanfile.settings)
         self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile)
         self.fpic = self._conanfile.options.get_safe("fPIC")
@@ -60,8 +60,8 @@ class AutotoolsToolchain:
         self._build = self._conanfile.conf.get("tools.gnu:build_triplet")
         self._target = None
 
-        is_cross_building = cross_building(self._conanfile)
-        if is_cross_building:
+        self._is_cross_building = cross_building(self._conanfile)
+        if self._is_cross_building:
             os_host = conanfile.settings.get_safe("os")
             arch_host = conanfile.settings.get_safe("arch")
             os_build = conanfile.settings_build.get_safe('os')
@@ -84,11 +84,12 @@ class AutotoolsToolchain:
         self.autoreconf_args = self._default_autoreconf_flags()
         self.make_args = []
         # Apple stuff
-        is_cross_building_osx = (is_cross_building
+        is_cross_building_osx = (self._is_cross_building
                                  and conanfile.settings_build.get_safe('os') == "Macos"
                                  and is_apple_os(conanfile))
-        min_flag, arch_flag, isysroot_flag = resolve_apple_flags(conanfile,
-                                                                 is_cross_building=is_cross_building_osx)
+        min_flag, arch_flag, isysroot_flag = (
+            resolve_apple_flags(conanfile, is_cross_building=is_cross_building_osx)
+        )
         # https://man.archlinux.org/man/clang.1.en#Target_Selection_Options
         self.apple_arch_flag = arch_flag
         # -isysroot makes all includes for your library relative to the build directory
@@ -102,7 +103,8 @@ class AutotoolsToolchain:
         return flag
 
     def _msvc_extra_flags(self):
-        if is_msvc(self._conanfile) and check_min_vs(self._conanfile, "180", raise_invalid=False):
+        if is_msvc(self._conanfile) and check_min_vs(self._conanfile, "180",
+                                                     raise_invalid=False):
             return ["-FS"]
         return []
 
@@ -128,7 +130,7 @@ class AutotoolsToolchain:
     @property
     def cflags(self):
         fpic = "-fPIC" if self.fpic else None
-        ret = [self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag]
+        ret = [self.cstd, self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag]
         apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]
         conf_flags = self._conanfile.conf.get("tools.build:cflags", default=[], check_type=list)
         vs_flag = self._add_msvc_flags(self.extra_cflags)
@@ -160,7 +162,8 @@ class AutotoolsToolchain:
         compilers_by_conf = self._conanfile.conf.get("tools.build:compiler_executables", default={},
                                                      check_type=dict)
         if compilers_by_conf:
-            compilers_mapping = {"c": "CC", "cpp": "CXX", "cuda": "NVCC", "fortran": "FC", "rc": "RC"}
+            compilers_mapping = {"c": "CC", "cpp": "CXX", "cuda": "NVCC", "fortran": "FC",
+                                 "rc": "RC"}
             for comp, env_var in compilers_mapping.items():
                 if comp in compilers_by_conf:
                     compiler = compilers_by_conf[comp]
@@ -172,6 +175,16 @@ class AutotoolsToolchain:
         env.append("CFLAGS", self.cflags)
         env.append("LDFLAGS", self.ldflags)
         env.prepend_path("PKG_CONFIG_PATH", self._conanfile.generators_folder)
+        # Issue related: https://github.com/conan-io/conan/issues/15486
+        if self._is_cross_building and self._conanfile.conf_build:
+            compilers_build_mapping = (
+                self._conanfile.conf_build.get("tools.build:compiler_executables", default={},
+                                               check_type=dict)
+            )
+            if "c" in compilers_build_mapping:
+                env.define("CC_FOR_BUILD", compilers_build_mapping["c"])
+            if "cpp" in compilers_build_mapping:
+                env.define("CXX_FOR_BUILD", compilers_build_mapping["cpp"])
         return env
 
     def vars(self):
diff --git a/conan/tools/google/bazel.py b/conan/tools/google/bazel.py
index baa5a5e8e..e0a8cbb4d 100644
--- a/conan/tools/google/bazel.py
+++ b/conan/tools/google/bazel.py
@@ -53,6 +53,8 @@ class Bazel(object):
         # See more info in https://bazel.build/run/bazelrc
         bazelrc_paths.extend(self._conanfile.conf.get("tools.google.bazel:bazelrc_path", default=[],
                                                       check_type=list))
+        # Note: In case of error like this: ... https://bcr.bazel.build/: PKIX path building failed
+        # Check this comment: https://github.com/bazelbuild/bazel/issues/3915#issuecomment-1120894057
         command = "bazel"
         for rc in bazelrc_paths:
             rc = rc.replace("\\", "/")
diff --git a/conan/tools/google/bazeldeps.py b/conan/tools/google/bazeldeps.py
index b2d64f985..4cb213e88 100644
--- a/conan/tools/google/bazeldeps.py
+++ b/conan/tools/google/bazeldeps.py
@@ -205,16 +205,22 @@ def _relativize_path(path, pattern):
 
 class _BazelDependenciesBZLGenerator:
     """
-    Bazel needs to know all the dependencies for its current project. So, the only way
+    Bazel 6.0 needs to know all the dependencies for its current project. So, the only way
     to do that is to tell the WORKSPACE file how to load all the Conan ones. This is the goal
     of the function created by this class, the ``load_conan_dependencies`` one.
 
     More information:
         * https://bazel.build/reference/be/workspace#new_local_repository
+
+    Bazel >= 7.1 needs to know all the dependencies as well, but provided via the MODULE.bazel file.
+    Therefor we provide a static repository rule to load the dependencies. This rule is used by a
+    module extension, passing the package path and the BUILD file path to the repository rule.
     """
 
-    filename = "dependencies.bzl"
-    template = textwrap.dedent("""\
+    repository_filename = "dependencies.bzl"
+    modules_filename = "conan_deps_module_extension.bzl"
+    repository_rules_filename = "conan_deps_repo_rules.bzl"
+    repository_template = textwrap.dedent("""\
         # This Bazel module should be loaded by your WORKSPACE file.
         # Add these lines to your WORKSPACE one (assuming that you're using the "bazel_layout"):
         # load("@//conan:dependencies.bzl", "load_conan_dependencies")
@@ -229,19 +235,95 @@ class _BazelDependenciesBZLGenerator:
             )
         {% endfor %}
         """)
+    module_template = textwrap.dedent("""\
+        # This module provides a repo for each requires-dependency in your conanfile.
+        # It's generated by the BazelDeps, and should be used in your Module.bazel file.
+        load(":conan_deps_repo_rules.bzl", "conan_dependency_repo")
+
+        def _load_dependenies_impl(mctx):
+        {% for repository_name, pkg_folder, pkg_build_file_path in dependencies %}
+            conan_dependency_repo(
+                name = "{{repository_name}}",
+                package_path = "{{pkg_folder}}",
+                build_file_path = "{{pkg_build_file_path}}",
+            )
+        {% endfor %}
+
+            return mctx.extension_metadata(
+                # It will only warn you if any direct
+                # dependency is not imported by the 'use_repo' or even it is imported
+                # but not created. Notice that root_module_direct_dev_deps can not be None as we
+                # are giving 'all' value to root_module_direct_deps.
+                # Fix the 'use_repo' calls by running 'bazel mod tidy'
+                root_module_direct_deps = 'all',
+                root_module_direct_dev_deps = [],
+
+                # Prevent writing function content to lockfiles:
+                # - https://bazel.build/rules/lib/builtins/module_ctx#extension_metadata
+                # Important for remote build. Actually it's not reproducible, as local paths will
+                # be different on different machines. But we assume that conan works correctly here.
+                # IMPORTANT: Not compatible with bazel < 7.1
+                reproducible = True,
+            )
+
+        conan_extension = module_extension(
+            implementation = _load_dependenies_impl,
+            os_dependent = True,
+            arch_dependent = True,
+        )
+        """)
+    repository_rules_content = textwrap.dedent("""\
+        # This bazel repository rule is used to load Conan dependencies into the Bazel workspace.
+        # It's used by a generated module file that provides information about the conan packages.
+        # Each conan package is loaded into a bazel repository rule, with having the name of the
+        # package. The whole method is based on symlinks to not copy the whole package into the
+        # Bazel workspace, which is expensive.
+        def _conan_dependency_repo(rctx):
+            package_path = rctx.workspace_root.get_child(rctx.attr.package_path)
+
+            child_packages = package_path.readdir()
+            for child in child_packages:
+                rctx.symlink(child, child.basename)
+
+            rctx.symlink(rctx.attr.build_file_path, "BUILD.bazel")
+
+        conan_dependency_repo = repository_rule(
+            implementation = _conan_dependency_repo,
+            attrs = {
+                "package_path": attr.string(
+                    mandatory = True,
+                    doc = "The path to the Conan package in conan cache.",
+                ),
+                "build_file_path": attr.string(
+                    mandatory = True,
+                    doc = "The path to the BUILD file.",
+                ),
+            },
+        )
+        """)
 
     def __init__(self, conanfile, dependencies):
         self._conanfile = conanfile
         self._dependencies = dependencies
 
+    def _generate_6x_compatible(self):
+        repository_template = Template(self.repository_template, trim_blocks=True,
+                                       lstrip_blocks=True,
+                                       undefined=StrictUndefined)
+        content = repository_template.render(dependencies=self._dependencies)
+        # dependencies.bzl file (Bazel 6.x compatible)
+        save(self.repository_filename, content)
+
     def generate(self):
-        template = Template(self.template, trim_blocks=True, lstrip_blocks=True,
-                            undefined=StrictUndefined)
-        content = template.render(dependencies=self._dependencies)
-        # Saving the BUILD (empty) and dependencies.bzl files
-        save(self.filename, content)
-        save("BUILD.bazel", "# This is an empty BUILD file to be able to load the "
-                            "dependencies.bzl one.")
+        # Keeping available Bazel 6.x, but it'll likely be dropped soon
+        self._generate_6x_compatible()
+        # Bazel 7.x files
+        module_template = Template(self.module_template, trim_blocks=True, lstrip_blocks=True,
+                                   undefined=StrictUndefined)
+        content = module_template.render(dependencies=self._dependencies)
+        save(self.modules_filename, content)
+        save(self.repository_rules_filename, self.repository_rules_content)
+        save("BUILD.bazel", "# This is an empty BUILD file.")
 
 
 class _BazelBUILDGenerator:
@@ -336,8 +418,6 @@ class _BazelBUILDGenerator:
     )
     {% endif %}
     {% endmacro %}
-    load("@rules_cc//cc:defs.bzl", "cc_import", "cc_library")
-
     # Components precompiled libs
     {% for component in components %}
     {{ cc_import_macro(component["libs"]) }}
@@ -557,14 +637,28 @@ class BazelDeps:
 
     def generate(self):
         """
-        Generates all the targets <DEP>/BUILD.bazel files and the dependencies.bzl one in the
-        build folder. It's important to highlight that the dependencies.bzl file should be loaded
-        by your WORKSPACE Bazel file:
+        Generates all the targets <DEP>/BUILD.bazel files, a dependencies.bzl (for bazel<7), a
+        conan_deps_repo_rules.bzl and a conan_deps_module_extension.bzl file (for bazel>=7.1) one in the
+        build folder.
+
+        In case of bazel < 7, it's important to highlight that the ``dependencies.bzl`` file should
+        be loaded by your WORKSPACE Bazel file:
 
         .. code-block:: python
 
             load("@//[BUILD_FOLDER]:dependencies.bzl", "load_conan_dependencies")
             load_conan_dependencies()
+
+        In case of bazel >= 7.1, the ``conan_deps_module_extension.bzl`` file should be loaded by your
+        Module.bazel file, e.g. like this:
+
+        .. code-block:: python
+
+            load_conan_dependencies = use_extension(
+                "//build:conan_deps_module_extension.bzl",
+                "conan_extension"
+            )
+            use_repo(load_conan_dependencies, "dep-1", "dep-2", ...)
         """
         check_duplicated_generator(self, self._conanfile)
         requirements = _get_requirements(self._conanfile, self.build_context_activated)
diff --git a/conan/tools/meson/helpers.py b/conan/tools/meson/helpers.py
index d0decdf8b..ba8e1eb85 100644
--- a/conan/tools/meson/helpers.py
+++ b/conan/tools/meson/helpers.py
@@ -2,7 +2,7 @@ from conan.api.output import ConanOutput
 from conan.tools.build.flags import cppstd_msvc_flag
 from conans.model.options import _PackageOption
 
-__all__ = ["to_meson_machine", "to_meson_value", "to_cppstd_flag"]
+__all__ = ["to_meson_machine", "to_meson_value", "to_cppstd_flag", "to_cstd_flag"]
 
 # https://mesonbuild.com/Reference-tables.html#operating-system-names
 _meson_system_map = {
@@ -126,3 +126,16 @@ def to_cppstd_flag(compiler, compiler_version, cppstd):
         return 'v%s' % flag if flag else None
     else:
         return _cppstd_map.get(cppstd)
+
+
+def to_cstd_flag(cstd):
+    """ possible values
+    none, c89, c99, c11, c17, c18, c2x, c23, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x, gnu23
+    """
+    _cstd_map = {
+        '99': "c99",
+        '11': "c11",
+        '17': "c17",
+        '23': "c23",
+    }
+    return _cstd_map.get(cstd, cstd)
diff --git a/conan/tools/meson/toolchain.py b/conan/tools/meson/toolchain.py
index d00f29145..743d38cbb 100644
--- a/conan/tools/meson/toolchain.py
+++ b/conan/tools/meson/toolchain.py
@@ -109,6 +109,9 @@ class MesonToolchain(object):
     {% if cpp_std %}
     cpp_std = '{{cpp_std}}'
     {% endif %}
+    {% if c_std %}
+    c_std = '{{c_std}}'
+    {% endif %}
     {% if backend %}
     backend = '{{backend}}'
     {% endif %}
@@ -188,13 +191,26 @@ class MesonToolchain(object):
         cppstd = self._conanfile.settings.get_safe("compiler.cppstd")
         self._cpp_std = to_cppstd_flag(compiler, compiler_version, cppstd)
 
+        cstd = self._conanfile.settings.get_safe("compiler.cstd")
+        self._c_std = to_cstd_flag(cstd)
+
         self._b_vscrt = None
         if compiler in ("msvc", "clang"):
             vscrt = msvc_runtime_flag(self._conanfile)
             if vscrt:
                 self._b_vscrt = str(vscrt).lower()
 
-        #: Dict-like object that defines Meson``properties`` with ``key=value`` format
+        # Extra flags
+        #: List of extra ``CXX`` flags. Added to ``cpp_args``
+        self.extra_cxxflags = []
+        #: List of extra ``C`` flags. Added to ``c_args``
+        self.extra_cflags = []
+        #: List of extra linker flags. Added to ``c_link_args`` and ``cpp_link_args``
+        self.extra_ldflags = []
+        #: List of extra preprocessor definitions. Added to ``c_args`` and ``cpp_args`` with the
+        #: format ``-D[FLAG_N]``.
+        self.extra_defines = []
+        #: Dict-like object that defines Meson ``properties`` with ``key=value`` format
         self.properties = {}
         #: Dict-like object that defines Meson ``project options`` with ``key=value`` format
         self.project_options = {
@@ -408,13 +424,14 @@ class MesonToolchain(object):
         exelinkflags = self._conanfile_conf.get("tools.build:exelinkflags", default=[], check_type=list)
         linker_scripts = self._conanfile_conf.get("tools.build:linker_scripts", default=[], check_type=list)
         linker_script_flags = ['-T"' + linker_script + '"' for linker_script in linker_scripts]
-        defines = [f"-D{d}" for d in self._conanfile.conf.get("tools.build:defines", default=[], check_type=list)]
+        defines = self._conanfile.conf.get("tools.build:defines", default=[], check_type=list)
         sys_root = [f"--sysroot={self._sys_root}"] if self._sys_root else [""]
         return {
-            "cxxflags": cxxflags + sys_root,
-            "cflags": cflags + sys_root,
-            "ldflags": sharedlinkflags + exelinkflags + linker_script_flags + sys_root,
-            "defines": defines
+            "cxxflags": cxxflags + sys_root + self.extra_cxxflags,
+            "cflags": cflags + sys_root + self.extra_cflags,
+            "ldflags": sharedlinkflags + exelinkflags + linker_script_flags
+                       + sys_root + self.extra_ldflags,
+            "defines": [f"-D{d}" for d in (defines + self.extra_defines)]
         }
 
     @staticmethod
@@ -494,6 +511,7 @@ class MesonToolchain(object):
             "b_ndebug": to_meson_value(self._b_ndebug),  # boolean as string
             # https://mesonbuild.com/Builtin-options.html#compiler-options
             "cpp_std": self._cpp_std,
+            "c_std": self._c_std,
             "c_args": to_meson_value(self._filter_list_empty_fields(self.c_args)),
             "c_link_args": to_meson_value(self._filter_list_empty_fields(self.c_link_args)),
             "cpp_args": to_meson_value(self._filter_list_empty_fields(self.cpp_args)),
diff --git a/conan/tools/microsoft/toolchain.py b/conan/tools/microsoft/toolchain.py
index e5427001c..5e33d5103 100644
--- a/conan/tools/microsoft/toolchain.py
+++ b/conan/tools/microsoft/toolchain.py
@@ -27,6 +27,7 @@ class MSBuildToolchain(object):
               <PreprocessorDefinitions>{{ defines }}%(PreprocessorDefinitions)</PreprocessorDefinitions>
               <AdditionalOptions>{{ compiler_flags }} %(AdditionalOptions)</AdditionalOptions>
               <RuntimeLibrary>{{ runtime_library }}</RuntimeLibrary>
+              {% if cstd %}<LanguageStandard_C>{{ cstd }}</LanguageStandard_C>{% endif %}
               <LanguageStandard>{{ cppstd }}</LanguageStandard>{{ parallel }}{{ compile_options }}
             </ClCompile>
             <Link>
@@ -69,6 +70,7 @@ class MSBuildToolchain(object):
         self.runtime_library = self._runtime_library(conanfile.settings)
         #: cppstd value. By default, ``compiler.cppstd`` one.
         self.cppstd = conanfile.settings.get_safe("compiler.cppstd")
+        self.cstd = conanfile.settings.get_safe("compiler.cstd")
         #: VS IDE Toolset, e.g., ``"v140"``. If ``compiler=msvc``, you can use ``compiler.toolset``
         #: setting, else, it'll be based on ``msvc`` version.
         self.toolset = msvs_toolset(conanfile)
@@ -139,6 +141,7 @@ class MSBuildToolchain(object):
         self.ldflags.extend(sharedlinkflags + exelinkflags)
 
         cppstd = "stdcpp%s" % self.cppstd if self.cppstd else ""
+        cstd = f"stdc{self.cstd}" if self.cstd else ""
         runtime_library = self.runtime_library
         toolset = self.toolset or ""
         compile_options = self._conanfile.conf.get("tools.microsoft.msbuildtoolchain:compile_options",
@@ -161,6 +164,7 @@ class MSBuildToolchain(object):
             'compiler_flags': " ".join(self.cxxflags + self.cflags),
             'linker_flags': " ".join(self.ldflags),
             "cppstd": cppstd,
+            "cstd": cstd,
             "runtime_library": runtime_library,
             "toolset": toolset,
             "compile_options": compile_options,
diff --git a/conan/tools/microsoft/visual.py b/conan/tools/microsoft/visual.py
index 844031489..e4e76737b 100644
--- a/conan/tools/microsoft/visual.py
+++ b/conan/tools/microsoft/visual.py
@@ -118,6 +118,7 @@ class VCVars:
         if vs_install_path == "":  # Empty string means "disable"
             return
 
+        msvc_update = conanfile.conf.get("tools.microsoft:msvc_update")
         if compiler == "clang":
             # The vcvars only needed for LLVM/Clang and VS ClangCL, who define runtime
             if not conanfile.settings.get_safe("compiler.runtime"):
@@ -127,20 +128,24 @@ class VCVars:
             vs_version = {"v140": "14",
                           "v141": "15",
                           "v142": "16",
-                          "v143": "17"}.get(toolset_version)
+                          "v143": "17",
+                          "v144": "17"}.get(toolset_version)
             if vs_version is None:
-                raise ConanException("Visual Studio Runtime version (v140-v143) not defined")
+                raise ConanException("Visual Studio Runtime version (v140-v144) not defined")
             vcvars_ver = {"v140": "14.0",
                           "v141": "14.1",
                           "v142": "14.2",
-                          "v143": "14.3"}.get(toolset_version)
+                          "v143": "14.3",
+                          "v144": "14.4"}.get(toolset_version)
+            if vcvars_ver and msvc_update is not None:
+                vcvars_ver += f"{msvc_update}"
         else:
             vs_version = vs_ide_version(conanfile)
             if int(vs_version) <= 14:
                 vcvars_ver = None
             else:
                 compiler_version = str(conanfile.settings.compiler.version)
-                compiler_update = conanfile.settings.get_safe("compiler.update", "")
+                compiler_update = msvc_update or conanfile.settings.get_safe("compiler.update", "")
                 # The equivalent of compiler 19.26 is toolset 14.26
                 vcvars_ver = "14.{}{}".format(compiler_version[-1], compiler_update)
 
diff --git a/conan/tools/qbs/qbs.py b/conan/tools/qbs/qbs.py
index db4bb87e0..d65a91b3f 100644
--- a/conan/tools/qbs/qbs.py
+++ b/conan/tools/qbs/qbs.py
@@ -1,6 +1,6 @@
 import os
 
-from conan.tools.build import build_jobs
+from conan.tools.build import build_jobs, cmd_args_to_string
 from conan.errors import ConanException
 
 
@@ -59,7 +59,7 @@ class Qbs(object):
             config = self._configuration[name]
             args.extend(_configuration_dict_to_commandlist(name, config))
 
-        cmd = 'qbs build %s' % (' '.join(args))
+        cmd = 'qbs build %s' % cmd_args_to_string(args)
         self._conanfile.run(cmd)
 
     def build_all(self):
@@ -79,7 +79,7 @@ class Qbs(object):
             config = self._configuration[name]
             args.extend(_configuration_dict_to_commandlist(name, config))
 
-        cmd = 'qbs build %s' % (' '.join(args))
+        cmd = 'qbs build %s' % cmd_args_to_string(args)
         self._conanfile.run(cmd)
 
     def install(self):
@@ -92,5 +92,5 @@ class Qbs(object):
         for name in self._configuration:
             args.append('config:%s' % name)
 
-        cmd = 'qbs install %s' % (' '.join(args))
+        cmd = 'qbs install %s' % cmd_args_to_string(args)
         self._conanfile.run(cmd)
diff --git a/conans/client/conanfile/configure.py b/conans/client/conanfile/configure.py
index 116a879a8..4b0aa99f1 100644
--- a/conans/client/conanfile/configure.py
+++ b/conans/client/conanfile/configure.py
@@ -1,7 +1,8 @@
 from conans.errors import conanfile_exception_formatter
 from conans.model.pkg_type import PackageType
 from conans.model.requires import BuildRequirements, TestRequirements, ToolRequirements
-from conans.client.conanfile.implementations import auto_shared_fpic_config_options, auto_shared_fpic_configure
+from conans.client.conanfile.implementations import auto_shared_fpic_config_options, \
+    auto_shared_fpic_configure, auto_language
 
 
 def run_configure_method(conanfile, down_options, profile_options, ref):
@@ -15,6 +16,8 @@ def run_configure_method(conanfile, down_options, profile_options, ref):
     elif "auto_shared_fpic" in conanfile.implements:
         auto_shared_fpic_config_options(conanfile)
 
+    auto_language(conanfile)  # default implementation removes `compiler.cstd`
+
     # Assign only the current package options values, but none of the dependencies
     is_consumer = conanfile._conan_is_consumer
     conanfile.options.apply_downstream(down_options, profile_options, ref, is_consumer)
diff --git a/conans/client/conanfile/implementations.py b/conans/client/conanfile/implementations.py
index 133ddcea7..14cabc760 100644
--- a/conans/client/conanfile/implementations.py
+++ b/conans/client/conanfile/implementations.py
@@ -17,3 +17,14 @@ def auto_shared_fpic_configure(conanfile):
 def auto_header_only_package_id(conanfile):
     if conanfile.options.get_safe("header_only") or conanfile.package_type is PackageType.HEADER:
         conanfile.info.clear()
+
+
+def auto_language(conanfile):
+    if not conanfile.languages:
+        conanfile.settings.rm_safe("compiler.cstd")
+        return
+    if "C" not in conanfile.languages:
+        conanfile.settings.rm_safe("compiler.cstd")
+    if "C++" not in conanfile.languages:
+        conanfile.settings.rm_safe("compiler.cppstd")
+        conanfile.settings.rm_safe("compiler.libcxx")
diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py
index bf64917c7..23b5e28f5 100644
--- a/conans/client/conf/__init__.py
+++ b/conans/client/conf/__init__.py
@@ -100,6 +100,7 @@ compiler:
         threads: [null, posix, win32]  # Windows MinGW
         exception: [null, dwarf2, sjlj, seh]  # Windows MinGW
         cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
+        cstd: [null, 99, gnu99, 11, gnu11, 17, gnu17, 23, gnu23]
     msvc:
         version: [170, 180, 190, 191, 192, 193, 194]
         update: [null, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
@@ -107,6 +108,7 @@ compiler:
         runtime_type: [Debug, Release]
         cppstd: [null, 14, 17, 20, 23]
         toolset: [null, v110_xp, v120_xp, v140_xp, v141_xp]
+        cstd: [null, 11, 17]
     clang:
         version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0",
                   "5.0", "6.0", "7.0", "7.1",
@@ -115,12 +117,14 @@ compiler:
         cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
         runtime: [null, static, dynamic]
         runtime_type: [null, Debug, Release]
-        runtime_version: [null, v140, v141, v142, v143]
+        runtime_version: [null, v140, v141, v142, v143, v144]
+        cstd: [null, 99, gnu99, 11, gnu11, 17, gnu17, 23, gnu23]
     apple-clang:
         version: ["5.0", "5.1", "6.0", "6.1", "7.0", "7.3", "8.0", "8.1", "9.0", "9.1",
                   "10.0", "11.0", "12.0", "13", "13.0", "13.1", "14", "14.0", "15", "15.0"]
         libcxx: [libstdc++, libc++]
         cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
+        cstd: [null, 99, gnu99, 11, gnu11, 17, gnu17, 23, gnu23]
     intel-cc:
         version: ["2021.1", "2021.2", "2021.3", "2021.4", "2022.1", "2022.2",
                   "2022.3", "2023.0", "2023.1", "2023.2", "2024.0",]
diff --git a/conans/client/graph/compatibility.py b/conans/client/graph/compatibility.py
index 1d67e7cf5..a23669c88 100644
--- a/conans/client/graph/compatibility.py
+++ b/conans/client/graph/compatibility.py
@@ -23,7 +23,7 @@ def compatibility(conanfile):
 _default_cppstd_compat = """\
 # This file was generated by Conan. Remove this comment if you edit this file or Conan
 # will destroy your changes.
-from conan.tools.build import supported_cppstd
+from conan.tools.build import supported_cppstd, supported_cstd
 from conan.errors import ConanException
 
 
@@ -44,6 +44,14 @@ def cppstd_compat(conanfile):
         else: # The current cppst must be included in case there is other factor
             factors.append([{"compiler.cppstd": v} for v in cppstd_possible_values])
 
+    cstd = conanfile.settings.get_safe("compiler.cstd")
+    if cstd is not None and extension_properties.get("compatibility_cstd") is not False:
+        cstd_possible_values = supported_cstd(conanfile)
+        if cstd_possible_values is None:
+            conanfile.output.warning(f'No cstd compatibility defined for compiler "{compiler}"')
+        else:
+            factors.append([{"compiler.cstd": v} for v in cstd_possible_values if v != cstd])
+
     if compiler == "msvc":
         msvc_fallback = {"194": "193"}.get(compiler_version)
         if msvc_fallback:
diff --git a/conans/client/profile_loader.py b/conans/client/profile_loader.py
index 6b1ba23e8..cc4763fba 100644
--- a/conans/client/profile_loader.py
+++ b/conans/client/profile_loader.py
@@ -39,6 +39,7 @@ def profile_plugin(profile):
             except ConanException:
                 pass
     _check_correct_cppstd(settings)
+    _check_correct_cstd(settings)
 
 def _check_correct_cppstd(settings):
     from conan.tools.scm import Version
@@ -76,6 +77,36 @@ def _check_correct_cppstd(settings):
                     "14": "190"}.get(cppstd)
         if mver and version < mver:
             _error(compiler, cppstd, mver, version)
+
+
+def _check_correct_cstd(settings):
+    from conan.tools.scm import Version
+    def _error(compiler, cstd, min_version, version):
+        from conan.errors import ConanException
+        raise ConanException(f"The provided compiler.cstd={cstd} requires at least {compiler}"
+                             f">={min_version} but version {version} provided")
+    cstd = settings.get("compiler.cstd")
+    version = settings.get("compiler.version")
+
+    if cstd and version:
+        cstd = cstd.replace("gnu", "")
+        version = Version(version)
+        mver = None
+        compiler = settings.get("compiler")
+        if compiler == "gcc":
+            # TODO: right versions
+            mver = {}.get(cstd)
+        elif compiler == "clang":
+            # TODO: right versions
+            mver = {}.get(cstd)
+        elif compiler == "apple-clang":
+            # TODO: Right versions
+            mver = {}.get(cstd)
+        elif compiler == "msvc":
+            mver = {"17": "192",
+                    "11": "192"}.get(cstd)
+        if mver and version < mver:
+            _error(compiler, cppstd, mver, version)
 """
 
 
diff --git a/conans/client/subsystems.py b/conans/client/subsystems.py
index daba56c06..ac7ca25c7 100644
--- a/conans/client/subsystems.py
+++ b/conans/client/subsystems.py
@@ -82,6 +82,7 @@ def _windows_bash_wrapper(conanfile, command, env, envfiles_folder):
         # - CHERE_INVOKING is necessary to keep the CWD and not change automatically to the user home
         msys2_mode_env.define("MSYSTEM", _msystem)
         msys2_mode_env.define("MSYS2_PATH_TYPE", "inherit")
+        msys2_mode_env.unset("ORIGINAL_PATH")
         # So --login do not change automatically to the user home
         msys2_mode_env.define("CHERE_INVOKING", "1")
         path = os.path.join(conanfile.generators_folder, "msys2_mode.bat")
diff --git a/conans/model/conan_file.py b/conans/model/conan_file.py
index 96e819ff1..7fcdbf8ac 100644
--- a/conans/model/conan_file.py
+++ b/conans/model/conan_file.py
@@ -47,6 +47,7 @@ class ConanFile:
     default_options = None
     default_build_options = None
     package_type = None
+    languages = []
 
     implements = []
 
@@ -91,6 +92,8 @@ class ConanFile:
 
         if isinstance(self.generators, str):
             self.generators = [self.generators]
+        if isinstance(self.languages, str):
+            self.languages = [self.languages]
         if isinstance(self.settings, str):
             self.settings = [self.settings]
         self.requires = Requirements(self.requires, self.build_requires, self.test_requires,
@@ -134,6 +137,7 @@ class ConanFile:
         result["version"] = str(self.version) if self.version is not None else None
         result["topics"] = list(self.topics) if self.topics is not None else None
         result["package_type"] = str(self.package_type)
+        result["languages"] = self.languages
 
         settings = self.settings
         if settings is not None:
diff --git a/conans/model/conanfile_interface.py b/conans/model/conanfile_interface.py
index 0ebb1b1ff..2130ff85b 100644
--- a/conans/model/conanfile_interface.py
+++ b/conans/model/conanfile_interface.py
@@ -100,6 +100,10 @@ class ConanFileInterface:
     def package_type(self):
         return self._conanfile.package_type
 
+    @property
+    def languages(self):
+        return self._conanfile.languages
+
     @property
     def info(self):
         return self._conanfile.info
diff --git a/conans/model/conf.py b/conans/model/conf.py
index 7809f4d9d..e11037845 100644
--- a/conans/model/conf.py
+++ b/conans/model/conf.py
@@ -73,6 +73,7 @@ BUILT_IN_CONFS = {
     "tools.cmake.cmaketoolchain:toolset_arch": "Toolset architecture to be used as part of CMAKE_GENERATOR_TOOLSET in CMakeToolchain",
     "tools.cmake.cmaketoolchain:toolset_cuda": "(Experimental) Path to a CUDA toolset to use, or version if installed at the system level",
     "tools.cmake.cmaketoolchain:presets_environment": "String to define wether to add or not the environment section to the CMake presets. Empty by default, will generate the environment section in CMakePresets. Can take values: 'disabled'.",
+    "tools.cmake.cmaketoolchain:extra_variables": "Dictionary with variables to be injected in CMakeToolchain (potential override of CMakeToolchain defined variables)",
     "tools.cmake.cmake_layout:build_folder_vars": "Settings and Options that will produce a different build folder and different CMake presets names",
     "tools.cmake.cmake_layout:build_folder": "(Experimental) Allow configuring the base folder of the build for local builds",
     "tools.cmake.cmake_layout:test_folder": "(Experimental) Allow configuring the base folder of the build for test_package",


Test patch:
diff --git a/conan/test/utils/mocks.py b/conan/test/utils/mocks.py
index 6c1a160ef..bfed795b6 100644
--- a/conan/test/utils/mocks.py
+++ b/conan/test/utils/mocks.py
@@ -92,6 +92,7 @@ class ConanFileMock(ConanFile):
         self.options = options or Options()
         self.generators = []
         self.conf = Conf()
+        self.conf_build = Conf()
         self.folders = Folders()
         self.folders.set_base_source(".")
         self.folders.set_base_export_sources(".")
diff --git a/test/conftest.py b/test/conftest.py
index a85c2b2af..bc148aabe 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -181,6 +181,7 @@ tools_locations = {
             "path": {'Darwin': f'{homebrew_root}/share/android-ndk'}
         }
     },
+    "qbs": {"disabled": True},
     # TODO: Intel oneAPI is not installed in CI yet. Uncomment this line whenever it's done.
     # "intel_oneapi": {
     #     "default": "2021.3",
diff --git a/test/functional/test_profile_detect_api.py b/test/functional/test_profile_detect_api.py
index 24f6b3f8d..1bac560e8 100644
--- a/test/functional/test_profile_detect_api.py
+++ b/test/functional/test_profile_detect_api.py
@@ -76,3 +76,17 @@ class TestProfileDetectAPI:
             user.confvar:libc_version={libc_version}
             """)
         assert expected in client.out
+
+    @pytest.mark.skipif(platform.system() != "Darwin", reason="Only OSX")
+    def test_profile_detect_darwin_sdk(self):
+        client = TestClient()
+        tpl1 = textwrap.dedent("""\
+            [settings]
+            os = "Macos"
+            os.sdk_version = {{ detect_api.detect_sdk_version(sdk="macosx")  }}
+            """)
+
+        client.save({"profile1": tpl1})
+        client.run("profile show -pr=profile1")
+        sdk_version = detect_api.detect_sdk_version(sdk="macosx")
+        assert f"os.sdk_version={sdk_version}" in client.out
diff --git a/test/functional/toolchains/google/test_bazel.py b/test/functional/toolchains/google/test_bazel.py
index 6ce6414ea..f9ce5e026 100644
--- a/test/functional/toolchains/google/test_bazel.py
+++ b/test/functional/toolchains/google/test_bazel.py
@@ -32,8 +32,8 @@ def base_profile():
 
 
 @pytest.mark.parametrize("build_type", ["Debug", "Release", "RelWithDebInfo", "MinSizeRel"])
-@pytest.mark.tool("bazel")
-def test_basic_exe(bazelrc, build_type, base_profile):
+@pytest.mark.tool("bazel", "6.3.2")
+def test_basic_exe_6x(bazelrc, build_type, base_profile):
     client = TestClient(path_with_spaces=False)
     client.run("new bazel_exe -d name=myapp -d version=1.0")
     # The build:<config> define several configurations that can be activated by passing
@@ -49,9 +49,27 @@ def test_basic_exe(bazelrc, build_type, base_profile):
         assert "myapp/1.0: Hello World Debug!" in client.out
 
 
+@pytest.mark.parametrize("build_type", ["Debug", "Release", "RelWithDebInfo", "MinSizeRel"])
+@pytest.mark.tool("bazel", "7.1.2")
+def test_basic_exe(bazelrc, build_type, base_profile):
+    client = TestClient(path_with_spaces=False)
+    client.run("new bazel_7_exe -d name=myapp -d version=1.0")
+    # The build:<config> define several configurations that can be activated by passing
+    # the bazel config with tools.google.bazel:configs
+    client.save({"mybazelrc": bazelrc})
+    profile = base_profile.format(build_type=build_type,
+                                  curdir=client.current_folder.replace("\\", "/"))
+    client.save({"my_profile": profile})
+    client.run("create . --profile=./my_profile")
+    if build_type != "Debug":
+        assert "myapp/1.0: Hello World Release!" in client.out
+    else:
+        assert "myapp/1.0: Hello World Debug!" in client.out
+
+
 @pytest.mark.parametrize("shared", [False, True])
-@pytest.mark.tool("bazel")
-def test_transitive_libs_consuming(shared):
+@pytest.mark.tool("bazel", "6.3.2")
+def test_transitive_libs_consuming_6x(shared):
     """
     Testing the next dependencies structure for shared/static libs
 
@@ -107,8 +125,6 @@ def test_transitive_libs_consuming(shared):
         load_conan_dependencies()
         """)
         bazel_build_linux = textwrap.dedent("""\
-        load("@rules_cc//cc:defs.bzl", "cc_library")
-
         cc_library(
             name = "mysecondlib",
             srcs = ["mysecondlib.cpp"],
@@ -117,8 +133,6 @@ def test_transitive_libs_consuming(shared):
         )
         """)
         bazel_build = textwrap.dedent("""\
-        load("@rules_cc//cc:defs.bzl", "cc_library")
-
         cc_library(
             name = "mysecondlib",
             srcs = ["mysecondlib.cpp"],
@@ -177,3 +191,129 @@ def test_transitive_libs_consuming(shared):
         client.run(f"create . -o '*:shared={shared}'")
         assert "mysecondlib() First define MY_VALUE and other define 2" in client.out
         assert "myfirstlib/1.2.11: Hello World Release!"
+
+
+@pytest.mark.parametrize("shared", [False, True])
+@pytest.mark.tool("bazel", "7.1.2")
+def test_transitive_libs_consuming(shared):
+    """
+    Testing the next dependencies structure for shared/static libs
+
+    /.
+    |- myfirstlib/
+         |- conanfile.py
+         |- MODULE.bazel
+         |- main/
+            |- BUILD
+            |- myfirstlib.cpp
+            |- myfirstlib.h
+    |- mysecondlib/  (requires myfirstlib)
+         |- conanfile.py
+         |- MODULE.bazel
+         |- main/
+            |- BUILD
+            |- mysecondlib.cpp
+            |- mysecondlib.h
+         |- test_package/
+            |- MODULE.bazel
+            |- conanfile.py
+            |- main
+                |- example.cpp
+                |- BUILD
+    """
+    client = TestClient(path_with_spaces=False)
+    # A regular library made with Bazel
+    with client.chdir("myfirstlib"):
+        client.run("new bazel_7_lib -d name=myfirstlib -d version=1.2.11")
+        conanfile = client.load("conanfile.py")
+        conanfile += """
+        self.cpp_info.defines.append("MY_DEFINE=\\"MY_VALUE\\"")
+        self.cpp_info.defines.append("MY_OTHER_DEFINE=2")
+        if self.settings.os != "Windows":
+            self.cpp_info.system_libs.append("m")
+        else:
+            self.cpp_info.system_libs.append("ws2_32")
+        """
+        client.save({"conanfile.py": conanfile})
+        client.run(f"create . -o '*:shared={shared}' -tf ''")  # skipping tests
+
+    with client.chdir("mysecondlib"):
+        # We prepare a consumer with Bazel (library mysecondlib using myfirstlib)
+        # and a test_package with an example executable
+        os_ = platform.system()
+        client.run("new bazel_7_lib -d name=mysecondlib -d version=1.0")
+        conanfile = client.load("conanfile.py")
+        conanfile = conanfile.replace('generators = "BazelToolchain"',
+                                      'generators = "BazelToolchain", "BazelDeps"\n'
+                                      '    requires = "myfirstlib/1.2.11"')
+        workspace = textwrap.dedent("""
+        load_conan_dependencies = use_extension("//conan:conan_deps_module_extension.bzl", "conan_extension")
+        use_repo(load_conan_dependencies, "myfirstlib")
+        """)
+        bazel_build_linux = textwrap.dedent("""\
+        cc_library(
+            name = "mysecondlib",
+            srcs = ["mysecondlib.cpp"],
+            hdrs = ["mysecondlib.h"],
+            deps = [ "@myfirstlib//:myfirstlib" ]
+        )
+        """)
+        bazel_build = textwrap.dedent("""\
+        cc_library(
+            name = "mysecondlib",
+            srcs = ["mysecondlib.cpp"],
+            hdrs = ["mysecondlib.h"],
+            deps = [ "@myfirstlib//:myfirstlib" ]
+        )
+
+        cc_shared_library(
+            name = "mysecondlib_shared",
+            shared_lib_name = "libmysecondlib_shared.{}",
+            deps = [":mysecondlib"],
+        )
+        """.format("dylib" if os_ == "Darwin" else "dll"))
+        mysecondlib_cpp = textwrap.dedent("""
+        #include <iostream>
+        #include "mysecondlib.h"
+        #include "myfirstlib.h"
+        #include <cmath>
+
+        void mysecondlib(){
+            std::cout << "mysecondlib() First define " << MY_DEFINE << " and other define " << MY_OTHER_DEFINE << std::endl;
+            myfirstlib();
+            // This comes from the systemlibs declared in the myfirstlib
+            sqrt(25);
+        }
+        void mysecondlib_print_vector(const std::vector<std::string> &strings) {
+            for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); ++it) {
+                std::cout << "mysecondlib/1.0 " << *it << std::endl;
+            }
+        }
+        """)
+        mysecondlib_cpp_win = textwrap.dedent("""
+        #include <iostream>
+        #include "mysecondlib.h"
+        #include "myfirstlib.h"
+        #include <WinSock2.h>
+
+        void mysecondlib(){
+            SOCKET foo; // From the system library
+            std::cout << "mysecondlib() First define " << MY_DEFINE << " and other define " << MY_OTHER_DEFINE << std::endl;
+            myfirstlib();
+        }
+        void mysecondlib_print_vector(const std::vector<std::string> &strings) {
+            for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); ++it) {
+                std::cout << "mysecondlib/1.0 " << *it << std::endl;
+            }
+        }
+        """)
+        # Overwriting files
+        client.save({"conanfile.py": conanfile,
+                     "MODULE.bazel": workspace,
+                     "main/BUILD": bazel_build_linux if os_ == "Linux" else bazel_build,
+                     "main/mysecondlib.cpp": mysecondlib_cpp if os_ != "Windows" else mysecondlib_cpp_win,
+                     })
+
+        client.run(f"create . -o '*:shared={shared}'")
+        assert "mysecondlib() First define MY_VALUE and other define 2" in client.out
+        assert "myfirstlib/1.2.11: Hello World Release!"
diff --git a/test/functional/toolchains/google/test_bazeltoolchain_cross_compilation.py b/test/functional/toolchains/google/test_bazeltoolchain_cross_compilation.py
index 197887d50..1768210ef 100644
--- a/test/functional/toolchains/google/test_bazeltoolchain_cross_compilation.py
+++ b/test/functional/toolchains/google/test_bazeltoolchain_cross_compilation.py
@@ -9,7 +9,7 @@ from conan.test.utils.tools import TestClient
 
 
 @pytest.mark.skipif(platform.system() != "Darwin", reason="Only for Darwin")
-@pytest.mark.tool("bazel")
+@pytest.mark.tool("bazel", "6.3.2")  # not working for Bazel 7.x
 def test_bazel_simple_cross_compilation():
     profile = textwrap.dedent("""
     [settings]
@@ -53,7 +53,6 @@ def test_bazel_simple_cross_compilation():
             bazel.build()
     """)
     BUILD = textwrap.dedent("""
-    load("@rules_cc//cc:defs.bzl", "cc_library")
     cc_library(
         name = "myapp",
         srcs = ["myapp.cpp"],
diff --git a/test/functional/toolchains/qbs/test_qbs.py b/test/functional/toolchains/qbs/test_qbs.py
new file mode 100644
index 000000000..c61439f21
--- /dev/null
+++ b/test/functional/toolchains/qbs/test_qbs.py
@@ -0,0 +1,14 @@
+import pytest
+
+from conan.test.utils.tools import TestClient
+
+@pytest.mark.parametrize('shared', [
+    ('False'),
+    ('True'),
+])
+@pytest.mark.tool("qbs")
+def test_api_qbs_create_lib(shared):
+    client = TestClient()
+    client.run("new qbs_lib -d name=hello -d version=1.0")
+    client.run("create . -o:h &:shared={shared}".format(shared=shared))
+    assert "compiling hello.cpp" in client.out
\ No newline at end of file
diff --git a/test/integration/command/runner_test.py b/test/integration/command/runner_test.py
index 9a68ec67f..6071b7109 100644
--- a/test/integration/command/runner_test.py
+++ b/test/integration/command/runner_test.py
@@ -34,7 +34,135 @@ def dockerfile_path(name=None):
 
 
 @pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
-# @pytest.mark.xfail(reason="conan inside docker optional test")
+def test_create_docker_runner_cache_shared():
+    """
+    Tests the ``conan create . ``
+    """
+    client = TestClient()
+    profile_build = textwrap.dedent(f"""\
+    [settings]
+    arch=x86_64
+    build_type=Release
+    compiler=gcc
+    compiler.cppstd=gnu17
+    compiler.libcxx=libstdc++11
+    compiler.version=11
+    os=Linux
+    """)
+
+    profile_host = textwrap.dedent(f"""\
+    [settings]
+    arch=x86_64
+    build_type=Release
+    compiler=gcc
+    compiler.cppstd=gnu17
+    compiler.libcxx=libstdc++11
+    compiler.version=11
+    os=Linux
+    [runner]
+    type=docker
+    dockerfile={dockerfile_path()}
+    build_context={conan_base_path()}
+    image=conan-runner-default-test
+    cache=shared
+    remove=True
+    """)
+
+    client.save({"host": profile_host, "build": profile_build})
+    client.run("new cmake_lib -d name=pkg -d version=0.2")
+    client.run("create . -pr:h host -pr:b build")
+
+    assert "[100%] Built target example" in client.out
+    assert "Removing container" in client.out
+
+
+@pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
+def test_create_docker_runner_cache_shared_profile_from_cache():
+    """
+    Tests the ``conan create . ``
+    """
+    client = TestClient()
+    profile_build = textwrap.dedent(f"""\
+    [settings]
+    arch=x86_64
+    build_type=Release
+    compiler=gcc
+    compiler.cppstd=gnu17
+    compiler.libcxx=libstdc++11
+    compiler.version=11
+    os=Linux
+    """)
+
+    profile_host = textwrap.dedent(f"""\
+    [settings]
+    arch=x86_64
+    build_type=Release
+    compiler=gcc
+    compiler.cppstd=gnu17
+    compiler.libcxx=libstdc++11
+    compiler.version=11
+    os=Linux
+    [runner]
+    type=docker
+    dockerfile={dockerfile_path()}
+    build_context={conan_base_path()}
+    image=conan-runner-default-test
+    cache=shared
+    remove=True
+    """)
+
+    client.save({"default_host": profile_host, "default_build": profile_build}, path=client.cache.profiles_path)
+    client.run("new cmake_lib -d name=pkg -d version=0.2")
+    client.run("create . -pr:h default_host -pr:b default_build")
+
+    assert "[100%] Built target example" in client.out
+    assert "Removing container" in client.out
+
+
+@pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
+def test_create_docker_runner_cache_shared_profile_folder():
+    """
+    Tests the ``conan create . ``
+    """
+    client = TestClient()
+    profile_build = textwrap.dedent(f"""\
+    [settings]
+    arch=x86_64
+    build_type=Release
+    compiler=gcc
+    compiler.cppstd=gnu17
+    compiler.libcxx=libstdc++11
+    compiler.version=11
+    os=Linux
+    """)
+
+    profile_host = textwrap.dedent(f"""\
+    [settings]
+    arch=x86_64
+    build_type=Release
+    compiler=gcc
+    compiler.cppstd=gnu17
+    compiler.libcxx=libstdc++11
+    compiler.version=11
+    os=Linux
+    [runner]
+    type=docker
+    dockerfile={dockerfile_path()}
+    build_context={conan_base_path()}
+    image=conan-runner-default-test
+    cache=shared
+    remove=True
+    """)
+
+    client.save({"build": profile_build})
+    client.save({"docker_default": profile_host}, path = os.path.join(client.cache_folder, "profiles"))
+    client.run("new cmake_lib -d name=pkg -d version=0.2")
+    client.run("create . -pr:h docker_default -pr:b build")
+
+    assert "[100%] Built target example" in client.out
+    assert "Removing container" in client.out
+
+@pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
 def test_create_docker_runner_dockerfile_folder_path():
     """
     Tests the ``conan create . ``
@@ -105,7 +233,6 @@ def test_create_docker_runner_dockerfile_folder_path():
 
 
 @pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
-# @pytest.mark.xfail(reason="conan inside docker optional test")
 def test_create_docker_runner_dockerfile_file_path():
     """
     Tests the ``conan create . ``
@@ -150,7 +277,6 @@ def test_create_docker_runner_dockerfile_file_path():
 
 
 @pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
-# @pytest.mark.xfail(reason="conan inside docker optional test")
 @pytest.mark.parametrize("build_type,shared", [("Release", False), ("Debug", True)])
 @pytest.mark.tool("ninja")
 def test_create_docker_runner_with_ninja(build_type, shared):
@@ -215,55 +341,8 @@ def test_create_docker_runner_with_ninja(build_type, shared):
     assert 'cmake -G "Ninja"' in client.out
     assert "main: {}!".format(build_type) in client.out
 
-
-@pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
-# @pytest.mark.xfail(reason="conan inside docker optional test")
-def test_create_docker_runner_profile_abs_path():
-    """
-    Tests the ``conan create . ``
-    """
-    client = TestClient()
-    profile_build = textwrap.dedent(f"""\
-    [settings]
-    arch=x86_64
-    build_type=Release
-    compiler=gcc
-    compiler.cppstd=gnu17
-    compiler.libcxx=libstdc++11
-    compiler.version=11
-    os=Linux
-    """)
-    profile_host = textwrap.dedent(f"""\
-    [settings]
-    arch=x86_64
-    build_type=Release
-    compiler=gcc
-    compiler.cppstd=gnu17
-    compiler.libcxx=libstdc++11
-    compiler.version=11
-    os=Linux
-    [runner]
-    type=docker
-    dockerfile={dockerfile_path("Dockerfile_test")}
-    build_context={conan_base_path()}
-    image=conan-runner-default-test
-    cache=copy
-    remove=True
-    """)
-
-    client.save({"host": profile_host, "build": profile_build})
-    client.run("new cmake_lib -d name=pkg -d version=0.2")
-    client.run(f"create . -pr:h '{os.path.join(client.current_folder, 'host')}' -pr:b '{os.path.join(client.current_folder, 'build')}'")
-
-    assert "Restore: pkg/0.2" in client.out
-    assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
-    assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata" in client.out
-    assert "Removing container" in client.out
-
-
 @pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
-# @pytest.mark.xfail(reason="conan inside docker optional test")
-def test_create_docker_runner_profile_abs_path_from_configfile():
+def test_create_docker_runner_from_configfile():
     """
     Tests the ``conan create . ``
     """
@@ -307,7 +386,7 @@ def test_create_docker_runner_profile_abs_path_from_configfile():
 
     client.save({"host": profile_host, "build": profile_build})
     client.run("new cmake_lib -d name=pkg -d version=0.2")
-    client.run(f"create . -pr:h '{os.path.join(client.current_folder, 'host')}' -pr:b '{os.path.join(client.current_folder, 'build')}'")
+    client.run("create . -pr:h 'host' -pr:b 'build'")
 
     assert "Container my-custom-conan-runner-container running" in client.out
     assert "Restore: pkg/0.2" in client.out
@@ -317,8 +396,7 @@ def test_create_docker_runner_profile_abs_path_from_configfile():
 
 
 @pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
-# @pytest.mark.xfail(reason="conan inside docker optional test")
-def test_create_docker_runner_profile_abs_path_from_configfile_with_args():
+def test_create_docker_runner_from_configfile_with_args():
     """
     Tests the ``conan create . ``
     """
@@ -364,7 +442,7 @@ def test_create_docker_runner_profile_abs_path_from_configfile_with_args():
 
     client.save({"host": profile_host, "build": profile_build})
     client.run("new cmake_lib -d name=pkg -d version=0.2")
-    client.run(f"create . -pr:h '{os.path.join(client.current_folder, 'host')}' -pr:b '{os.path.join(client.current_folder, 'build')}'")
+    client.run("create . -pr:h 'host' -pr:b 'build'")
 
     assert "test/integration/command/dockerfiles/Dockerfile_args" in client.out
     assert "Restore: pkg/0.2" in client.out
@@ -374,7 +452,6 @@ def test_create_docker_runner_profile_abs_path_from_configfile_with_args():
 
 
 @pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
-# @pytest.mark.xfail(reason="conan inside docker optional test")
 def test_create_docker_runner_default_build_profile():
     """
     Tests the ``conan create . ``
@@ -410,7 +487,6 @@ def test_create_docker_runner_default_build_profile():
 
 
 @pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason="Only docker running")
-# @pytest.mark.xfail(reason="conan inside docker optional test")
 def test_create_docker_runner_default_build_profile_error():
     """
     Tests the ``conan create . ``
diff --git a/test/integration/command_v2/test_inspect.py b/test/integration/command_v2/test_inspect.py
index 129ee3761..8de7c470a 100644
--- a/test/integration/command_v2/test_inspect.py
+++ b/test/integration/command_v2/test_inspect.py
@@ -14,6 +14,7 @@ def test_basic_inspect():
                      '    shared: False',
                      'generators: []',
                      'label: ',
+                     'languages: []',
                      'name: foo',
                      'options:',
                      '    shared: False',
@@ -83,6 +84,7 @@ def test_normal_inspect():
                                    'generators: []',
                                    'homepage: <Your project homepage goes here>',
                                    'label: ',
+                                   'languages: []',
                                    'license: <Your project license goes here>',
                                    'name: pkg',
                                    'options:',
@@ -126,6 +128,7 @@ def test_requiremens_inspect():
     tc.run("inspect .")
     assert ['generators: []',
             'label: ',
+            'languages: []',
             "license: ['MIT', 'Apache']",
             'options:',
             'options_definitions:',
diff --git a/test/integration/package_id/test_cache_compatibles.py b/test/integration/package_id/test_cache_compatibles.py
index 35fe89e92..74f1c364c 100644
--- a/test/integration/package_id/test_cache_compatibles.py
+++ b/test/integration/package_id/test_cache_compatibles.py
@@ -311,6 +311,37 @@ class TestDefaultCompat:
         assert "valid standard!!" in c.out
         assert "pkg/0.1: CPPSTD: 17" in c.out
 
+    def test_check_min_cstd(self):
+        """ test that the check_min_cstd works fine wiht compatibility
+        """
+        conanfile = textwrap.dedent("""
+            from conan import ConanFile
+            from conan.tools.build import check_min_cstd
+            class Pkg(ConanFile):
+                name = "pkg"
+                version = "0.1"
+                settings = "os", "arch", "compiler", "build_type"
+                languages = "C"
+                def validate(self):
+                    check_min_cstd(self, "17", False)
+                    self.output.info("valid standard!!")
+                def package_info(self):
+                    self.output.info("CSTD: {}".format(self.settings.compiler.cstd))
+            """)
+
+        c = TestClient()
+        c.save({"conanfile.py": conanfile})
+        settings = "-s compiler=gcc -s compiler.version=9 -s compiler.libcxx=libstdc++11"
+        c.run(f"create .  {settings} -s compiler.cstd=17")
+        assert "pkg/0.1: valid standard!!" in c.out
+        assert "pkg/0.1: CSTD: 17" in c.out
+        c.run(f"install {settings} --requires=pkg/0.1 -s compiler.cstd=11", assert_error=True)
+        assert "pkg/0.1: Invalid: Current cstd (11) is lower than the required C standard (17)."\
+               in c.out
+        c.run(f"install {settings} --requires=pkg/0.1 -s compiler.cstd=23")
+        assert "valid standard!!" in c.out
+        assert "pkg/0.1: CSTD: 17" in c.out
+
     def test_check_min_cppstd_interface(self):
         """ test that says that compatible binaries are ok, as long as the user defined
         cppstd>=14. The syntax is a bit forced, maybe we want to improve ``check_min_cppstd``
diff --git a/test/integration/toolchains/cmake/test_cmaketoolchain.py b/test/integration/toolchains/cmake/test_cmaketoolchain.py
index df1fff5ef..c21b35ffc 100644
--- a/test/integration/toolchains/cmake/test_cmaketoolchain.py
+++ b/test/integration/toolchains/cmake/test_cmaketoolchain.py
@@ -1501,7 +1501,6 @@ def test_toolchain_keep_absolute_paths():
     presets = json.loads(c.load(user_presets["include"][0]))
     assert os.path.isabs(presets["configurePresets"][0]["toolchainFile"])
 
-
 def test_output_dirs_gnudirs_local_default():
     # https://github.com/conan-io/conan/issues/14733
     c = TestClient()
@@ -1575,3 +1574,59 @@ def test_output_dirs_gnudirs_local_custom():
     c.run("build .")
     _assert_install(c.out)
     assert "CMAKE_INSTALL_PREFIX" not in c.out
+
+
+def test_toolchain_extra_variables():
+    windows_profile = textwrap.dedent("""
+        [settings]
+        os=Windows
+        arch=x86_64
+        [conf]
+        tools.cmake.cmaketoolchain:extra_variables={'CMAKE_GENERATOR_INSTANCE': '${GENERATOR_INSTANCE}/buildTools/', 'FOO': '42' }
+        """)
+
+    client = TestClient()
+    client.save({"conanfile.txt": "[generators]\nCMakeToolchain",
+                 "windows": windows_profile})
+
+    # Test passing extra_variables from pro ile
+    client.run("install . --profile:host=windows")
+    toolchain = client.load("conan_toolchain.cmake")
+    assert 'set(CMAKE_GENERATOR_INSTANCE "${GENERATOR_INSTANCE}/buildTools/")' in toolchain
+    assert 'set(FOO "42")' in toolchain
+
+    # Test input from command line passing dict between doble quotes
+    client.run(textwrap.dedent(r"""
+        install . -c tools.cmake.cmaketoolchain:extra_variables="{'CMAKE_GENERATOR_INSTANCE': '${GENERATOR_INSTANCE}/buildTools/', 'FOO': 42.2, 'DICT': {'value': 1}, 'CACHE_VAR': {'value': 'hello world', 'cache': True, 'type': 'BOOL', 'docstring': 'test variable'}}"
+    """)
+    )
+
+    toolchain = client.load("conan_toolchain.cmake")
+    assert 'set(CMAKE_GENERATOR_INSTANCE "${GENERATOR_INSTANCE}/buildTools/")' in toolchain
+    assert 'set(FOO 42.2)' in toolchain
+    assert 'set(DICT 1)' in toolchain
+    assert 'set(CACHE_VAR "hello world" CACHE BOOL "test variable")' in toolchain
+
+
+    client.run(textwrap.dedent("""
+        install . -c tools.cmake.cmaketoolchain:extra_variables="{'invalid': {'value': 'hello world', 'cache': 'true'}}"
+    """) , assert_error=True)
+    assert 'tools.cmake.cmaketoolchain:extra_variables "cache" must be a boolean (True/False)' in client.out
+
+    # Test invalid cache variable
+    client.run(textwrap.dedent("""
+        install . -c tools.cmake.cmaketoolchain:extra_variables="{'invalid': {'value': 'hello world', 'cache': True}}"
+    """) , assert_error=True)
+    assert 'tools.cmake.cmaketoolchain:extra_variables needs "type" defined for cache variable "invalid"' in client.out
+
+    client.run(textwrap.dedent("""
+        install . -c tools.cmake.cmaketoolchain:extra_variables="{'invalid': {'value': 'hello world', 'cache': True, 'type': 'INVALID_TYPE'}}"
+    """) , assert_error=True)
+    assert 'tools.cmake.cmaketoolchain:extra_variables invalid type "INVALID_TYPE" for cache variable "invalid". Possible types: BOOL, FILEPATH, PATH, STRING, INTERNAL' in client.out
+
+    client.run(textwrap.dedent("""
+        install . -c tools.cmake.cmaketoolchain:extra_variables="{'CACHE_VAR_DEFAULT_DOC': {'value': 'hello world', 'cache': True, 'type': 'PATH'}}"
+    """))
+    toolchain = client.load("conan_toolchain.cmake")
+    assert 'set(CACHE_VAR_DEFAULT_DOC "hello world" CACHE PATH "CACHE_VAR_DEFAULT_DOC")' in toolchain
+
diff --git a/test/integration/toolchains/gnu/test_autotoolstoolchain.py b/test/integration/toolchains/gnu/test_autotoolstoolchain.py
index c80468a71..7364274ae 100644
--- a/test/integration/toolchains/gnu/test_autotoolstoolchain.py
+++ b/test/integration/toolchains/gnu/test_autotoolstoolchain.py
@@ -266,6 +266,9 @@ def test_toolchain_and_compilers_build_context():
             assert 'export CC="gcc"' in content
             assert 'export CXX="g++"' in content
             assert 'export RC="windres"' in content
+            # Issue: https://github.com/conan-io/conan/issues/15486
+            assert 'export CC_FOR_BUILD="clang"' in content
+            assert 'export CXX_FOR_BUILD="clang++"' in content
     """)
     client = TestClient()
     client.save({
diff --git a/test/integration/toolchains/google/test_bazeldeps.py b/test/integration/toolchains/google/test_bazeldeps.py
index 2eb9c971f..d4b99059a 100644
--- a/test/integration/toolchains/google/test_bazeldeps.py
+++ b/test/integration/toolchains/google/test_bazeldeps.py
@@ -1,4 +1,5 @@
 import os
+import pathlib
 import textwrap
 
 from conan.test.assets.genconanfile import GenConanfile
@@ -53,8 +54,6 @@ def test_bazel_relative_paths():
     assert "conanfile.py: Generator 'BazelToolchain' calling 'generate()'" in c.out
     build_file = c.load("consumer/conandeps/dep/BUILD.bazel")
     expected = textwrap.dedent("""\
-    load("@rules_cc//cc:defs.bzl", "cc_import", "cc_library")
-
     # Components precompiled libs
     # Root package precompiled libs
 
@@ -150,8 +149,6 @@ def test_bazeldeps_and_tool_requires():
     c.run("install --requires=dep/0.1 -g BazelDeps --build=missing")
     build_file = c.load("dep/BUILD.bazel")
     expected = textwrap.dedent("""\
-    load("@rules_cc//cc:defs.bzl", "cc_import", "cc_library")
-
     # Components precompiled libs
     # Root package precompiled libs
     cc_import(
@@ -617,6 +614,7 @@ def test_with_editable_layout():
     recipes_folder = client.current_folder.replace("\\", "/")
     with client.chdir("pkg"):
         client.run("install . -g BazelDeps")
+        # TODO: Remove when dropped Bazel 6.x compatibility
         content = client.load("dependencies.bzl")
         assert textwrap.dedent(f"""\
         def load_conan_dependencies():
@@ -625,7 +623,17 @@ def test_with_editable_layout():
                 path="{recipes_folder}/dep",
                 build_file="{recipes_folder}/pkg/dep/BUILD.bazel",
             )""") in content
+        # Bazel 7.x
+        content = client.load("conan_deps_module_extension.bzl")
+        assert textwrap.dedent(f"""\
+        def _load_dependenies_impl(mctx):
+            conan_dependency_repo(
+                name = "dep",
+                package_path = "{recipes_folder}/dep",
+                build_file_path = "{recipes_folder}/pkg/dep/BUILD.bazel",
+            )""") in content
         content = client.load("dep/BUILD.bazel")
+        assert pathlib.Path(client.current_folder, "conan_deps_repo_rules.bzl").exists()
         assert textwrap.dedent("""\
         cc_import(
             name = "mylib_precompiled",
@@ -756,10 +764,16 @@ def test_tool_requires():
             ":component3",
         ],
     )""") in client.load("build-other-repo/BUILD.bazel")
+    # TODO: Remove when dropped Bazel 6.x compatibility
     # Let's check if the names used in the dependencies.bzl are correct
     content = client.load("dependencies.bzl")
     assert 'name="build-other-repo"' in content  # build context + bazel_repository_name prop
     assert 'name="build-tool"' in content  # build context + package reference name
+    # Bazel 7.x
+    # Let's check if the names used in the conan_deps_repo_rules.bzl are correct
+    content = client.load("conan_deps_module_extension.bzl")
+    assert 'name = "build-other-repo"' in content  # build context + bazel_repository_name prop
+    assert 'name = "build-tool"' in content  # build context + package reference name
 
 
 def test_tool_requires_not_created_if_no_activated():
diff --git a/test/integration/toolchains/meson/test_mesontoolchain.py b/test/integration/toolchains/meson/test_mesontoolchain.py
index 602b4bb9a..d9ca23ea9 100644
--- a/test/integration/toolchains/meson/test_mesontoolchain.py
+++ b/test/integration/toolchains/meson/test_mesontoolchain.py
@@ -105,6 +105,46 @@ def test_extra_flags_via_conf():
     assert "cpp_link_args = ['-flag0', '-other=val', '-flag5', '-flag6']" in content
 
 
+def test_extra_flags_via_toolchain():
+    profile = textwrap.dedent("""
+        [settings]
+        os=Windows
+        arch=x86_64
+        compiler=gcc
+        compiler.version=9
+        compiler.cppstd=17
+        compiler.libcxx=libstdc++
+        build_type=Release
+
+        [buildenv]
+        CFLAGS=-flag0 -other=val
+        CXXFLAGS=-flag0 -other=val
+        LDFLAGS=-flag0 -other=val
+   """)
+    t = TestClient()
+    conanfile = textwrap.dedent("""
+    from conan import ConanFile
+    from conan.tools.meson import MesonToolchain
+    class Pkg(ConanFile):
+        settings = "os", "compiler", "arch", "build_type"
+        def generate(self):
+            tc = MesonToolchain(self)
+            tc.extra_cxxflags = ["-flag1", "-flag2"]
+            tc.extra_cflags = ["-flag3", "-flag4"]
+            tc.extra_ldflags = ["-flag5", "-flag6"]
+            tc.extra_defines = ["define1=0"]
+            tc.generate()
+    """)
+    t.save({"conanfile.py": conanfile,
+            "profile": profile})
+    t.run("install . -pr:h=profile -pr:b=profile")
+    content = t.load(MesonToolchain.native_filename)
+    assert "cpp_args = ['-flag0', '-other=val', '-flag1', '-flag2', '-Ddefine1=0', '-D_GLIBCXX_USE_CXX11_ABI=0']" in content
+    assert "c_args = ['-flag0', '-other=val', '-flag3', '-flag4', '-Ddefine1=0']" in content
+    assert "c_link_args = ['-flag0', '-other=val', '-flag5', '-flag6']" in content
+    assert "cpp_link_args = ['-flag0', '-other=val', '-flag5', '-flag6']" in content
+
+
 def test_linker_scripts_via_conf():
     profile = textwrap.dedent("""
         [settings]
@@ -156,6 +196,29 @@ def test_correct_quotes():
     assert "buildtype = 'release'" in content
 
 
+def test_c_std():
+    profile = textwrap.dedent("""
+       [settings]
+       os=Windows
+       arch=x86_64
+       compiler=gcc
+       compiler.version=9
+       compiler.cstd=11
+       build_type=Release
+       """)
+    t = TestClient()
+    t.save({"conanfile.py": GenConanfile().with_settings("os", "compiler", "build_type", "arch")
+                                          .with_generator("MesonToolchain")
+                                          .with_class_attribute("languages='C'"),
+            "profile": profile})
+
+    t.run("install . -pr:h=profile -pr:b=profile")
+    content = t.load(MesonToolchain.native_filename)
+    assert "c_std = 'c11'" in content
+    assert "backend = 'ninja'" in content
+    assert "buildtype = 'release'" in content
+
+
 def test_deactivate_nowrap():
     # https://github.com/conan-io/conan/issues/10671
     t = TestClient()
diff --git a/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py b/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
index 5ea435a3f..e5afa10d7 100644
--- a/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
+++ b/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
@@ -130,6 +130,21 @@ def test_cppstd():
     assert "/std:c++17" in env["CXXFLAGS"]
 
 
+def test_cstd():
+    conanfile = ConanFileMock()
+    conanfile.settings = MockSettings(
+        {"build_type": "Release",
+         "arch": "x86",
+         "compiler": "gcc",
+         "compiler.libcxx": "libstdc++11",
+         "compiler.version": "7.1",
+         "compiler.cstd": "17"})
+    conanfile.settings_build = MockSettings({"os": "Linux", "arch": "x86"})
+    be = AutotoolsToolchain(conanfile)
+    env = be.vars()
+    assert "-std=c17" in env["CFLAGS"]
+
+
 def test_fpic():
     conanfile = ConanFileMock()
     conanfile.settings = MockSettings({"os": "Linux"})
diff --git a/test/unittests/tools/microsoft/test_msbuild.py b/test/unittests/tools/microsoft/test_msbuild.py
index 9f0e5b1bf..3fc984531 100644
--- a/test/unittests/tools/microsoft/test_msbuild.py
+++ b/test/unittests/tools/microsoft/test_msbuild.py
@@ -104,7 +104,8 @@ def test_msbuild_standard():
     conanfile.conf.define("tools.microsoft.msbuild:installation_path", ".")
     conanfile.settings = "os", "compiler", "build_type", "arch"
     conanfile.settings = Settings({"build_type": ["Release"],
-                                   "compiler": {"msvc": {"version": ["193"], "cppstd": ["20"]}},
+                                   "compiler": {"msvc": {"version": ["193"], "cppstd": ["20"],
+                                                         "cstd": ["17"]}},
                                    "os": ["Windows"],
                                    "arch": ["x86_64"]})
     conanfile.settings_build = conanfile.settings
@@ -112,6 +113,7 @@ def test_msbuild_standard():
     conanfile.settings.compiler = "msvc"
     conanfile.settings.compiler.version = "193"
     conanfile.settings.compiler.cppstd = "20"
+    conanfile.settings.compiler.cstd = "17"
     conanfile.settings.os = "Windows"
     conanfile.settings.arch = "x86_64"
 
@@ -119,6 +121,7 @@ def test_msbuild_standard():
     props_file = os.path.join(test_folder, 'conantoolchain_release_x64.props')
     msbuild.generate()
     assert '<LanguageStandard>stdcpp20</LanguageStandard>' in load(props_file)
+    assert '<LanguageStandard_C>stdc17</LanguageStandard_C>' in load(props_file)
 
 
 def test_resource_compile():
diff --git a/test/unittests/util/detect_test.py b/test/unittests/util/detect_test.py
index 28b004230..1ac0e59a9 100644
--- a/test/unittests/util/detect_test.py
+++ b/test/unittests/util/detect_test.py
@@ -1,8 +1,11 @@
 import unittest
 
 import mock
+from unittest.mock import patch
+import pytest
 from parameterized import parameterized
 
+from conan.internal.api.detect_api import _cc_compiler
 from conans.client.conf.detect import detect_defaults_settings
 from conans.model.version import Version
 from conan.test.utils.mocks import RedirectedTestOutput
@@ -56,3 +59,18 @@ class DetectTest(unittest.TestCase):
             with environment_update({"CC": "clang-9 --gcc-toolchain=/usr/lib/gcc/x86_64-linux-gnu/9"}):
                 detect_defaults_settings()
                 self.assertIn("CC and CXX: clang-9 --gcc-toolchain", output)
+
+
+@pytest.mark.parametrize("version_return,expected_version", [
+    ["cc.exe (Rev3, Built by MSYS2 project) 14.1.0", "14.1.0"],
+    ["g++ (Conan-Build-gcc--binutils-2.42) 14.1.0", "14.1.0"],
+    ["clang version 18.1.0rc (https://github.com/llvm/llvm-project.git 461274b81d8641eab64d494accddc81d7db8a09e)", "18.1.0"],
+    ["cc.exe (Rev3, Built by MSYS2 project) 14.0", "14.0"],
+    ["clang version 18 (https://github.com/llvm/llvm-project.git 461274b81d8641eab64d494accddc81d7db8a09e)", "18"],
+    ["cc.exe (Rev3, Built by MSYS2 project) 14", "14"],
+])
+@patch("conan.internal.api.detect_api.detect_runner")
+def test_detect_cc_versionings(detect_runner_mock, version_return, expected_version):
+    detect_runner_mock.return_value = 0, version_return
+    compiler, installed_version, compiler_exe = _cc_compiler()
+    assert installed_version == Version(expected_version)