1 commentaires

 
GN⁺ 2023-12-04
Avis sur Hacker News
  • Quand on regarde l’histoire des générations ARM utilisées par le Raspberry Pi, on est surpris de voir à quel point la puce était ancienne
    Même en 2014, quand le Raspberry Pi B+ est sorti, le cœur ARM1176 utilisé datait de 2003, il avait donc déjà 11 ans
    Il n’est donc pas étonnant que, lorsqu’on compile sur une autre plateforme comme un Raspberry Pi plus récent, il faille éventuellement préciser les flags d’architecture pour produire du code compatible
    En revanche, si l’architecture correcte n’est pas sélectionnée par défaut même lorsqu’on compile sur le Raspberry Pi B+ lui-même, cela ressemble à une erreur de configuration dans les valeurs par défaut de la distribution

    • Dans mon souvenir, le Pi original utilisait des puces restantes destinées à des boîtiers TV
      Pour ce genre de produit, pour des raisons de coût, on met rarement plus de puissance de calcul que nécessaire
    • À la base, c’était un produit conçu comme un ordinateur bon marché
    • En réalité, la compilation n’a pas été faite sur un B+
      L’article dit : « j’ai pris un binaire depuis l’hôte de build, un Pi 4B bien plus rapide, et j’ai essayé de l’exécuter sur cette vieille machine, ce qui a provoqué une illegal instruction »
      C’est un peu comme essayer d’exécuter sur un vieux PC avec Windows XP un .EXE compilé avec un MSVC récent sous Windows 11
      Il est même assez probable que toute la distribution Pi qui tourne sur le Pi 4B ne fonctionne pas sur le B+, et que le noyau ait été compilé de la même manière
  • Il me semble que le billet ou l’article ne le traite pas clairement, mais est-ce que ce n’est pas un bug ?
    En cherchant dans les bugs LLVM, j’ai trouvé une entrée qui ressemblait beaucoup au même problème, mais elle datait de 2012 et était fermée. À lire les derniers commentaires, on pouvait avoir l’impression que ce n’était peut-être pas vraiment corrigé, mais je n’ai fait que survoler, donc j’ai peut-être mal compris
    https://github.com/llvm/llvm-project/issues/13989
    En relisant, l’article dit à la fin que si l’on passe explicitement la cible, on obtient un programme qui fonctionne. Dans ce cas, ça ressemble à une sorte de bug de configuration ; sous Unix, j’aurais tendance à penser que la cible par défaut est le processeur courant, mais je n’en suis pas sûr
    Le bug que j’ai lié semblait être un problème où du code incorrect était généré même lorsque la cible était correctement définie ; heureusement, cela ne semble plus être le cas aujourd’hui

    • Oui. Le bug lié concernait un compilateur à qui l’on demandait de cibler armv6, mais qui émettait quand même des instructions armv7
      Le problème de Rachel a été résolu en indiquant au compilateur de cibler armv6 ; ce bug a donc déjà été corrigé et semble distinct de ce problème
    • C’est évidemment un bug, mais l’auteur semble avoir préféré écrire un billet de blog au titre un peu accrocheur et conclure par « c’est trop bizarre » plutôt que de le signaler
  • ClickHouse, la base de données sur laquelle je travaille, fait pas mal d’efforts pour rester compatible avec du matériel très ancien
    Le binaire ARM standard exige Armv8.2, datant de 2016, et peut être utilisé à partir du Raspberry Pi 2. Le binaire x86 tourne sur du matériel d’environ 2010 disposant de SSE4.2 et des instructions pclmul* pour le CRC rapide
    Nous construisons aussi des binaires pour les systèmes n’ayant que Armv8.0 et SSE2, mais ils ne sont pas testés en CI. Le script d’installation rapide télécharge et décompresse le binaire adapté à l’hôte cible
    Je trouve qu’il est globalement difficile de trouver le bon équilibre entre la rétrocompatibilité et l’exploitation des fonctionnalités CPU des générations AArch64 récentes
    https://en.wikipedia.org/wiki/AArch64
    Il y a eu un nombre étonnamment élevé d’institutions aux budgets serrés — par exemple des universités de pays émergents — ou d’utilisateurs amateurs qui n’ont pas les moyens de mettre leur matériel à niveau
    Techniquement, ce qui a été assez pénible, c’est que les flags CPU de /proc/cpuinfo ne correspondent pas toujours aux flags -march= passés au compilateur. Par exemple, ils apparaissent différemment, comme "lrcpc" et "rcpc"
    Pour que cela fonctionne correctement, il faut en pratique maintenir deux ensembles de flags

    • Dans ce genre de cas, je pense qu’il est préférable pour tout le monde de fournir plusieurs builds, afin que les clients puissent choisir celui qui correspond le mieux à leur architecture
  • Le problème semble très probablement être que, dans le paquet clang-13 actuel de bookworm, la cible configurée a changé
    Plus précisément, avec bullseye et clang-11, la cible par défaut est armv6k-unknown-linux-gnueabihf, tandis qu’avec bookworm et clang-13, c’est arm-unknown-linux-gnueabihf
    Ou alors il se peut que la valeur par défaut de cette configuration de build ait changé côté LLVM

  • Il ne s’agit probablement pas d’un changement intentionnel
    Comme des commentaires voisins l’ont mentionné à propos de /etc/env.d/gcc, il est assez possible que cela vienne de la façon dont les informations sont lues depuis l’environnement
    Le triplet par défaut devrait être quelque chose comme arm-unknown-linux si clang ne trouve pas, ou ne reçoit pas, d’informations plus précises, mais le mécanisme qui fournit une cible plus spécifique semble cassé
    Cela peut vouloir dire qu’il n’y a pas de buildbot ARMv6, ou bien qu’il y en a un mais que, là-bas, la configuration implicite fonctionne encore correctement
    LLVM est un très bon cross-compilateur. On peut compiler de n’importe quelle cible vers n’importe quelle autre sans gros problème
    Clang est un peu moins séduisant sur ce point. S’il a été compilé avec la prise en charge de la cible et qu’on peut lui indiquer correctement pour quelle cible compiler, il fera probablement ce qu’il faut. Dans cet article aussi, la supposition était fausse, mais une fois des informations supplémentaires fournies, il a fonctionné correctement
    La situation des bibliothèques d’exécution est encore pire. Même si l’on compile pour une cible comme armv4, il faut trouver la libc correspondante, entre autres, et il peut être nécessaire d’indiquer au compilateur l’emplacement de ces bibliothèques et en-têtes ; sur ce point, les détails restent encore flous

    • La plupart des distributions et des compilateurs ont, de fait, abandonné la prise en charge d’ARMv6 il y a quelques années
      J’ai rencontré un problème similaire en compilant des binaires pour un ancien NAS Synology
    • Pourquoi Clang devrait-il lire des informations depuis /etc/env.d/gcc ?
  • clang/clang++ lisent les flags de cible et les profils dans /etc/env.d/gcc, et c’est au système d’exploitation de les maintenir correctement
    Sur ce système d’exploitation, cette gestion ne semble pas avoir été faite correctement
    Mon SBC Gentoo ARM basé sur une architecture armv4 plus ancienne continue de fonctionner correctement, même avec les dernières mises à jour de gcc/clang
    grep CTARGET /etc/env.d/gcc -r
    /etc/env.d/gcc/armv4tl-softfloat-linux-gnueabi-11.3.0:CTARGET="armv4tl-softfloat-linux-gnueabi"

    • /etc/env.d est un répertoire propre à Gentoo qui définit les variables d’environnement par défaut des sessions utilisateur
      Clang n’a pas de fonctionnalité qui lit ce répertoire, il ne faut donc pas supposer qu’il existe aussi sur d’autres distributions
      C’est simplement que la configuration des compilateurs de Gentoo lit la variable d’environnement CTARGET pour choisir la cible, et que Gentoo utilise /etc/env.d pour définir cette valeur
  • L’article ne précise pas s’il s’agit de Debian ou de Raspbian, ni, si c’est Debian, du port armel ou du port armhf
    Sans cette information, discuter de l’ensemble d’instructions pour lequel LLVM compile n’a pas beaucoup de sens. Cela dépend de la configuration de cible native de LLVM
    Pour référence, llvm-toolchaim-snapshot de Debian prend toujours en charge armel, qui utilise encore ARMv5T comme base. En revanche, il y a actuellement un bug distinct dans la bibliothèque OpenMP de LLVM, ce qui empêche la compilation de réussir

    • Ce qui est étrange, c’est que le binaire Clang lui-même est compilé avec un jeu d’instructions compatible avec le Pi B+, mais qu’il ne cible pas, lui, un jeu d’instructions compatible avec le Pi B+
      C’est vraiment bizarre. Comme il n’est pas question de l’utiliser comme cross-compilateur, en théorie, l’hôte et la cible devraient être identiques
      L’image est probablement Raspbian. Je ne vois pas de raison de ne pas le supposer
  • La sortie de la commande dpkg-architecture et le contenu du fichier /etc/os-release seraient utiles
    Sans cela, il est difficile de faire un commentaire utile

  • Le titre est malheureusement sensationnaliste
    Il s’agit d’un changement de cible par défaut, et clang peut toujours compiler des binaires pour le Pi B+
    Il suffit de préciser explicitement l’architecture. Il vaudrait donc mieux modifier légèrement le titre pour faire apparaître plus clairement qu’il s’agit d’un changement de configuration par défaut

    • Si, même en compilant sur la machine cible elle-même, on n’arrive pas à produire un binaire pour cette machine cible, cela ne me paraît pas si sensationnaliste que ça
  • Je trouve intéressant que, pour déboguer pourquoi un programme ne s’exécute pas sur ARM, on puisse apparemment procéder à peu près de cette manière
    J’ai un build Unity Linux qui ne s’exécute pas dans un conteneur ; même en passant le flag amd64 à l’exécution de Docker, Unity mono tente d’utiliser un appel système indisponible
    J’ai trouvé un contournement et je n’ai donc pas encore débogué. J’ai activé le mode développement et modifié les paramètres de build pour ne plus utiliser mono
    Un jour, il faudra que je m’y replonge pour en apprendre davantage