Repository: conan-io/conan

Issue:
AutoToolsBuildEnv needs to be more flexible with "host"
To help us debug your issue please explain:

- [ ] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [ ] I've specified the Conan version, operating system version and any tool that can be relevant.
- [ ] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.

I found a couple problems with the `get_gnu_triplet()` method of `oss.py`:
```py
# Calculate the arch
machine = {"x86": "i686" if os != "Linux" else "x86",
           "x86_64": "x86_64",
           "armv6": "arm",
           "armv7": "arm",
           "armv7s": "arm",
           "armv7k": "arm",
           "armv7hf": "arm",
           "armv8": "aarch64"}.get(arch, None)
if machine is None:
    raise ConanException("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" % arch)
```

First, the exception being raised is swallowed by `AutoBuildToolsBuildEnv._get_host_build_target_flags():

```
try:
    build = get_gnu_triplet(os_detected, arch_detected, self._compiler)
except ConanException:
    build = None
try:
    host = get_gnu_triplet(self._os, self._arch, self._compiler)
except ConanException:
    host = None
```

A warning would be great, instead of just silently building apps very badly.

Second, any way to make that a little more flexible instead of hardcoding architectures in there? I ran into this after adding `armv5te` to my `settings.yml` file and now I have two options: change all of my recipes (and fork open source recipes) to check for `arch==armv5te` and provide the `host` parameter explicitly or wait for this bug to get fixed. Neither solution is good at all.

Maybe a replacement could look something more like this:

```
# Calculate the arch
if 'x86' == arch:
    machine = "i686" if os != "Linux" else "x86"
elif arch == 'armv8':
    machine = 'aarch64'
elif arch.startswith('arm'):
    machine = 'arm'
else:
    machine = arch
```

This should work reasonably well so long as you stay on top of adding new ARM architectures in the future.



Discussion:
Glad you guys approved it - that's great news. I wonder if you might be able to squeeze something simpler in to an earlier release though. I actually jumped online just now to modify my original suggestion, but there's no reason an environment variable couldn't be added to the current implementation, like so:

```py
# Calculate the arch
best_guess_at_machine = {"x86": "i686" if os != "Linux" else "x86",
           "x86_64": "x86_64",
           "armv6": "arm",
           "armv7": "arm",
           "armv7s": "arm",
           "armv7k": "arm",
           "armv7hf": "arm",
           "armv8": "aarch64"}.get(arch, None)
machine = os.environ.get('CONAN_AUTOTOOLS_HOST_MACHINE', best_guess_at_machine)
if machine is None:
    raise ConanException("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" % arch)
```

This should be a non-breaking change that won't affect a soul, unless they know about the new, special environment variable. It will allow me to continue the very exciting work I was doing yesterday, which was us starting to use Conan for our _current_ platform (ARM9/armv5te), instead of only our _future_ platform (armv7hf).
Your suggestion of the env var doesn't work. This `get_gnu_triplet` is used both for the `host`(targeting machine) and the `build` (current machine) so it can change if we are cross building, and the env var won't be valid anymore.
I'm opening a PR in some minutes adding more flexible detections as you suggested first. 

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
@@ -84,11 +84,13 @@ def _get_host_build_target_flags(self):
 
         try:
             build = get_gnu_triplet(os_detected, arch_detected, self._compiler)
-        except ConanException:
+        except ConanException as exc:
+            self._conanfile.output.warn(str(exc))
             build = None
         try:
             host = get_gnu_triplet(self._os, self._arch, self._compiler)
-        except ConanException:
+        except ConanException as exc:
+            self._conanfile.output.warn(str(exc))
             host = None
         return build, host, None
 
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
@@ -327,28 +327,43 @@ def get_cross_building_settings(settings, self_os=None, self_arch=None):
     return build_os, build_arch, host_os, host_arch
 
 
-def get_gnu_triplet(os, arch, compiler=None):
+def get_gnu_triplet(os_, arch, compiler=None):
     """
     Returns string with <machine>-<vendor>-<op_system> triplet (<vendor> can be omitted in practice)
 
-    :param os: os to be used to create the triplet
+    :param os_: os to be used to create the triplet
     :param arch: arch to be used to create the triplet
     :param compiler: compiler used to create the triplet (only needed fo windows)
     """
 
-    if os == "Windows" and compiler is None:
+    if os_ == "Windows" and compiler is None:
         raise ConanException("'compiler' parameter for 'get_gnu_triplet()' is not specified and "
                              "needed for os=Windows")
 
     # Calculate the arch
-    machine = {"x86": "i686" if os != "Linux" else "x86",
+    machine = {"x86": "i686" if os_ != "Linux" else "x86",
                "x86_64": "x86_64",
-               "armv6": "arm",
-               "armv7": "arm",
-               "armv7s": "arm",
-               "armv7k": "arm",
-               "armv7hf": "arm",
                "armv8": "aarch64"}.get(arch, None)
+
+    if not machine:
+        # https://wiki.debian.org/Multiarch/Tuples
+        if "arm" in arch:
+            machine = "arm"
+        elif "ppc64le" in arch:
+            machine = "powerpc64le"
+        elif "ppc64" in arch:
+            machine = "powerpc64"
+        elif "powerpc" in arch:
+            machine = "powerpc"
+        elif "mips64" in arch:
+            machine = "mips64"
+        elif "mips" in arch:
+            machine = "mips"
+        elif "sparcv9" in arch:
+            machine = "sparc64"
+        elif "sparc" in arch:
+            machine = "sparc"
+
     if machine is None:
         raise ConanException("Unknown '%s' machine, Conan doesn't know how to "
                              "translate it to the GNU triplet, please report at "
@@ -369,13 +384,13 @@ def get_gnu_triplet(os, arch, compiler=None):
                  "Macos": "apple-darwin",
                  "iOS": "apple-darwin",
                  "watchOS": "apple-darwin",
-                 "tvOS": "apple-darwin"}.get(os, os.lower())
+                 "tvOS": "apple-darwin"}.get(os_, os_.lower())
 
-    if os in ("Linux", "Android"):
+    if os_ in ("Linux", "Android"):
         if "arm" in arch and arch != "armv8":
             op_system += "eabi"
 
-        if arch == "armv7hf" and os == "Linux":
+        if arch == "armv7hf" and os_ == "Linux":
             op_system += "hf"
 
     return "%s-%s" % (machine, op_system)


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
@@ -47,6 +47,16 @@ def partial_build_test(self):
         be.make()
         self.assertIsNone(conan_file.command)
 
+    def warn_when_no_triplet_test(self):
+        conan_file = ConanFileMock()
+        deps_cpp_info = namedtuple("Deps", "libs, include_paths, lib_paths, defines, cflags, "
+                                   "cppflags, sharedlinkflags, exelinkflags, sysroot")
+        conan_file.deps_cpp_info = deps_cpp_info([], [], [], [], [], [], [], [], "")
+        conan_file.settings = MockSettings({"arch": "UNKNOWN_ARCH", "os": "Linux"})
+        AutoToolsBuildEnvironment(conan_file)
+        self.assertIn("Unknown 'UNKNOWN_ARCH' machine, Conan doesn't know "
+                      "how to translate it to the GNU triplet", conan_file.output)
+
     def test_cppstd(self):
         options = MockOptions({})
         # Valid one for GCC
diff --git a/conans/test/util/tools_test.py b/conans/test/util/tools_test.py
--- a/conans/test/util/tools_test.py
+++ b/conans/test/util/tools_test.py
@@ -982,6 +982,26 @@ def get_values(this_os, this_arch, setting_os, setting_arch, compiler=None):
             host = tools.get_gnu_triplet(setting_os, setting_arch, compiler)
             return build, host
 
+        build, host = get_values("Linux", "armv6", "Linux", "armv6")
+        self.assertEquals(build, "arm-linux-gnueabi")
+        self.assertEquals(host, "arm-linux-gnueabi")
+
+        build, host = get_values("Linux", "sparc", "Linux", "sparcv9")
+        self.assertEquals(build, "sparc-linux-gnu")
+        self.assertEquals(host, "sparc64-linux-gnu")
+
+        build, host = get_values("Linux", "mips", "Linux", "mips64")
+        self.assertEquals(build, "mips-linux-gnu")
+        self.assertEquals(host, "mips64-linux-gnu")
+
+        build, host = get_values("Linux", "ppc64le", "Linux", "ppc64")
+        self.assertEquals(build, "powerpc64le-linux-gnu")
+        self.assertEquals(host, "powerpc64-linux-gnu")
+
+        build, host = get_values("Linux", "armv5te", "Linux", "arm_whatever")
+        self.assertEquals(build, "arm-linux-gnueabi")
+        self.assertEquals(host, "arm-linux-gnueabi")
+
         build, host = get_values("Linux", "x86_64", "Linux", "armv7hf")
         self.assertEquals(build, "x86_64-linux-gnu")
         self.assertEquals(host, "arm-linux-gnueabihf")
@@ -1074,18 +1094,18 @@ def get_values(this_os, this_arch, setting_os, setting_arch, compiler=None):
         self.assertEquals(build, "x86_64-apple-darwin")
         self.assertEquals(host, "aarch64-apple-darwin")
 
-        for os in ["Windows", "Linux"]:
+        for _os in ["Windows", "Linux"]:
             for arch in ["x86_64", "x86"]:
-                triplet = tools.get_gnu_triplet(os, arch, "gcc")
+                triplet = tools.get_gnu_triplet(_os, arch, "gcc")
 
                 output = ""
                 if arch == "x86_64":
                     output += "x86_64"
                 else:
-                    output += "i686" if os != "Linux" else "x86"
+                    output += "i686" if _os != "Linux" else "x86"
 
                 output += "-"
-                if os == "Windows":
+                if _os == "Windows":
                     output += "w64-mingw32"
                 else:
                     output += "linux-gnu"