Repository: conan-io/conan
Pull request: [feature] Add tools can_run
- Added under cross_building namespace
- TODO: Elaborate tests 

Changelog: Feature: Tools `can_run` validates if it is possible to run a and application build for a non-native architecture.
Docs: https://github.com/conan-io/docs/pull/2547
closes #11035

- [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/develop/.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. 

<sup>**Note:** By default this PR will skip the slower tests and will use a limited set of python versions. Check [here](https://github.com/conan-io/conan/blob/develop/.github/PR_INCREASE_TESTING.md) how to increase the testing level by writing some tags in the current PR body text.</sup>


Problem statement:
[feature] Ability to identify if binaries can be executed on a particular platform
Typically there is made use of `tools.cross_building(self.settings)` to identify that for example test binaries can't be executed on a particular platform. Though this particular solution is not really sufficient to handle for example the case of running on a macOS with Apple Silicon (M1) chipset, as in that particular case you can execute both x86_64 and armv8 binaries without any issue (even without Rosetta enabled). 

Extending `tools.cross_building` with yet another parameter similar to `skip_x64_x86` seems not a good option. Therefore it would be good to have a dedicated method for this usecase like for example `tools.can_run()`.

Hints from issue discussion:
It's true you don't need to invoke Rosetta manually on M1 to execute x86_64, but still, the architecture is not the same and Mac will run Rosetta 2 dynamically, which has some loss of performance. I could use QEMU on Linux and say the same thing, but still, is not optimized.

I disagree adding such feature because any possible incompatibility error when executing an app, will result result someone asking to Conan issues or Conan Center Index for a solution, which is not related to Conan.

Running aligned architecture is the best option ever, and Conan already supports M1, which means, you can package ARM packages too.
I don't dislike being able to run things that are cross-built in platforms that allow it, and it seems this feature could make sense.

A different story is if we want to cross-build and/or cross-execute in ConanCenter. I see a point if that execution subsystem is not rock solid, as any potential error will result in further undesirable broken builds, support, tickets, discussions, etc in ConanCenter.
also, as I understand, this move could be a temporary. e.g. previously, Rosetta allowed to execute x86 (32-bit) and PowerPC binaries on x86_64 machines, but eventually Apple has removed that support completely, as x86_64 Apple machines became more wide-spread than x86(32) and PowerPC. actually, it lasted only OS 3 releases (from 10.4 to 10.7) that time.
> also, as I understand, this move could be a temporary. e.g. previously, Rosetta allowed to execute x86 (32-bit) and PowerPC binaries on x86_64 machines, but eventually Apple has removed that support completely, as x86_64 Apple machines became more wide-spread than x86(32) and PowerPC. actually, it lasted only OS 3 releases (from 10.4 to 10.7) that time.

Yes, if the OSX support for this might be changing, dropped, etc., then trying to have something robust in Conan can be a maintenance burden and source of bugs and support tickets. And if support for x86(32) lasted only 3 releases, is not looking good...
the suggestion might be to implement an external configuration for cross-building function. maybe just a single boolean value within profile (or conf) that overrides the result of `tools.cross_building`. as there are other similar cases (e.g. https://github.com/conan-io/conan/issues/10923) when conan's built-in logic is not suitable enough.
> the suggestion might be to implement an external configuration for cross-building function. maybe just a single boolean value within profile (or conf) that overrides the result of tools.cross_building. as there are other similar cases (e.g. https://github.com/conan-io/conan/issues/10923) when conan's built-in logic is not suitable enough.

It cannot be a conf to alter the ``cross_building`` result. We still want to have the ``cross_building()`` to return ``True`` when building x86_64 in M1 computer, but still we want something else to tell that we can indeed run the binary (Note that the logic used now in recipes is ``if not cross_building(): run...``

So the only possible reasonable alternative I see at this moment is:

- Add a ``can_run()`` method.
- This methods uses internally ``cross_building()`` returning ``False`` if cross_building
- Unless there is a ``conf`` that says ``can_run=True`` and bypass the ``cross_building`` result (only for the ``can_run()``)

This might be dummy implementation, but allows recipes to have clean logic and users to control manually the execution, without needing to implement any "smart" logic inside conan.
yes, I support that direction

Commit message: Add can_run

Signed-off-by: Uilian Ries <uilianries@gmail.com>

Patch to review:
diff --git a/conan/tools/build/cross_building.py b/conan/tools/build/cross_building.py
index 0e92ace864c..fe68b8403f0 100644
--- a/conan/tools/build/cross_building.py
+++ b/conan/tools/build/cross_building.py
@@ -28,3 +28,14 @@ def get_cross_building_settings(conanfile):
                 os_host, arch_host)
     else:
         return os_host, arch_host, os_host, arch_host
+
+
+def can_run(conanfile):
+    """
+    Validates if the current build platform can run a file which is not for same arch
+    See https://github.com/conan-io/conan/issues/11035
+    """
+    allowed = conanfile.conf.get("tools.build.cross_building:can_run", check_type=bool)
+    if not allowed:
+        return not cross_building(conanfile)
+    return True


Code review comments:
diff_hunk: @@ -28,3 +28,14 @@ def get_cross_building_settings(conanfile):
                 os_host, arch_host)
     else:
         return os_host, arch_host, os_host, arch_host
+
+
+def can_run(conanfile):
+    """
+    Validates if the current build platform can run a file which is not for same arch
+    See https://github.com/conan-io/conan/issues/11035
+    """
+    allowed = conanfile.conf.get("tools.build.cross_building:can_run", check_type=bool)
+    if not allowed:
path: conan/tools/build/cross_building.py
text: @user1:
I would take both ``True`` and ``False`` as definitive values, and return them.

And then, only fallback to ``not cross_building()`` for the case the ``can_run`` is ``None`` (not defined by user)

@author:
Yes, totally makes sense! I gonna update it! 

@author:
Done.