Repository: conan-io/conan

Issue:
Conan running on ARM device: detected arch issues
When running conan in an ARM device the `detected_architecture` is not detecting the arm, eventually, the main problem was that it was considering cross-building and adjusting a wrong triplet in Autotools causing the build to fail.






Discussion:

Resolving patch:
diff --git a/conans/client/build/autotools_environment.py b/conans/client/build/autotools_environment.py
--- a/conans/client/build/autotools_environment.py
+++ b/conans/client/build/autotools_environment.py
@@ -57,47 +57,63 @@ def __init__(self, conanfile, win_bash=False, include_rpath_flags=False):
         # Not declared by default
         self.fpic = None
 
+    def _get_triplet(self, the_arch, the_os):
+        """
+        machine-vendor-op_system, But vendor can be omitted in practice
+        """
+
+        # Calculate the arch
+        machine = {"x86": "i686" if the_os != "Linux" else "x86",
+                   "x86_64": "x86_64",
+                   "armv6": "arm",
+                   "armv7": "arm",
+                   "armv7s": "arm",
+                   "armv7k": "arm",
+                   "armv7hf": "arm",
+                   "armv8": "aarch64"}.get(the_arch, None)
+        if machine is None:
+            self._conanfile.output.warn("Unknown '%s' machine, Conan doesn't know how to "
+                                        "translate it to the GNU triplet, please report at "
+                                        " https://github.com/conan-io/conan/issues" % the_arch)
+            return "unknown"
+
+        # Calculate the OS
+        compiler = self._conanfile.settings.get_safe("compiler")
+        if compiler == "gcc":
+            windows_op = "w64-mingw32"
+        elif compiler == "Visual Studio":
+            windows_op = "windows-msvc"
+        else:
+            windows_op = "windows"
+
+        op_system = {"Windows": windows_op,
+                     "Linux": "linux-gnu",
+                     "Darwin": "apple-darwin",
+                     "Android": "linux-android",
+                     "Macos": "apple-darwin",
+                     "iOS": "apple-darwin",
+                     "watchOS": "apple-darwin",
+                     "tvOS": "apple-darwin"}.get(the_os, the_os.lower())
+
+        if the_os in ("Linux", "Android"):
+            if "arm" in the_arch and the_arch != "armv8":
+                op_system += "eabi"
+
+            if the_arch == "armv7hf" and the_os == "Linux":
+                op_system += "hf"
+
+        return "%s-%s" % (machine, op_system)
+
     def _get_host_build_target_flags(self, arch_detected, os_detected):
         """Based on google search for build/host triplets, it could need a lot
         and complex verification"""
+
         if not cross_building(self._conanfile.settings, os_detected, arch_detected):
             return False, False, False
 
-        arch_setting = self._conanfile.settings.get_safe("arch")
-        os_setting = self._conanfile.settings.get_safe("os")
-
-        if os_detected == "Windows" and os_setting != "Windows":
-            # Don't know what to do with these, even exists? its only for configure
-            return None, None, None
-
-        # Building FOR windows
-        if os_setting == "Windows":
-            build = "i686-w64-mingw32" if arch_detected == "x86" else "x86_64-w64-mingw32"
-            host = "i686-w64-mingw32" if arch_setting == "x86" else "x86_64-w64-mingw32"
-        else:  # Building for Linux or Android
-            build = "%s-%s" % (arch_detected, {"Linux": "linux-gnu",
-                                               "Darwin": "apple-darwin"}.get(os_detected,
-                                                                             os_detected.lower()))
-            if arch_setting == "x86":
-                host_arch = "i686"
-            elif arch_setting == "armv8":
-                host_arch = "aarch64"
-            else:
-                host_arch = "arm" if "arm" in arch_setting else arch_setting
-
-            host = "%s%s" % (host_arch, {"Linux": "-linux-gnu",
-                                         "Android": "-linux-android",
-                                         "Macos": "-apple-darwin",
-                                         "iOS": "-apple-darwin",
-                                         "watchOS": "-apple-darwin",
-                                         "tvOS": "-apple-darwin"}.get(os_setting, ""))
-
-            if os_setting in ("Linux", "Android"):
-                if "arm" in arch_setting and arch_setting != "armv8":
-                    host += "eabi"
-
-                if arch_setting == "armv7hf" and os_setting == "Linux":
-                    host += "hf"
+        build = self._get_triplet(arch_detected, os_detected)
+        host = self._get_triplet(self._conanfile.settings.get_safe("arch"),
+                                 self._conanfile.settings.get_safe("os"))
 
         return build, host, None
 
@@ -127,7 +143,9 @@ def configure(self, configure_dir=None, args=None, build=None, host=None, target
             configure_dir = "."
         auto_build, auto_host, auto_target = None, None, None
         if build is None or host is None or target is None:
-            flags = self._get_host_build_target_flags(detected_architecture(), platform.system())
+            arch_detected = detected_architecture() or platform.machine()
+            os_detected = platform.system()
+            flags = self._get_host_build_target_flags(arch_detected, os_detected)
             auto_build, auto_host, auto_target = flags
         triplet_args = []
 
@@ -154,8 +172,10 @@ def configure(self, configure_dir=None, args=None, build=None, host=None, target
         with environment_append(pkg_env):
             with environment_append(self.vars):
                 configure_dir = self._adjust_path(configure_dir)
-                self._conanfile.run('%s/configure %s %s'
-                                    % (configure_dir, args_to_string(args), " ".join(triplet_args)),
+                command = '%s/configure %s %s' % (configure_dir,
+                                                  args_to_string(args), " ".join(triplet_args))
+                self._conanfile.output.info("Calling:\n > %s" % command)
+                self._conanfile.run(command,
                                     win_bash=self._win_bash,
                                     subsystem=self.subsystem)
 
diff --git a/conans/client/tools/oss.py b/conans/client/tools/oss.py
--- a/conans/client/tools/oss.py
+++ b/conans/client/tools/oss.py
@@ -34,10 +34,16 @@ def cpu_count():
 
 def detected_architecture():
     # FIXME: Very weak check but not very common to run conan in other architectures
-    if "64" in platform.machine():
+    machine = platform.machine()
+    if "64" in machine:
         return "x86_64"
-    elif "86" in platform.machine():
+    elif "86" in machine:
         return "x86"
+    elif "armv8" in machine:
+        return "armv8"
+    elif "armv7" in machine:
+        return "armv7"
+
     return None
 
 # DETECT OS, VERSION AND DISTRIBUTIONS


Test patch:
diff --git a/conans/test/build_helpers/autotools_configure_test.py b/conans/test/build_helpers/autotools_configure_test.py
--- a/conans/test/build_helpers/autotools_configure_test.py
+++ b/conans/test/build_helpers/autotools_configure_test.py
@@ -387,9 +387,11 @@ def test_previous_env(self):
             self.assertEquals(be.vars["CPPFLAGS"], "MyCppFlag")
 
     def cross_build_flags_test(self):
-        def get_values(this_os, this_arch, setting_os, setting_arch):
+
+        def get_values(this_os, this_arch, setting_os, setting_arch, compiler=None):
             settings = MockSettings({"arch": setting_arch,
-                                     "os": setting_os})
+                                     "os": setting_os,
+                                     "compiler": compiler})
             conanfile = MockConanfile(settings)
             conanfile.settings = settings
             be = AutoToolsBuildEnvironment(conanfile)
@@ -415,7 +417,17 @@ def get_values(this_os, this_arch, setting_os, setting_arch):
 
         build, host, target = get_values("Linux", "x86_64", "Linux", "x86")
         self.assertEquals(build, "x86_64-linux-gnu")
-        self.assertEquals(host, "i686-linux-gnu")
+        self.assertEquals(host, "x86-linux-gnu")
+        self.assertFalse(target)
+
+        build, host, target = get_values("Linux", "x86_64", "Windows", "x86", compiler="gcc")
+        self.assertEquals(build, "x86_64-linux-gnu")
+        self.assertEquals(host, "i686-w64-mingw32")
+        self.assertFalse(target)
+
+        build, host, target = get_values("Linux", "x86_64", "Windows", "x86", compiler="Visual Studio")
+        self.assertEquals(build, "x86_64-linux-gnu")
+        self.assertEquals(host, "i686-windows-msvc")  # Not very common but exists sometimes
         self.assertFalse(target)
 
         build, host, target = get_values("Linux", "x86_64", "Linux", "armv7hf")
@@ -454,12 +466,12 @@ def get_values(this_os, this_arch, setting_os, setting_arch):
         self.assertEquals(build, "x86_64-linux-gnu")
         self.assertEquals(host, "arm-linux-androideabi")
 
-        build, host, target = get_values("Linux", "x86_64", "Windows", "x86")
-        self.assertEquals(build, "x86_64-w64-mingw32")
+        build, host, target = get_values("Linux", "x86_64", "Windows", "x86", compiler="gcc")
+        self.assertEquals(build, "x86_64-linux-gnu")
         self.assertEquals(host, "i686-w64-mingw32")
 
-        build, host, target = get_values("Linux", "x86_64", "Windows", "x86_64")
-        self.assertEquals(build, "x86_64-w64-mingw32")
+        build, host, target = get_values("Linux", "x86_64", "Windows", "x86_64", compiler="gcc")
+        self.assertEquals(build, "x86_64-linux-gnu")
         self.assertEquals(host, "x86_64-w64-mingw32")
 
         build, host, target = get_values("Windows", "x86_64", "Windows", "x86_64")
@@ -472,19 +484,14 @@ def get_values(this_os, this_arch, setting_os, setting_arch):
         self.assertFalse(host)
         self.assertFalse(target)
 
-        build, host, target = get_values("Windows", "x86_64", "Windows", "x86")
+        build, host, target = get_values("Windows", "x86_64", "Windows", "x86", compiler="gcc")
         self.assertEquals(build, "x86_64-w64-mingw32")
         self.assertEquals(host, "i686-w64-mingw32")
         self.assertFalse(target)
 
-        build, host, target = get_values("Windows", "x86_64", "Linux", "armv7hf")
-        self.assertFalse(build)
-        self.assertFalse(host)
-        self.assertFalse(target)
-
-        build, host, target = get_values("Windows", "x86_64", "Linux", "x86_64")
-        self.assertFalse(build)
-        self.assertFalse(host)
+        build, host, target = get_values("Windows", "x86_64", "Linux", "armv7hf", compiler="gcc")
+        self.assertEquals(build, "x86_64-w64-mingw32")
+        self.assertEquals(host, "arm-linux-gnueabihf")
         self.assertFalse(target)
 
         build, host, target = get_values("Darwin", "x86_64", "Android", "armv7hf")
@@ -504,9 +511,9 @@ def get_values(this_os, this_arch, setting_os, setting_arch):
         self.assertEquals(build, "x86_64-apple-darwin")
         self.assertEquals(host, "arm-apple-darwin")
 
-        build, host, target = get_values("Darwin", "x86_64", "tvOS", "arm64")
+        build, host, target = get_values("Darwin", "x86_64", "tvOS", "armv8")
         self.assertEquals(build, "x86_64-apple-darwin")
-        self.assertEquals(host, "arm-apple-darwin")
+        self.assertEquals(host, "aarch64-apple-darwin")
 
     def test_pkg_config_paths(self):
         if platform.system() == "Windows":
@@ -557,10 +564,9 @@ def cross_build_command_test(self):
         ab.configure(target="i686-apple-darwin")
         self.assertEquals(runner.command_called, "./configure  --target=i686-apple-darwin")
 
-
     def test_make_targets(self):
         runner = RunnerMock()
-        conanfile = MockConanfile(MockSettings({}),None,runner)
+        conanfile = MockConanfile(MockSettings({}), None, runner)
         
         ab = AutoToolsBuildEnvironment(conanfile)
         ab.configure()
diff --git a/conans/test/utils/conanfile.py b/conans/test/utils/conanfile.py
--- a/conans/test/utils/conanfile.py
+++ b/conans/test/utils/conanfile.py
@@ -1,3 +1,5 @@
+from conans.test.utils.tools import TestBufferConanOutput
+
 
 class MockSettings(object):
 
@@ -33,6 +35,8 @@ def __init__(self, settings, options=None, runner=None):
         self.runner = runner
         self.options = options or MockOptions({})
         self.generators = []
+        self.output = TestBufferConanOutput()
+
         self.should_configure = True
         self.should_build = True
         self.should_install = True