TechTuto #01 - Utiliser la STL sur Casio - Partie 1 - Intro / Installation
Posté le 09/06/2022 18:41
Soyez les bienvenus dans cette petite série d'articles que nous pourrions qualifier de "techniques", dans le sens où le but est de proposer des éléments de résolution de problèmes concrets et pratiques qui apparaissent souvent durant la création d'un programme. Le but n'est clairement pas de proposer des tutoriels exhaustifs sur un sujet, il en existe certainement des milliers d'autres soit plus complets, soit plus détaillés et donc tout simplement meilleurs sur Internet, mais bien de préciser ce qu'il est possible de faire sur nos belles machines Casio avec les outils disponibles. Nous allons donc donner dans le tutoriel applicatif sur nos machines favorites
Dans la philosophie, il s'agit avant tout d'un échange, tout commentaire (constructif bien entendu) et toute expérience (bonne ou mauvaise) sera intéressante à partager via les commentaires/messages. Alors n'hésitez pas à participer.
Pour commencer ce que j'espère être une série au moyen/long terme, je vous propose de regarder d'un peu plus près une librairie très intéressante : la Standard Template Library ou STL.
La STL, c'est quoi au juste ?
La Standard Template Library (on écrira STL par la suite, c'est nettement plus court
) est une bibliothèque destinée au langage C++ et normalisée par l'ISO à travers le document ISO/CEI 14882. Elle est mise en œuvre à l'aide des templates (ou autrement nommés modèles/patrons en français).
Cette bibliothèque offre les fonctionnalités (principales) suivantes :
- un ensemble de
classes conteneurs (
containers), telles que les vecteurs (
vector), les tableaux associatifs (
map), les listes doublement chaînées (
list), etc. qui peuvent être utilisées pour contenir n'importe quel type de données à condition que le type concerné supporte certaines opérations telle que la copie et l'assignation.
- une abstraction des pointeurs :
les itérateurs (
iterator), qui fournissent un moyen simple et élégant de parcourir des séquences d'objets dans les conteneurs sus-cités et qui permettent la description d'algorithmes indépendamment de toute structure de données.
- des
algorithmes génériques tels que des algorithmes d'insertion/suppression, recherche et tri dans les conteneurs.
- une
classe string permettant de gérer efficacement et de manière sûre les chaînes de caractères.
- et diverses autres classes ou méthodes qui rendent la vie du programmeur C++ nettement plus facile
Cette définition est assez large, mais elle contient des points néanmoins très très importants :
- il s'agit d'une
librairie C++, pas C. Elle n'est pas utilisable sans avoir accès à un compilateur C++, qui fort heureusement est disponible pour nos machines Casio (ce bon vieux GCC dans sa version SH). En particulier la définition des classes reposant sur l'usage de
templates rend nécessaire le langage C++.
- il s'agit d'une
librairie normalisée (au sens de correspondant à une norme, i.e. standardisée), donc compatible sur diverses architectures, permettant ainsi la retranscription aisée d'un programme sur une autre cible, en minimisant les parties à ré-écrire.
OK, OK, mais concrètement on peut faire quoi avec cette STL ?
Imaginons un instant que vous vouliez écrire un programme dont les données seront contenues dans un tableau, mais dont la taille vous est par avance inconnue (par exemple reposant sur les entrées au bon vouloir d'un utilisateur). Il existe classiquement la méthode de l’allocation dynamique via
malloc, que les programmeurs avec un peu d’expérience connaissent bien. Mais cela nécessite l’écriture de routines spécifiques pour gérer un nombre de cas usuels (insertion d’un nouvel éléments dans le tableau, suppression d’un élément, …). Les plus courageux peuvent se lancer dans l'écriture de fonction permettant d'opérer dans un tableau dynamiquement alloué ou dans une liste chaînée. Bien entendu tout cela est faisable, mais au prix d’un effort conséquent de programmation. Disons simplement que c'est sympa à faire une fois pour comprendre, mais devient vite pénible si on considère que ce cas revient dans de très nombreux programmes.
L'idéal serait d'avoir des méthodes génériques permettant d'opérer de la même manière quel que soit le contenu à stocker. En gros, séparer le contenant du contenu, comme une bouteille en verre sait aussi bien contenir du lait que de l'eau ou même du sable ... Et bien soyez heureux, nous allons justement voir comment arriver à ce résultat dans vos programmes.
En effet, la
STL offre un ensemble de conteneurs qui permettent de stocker divers types de données indépendamment de leur type. Par exemple, si vous voulez stocker des données de type
uint32_t, ou de type
char* ou bien encore de type
tartampion, la STL vous offre un certain nombre de conteneurs génériques opérationnels de manière totalement transparente (par exemple une liste chainée
list ou bien un tableau dynamique
vector pourraient être de bons candidats).
Ainsi si on désire stocker dans une liste doublement chaînée (pas de panique, on expliquera bientôt) des entiers non signés sur 16bit, rien de plus simple, il suffit de déclarer :
std::list<uint16_t> maListe;
pour ensuite remplir la liste, il suffit d’ajouter des éléments à la fin de cette dernière :
maListe.push_back( 10 );
maListe.push_back( 45 );
maListe.push_back( 60 );
ce qui en langage décodé revient à créer une liste d'entiers positifs sur 16bits dans une liste portant le doux nom de maListe (je sais c'est original et recherché comme nom
). Ensuite on ajoute à cette liste les entiers 45 puis 60.
De même pour stocker des pointeurs vers des objets de type Point2D, là encore très facile :
class Point2D
{
public:
float x;
float y;
Point2D( float xn, float yn ) {x=xn; y=yn;};
~Point2D( );
};
std::vector<Point2D *> maListeDePoint2D;
l’insertion est dans ce cas juste un peu plus subtile, car il faut créer les instances d’objets dont on désire garder trace du pointeur dans notre liste :
Point2D *monPoint = new Point2D( 1.0f, 2.0f );
maListeDePoint2D.push_back( monPoint );
cette fois on stocke dans un tableau dynamique (
vector, mais on y reviendra là encore par la suite) les adresses des pointeurs de type Point2D instanciés par l'opérateur
new.
Donc vous l’aurez compris, le but de la STL est d’offrir tout un éventail de classes permettant de gagner énormément de temps lors de la réalisation d’un programme en C++. Elle permet en effet de ne pas avoir à coder des pans entiers de programmes simplement destinés à manipuler des types de données en offrant des classes génériques, mais surtout ces classes sont très largement utilisées par la communauté depuis de nombreuses années et les bugs ont été très largement corrigés (les premières pierres de la STL ayant été posées à la fin des années 70).
Le principal apport de la STL est d'offrir un code C++ normalisé pour certains objets classiques, garantissant ainsi un code source lisible, facilement réutilisable et maintenable.
Comment on se sert de la STL sur Casio ?
Nous partirons sur le principe que vous codez via
gint, l’implémentation de la STL étant basée sur
gint/
fxSDK/
fxlibc et le compilateur GCC adapté à l’architecture SH.
Sur une installation fonctionnelle de
gint/
fxSDK, il suffit alors de passer par
giteapc pour ajouter la librairie
µSTL2.3
giteapc install Slyvtt/uSTL2_3
µSTL est une implémentation légère de la STL destinée en priorité aux architectures dites embarquées et n’offrant pas une puissance de calcul démesurée (typiquement nos Casio correspondent bien à cette définition). Cette version légère reprend néanmoins le standard de la STL et offre les fonctions les plus importantes de cette dernière. Je vous invite éventuellement à regarder le fil du développement de cette librairie ici :
µSTL pour Casio
Lors de la création d’un nouveau projet avec fxSDK
fxsdk new monProjet
il vous faudra procéder à quelques ajustements dans le projet afin de vous mettre en ordre de bataille pour compiler en C++ et pour préciser le linkage avec la librairie STL. Pour ce faire, deux étapes sont à réaliser :
1/ le fichier main.c situé dans le répertoire
src de votre projet doit être renommé en
main.cc afin de faire comprendre au compilateur GCC que le code source est bien en C++ et pas en C (
note: a priori ceci est inutile si on applique bien le point 2/, mais reste néanmoins recommandé afin d'éviter tout problème).
2/ il faut indiquer les options de compilation et de linkage dans le fichier
CMakeLists.txt situé à la racine de votre projet et le mettre en conformité avec votre changement fait en 1/ :
a) il faut changer les lignes
set(SOURCES
src/main.c
# ...
)
par
set(SOURCES
src/main.cc
# ...
)
afin de refléter le changement d’extension du fichier
main vu en 1/.
b) il faut changer la ligne
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os)
par
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -c -std=c++11 -fno-rtti -fno-use-cxa-atexit)
ceci permet de dire au compilateur quel standard du langage il doit utiliser (ici C++ version du standard 2011) ainsi que diverses options nécessaires pour avoir une STL fonctionnelle.
c) enfin, il faut changer la ligne
target_link_libraries(myaddin Gint::Gint)
par
target_link_libraries(myaddin Gint::Gint -lustl -lc)
afin de correctement
linker votre programme avec la librairie µSTL compilée pour votre toolchain.
A ce stade, il devient possible d'utiliser la STL dans un projet pour Casio (Graph 35 ou 90).
Mon premier exemple utilisant la STL sur Casio
Nous allons écrire notre tout premier programme utilisant la STL afin de vérifier que tout fonctionne bien, ce qui nous permettra de clore ce premier article avec une installation fonctionnelle. Nous entrerons plus en avant dans l'utilisation de la STL dans les articles à venir. Ce petit programme ne sera donc pas explicité dans le détail, mais permettra seulement de vérifier que votre installation fonctionne correctement, ce qui constituera le point de départ pour les articles suivants (nous considérerons donc que cette étape est franchie et ne reviendrons donc pas sur cette phase d'installation).
Notre premier programme consiste donc en un simple remplissage d'un tableau dynamique de type
vector, et en son affichage afin de vérifier que tout fonctionne de manière adéquate (compilation, linkage et exécution sur les machines Graph 35/Graph 90).
Ouvrons donc le fichier source
main.cc de notre projet et copions le texte du programme suivant :
Afficher main.cc
Cacher main.cc
#include <gint/display.h>
#include <gint/keyboard.h>
#include <vector>
#define std ustl // A garder pour pouvoir faire des appels via std::
int main(void)
{
dclear(C_WHITE);
dtext(1, 1, C_BLACK, "uSTL vector test.");
std::vector<int> v;
v.push_back( 10 );
v.push_back( 20 );
auto it = v.emplace( v.begin(), -10 );
v.emplace( it+1, 0 );
for( unsigned int k=0; k<v.size(); k++)
dprint( 1, 10+k*10, C_BLACK, "v[%d] = %d", k, v[k] );
dupdate();
getkey();
return 1;
}
Le fichier
CMakeLists.txt complet doit ressembler au minimum à cela:
Afficher CMakeLists.txt
Cacher CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyAddin)
include(GenerateG1A)
include(GenerateG3A)
include(Fxconv)
find_package(Gint 2.4 REQUIRED)
set(SOURCES
src/main.cc
# ...
)
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
set(ASSETS
# ...
)
set(ASSETS_fx
assets-fx/example.png
# ...
)
set(ASSETS_cg
assets-cg/example.png
# ...
)
fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA)
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}})
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -c -std=c++11 -fno-rtti -fno-use-cxa-atexit)
target_link_libraries(myaddin Gint::Gint -lustl -lc)
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
generate_g1a(TARGET myaddin OUTPUT "Tuto001.g1a"
NAME "STLTuto001" ICON assets-fx/icon.png)
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
generate_g3a(TARGET myaddin OUTPUT "Tuto001.g3a"
NAME "STLTuto001" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png)
endif()
Ce simple code peut être compilé via :
fxsdk build-fx
pour les monochromes Graph 35 (fx9860G) avec ce résultat visuellement lors de l'exécution sur la machine
ou
fxsdk build-cg
pour la Graph 90+E (fxCG 10/20/50) avec ce résultat visuellement lors de l'exécution sur la machine
Petite remarque en passant: n'ayant que des machines en SH4 (Graph 90+E, Graph 35+E II et fxCG-20), je n'ai pas pu tester sur les anciens modèles monochrome en SH3. Donc mea culpa si tout ne fonctionne pas très bien. Une recompilation de la librairie STL est certainement à prévoir sur cette architecture .
Logiquement la compilation devrait se passer sans problème. Si tel n'est pas le cas, laissez un commentaire afin que le
SAV puisse vous aider à atteindre cette étape importante pour la suite.
Il vous reste donc à copier le fichier
g1a ou le
g3a à la racine de votre machine selon son type et à exécuter l'Addin correspondant. Vous devriez obtenir le résultat présenté sur les captures d'écran précédentes.
Si vous arrivez à ce point, bravo à vous
, vous avez désormais une installation complètement fonctionnelle de la STL dans votre
toolchain de développement pour Casio. Vous pourrez donc profiter des nombreux avantages offerts par cette libraire.
La suite ...
Dans les articles à venir, nous ferons un tour rapide des différents conteneurs disponibles dans la STL afin de vous en présenter les avantages et inconvénients (et les points à considérer pour choisir le meilleur candidat pour telle ou telle application) ainsi que les principales méthodes associées.
En attendant, n'hésitez pas à faire vos commentaires et/ou à faire remonter vos questions/avis ...
A très bientôt pour les prochains épisodes.
Liens utiles
Si vous voulez trouver plus de documentation sur la STL, la µSTL ainsi que sur leur utilisation, voici quelques liens utiles pour aller plus loin :
Site de la µSTL par l'auteur de la librairie Mike Sharov.
Le site CPlusPLus et en particulier le chapitre sur les containers.
Le site CppReference et là encore le chapitre sur les containers.
Pour ces deux derniers sites, n'hésitez pas à les mettre dans vos favoris, si vous codez en C++, ils constituent une mine d'or et permettent de trouver plein infos sur le C/C++.
Citer : Posté le 09/06/2022 22:05 | #
Il y a une raison qui oblige a ajouter le flag -fno-rtti? Je dis ca parce que je n'ai pas besoin de le mettre pour compiler KhiCAS et ca peut etre dommage d'empecher de faire du C++ objet avec des methodes virtuelles.
Citer : Posté le 09/06/2022 22:16 | #
Il faut que je regarde plus dans le détail, mais j'ai eu pas mal de soucis lors de la compilation de la librairie et j'ai réussi à m'en sortir avec cela, il faudrait que je regarde spécifiquement si on peut s'en passer.
Effectivement cela pose des problèmes avec les méthodes virtuelles, notamment souvent les destructeurs sont souvent de la forme
J'avoue ne pas m'être repenché sur ce point particulier récemment, il faut que je me remette dessus.
Citer : Posté le 09/06/2022 22:19 | #
RTTI n'est pas nécessaire pour l'héritage virtuel, il n'est nécessaire que pour dynamic_cast et typeid.
Citer : Posté le 09/06/2022 22:24 | #
Oui mais rappelle toi c'est l'astuce qu'on a trouvé pour que la compile et le linkage passe : discussion fno-rtti / frtti
Il faudrait se remettre sur ce point spécifiquement car j'avoue que c'est toujours pas très clair pour moi cette histoire ...
Citer : Posté le 09/06/2022 22:31 | #
Evidemment si la µSTL s'en sert ça devient nécessaire, j'avais oublié. Rappelle-toi que même si la majorité du code c'est des templates, il y a sans doute une partie qui est compilée quand tu installes la µSTL, et si tous les usages de dynamic_cast et typeid sont là alors c'est pas surprenant que tu puisses compiler ton code avec -fno-rtti. Ce n'est un problème que si ton code inclut des templates qui eux utilisent RTTI.
Citer : Posté le 10/06/2022 06:43 | #
RTTI n'est pas nécessaire pour l'héritage virtuel, il n'est nécessaire que pour dynamic_cast et typeid.
Pour implementer des methodes virtuelles, il faut un mecanisme pour identifier une classe dans une hierarchie de classes, ca doit etre la meme chose que ce que fait dynamic_cast non? En tout cas, KhiCAS utilise un peu dynamic_cast ainsi que des methodes virtuelles (par exemple pour gerer les corps finis non premiers) et ca compile et linke avec la version de ustl que j'utilise, donc je suppose que ca devrait aussi pouvoir se faire avec ustl 2.3.
Ceci dit, ca ne va pas concerner grand monde, c'est juste une amelioration a garder en tete je pense.
Citer : Posté le 10/06/2022 09:33 | #
Non pour les méthodes virtuelles c'est un peu plus simple. Si tu as une classe virtuelle T, toutes les instances de T contiennent un pointeur vers leur "table virtuelle", qui est essentiellement une liste de méthodes. En pratique, chaque classe héritée possède sa table virtuelle, et les instances des classes héritées pointent vers la table virtuelle de la classe héritée en question. Tout ça se passe sans RTTI; par contre c'est pas suffisant pour dynamic_cast ou typeid parce que simplement avoir accès à une table virtuelle ne te donne pas l'identité de la classe.
Mais sinon oui tu as raison. La seule subtilité c'est qu'il y a des changements d'ABI, donc on ne peut pas mélanger du code compilé avec RTTI et du code compilé sans.
Citer : Posté le 10/06/2022 10:40 | #
Faut que je refasse un essai de compilation de la µSTL2.3 avec RTTI ET de l'Addin aussi avec support RTTI.
J'ai plus tous les détails en tête, mais je me souviens avoir vraiment galéré avec ça.
Cela dit, je préférerais aussi avoir le RTTI qui du coup permettrait d'avoir le dynamic_cast.
Par contre, clairement avec le -fno-rtti, à ce stade, dès que l'on a le keyword virtual, ça crie violemment et ça ne link pas à la fin. Donc ça peut être un peu pénible.
Je me remets dessus dès que j'ai un peu de temps pour refaire des essais, et je vous tiens au courant.
Citer : Posté le 10/06/2022 13:30 | #
Non pour les méthodes virtuelles c'est un peu plus simple. Si tu as une classe virtuelle T, toutes les instances de T contiennent un pointeur vers leur "table virtuelle", qui est essentiellement une liste de méthodes. En pratique, chaque classe héritée possède sa table virtuelle, et les instances des classes héritées pointent vers la table virtuelle de la classe héritée en question. Tout ça se passe sans RTTI; par contre c'est pas suffisant pour dynamic_cast ou typeid parce que simplement avoir accès à une table virtuelle ne te donne pas l'identité de la classe..
Le pointeur sur la table virtuelle devrait permettre d'identifier la classe, en tout cas suffisamment pour pouvoir faire un dynamic_cast, non? Maintenant c'est peut-etre inefficace (naivement on stocke pour chaque classe les pointeurs de la TVM de toutes les classes derivees et on compare).
Citer : Posté le 10/06/2022 16:14 | #
Clarifions déjà que ce n'est pas ce qui se passe en pratique. Si tu as deux instances polymorphes d'une classe sous la main, tu pourrais en effet comparer les pointeurs pour savoir si elles sont de la même classe dérivée, mais avec les informations que tu as avec -fno-rtti c'est tout. Pour les appels de méthodes virtuelles il suffit d'avoir un pointeur vers la table virtuelle, et le compilateur va au plus simple.
Dans ce que tu décris, tu stockes à la fois l'identité de chaque classe (en la liant à sa table virtuelle) et le graphe d'héritage, ce qui reproduit essentiellement le fonctionnement de RTTI. A ceci près que RTTI ne le fait pas avec les tables virtuelles parce que (1) les pointeurs exacts ne sont pas connus à l'avance, et (2) tous les types ne sont pas des nouvelles classes virtuelles.
Donc oui ce que tu proposes est assez proche de l'idée théorique, cela dit je ne conseille pas de le coder à la main, ce serait bien fastidieux. Activer RTTI est plus simple
Citer : Posté le 10/06/2022 17:39 | #
Ca c'est sur, et c'est bien ce que je fais. J'ai un define pour pouvoir compiler sans rtti dans giac, mais rtti ne coute pas enormement en taille de code (on comprend bien pourquoi), contrairement a d'autres options, je pense en particulier aux exceptions, donc je n'active le flag que si la toolchain n'a pas de support pour rtti.
Citer : Posté le 11/06/2022 09:24 | #
Bon j'ai refais un test avec compilation de la librairie avec support RTTI : ça passe sans problème.
Au linkage de l'Addin avec support RTTI : erreurs multiples - références indéfinies :
-- Configuring done
-- Generating done
-- Build files have been written to: /home/sylvain/Programmes/TutosPC/Tuto001/build-cg
[ 33%] Building CXX object CMakeFiles/myaddin.dir/src/main.cc.obj
[ 66%] Building FXCONV object CMakeFiles/myaddin.dir/assets-cg/example.png
[100%] Linking CXX executable myaddin
/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libustl.a(memblock.cc.obj):(.rodata._ZTIN4ustl8cmemlinkE[_ZTIN4ustl8cmemlinkE]+0x0) : référence indéfinie vers « __ZTVN10__cxxabiv117__class_type_infoE »
/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libustl.a(memblock.cc.obj):(.rodata._ZTIN4ustl7memlinkE[_ZTIN4ustl7memlinkE]+0x0) : référence indéfinie vers « __ZTVN10__cxxabiv120__si_class_type_infoE »
/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libustl.a(memblock.cc.obj):(.rodata._ZTIN4ustl8memblockE[_ZTIN4ustl8memblockE]+0x0) : référence indéfinie vers « __ZTVN10__cxxabiv120__si_class_type_infoE »
/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libustl.a(mistream.cc.obj):(.rodata._ZTIN4ustl8ios_baseE[_ZTIN4ustl8ios_baseE]+0x0) : référence indéfinie vers « __ZTVN10__cxxabiv117__class_type_infoE »
/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libustl.a(mistream.cc.obj):(.rodata._ZTIN4ustl7istreamE[_ZTIN4ustl7istreamE]+0x0) : référence indéfinie vers « __ZTVN10__cxxabiv121__vmi_class_type_infoE »
/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libustl.a(mistream.cc.obj):(.rodata._ZTIN4ustl7ostreamE[_ZTIN4ustl7ostreamE]+0x0) : référence indéfinie vers « __ZTVN10__cxxabiv121__vmi_class_type_infoE »
/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libustl.a(sostream.cc.obj):(.rodata._ZTIN4ustl13ostringstreamE[_ZTIN4ustl13ostringstreamE]+0x0) : référence indéfinie vers « __ZTVN10__cxxabiv120__si_class_type_infoE »
/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld : /home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/libustl.a(ustring.cc.obj):(.rodata._ZTIN4ustl6stringE[_ZTIN4ustl6stringE]+0x0) : référence indéfinie vers « __ZTVN10__cxxabiv120__si_class_type_infoE »
collect2: erreur: ld a retourné le statut de sortie 1
make[2]: *** [CMakeFiles/myaddin.dir/build.make:98 : myaddin] Erreur 1
make[1]: *** [CMakeFiles/Makefile2:76 : CMakeFiles/myaddin.dir/all] Erreur 2
make: *** [Makefile:84 : all] Erreur 2
en regardant en décodé ce que ça donne :
on retrouve un problème avec la
Il y a je pense à creuser dans ce sujet du support RTTI / des classes virtuelles.
J'ai vérifié "hors appel STL" avec un simple programme C++ avec une méthode virtuelle que le support RTTI est OK, mais dès que l'on fait des appels à la STL avec des classes contenant des méthodes virtuelles, ça link plus du tout.
Donc a ce stade, je confirme la nécessité du -fno-rtti pour utiliser la STL.
Citer : Posté le 11/06/2022 15:32 | #
Ces symboles existent dans mon SDK, dans la libsupc++.a. Je ne sais plus comment j'ai genere ce fichier, peut-etre a partir des sources de gcc...
Citer : Posté le 11/06/2022 16:37 | #
Oui effectivement la libsupc++ devrait permettre de trouver ces symboles.
Lephe, si je me rappelle bien, tu avais réussi à faire le build de la lib c++ freestanding ? non ?!?
Ca pourrait peut être nous permettre aussi d'avoir le support des exceptions, qui est une plaie avec la µSTL 3.0.
Y'a un chantier à ouvrir
Citer : Posté le 11/06/2022 18:00 | #
Oui j'ai réussi. Mais je faisais pas forcément ça de façon très maline, je le faisais dans le dossier de build de GCC, alors que l'ordre n'est pas pratique. Je me suis promis de tester en clonant indépendamment la libstdc++. Mais je n'ai pas encore pris le temps de tester >_>
Citer : Posté le 05/01/2023 18:41 | #
c'est comment au niveau des performances?
Citer : Posté le 06/01/2023 17:06 | #
Je me sers vraiment beaucoup de containers dans Outrun (pour stocker la piste, les voitures) et les performances sont pas mauvaises du tout.
Citer : Posté le 06/01/2023 18:26 | #
cool!
Citer : Posté le 06/01/2023 18:29 | #
J'avoue que quand c'est sorti j'avais pas trop les compétences pour comprendre à quoi ça servait concrètement mais là j'en ai besoin pour fix un bug de Windmill et ça m'aide grandement !