Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.

Forum Casio - Vos tutoriels et astuces


Index du Forum » Vos tutoriels et astuces » [Tutoriel] Compiler sous Linux avec un cross-compilateur gcc
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

[Tutoriel] Compiler sous Linux avec un cross-compilateur gcc

Posté le 31/05/2014 17:02

Qui dit Linux implique son puissant compilateur gcc, et de nombreux outils permettant de développer plus librement, plus efficacement. Dans ce tutoriel, je vous propose de compiler GCC et sa suite pour développer des programmes pour les calculatrices Casio.

Pour pouvoir bien suivre, vous devez savoir vous servir d'un terminal et des commandes de base. Ouvrez-en un pour commencer, et essayez de ne pas le fermer par erreur, ça pourrait gêner. Accrochez-vous bien !

Arch Linux. Les paquets sh-elf-binutils-casio et sh-elf-gcc-casio sont dispo pour vous. Vous pouvez installer ça et passer directement à l'étape 7. En cas de pépin, me pinger ainsi que Dark Storm.

Windows. Vous pouvez suivre ce tutoriel sous Windows 10 en utilisant WSL, un composant de Windows 10 qui vous permet de lancer des programmes Linux. KikooDX a testé pour vous déjà.

Sommaire

1. Installation des dépendances
2. Considérations sur l'architecture cible
3. Préparation de l'environnement de compilation

4. Compilation de binutils
5. Compilation de gcc et de libgcc
6. Compilation de newlib (experts)

7. Choisir un environnement de développement



1. Installation des dépendances

Dans ce tutoriel, on va compiler plusieurs programmes : d'abord binutils, une suite d'outils qui gère les programmes en assembleur, l'édition des liens, les fichiers exécutables et tout ce qui n'est pas du C ; ensuite le compilateur gcc qui compile le code C en assembleur ; et si vous êtes aventureux, peut-être même une version expérimentale de newlib, une bibliothèque standard qui fournit les fonctions fondamentales du C.

Le gcc qui compile vers la calculatrice produit du code en assembleur SuperH, ce n'est pas celui de votre système qui compile probablement en assembleur x86_64. Il ne s'appelle pas gcc mais quelque chose de plus long comme sh-elf-gcc. Vous devez faire très attention à ne pas confondre les deux !

À l'heure où j'écris cette version du tutoriel (12 Septembre 2019), les dernières versions disponibles sont binutils-2.32 et gcc-9.2.0. N'hésitez pas à prendre des versions plus récentes, tant que vous les prenez proches dans le temps. Attention, la dernière version n'est pas toujours en bas de la liste ! La communauté d'OSDev (qui compile gcc à tour de bras) a un tableau où elle indique les combinaisons qui ont marché. Si vous en réusissez une nouvelle, allez leur dire.

La manipulation peut échouer à cause d'erreurs de compilation imprévisibles et que vous ne saurez souvent pas résoudre ; en général soit il vous manque des dépendances soit vous êtes tombé sur des versions qui ne veulent pas marcher chez vous, vous pouvez alors essayer avec d'autres.

Téléchargement de binutils
Téléchargement de gcc
Compilations réussies par la communauté d'OSDev

Bien sûr gcc est un logiciel complexe qui s'appuie sur différentes bibliothèques pour faire son boulot : il y a donc un certain nombre de dépendances à installer. Les noms de paquets ci-dessous sont pour Debian et ses dérivés (Ubuntu, Mint, ElementaryOS...), à utiliser avec apt. Si vous avez une autre distribution vous saurez vous débrouiller.

  mpfr     (libmpfr-dev)  : flottants à précision variable
  mpc      (libmpc-dev)   : complexes à précision variable
  gmp      (libgmp-dev)   : arithmétique à multi-précision
  png      (libpng-dev)   : manipulation d'images
  ppl      (libppl-dev)   : polyèdres Parma (optimisation magique)
  flex     (flex)         : générateur d'analyseurs lexicaux
  g++      (g++)          : compilateur C++
  git      (git)          : gestionnaire de versions
  texinfo  (texinfo)      : générateur de documentation formatée


2. Considérations sur l'architecture cible

Les processeurs des calculatrices Casio font partie de la lignée des SuperH, et vous savez peut-être qu'il y en a deux versions en circulation : les vieilles machines d'avant 2012 utilisent des processeurs SuperH-3, et les autres des SuperH-4A. Un certain nombre de membres anciens et respectés utilisent toujours des SH3, donc il est important de pouvoir créer des programmes pour les deux.

Dans ce tutoriel, on va compiler un GCC qu'on appellera sh-elf-gcc qui sera capable de cibler deux architectures : SuperH-3 et SuperH-4 sans FPU.

La méthode proposée dans les anciennes versions du tutoriel ne permettait que de cibler une seule architecture à la fois. Les compilateurs s'appelaient alors sh3eb-elf-gcc et sh4eb-nofpu-elf-gcc. Vous pouvez toujours utiliser le premier, mais cela n'a plus vraiment d'intérêt puis qu'on peut avoir les deux ensemble. Le deuxième n'est pas véritablement sans FPU et pose des problèmes sérieux : ne l'utilisez pas.

Passons aux choses sérieuses maintenant !



3. Préparation de l'environnement de compilation

Tout ce qu'on va créer aujourd'hui ira dans un dossier de votre ordinateur. Le compilateur sera installé là, et les bibliothèques pour programmer sur la calculatrice seront là aussi. Je vous conseille vivement de choisir un dossier dans votre répertoire personnel. Pour moi, ce sera dans $HOME/opt avec le numéro de version car j'en compile souvent. Vous pouvez choisir ce que vous voulez, par exemple $HOME/Documents/Casio/gcc (ça ne changera rien à la suite).

% export PREFIX="$HOME/opt/sh-elf-2.32-9.2.0"
% mkdir -p $PREFIX
% cd $PREFIX

Si vous fermez votre terminal au milieu du tutoriel, et en ouvrez un autre ensuite, retapez ces trois commandes, retapez le export PATH plus bas, puis reprenez le tutoriel là où vous étiez arrêté.

Extrayez le contenu des archives que vous avez téléchargées dans ce dossier, et créez deux répertoires build-binutils et build-gcc. Si par exemple les archives sont au format .tar.xz dans le dossier que vous venez de choisir, vous pouvez les extraire avec tar. Pour créer les sous-dossiers, utilisez mkdir comme d'habitude.

% tar -xJf binutils-2.32.tar.xz
% tar -xJf gcc-9.2.0.tar.xz
% mkdir build-binutils build-gcc

Après cela, votre dossier doit ressembler ceci quand vous exécutez la commande "tree -L 1" :

% tree -L 1
.
├── binutils-2.32
├── binutils-2.32.tar.xz
├── build-binutils
├── build-gcc
├── gcc-9.2.0
└── gcc-9.2.0.tar.xz

Le compilateur et tous les outils de sa suite vont arriver dans un sous-dossier bin. Pour pouvoir les utiliser sur la ligne de commande, vous devez les ajouter au PATH. (Le PATH est l'ensemble des dossiers dans lesquels le terminal cherche les commandes.) Utilisez la commande ci-dessous pour modifier temporairement le PATH.

% export PATH="$PATH:$PREFIX/bin"

La modification sera perdue quand le terminal sera fermé. Pour que ce changement soit permanent, il faut ajouter la commande à la fin du fichier $HOME/.profile, ou à $HOME/.bashrc si vous utilisez WSL sous Windows 10. La commande suivante le fait pour vous.

% echo "export PATH=\"\$PATH:$PREFIX/bin\"" >> $HOME/.profile



4. Compilation de binutils

La compilation de binutils est très classique : d'abord on configure nos options avec ./configure, ensuite on compile avec make, puis on installe avec make install. C'est comme ça pour un nombre incalculable de logiciels.

Notez (ça marche jusqu'à la fin du tutoriel) que make possède une option -j pour compiler avec plusieurs processus en même temps, pour aller plus vite. Utilisez toujours -j suivi d'un nombre, typiquement votre nombre de coeurs. Pour moi, -j4.

Choisir le bon nombre de threads pour -j (pour ceux que ça intéresse)

% cd build-binutils
% ../binutils-2.32/configure --prefix=$PREFIX --target=sh3eb-elf --with-multilib-list=m3,m4-nofpu --disable-nls --program-prefix=sh-elf-

Ici, l'option --prefix indique où on va installer le compilateur. --target avec --with-multilib-list permet de spécifier à la fois SuperH-3 et SuperH-4 sans FPU comme cibles. Enfin, --program-prefix permet de donner un nom personnalisé au compilateur, ici sh-elf-gcc.

(experts) La liste complète des options de compilation est donnée par configure --help, en voici quelques-unes suscesptibles de vous intéresser :

--disable-nls pour forcer les diagnostics en anglais
--disable-werror pour supprimer l'option -Werror
--enable-libssp pour compiler libssp (protection de pile)
--enable-lto pour activer le support des optimisations au linkage (puissant)

Une fois que tout est configuré, il n'y a plus qu'à compiler et à installer. Normalement ça va assez vite, comptez quelques minutes. Si vous avez une erreur de compilation, vérifiez les dépendances et les en-têtes possiblement manquants. Sinon, changez de version de binutils et éventuellement de gcc.

% make -j4
% make install

Les exécutables de binutils ont dû apparaître dans $PREFIX/bin. Essayez de taper $PREFIX/bin/sh-elf-as --version pour vérifier que ça marche !



5. Compilation de gcc et de libgcc

Maintenant, on recommence pareil, mais cette fois on compile un morceau beaucoup plus gros : gcc. L'option --enable-languages vous permet de choisir les langages que vous voulez pouvoir compiler, notamment C, C++, Ada, Go ou Fortran. Attention au temps de compilation qui va vite monter !

% cd $PREFIX/build-gcc
% ../gcc-9.2.0/configure --prefix=$PREFIX --target=sh3eb-elf --with-multilib-list=m3,m4-nofpu --enable-languages=c,c++ --without-headers --with-newlib --disable-nls --program-prefix=sh-elf-

(experts) Les options --disable-werror, --enable-libssp et --enable-lto doivent être passées ici aussi si vous les avez passées à binutils.

Et c'est parti pour compiler ! Comptez entre 10 et 30 minutes (pour c,c++) selon la puissance de votre ordinateur, 5 à 6 heures sur un vieux Raspberry Pi !

% make -j4 all-gcc
% make install-gcc

GCC fournit également une bibliothèque appelée libgcc qui contient des fonctions indispensables. Tout le code compilé avec gcc doit être linké avec libgcc. On compile donc cette bibliothèque, ce qui se passe très vite et sans la moindre difficulté.

% make -j4 all-target-libgcc
% make install-target-libgcc

Vous pouvez désormais taper sh-elf-gcc -m3 et sh-elf-gcc -m4-nofpu et vous devez avoir juste une erreur fatale indiquant que vous n'avez pas donné de fichier à compiler. Si on prend une autre cible, par exemple avec sh-elf-gcc -m4, GCC doit se plaindre que -m4 n'est pas supporté parce que ne l'a pas demandé.

Si tout s'est bien passé, alors vous avez terminé ce tutoriel ! La partie 7 vous guidera vers un SDK pour créer vos add-ins


6. Compilation de newlib (experts)

Memallox a construit un port de newlib (en anglais) pour supporter une libc avec gcc. Pour l'instant c'est au stade expérimental ; vous pouvez sauter cette section jusqu'à ce que ce soit bien étudié. Si vous savez de quoi vous parlez, vous pouvez le compiler maintenant.

Clônez le dépôt de Memallox dans le répertoire de travail ou créez un lien symbolique. Ensuite, configurez de la même façon :

% git clone https://git.planet-casio.com/Memallox/libc
% mkdir build-newlib
% cd build-newlib
% ../libc/configure --prefix=$PREFIX --target=sh3eb-elf --enable-target-optspace
% make -j4
% make install

Là aussi les options de configuration --enable-libssp et --enable-lto peuvent vous intéresser. Ensuite, recompilez gcc (avec les mêmes options, en particulier --without-headers et --with-newlib) :

% cd build-gcc
% ../gcc-9.2.0/configure --prefix=$PREFIX --target=sh3eb-elf --with-multilib-list=m3,m4-nofpu --enable-languages=c,c++ --without-headers --with-newlib --disable-nls --program-prefix=sh-elf-
% make -j4 all-gcc
% make install-gcc
% make -j4 all-target-libgcc
% make install-target-libgcc

Je ne suis pas sûr qu'il soit nécessaire de recompiler libgcc mais ça ne coûte rien !



7. Choisir un environnement de développement

Maintenant que vous avez le compilateur, vous pouvez écrire des add-ins ! Enfin... presque. Il vous manque encore de quoi écrire à l'écran, récupérer les touches pressées sur le clavier, et convertir vos images.

Pour ça, vous avez (à l'heure où j'écris cette version du tutoriel), deux choix : utiliser fxlib porté pour GCC, ou bien utiliser le fxSDK.

Jusqu'ici le tutoriel pour développer des add-ins avec fxlib était sur cette page, mais je vais le déplacer dans un topic à part. Je l'ai temporairement laissé dans le spoiler ci-dessous.

Pour le fxSDK, la page du projet détaille son installation et son utilisation. C'est plus facile que GCC donc vous avez déjà quasiment tout fait !

Ancien tutoriel d'utilisation de fxlib (commence à être très vieux)
Cliquez pour recouvrir

Installation du g1a-wrapper

Votre binutils produit des fichiers au format ELF. Il y a encore un peu de travail à faire avant d'obtenir un g1a. Le g1a-wrapper est un petit programme qui va nous y aider. Clônez-le depuis un dépôt git et installez-le dans le dossier des binaires du compilateur.

% cd $PREFIX
% git clone "https://Lephenixnoir""@""bitbucket.org/Lephenixnoir/add-in-wrapper.git"
% cd add-in-wrapper
% make
% cp build/g1a-wrapper $PREFIX/bin


Environnement de projet

On va créer un modèle de projet que vous pourrez réutiliser. Tout ça se passe en-dehors de la compilation de gcc, je vous conseille donc de changer de dossier. ~/my-awesome-project pourrait être sympa. Dans tous les cas, vous pouvez fermer le terminal pour l'instant. Si vous avez de l'expérience dans la programmation C, je ne vais pas vous apprendre à organiser un projet... il vous faudra juste quelques fichiers donnés plus bas.

Voilà par exemple comment on pourrait organiser un projet:
- un dossier include contenant les 6 headers de fxlib (dispbios.h, endian.h, filebios.h, fxlib.h, keybios.h, timer.h)
- la bibliothèque libfx.a
- les fichiers addin.ld et crt0.s
- une icône, par exemple icon.bmp
- les sources (dans un dossier src par exemple)

Le code de base est un peu plus simple qu'avec le SDK (toutes les choses bourrines ayant été mises dans crt0.s) :[/justify]
#include <fxlib.h>

int main(void)
{
    unsigned int key;
    locate(1, 1);
    Print((unsigned char *)"gcc add-in");
    while(1) GetKey(&key);
    return 1;
}

Tous ces fichiers sont prêts à utiliser dans l'archive suivante.
Télécharger le projet d'exemple

Voilà sans plus attendre la commande à utiliser pour compiler ce nouveau projet. Y'a plein d'options, mais rien de bien méchant, vous allez voir...

$ sh3eb-elf-gcc -m3 -mb -mrenesas -ffreestanding -nostdlib -T addin.ld crt0.s addin.c -o addin.elf -I include -lgcc -L . -lfx -O2

- Les options -m3 et -mb indiquent qu'on veut du code pour SH3 (même si on utilise déjà le sh3eb-elf, il y a plusieurs variantes) utilisant le big-endian (cela concerne l'ordre des octets en mémoire dans des variables de plusieurs octets)
- L'option -mrenesas demande à GCC de produire du code compatible avec fxlib
- L'option -ffreestanding signale que le programme compilé tient « tout seul », sans s'appuyer sur un système d'exploitation (gcc fournit alors deux-trois choses en plus)
- L'option -I include indique que certains de nos fichiers d'en-tête sont dans le dossier include
- L'option -nostdlib indique que l'on n'a pas de bibliothèque standard (elle est dans fxlib)
- L'option -O2 active l'optimisation du code (facultatif, mais utile)

Ça c'est les options de compilation proprement dites. Ici, on compile tout d'un coup et on effectue l'édition des liens (génération du fichier exécutable) dans la foulée, donc les options se mélangent. Si vous avez un gros projet, vous allez compiler les fichiers un par un avec -c et tout linker ensuite. Les options que j'ai citées pour l'instant sont celles qu'on utilisera à la compilation. Les options suivantes sont spécifiques au linkage :

- L'option -T addin.ld indique au compilateur que les règles qu'on l'on veut voir respecter lors de l'édition des liens sont dans le fichier addin.ld
- Les options -L . et -lfx indiquent qu'on veut utiliser fxlib, et que le fichier libfx.a se trouve dans le dossier courant
- L'option -lgcc spécifie l'utilisation de libgcc (il faut toujours utiliser libgcc !)
- Bien sûr, -o addin.elf indique le nom du fichier de sortie

Notez que le fichier crt0.s est un autre fichier source qui contient du code indispensable. Pensez à le compiler aussi, ici en même temps que le programme addin.c. Le fichier de sortie est au format ELF (le format classique sous Linux), ce qu'on avait prévu en compilant un gcc pour l'architecture sh3eb-elf.

Génération du g1a

Le format ELF a plein d'avantages, mais on ne veut que du binaire pur. Pour cela, on va utiliser un programme de binutils, objcopy, qui va nous permettre de changer le format. En deux mots, supprimer l'ELF et ne garder que le binaire pur (ce qui est dit par -O binary). On supprime aussi deux-trois sections au passage (.comment et .bss), n'oubliez pas de le faire sinon vous aurez un fichier énormissime en sortie.

$ sh3eb-elf-objcopy -R .comment -R .bss -O binary addin.elf addin.bin

On n'a plus maintenant qu'à ajouter les informations de l'application add-in pour obtenir un fichier g1a. C'est le boulot du g1a-wrapper. Il y a des options pour pas mal de champs (que vous pouvez obtenir en exécutant g1a-wrapper --help), mais faisons simple et mettons juste une icône :

$ g1a-wrapper addin.bin -o addin.g1a -i icon.bmp


Terminé ! Vous n'avez plus qu'à transférer votre nouvel add-in... pour ça, seul un bon vieux terminal et des programmes en ligne de commande sont désormais dignes de vous. On en a quelques-uns :
- Le grand P7 de Cakeisalie5
- CasioUsb de Nessotrin


Merci d'avoir suivi ce tuto ! N'hésitez pas à laisser vos impressions, idées d'amélioration, messages de réussite ou même messages d'erreur dans les commentaires !

Fichier joint


Précédente 1, 2, 3 ··· 10 ··· 20, 21, 22, 23, 24, 25 Suivante
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

Citer : Posté le 14/02/2021 14:00 | #


En principe oui. Comme c'est un outil un peu récent j'ai pas eu beaucoup de retours encore, donc tu pourrais croiser un bug ; mais on devrait s'en sortir.
Kamrade Hors ligne Membre Points: 38 Défis: 0 Message

Citer : Posté le 14/02/2021 15:03 | #


C'est bon j'ai installer Giteapc sous ubuntu wsl est ça marche merci beaucoup je vais pouvoir recompiler gravity duck pour Graph 35+e2!
Ninestars En ligne Membre Points: 2413 Défis: 22 Message

Citer : Posté le 04/04/2021 19:10 | #


Salut Lephé !
Dans le tuto
Lephénixnoir a écrit :
Enfin, --program-prefix permet de donner un nom personnalisé au compilateur, ici sh-elf-gcc.
Il est pourtant écrit dans le bout de code --program-prefix=sh-elf- sans le gcc à la fin, c'est normal ?
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

Citer : Posté le 04/04/2021 19:25 | #


Oui, c'est normal : le préfixe est ajouté à tous les noms d'outils (et il y en a beaucoup !). Par exemple quand tu compiles gcc, tu obtiens normalement gcc et g++, et ces deux auront le sh-elf- ajouté devant (note le tiret final, qui est important sinon tu te retrouves avec sh-elfgcc).
Ninestars En ligne Membre Points: 2413 Défis: 22 Message

Citer : Posté le 04/04/2021 19:35 | #


Ok merci

Ajouté le 04/04/2021 à 20:40 :
Re : J'ai un message d'erreur à la compilation de gcc :
make: *** No rule to make target all-gcc'. Stop.[/quote]
Un indice ?
PS : je suis sur macOS, la compilation de binutils c'est déroulée sans peine

Quelqu'un a déjà tout compilé sur mac ?
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

Citer : Posté le 04/04/2021 20:44 | #


Ton configure a dû échouer quelque part, c'est « trop gros » comme erreur.
Ninestars En ligne Membre Points: 2413 Défis: 22 Message

Citer : Posté le 04/04/2021 20:51 | #


Hmm, en remontant le fil j'ai ça :
configure: error: Building GCC requires GMP 4.2+, MPFR 3.1.0+ and MPC 0.8.0+

J'ai bien installé gmp mpfr et mpc. Sauf que MPC est en 0.33 mais pourtant "up to date"
Warning: mpc 0.33 is already installed and up-to-date.

Il y a un sacré écart de version là entre 0.33 et 0.8 !
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

Citer : Posté le 04/04/2021 21:18 | #


Le mpc que tu as installé est un outil en ligne de commande pour contrôler MPD, un lecteur de musique. Le bon paquet s'appelle probablement libmpc ou un truc du genre (Multi-Precision Complex)
Ninestars En ligne Membre Points: 2413 Défis: 22 Message

Citer : Posté le 04/04/2021 22:00 | #


C'était bien ça ! Merci
Avensis Hors ligne Membre Points: 17 Défis: 0 Message

Citer : Posté le 25/04/2021 12:15 | #


Salut, merci pour le partage c'est vraiment génial.

Appvalley TutuApp Tweakbox
Ninestars En ligne Membre Points: 2413 Défis: 22 Message

Citer : Posté le 01/05/2021 16:21 | #


Bonjour !

Quand j'ai une erreur avec gcc c'est sous la forme
/Users/olivier/Documents/CASIO/gcc/bin/../lib/gcc/sh3eb-elf/10.2.0/../../../../sh3eb-elf/bin/ld: CMakeFiles/Windmill.dir/src/windmill.cpp.obj: in function __ZN8Windmill8load_mapEP3Map':
windmill.cpp:(.text+0xe10): undefined reference to
__ZdaPv'

J'aimerai pouvoir changer les points suivants :
- le chemin qui est hyper long, pouvoir le supprimer ou raccourcir
- le nom des fonction est pas trop lisible __ZN8Windmill8load_mapEP3Map
- la ligne est pas en décimal .text+0xe10
- pareil pour le nom de la fonction __ZdaPv

Il y a moyen de rendre plus lisible les messages d'erreur de gcc ?
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

Citer : Posté le 01/05/2021 16:25 | #


Donc ça ce n'est pas une erreur de g++, c'est une erreur de ld, l'éditeur de liens. La différence ? ld ne connaît pas le langage et il n'a pas le code source, pas de notion de fonctions, de lignes, etc.

• Raccourcir le chemin : pas possible à vue de nez.
• Pour le nom des fonctions, utilise c++filt :

% echo __ZN8Windmill8load_mapEP3Map | c++filt -_
Windmill::load_map(Map*)
% echo __ZdaPv | c++filt -_
operator delete[](void*)

.text+0xe10 ce n'est pas un numéro de ligne c'est une position dans le code objet, tu ne peux rien y faire

L'absence de l'opérateur delete fait qu'il faut que tu l'implémentes, à ma connaissance tu peux juste faire free(), le compilateur se charge d'appeler le destructeur. À vérifier de préférence.
Ninestars En ligne Membre Points: 2413 Défis: 22 Message

Citer : Posté le 01/05/2021 16:40 | #


Ok, merci de la réponse, est-ce possible d'utiliser c++filt en automatique ?

D'accord, il n'y a pas delete. ici dans mon code j'ai une variable Object** object dans Windmill, Object qui est struct avec quelques variables.
Originellement, j'ai dans mon code
delete[] object;
object = new Object* [list_object_length];
Comment je peux modifier en conséquence ?
J'ai remplacé delete[] par free() mais j'ai la même erreur _ZdaPv

Ajouté le 01/05/2021 à 16:47 :
Autant pour moi, il fallait chercher un peu
free(object);
object = (Object**) malloc(list_object_length * sizeof(Object));


Pas facile de jongle entre le C, le C++ et le C# (au boulot)
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

Citer : Posté le 01/05/2021 16:51 | #


Tu peux toujours faire fxsdk build-fx 2>&1 | c++filt. C'est un peu bourrin mais dans l'ensemble ça va marcher. C'est parce que c++filt cherche dans son entrée standard des noms de fonctions C++ obfusqués et les décode. Tout le texte autour est conservé sans changement. Le plus important est de bien attraper la sortie d'erreur (le descripteur 2) et de l'envoyer vers la sortie standard (le 1) parce que seule la sortie standard est passée à c++filt par le pipe.

Si tu es prêt à modifier un peu ta commande, tu peux aussi remplacer "/Users/olivier/Documents/CASIO/gcc/bin/../lib/gcc/sh3eb-elf/10.2.0/../../../../sh3eb-elf/bin/ld" par "sh-elf-ld" via une commande sed en plus de faire c++filt, ce qui répond à une autre de tes questions.

Perso j'ai des alias ffx et fcg pour compiler, peut-être que tu peux avoir un système similaire pour faire tes ajustements sans avoir à taper des commandes à rallonge.
Sales Hors ligne Membre Points: 3 Défis: 0 Message

Citer : Posté le 25/05/2021 22:36 | #


ça marche pour moi merci pour le partage
Neiviv-ui Hors ligne Membre Points: 27 Défis: 0 Message

Citer : Posté le 26/05/2021 16:41 | #


Salut,
J'ai essayé de faire un cross-compilateur armv7l ---> SuperH-3 / SuperH-4, et donc j'ai utilisé termux (je précise tout de même que termux supporte à peut près toutes les architectures utilisées par les téléphones).

Déjà GiteaPC fonctionne parfaitement donc ça fait une bonne nouvelle, mais il n'arrivait pas à compiler binutils, tout du moins il générait un warning au sujet d'une fonction non-prototypée (fgets_unlcoked). Du coup j'ai fait un fork de sh-elf-binutils, auquel j'ai d'ailleurs rajouté le système de dépendance avec pkg (le gestionnaire de paquets de termux) et elles y sont toutes exceptée la libppl qui est introuvable (mais qui, au moins pour binutils, ne sert à rien).
Le premier problème était tout bête, la fonction existait mais n'était prototypée dans <stdio.h> qu'en fonction d'une variable de pré-processeur, __ANDROID_API__ qui n'était pas correctement initialisée. Une fois la variable rajoutée dans les CFLAGS et CXXFLAGS, j'ai fait face à deux problèmes :

1. Si je passe CFLAGS et CXXFLAGS en arguments à configure, les anciens "-g et -O2" disparaissent, et je n'ai trouvé aucun moyen de les rajouter de façon correcte sans affecter pleins de variables dans configure.sh. Ce qui m'amène à la question suivante :"À votre avis, sont-ils vraiment nécessaires ?", je précise tout de même que même sans, il n'y a aucune erreur de compilation.

2. Pour revenir sur les dépendances, bison, par exemple, mais c'est le cas pour plein d'autres n'est pas pré-installé, mais le paquet existe, et configure regarde s'il est installé, mais ne génère pas d'erreur(s) donc est-il nécessaire ?
Et au même titre, isl (pkg : libisl) est-il nécessaire, car pour le coup lorsque configure ne le détecte pas, il précise
checking for isl 0.15 or later... no
required isl version is 0.15 or later

mais ne génère toujours pas d'erreur(s).

Je précise aussi que dans termux la commande gcc provient de clang et que gcc classique n'est pas installable en tant que paquet. Même chose pour g++.

Pour conclure sur sh-elf-binutils, j'ai l'impression que l'ajout des dépendances ainsi que la correction de __ANDROID_API__ suffisent à réussir la compilation de ce-dernier tout téléphones confondus, en tout cas j'ai testé sur deux téléphones différents et ça fonctionne sans problème.

Pour ce qui est de compiler sh-elf-gcc (car oui, ça à l'air d'être possible) j'ai fait face à d'autres problèmes :
- Il faut là aussi corriger __ANDROID_API__, mais du coup la même manip semble fonctionner.
- Il y a deux types de warnings extrêmement récurrents,
'__ANDROID_API__' macro redefined
et
unknown warning option '-Wshadow=local'
qui pullulent durant la compilation, mais en tant que tel ça ne pose pas problème.
- Vu que gcc vient de LLVM, il y a des warnings au sujet du fait que __VA_ARGS__ n'est qu'un standard GNU, mais clang ne met pas qu'il n'arrive pas à s'en servir donc je sais pas non plus si c'est réellement un problème.
- Globalement la compilation ne pose aucun problème, mais à un moment, une commande exécutant un certain nouveau fichier (dont j'ai oublié le nom, mais je vais refaire une compilation et le rajouter) résulte en quelque chose du genre : "error: Android 5.0 and above only supports PIE (position independent executables)". Bien entendu mon téléphone est sur android 10 donc je n'ai aucune idée d'où sort ce problème.

Il doit aussi y avoir d'autres problèmes après mais chaque chose en son temps.

Pour ce qui est de pourquoi essayer de le cross-compiler bah à mon avis il y a plusieurs raisons :
1. Si on peut généraliser la compilation à toutes les marques de téléphones sans modifier le code source de gcc (notamment grâce à termux), ça rend le portage beaucoup, beaucoup plus intéressant.
2. Je ne sais pas si c'est la cas d'autres personnes, mais quand je me déplace j'ai tout le temps mon téléphone et je passe déjà le clair de mon temps à coder de trucs en c pour celui-ci, alors pourquoi pas pour ma calculette.
3. J'ai aussi vu que les dev de termux ont réussi à rajouter le paquet libusb sans avoir les autorisations root, du coup peut-être qu'avec la nouvelle maj du fxsdk on pourra communiquer d'un téléphone à la calculette directement.

Merci d'avoir pris le temps de lire mon message, et je lirais vos avis (s'il y en a) avec beaucoup d'attention.
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

Citer : Posté le 26/05/2021 17:28 | #


Quelle aventure ! J'ai vu passer pas mal de commits mais je ne savais pas que tu avais fait tout ça. Wow !

Le premier problème était tout bête, la fonction existait mais n'était prototypée dans <stdio.h> qu'en fonction d'une variable de pré-processeur, __ANDROID_API__ qui n'était pas correctement initialisée. Une fois la variable rajoutée dans les CFLAGS et CXXFLAGS, j'ai fait face à deux problèmes :

1. Si je passe CFLAGS et CXXFLAGS en arguments à configure, les anciens "-g et -O2" disparaissent, et je n'ai trouvé aucun moyen de les rajouter de façon correcte sans affecter pleins de variables dans configure.sh. Ce qui m'amène à la question suivante :"À votre avis, sont-ils vraiment nécessaires ?", je précise tout de même que même sans, il n'y a aucune erreur de compilation.

Tu as essayé CFLAGS="-D__ANDROID_API__ -O2" ? Les flags -g et -O2 ne sont jamais nécessaires, mais -g est crucial pour debugger la toolchain et -O2 est crucial pour la vitesse du compilateur à la fin. Honnêtement -g on s'en fout, on debugge pas binutils. Mais -O2 ça paraît important surtout que les téléphones ils n'ont pas un Core i7

2. Pour revenir sur les dépendances, bison, par exemple, mais c'est le cas pour plein d'autres n'est pas pré-installé, mais le paquet existe, et configure regarde s'il est installé, mais ne génère pas d'erreur(s) donc est-il nécessaire ?

Ça c'est un peu au doigt mouillé mais je pense qu'il doit se rabattre sur autre chose. Regarde par exemple s'il n'a pas trouvé (et utilisé) yacc à la place de bison. libisl c'est des trucs type programmation linéaire et polyèdres, libppl aussi. Les deux sont nécessaires pour les optimisations de GCC (ie. une partie de l'option -O sur le compilateur SuperH). Si tu ne les as pas ces optimisations seront probablement désactivées, ce qui n'est pas dramatique surtout quand tu prototypes ; pour une release finale ça peut aider de les avoir (après tu peux compiler tes releases finales sur un PC une fois par mois ).

- Il y a deux types de warnings extrêmement récurrents,

Rien d'affolant comme tu t'en doutais.

- Vu que gcc vient de LLVM, il y a des warnings au sujet du fait que __VA_ARGS__ n'est qu'un standard GNU, mais clang ne met pas qu'il n'arrive pas à s'en servir donc je sais pas non plus si c'est réellement un problème.

Tu veux dire ##__VA_ARGS__ non ? C'est sans doute parce que des flags pedantic sont activés, rien de gênant a priori. Ça me fait bien rire cela dit parce qu'une solution standard a été implémentée ensuite (__VA_OPT__) mais Clang ne la supporte pas.

- Globalement la compilation ne pose aucun problème, mais à un moment, une commande exécutant un certain nouveau fichier (dont j'ai oublié le nom, mais je vais refaire une compilation et le rajouter) résulte en quelque chose du genre : "error: Android 5.0 and above only supports PIE (position independent executables)". Bien entendu mon téléphone est sur android 10 donc je n'ai aucune idée d'où sort ce problème.

Alors ça par contre c'est chiant. Ton téléphone est sur Android 10, le problème c'est sans doute qu'un fichier non-PIE est en train de se faire exécuter. Je pense que tu sais déjà, mais pour info PIE c'est une forme de code qui peut être chargé à n'importe quelle adresse virtuelle et marcher (ie. il hardcode pas l'adresse où il pense se faire charger). C'est utilisé par les libs dynamiques mais aussi par les exécutables pour une variété de raisons. Si quelque chose en plein milieu de la compilation se fait compiler en non-PIE et qu'il faut le changer, ça risque d'être un peu chiant à faire proprement.

Ça a l'air très intéressant en tous cas ! Mon téléphone est un vieux trucs à peine qualifiable de smartphone, donc c'est quelque chose que je n'ai pas du tout exploré, mais ça a l'air très bien. Je prends les pull requests avec joie quand tu jugeras ça stable !
Neiviv-ui Hors ligne Membre Points: 27 Défis: 0 Message

Citer : Posté le 02/06/2021 17:37 | #


Re-bonjour,
Désolé d'avoir pris des plombes à répondre, j'ai pas d'excuse.
Lephenixnoir a écrit :
Tu as essayé CFLAGS="-D__ANDROID_API__ -O2" ?

Effectivement ça fonctionne très bien, c'est juste que je voulais rester avec le même genre de truc que ce qui a été fait avec sh-elf-gcc et $extra_args : "../gcc-$VERSION/configure --prefix="$PREFIX" --target=sh3eb-elf --with-multilib-list=m3,m4-nofpu --enable-languages=c,c++ --without-headers --with-newlib --program-prefix=sh-elf- --enable-libssp --enable-lto $extra_args".

Pour libisl, libppl, bison etc... j'ai pas mis libisl et libppl parce qu'il y à un gros problème avec gcc (j'en parle dans la suite du message), et pour bison/yacc aucune idée parce que dans termux les deux réfèrent au même paquet, qui n'est pas installé.

Lephenixnoir a écrit :
Tu veux dire ##__VA_ARGS__ non ?

Tout à fait.

Lephenixnoir a écrit :
Alors ça par contre c'est chiant. Ton téléphone est sur Android 10, le problème c'est sans doute qu'un fichier non-PIE est en train de se faire exécuter. Je pense que tu sais déjà, mais pour info PIE c'est une forme de code qui peut être chargé à n'importe quelle adresse virtuelle et marcher (ie. il hardcode pas l'adresse où il pense se faire charger). C'est utilisé par les libs dynamiques mais aussi par les exécutables pour une variété de raisons. Si quelque chose en plein milieu de la compilation se fait compiler en non-PIE et qu'il faut le changer, ça risque d'être un peu chiant à faire proprement.

Effectivement c'est chiant, vraiment.

J'ai essayé pas mal de trucs pour empêcher la compilation avec no-pie et fno-pie, mais j'ai pas réussi juste avec des flags, et aller trifouiller le configure tiendra jamais entre les versions; qui plus est ce n'est apparemment pas compilé en non-PIE pour rien (j'ai pas tout saisi, mais ça ne fonctionne pas sans semble-t-il). J'avoue que ça me soûle, et ça explique pourquoi termux utilise clang et pas gcc, pour les citer
Les devs de termux a écrit :
# Replace gcc since gcc is deprecated by google on android and is not maintained upstream.
donc je vois vraiment pas comment je peux faire quelque chose si eux n'y arrivent pas.


===> Conclusion de ce message un peu défaitiste :
Pour ce qui est de sh-elf-binutils, ça fonctionne du feu de dieu, en tout cas j'ai essayé sur deux téléphones différents (ceci dit les deux étaient sur la même architecture, armv7l et android>=10), ainsi que sur deux émulations (PrimeOS et Anbox, en x86_64, et tout deux android 7.1 je crois), et ça fonctionne tout autant (mini problème de dépendances pour PrimeOS et Anbox avec libxml2 et clang mais c'est patché, peut-être pas tout de suite, s'il faut du temps pour que les dépôts s'actualisent, mais en tout cas elle a été rajoutée donc ce n'est qu'une question de temps). À priori avant Android 7 ça ne fonctionnera pas car termux a un clivage de ses dépôts entre Android<7 et Android>=7 donc il manquerait des dépendances.

À propos de dépendances, libppl c'est mort, parce que le paquet n'est plus maintenu donc il ne sera pas rajouté dans les dépôts, et de toutes façons sa compilation dépend des habilités du processeur donc je sais pas si on peut en faire un paquet (au passage j'arrive même pas à la compiler). Donc c'est vrai que si on avait pu avoir sh-elf-gcc ça aurait été utile de faire les releases sur un ordi.

Et enfin pour sh-elf-gcc, le portage (propre et qui tient dans le temps) est purement impossible, donc à priori ça tombe à l'eau.
J'ai pas de solutions, excepté utiliser clang comme cross-compilateur, mais (j'ai l'impression qu') il n'a pas l'air de supporter sh3eb et sh4a (si je dis pas de bêtises) comme cible. En tout cas catégorie RISC-V (32-bits) il y a ça :
'generic-rv32;generic-rv64;rocket-rv32;rocket-rv64;sifive-7-rv32;sifive-7-rv64;sifive-e31;sifive-e76;sifive-u54;sifive-u74'

Sincèrement je suis pas là pour demander à ce que quelqu'un s'embête à trouver comment faire avec clang (même si ça m'arrangerait ), et puis on sort complètement du cadre de giteapc, c'est juste que ça m'intéresse.
Lephenixnoir En ligne Administrateur Points: 21029 Défis: 143 Message

Citer : Posté le 02/06/2021 17:52 | #


Effectivement ça fonctionne très bien, c'est juste que je voulais rester avec le même genre de truc que ce qui a été fait avec sh-elf-gcc et $extra_args

Ah mais tu peux rajouter ce genre d'options sans hésiter, je le mergerais sans broncher. Si ça marche le script suivra.

J'ai essayé pas mal de trucs pour empêcher la compilation avec no-pie et fno-pie, mais j'ai pas réussi juste avec des flags, et aller trifouiller le configure tiendra jamais entre les versions; qui plus est ce n'est apparemment pas compilé en non-PIE pour rien (j'ai pas tout saisi, mais ça ne fonctionne pas sans semble-t-il). J'avoue que ça me soûle, et ça explique pourquoi termux utilise clang et pas gcc, pour les citer

Ce n'est pas un problème de GCC ça, c'est un problème du système de build qui rajoute des options au fur et à mesure et qui ne te permet pas de changer ce que tu veux.

N'oublie pas qu'il faut à la fois CFLAGS += -fPIC et LDFLAGS += -pie pour avoir des exécutables PIE à tous les coups. N'hésite pas à vérifier dans quel ordre les flags arrivent dans la commande de compilation.

Pour ce qui est de sh-elf-binutils, ça fonctionne du feu de dieu

Bien joué ! o/

J'ai pas de solutions, excepté utiliser clang comme cross-compilateur, mais (j'ai l'impression qu') il n'a pas l'air de supporter sh3eb et sh4a (si je dis pas de bêtises) comme cible.

LLVM n'a pas de backend SuperH donc oui GCC est la seule option ! Faire marcher Clang pour ça est 10 fois plus impossible que modifier le système de build de GCC pour être honnête.
Neiviv-ui Hors ligne Membre Points: 27 Défis: 0 Message

Citer : Posté le 02/06/2021 18:13 | #


Dommage
En vrai c'est pas très grave je m'y attendais.
Pour les CFLAGS et LDFLAGS j'ai déjà essayé mais ça fonctionne pas, ils sont mis au tout début et no-pie/fno-pie à la toute fin (de la commande qui pose problème, même si en fait elles sont un certain nombre). J'ai vu un certain NO_PIE_FLAG et NO_PIE_CFLAG passer mais si je me souviens bien les modifier durant la configuration ne fonctionne pas (ils sont remis à no-pie et fno-pie). Pareil durant le build.
Du coup je vais essayer d'autres trucs (enfin bon je promets rien), mais je risque de refaire comme la dernière fois et répondre avec une semaine de retard .
Palpatine_78 Hors ligne Membre Points: 261 Défis: 0 Message

Citer : Posté le 18/06/2021 10:03 | #


Bonjour

J'ai un problème de compilation en utilisant le paquet sh-elf-gcc-casio de l'AUR sur Arch Linux (après que sh-elf-binutils-casio se soit installé correctement).
J'ai rencontré ce problème sur deux pc arch linux différents (mais c'est sûrement de ma faute, je gère souvent mes PC d'une manière pas très intelligente..)
Est-ce que quelqu' un saurait à quoi c'est dû?

Merci à vous!

config.status: executing depdir commands
mkdir -p -- .deps
make[1] : on entre dans le répertoire « /home/benoit/yay/sh-elf-gcc-casio/src/gcc-11.1.0/gcc-build/build-x86_64-pc-linux-gnu/libcpp »
g++  -I../../../libcpp -I. -I../../../libcpp/../include -I../../../libcpp/include  -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions         -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security         -fstack-clash-protection -fcf-protection -Wp,-D_GLIBCXX_ASSERTIONS -W -Wall -Wno-narrowing -Wwrite-strings -Wmissing-format-attribute -pedantic -Wno-long-long  -fno-exceptions -fno-rtti -I../../../libcpp -I. -I../../../libcpp/../include -I../../../libcpp/include    -c -o charset.o -MT charset.o -MMD -MP -MF .deps/charset.Tpo ../../../libcpp/charset.c
g++  -I../../../libcpp -I. -I../../../libcpp/../include -I../../../libcpp/include  -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions         -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security         -fstack-clash-protection -fcf-protection -Wp,-D_GLIBCXX_ASSERTIONS -W -Wall -Wno-narrowing -Wwrite-strings -Wmissing-format-attribute -pedantic -Wno-long-long  -fno-exceptions -fno-rtti -I../../../libcpp -I. -I../../../libcpp/../include -I../../../libcpp/include    -c -o directives.o -MT directives.o -MMD -MP -MF .deps/directives.Tpo ../../../libcpp/directives.c
g++  -I../../../libcpp -I. -I../../../libcpp/../include -I../../../libcpp/include  -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions         -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security         -fstack-clash-protection -fcf-protection -Wp,-D_GLIBCXX_ASSERTIONS -W -Wall -Wno-narrowing -Wwrite-strings -Wmissing-format-attribute -pedantic -Wno-long-long  -fno-exceptions -fno-rtti -I../../../libcpp -I. -I../../../libcpp/../include -I../../../libcpp/include    -c -o errors.o -MT errors.o -MMD -MP -MF .deps/errors.Tpo ../../../libcpp/errors.c
g++  -I../../../libcpp -I. -I../../../libcpp/../include -I../../../libcpp/include  -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions         -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security         -fstack-clash-protection -fcf-protection -Wp,-D_GLIBCXX_ASSERTIONS -W -Wall -Wno-narrowing -Wwrite-strings -Wmissing-format-attribute -pedantic -Wno-long-long  -fno-exceptions -fno-rtti -I../../../libcpp -I. -I../../../libcpp/../include -I../../../libcpp/include    -c -o expr.o -MT expr.o -MMD -MP -MF .deps/expr.Tpo ../../../libcpp/expr.c
../../../libcpp/expr.c: Dans la fonction « unsigned int cpp_classify_number(cpp_reader*, const cpp_token*, const char**, location_t) »:
../../../libcpp/expr.c:811:35: erreur: le format n'est pas une chaîne littérale et il n'y a pas d'arguments de format [-Werror=format-security]
  811 |             cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location,
      |             ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  812 |                                    0, message);
      |                                    ~~~~~~~~~~~
../../../libcpp/expr.c:814:38: erreur: le format n'est pas une chaîne littérale et il n'y a pas d'arguments de format [-Werror=format-security]
  814 |             cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG,
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
  815 |                                       virtual_location, 0, message);
      |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../libcpp/expr.c:824:33: erreur: le format n'est pas une chaîne littérale et il n'y a pas d'arguments de format [-Werror=format-security]
  824 |           cpp_warning_with_line (pfile, CPP_W_SIZE_T_LITERALS,
      |           ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  825 |                                  virtual_location, 0, message);
      |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus : certains avertissements sont traités comme des erreurs
make[1]: *** [Makefile:226 : expr.o] Erreur 1
make[1] : on quitte le répertoire « /home/benoit/yay/sh-elf-gcc-casio/src/gcc-11.1.0/gcc-build/build-x86_64-pc-linux-gnu/libcpp »
make: *** [Makefile:2906 : all-build-libcpp] Erreur 2
==> ERREUR : Une erreur s’est produite dans build().
    Abandon…
Précédente 1, 2, 3 ··· 10 ··· 20, 21, 22, 23, 24, 25 Suivante

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2021 | Il y a 114 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd