Tous | Basic Casio | C/C++/ASM | LuaFX | Graphisme | Transferts | Logiciels | Diverses astuces

Calculatrice
Toutes
Graphs 35 à 100
Graph 25
Graphs 75/85/95 (SD)
Graph 100(+)
Classpad 300/330 (+)
Fx-CG 10/20
Fx-CP 400

Retour à la liste des tutoriels
Tutoriel Casio : Créer des bibliothèques de fonctions statiques
Tutoriel rédigé le : 2016-12-18 22:09  par Cakeisalie5  Catégorie : C/C++/ASM  Calculatrice : Toutes

Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (13 commentaires)

Créer des bibliothèques de fonctions statiques

Ce tutoriel est spécifique au développement sous Linux.
Sérieusement les gars ? Windows comme plateforme de développement ?!


La majorité des gens ici (puisque pas mal développent encore sous Windows) qui développent des "librairies" C n'en développent en réalité pas, je pensais en faire un topic, et le voici.


Compilation

La première chose que vous devriez avoir appris sur les langages de programmation, c'est la distinction entre les langages compilés et les langages interprétés... mais je reviens dessus pour m'assurer que c'est bien clair.

Imaginez que vous avez un livre en japonais et que vous ne comprenez que le français. Pour le traduire, vous avez plusieurs possibilités :
- séparer l'étape de traduction (compilation) et l'étape de lecture (exécution), ainsi une fois traduit le livre peut être lu autant de fois qu'il le faut et rapidement, en oubliant qu'il fallait qu'il soit traduit ;
- traduire à la volée, ce qui implique que vous devez traduire le livre en français à chaque fois que vous le lisez (à l'aide d'un traducteur, un interpréteur).

Pour le code, c'est la même chose : l'ordinateur ne lit que du code machine (le français), et vous codez dans un langage autre (le japonais peut ici représenter le C, le C++, ...). Donc la compilation, c'est l'art de transformer du texte organisé en du code machine.


Fichiers objet

À savoir, tout ce que je vais dire à partir de là concerne le format ELF. Ce format, que vous utilisez sans doute déjà sans le savoir, est un format qui peut se décliner en plusieurs types de fichiers : des fichiers objets (repositionnables), des exécutables, et d'autres choses hors-sujet.

Le format ELF, c'est plus ou moins des symboles (avec une table de correspondance symboles/adresse dans le fichier) et des références à des symboles externes (qui ne sont pas dans le fichier), du code machine et des données brutes, organisés dans des sections.

Prenons du code C comme exemple :

// Prototypes
int fonction2();

// Globales
int globale5 = 12346;

int fonction1(void)
{
    // les variables non-statiques ne génèrent pas de symbole
    int variable8 = 44;

    return (fonction2() + globale5 + variable8);
}


Ici, le fichier objet (une fois que GCC sera passé) contiendra deux symboles : _globale5 et _fonction1, et une référence à un symbole : _fonction2 (puisque celle-ci est utilisée dans fonction1). (oui, il faut savoir que le compilateur C ajoute un underscore devant tous les noms de fonctions/globales/variables statiques).

Une question qui peut vous venir à l'esprit, c'est "mais du coup, les globales et les fonctions donnent la même chose dans le fichier objet, comment on sait que ce sont des globales et des constantes ?". Cette question est hors de la portée de ce tutoriel, mais elle est intéressante, et pour répondre à celle-ci, vous devrez comprendre au moins un assembleur (du coup, si vous êtes là, j'imagine que ce sera davantage l'assembleur SuperH).


Link

Le linker, c'est le logiciel qui va prendre des fichiers objets et des libs statiques (on va en parler après) et qui va mélanger tout ça ensemble pour en faire un exécutable.

Si vous faites un exécutable avec simplement le fichier objet présent ci-dessus, il va vous produire une erreur du genre "Le symbole _fonction2 requis n'a pas été trouvé", il faut donc lui fournir un autre fichier objet avec le symbole _fonction2 dedans.

Par ailleurs, une fois que l'exécutable est créé, on n'a plus besoin de la table des symboles ou de la table des sections. Mais sachez que le fichier en .elf que le tutoriel de Lephenixnoir vous fait générer comporte encore cette table des symboles et des sections, rien ne vous empêche d'aller voir pour vérifier avec sh3eb-elf-nm.


Bibliothèques statiques

(oui, on dit une bibliothèque, puisqu'on emprunte des objets dans des bibliothèques (et non une librairie), ou une "lib", pour faire référence au terme anglais)

Une bibliothèque statique est tout bêtement une archive (un fichier avec plein de fichiers dedans, comme les fichiers ZIP ou TAR) de fichiers objet.

On pourrait dire "oui mais du coup, au lieu de linker la lib, autant prendre ses fichiers objet et linker avec, non ?", et non, parce que la grande particularité des libs statiques, c'est que les fichiers objets qu'elle contient sont facultatifs.

Reprenons le link. Lors de l'opération de link, tout ce qui est dans les fichiers objets que vous lui passerez directement sera mis dans l'exécutable. Seulement, il va manquer pas mal de symboles, comme au hasard, _memcpy ou _ML_vram_address -- eh bien, pour trouver ces symboles manquants, le linker va parcourir tous les fichiers objet présents dans les libs statiques linkées et prendre ceux où se trouvent les symboles qu'il manque à l'exécutable.

On peut donc voir les libs statiques comme des collections de symboles, donc des collections de fonctions (et éventuellement de constantes et autres données brutes) qui ne seront peut-être pas toutes ajoutées à l'exécutable d'un projet les utilisant.


Comment créer une lib statique ?

Faire une lib statique, ce n'est pas sorcier, il suffit de :
- compiler les fichiers source de la lib en fichiers objet ;
- créer une archive avec tous les fichiers objet ;
- éventuellement, créer un index des fichiers objet présents dans l'archive et de leurs symboles pour faciliter le job du linker.

Attention cependant : n'oubliez pas que le linker va inclure non pas des fonctions, mais des fichiers objet. Si vous mettez toutes les fonctions de la lib dans un fichier source et que, du coup, vous ne faites qu'un seul fichier objet, ce fichier objet sera inclus dans l'exécutable finale dès que l'un des symboles présents dedans sera requis. Divisez bien vos fonctions en fichiers, l'idéal étant une fonction par fichier, mais il y a des cas particuliers : imaginons qu'une fonction soit appelée par une seule autre fonction, et qu'elle ne soit pas prévue pour être appelée par l'utilisateur, alors il faut la mettre dans le fichier source de cette autre fonction et même en faire une fonction statique (disponible uniquement depuis le fichier).

Par exemple, pour créer la libmonochrome, son Makefile va faire :

sh3eb-elf-gcc -c -o obj/ML_vram_address.o src/ML_vram_address.c -I ./include -Wall -Wextra
sh3eb-elf-gcc -c -o obj/ML_clear_vram.o src/ML_clear_vram.c -I ./include -Wall -Wextra
...
sh3eb-elf-ar rc libmonochrome.a ./obj/ML_vram_address.o ./obj/ML_clear_vram.o ...
sh3eb-elf-ranlib libmonochrome.a



Gérer un projet de lib statique

Faire un simple projet pour créer la lib, c'est bien, mais penser à l'utilisateur, c'est mieux. Un projet de lib statique propose généralement trois étapes :
- la configuration : on donne (ou laisse par défaut) les dossiers d'installation des fichiers header, des fichiers lib, ...
- la création : créer la lib (avec les commandes données ci-dessus, par exemple) ;
- l'installation : installer les fichiers prêts à l'emploi sur la machine.

Avec la libmonochrome par exemple, pour créer la lib puis l'installer, on réalise trois commandes :
./configure --prefix=~/opt/sh3eb-elf
make
make install


Je vous conseille vraiment de garder ça aussi simple que ça pour l'utilisateur qui va se servir de votre lib derrière.


Libs déjà créées/portées

- libfx (1.0) : lib du SDK, originale par CASIO
- libinput (2.0, topic dédié) : manipulation avancée du clavier, originale par Ninestars.
- libmonochrome (1.1, topic dédié) : originale par PierrotLL, y a-t-il encore besoin de la présenter ?
- librtc (0.3, topic dédié) : manipulation du temps à l'aide de la Real-Time Clock.

(peut-être qu'un jour, quelqu'un trouvera le moyen d'en faire des packages pour les principales distributions utilisées par les membres, à savoir Arch/Manjaro et des Debian-based ?)


Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (13 commentaires)

Publicité et partenaires
Casio Education
Casio éducation

TI-Planet
Casiopeia
Casiopeia
CasioFan, la communauté ClassPad
CasioFan
CodeWalrus
CodeWalrus

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2015 | Il y a 47 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Rugby Manager | Jeu de basket | Jeu de handball | Jeu de tennis | Nova Raider | Réparation téléphone | Soccer Rush | Tasty Tale

Planète Casio est un site communautaire indépendant, géré bénévolement et n'est donc pas affilié à Casio | Toute reproduction de Planète Casio, même partielle, est interdite
Les fichiers, programmes et autres publications présents sur Planète Casio restent la propriété de leurs auteurs respectifs et peuvent être soumis à des licences ou des copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd