Repository: conan-io/conan

Issue:
[bug] meson toolchain incorrectly handles cross-compilation on same os/arch tuple.
### Environment details

* Conan version: 2.0.14
* Python version: 3.10.12


### Steps to reproduce

1. install a Yocto SDK or similar that produces ABI incompatible binaries on the same arch.
2. Set up a host profile that has the same os+arch as the build machine, but has an explicit `tools.build.cross_building:can_run=no` set in `[conf]`.
3. Attempt to build any meson package and watch it fail when it attempts to test the compilers.

(Note:   Support for this to work is necessary as it's entirely possible to have incompatible ABIs between Linux distributions and this is already a problem that plagues binaries hosted by conan-center - In our case, my development distro can't produce binaries that run on our embedded x86_64 distro and vice versa due to ld.so and libc differences so we need to use a cross compilation flow *despite* the architectures being compatible/identical.)

A quick check of the code shows that MesonToolchain only checks cross_compiling, and not can_run.  Even if it's not a full cross_compile, if it can't run the binaries, Meson needs to use the cross_compilation flow.


### Logs

```
... snipped ...
-------- Installing package wayland/1.22.0 (43 of 47) --------
wayland/1.22.0: Building from source
wayland/1.22.0: Package wayland/1.22.0:db57ab7809fab3515e28598fd861124ccd5fedb2
wayland/1.22.0: Copying sources to build folder
wayland/1.22.0: Building your package in /home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b
wayland/1.22.0: Calling generate()
wayland/1.22.0: Generators folder: /home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/build-relwithdebinfo/conan
WARN: deprecated: Please, do not use a Conan option value directly. Convert 'options.enable_libraries' into a valid Pythondata type, e.g, bool(self.options.shared)
WARN: deprecated: Please, do not use a Conan option value directly. Convert 'options.enable_dtd_validation' into a valid Pythondata type, e.g, bool(self.options.shared)
wayland/1.22.0: Generating aggregated env files
wayland/1.22.0: Generated aggregated env files: ['conanbuild.sh']
wayland/1.22.0: Calling build()
wayland/1.22.0: Meson configure cmd: meson setup --native-file "/home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/build-relwithdebinfo/conan/conan_meson_native.ini" "/home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/build-relwithdebinfo" "/home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/src" -Dprefix="/home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/p"
wayland/1.22.0: RUN: meson setup --native-file "/home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/build-relwithdebinfo/conan/conan_meson_native.ini" "/home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/build-relwithdebinfo" "/home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/src" -Dprefix="/home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/p"
DEPRECATION: "pkgconfig" entry is deprecated and should be replaced by "pkg-config"
The Meson build system
Version: 1.3.0
Source dir: /home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/src
Build dir: /home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/build-relwithdebinfo
Build type: native build
Project name: wayland
Project version: 1.22.0

../src/meson.build:1:0: ERROR: Compiler /usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/bin/x86_64-oe-linux/x86_64-oe-linux-gcc cannot compile programs.

A full log can be found at /home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/build-relwithdebinfo/meson-logs/meson-log.txt

wayland/1.22.0: ERROR: 
Package 'db57ab7809fab3515e28598fd861124ccd5fedb2' build failed
wayland/1.22.0: WARN: Build folder /home/kuroneko/.conan2/p/b/wayla32f3fb2af00f2/b/build-relwithdebinfo
*********************************************************
Recipe 'wayland/1.22.0' cannot build its binary
It is possible that this recipe is not Conan 2.0 ready
If the recipe comes from ConanCenter, report it at https://github.com/conan-io/conan-center-index/issues
If it is your recipe, check if it is updated to 2.0
*********************************************************

ERROR: wayland/1.22.0: Error in build() method, line 103
	meson.configure()
	ConanException: Error 1 while executing
```


Discussion:
Also noting #11035, it seems that this was overlooked as `can_run` would appear to be the correct mechanism.
bump.  This remains an issue and needs to be fixed.
Implemented in https://github.com/conan-io/conan/pull/15616 as ``tools.build.cross_building:cross_build`` configuration ``conf``, to fully control the ``cross_building()`` helper behavior from profiles.



Patch:
diff --git a/conan/tools/build/cross_building.py b/conan/tools/build/cross_building.py
index b446d562e00..7d7d009d732 100644
--- a/conan/tools/build/cross_building.py
+++ b/conan/tools/build/cross_building.py
@@ -9,6 +9,9 @@ def cross_building(conanfile=None, skip_x64_x86=False):
            x86_64 to x86, sparcv9 to sparc or ppc64 to ppc32
     :return: ``True`` if we are cross building, ``False`` otherwise.
     """
+    cross_build = conanfile.conf.get("tools.build.cross_building:cross_build", check_type=bool)
+    if cross_build is not None:
+        return cross_build
 
     build_os = conanfile.settings_build.get_safe('os')
     build_arch = conanfile.settings_build.get_safe('arch')
@@ -32,7 +35,7 @@ def cross_building(conanfile=None, skip_x64_x86=False):
 def can_run(conanfile):
     """
     Validates whether is possible to run a non-native app on the same architecture.
-    It’s an useful feature for the case your architecture can run more than one target.
+    It’s a useful feature for the case your architecture can run more than one target.
     For instance, Mac M1 machines can run both `armv8` and `x86_64`.
 
     :param conanfile: The current recipe object. Always use ``self``.
diff --git a/conans/model/conf.py b/conans/model/conf.py
index 0f76a9e20c7..854f6caa76a 100644
--- a/conans/model/conf.py
+++ b/conans/model/conf.py
@@ -108,6 +108,7 @@
     "tools.apple:enable_visibility": "(boolean) Enable/Disable Visibility Apple Clang flags",
     "tools.env.virtualenv:powershell": "If it is set to True it will generate powershell launchers if os=Windows",
     # Compilers/Flags configurations
+    "tools.build.cross_building:cross_build": "Decides whether cross-building or not regardless of arch/OS settings. Used by 'conan.tools.build.cross_building' function.",
     "tools.build:compiler_executables": "Defines a Python dict-like with the compilers path to be used. Allowed keys {'c', 'cpp', 'cuda', 'objc', 'objcxx', 'rc', 'fortran', 'asm', 'hip', 'ispc'}",
     "tools.build:cxxflags": "List of extra CXX flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",
     "tools.build:cflags": "List of extra C flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",


Test patch:
diff --git a/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py b/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
index 59af29058f4..47650ab9a18 100644
--- a/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
+++ b/conans/test/unittests/client/toolchain/autotools/autotools_toolchain_test.py
@@ -298,7 +298,7 @@ def test_apple_arch_flag():
 
     # Only set when crossbuilding
     conanfile = ConanFileMock()
-    conanfile.conf = {"tools.apple:sdk_path": "/path/to/sdk"}
+    conanfile.conf.define("tools.apple:sdk_path", "/path/to/sdk")
     conanfile.settings = MockSettings(
         {"build_type": "Debug",
          "os": "Macos",
@@ -365,7 +365,7 @@ def test_apple_isysrootflag():
 
     # Only set when crossbuilding
     conanfile = ConanFileMock()
-    conanfile.conf = {"tools.apple:sdk_path": "/path/to/sdk"}
+    conanfile.conf.define("tools.apple:sdk_path", "/path/to/sdk")
     conanfile.settings = MockSettings(
         {"build_type": "Debug",
          "os": "Macos",
diff --git a/conans/test/unittests/tools/build/test_cross_building.py b/conans/test/unittests/tools/build/test_cross_building.py
new file mode 100644
index 00000000000..71806c24c27
--- /dev/null
+++ b/conans/test/unittests/tools/build/test_cross_building.py
@@ -0,0 +1,16 @@
+import pytest
+
+from conan.tools.build import cross_building
+from conans.test.utils.mocks import ConanFileMock
+
+
+@pytest.mark.parametrize("cross_build", (True, False))
+def test_using_cross_build_conf(cross_build):
+    """
+    Tests cross_building function is using the conf variable to force or not.
+
+    Issue related: https://github.com/conan-io/conan/issues/15392
+    """
+    conanfile = ConanFileMock()
+    conanfile.conf.define("tools.build.cross_building:cross_build", cross_build)
+    assert cross_building(conanfile) == cross_build