Forums Casio - Vos tutoriels et astuces

Index du Forum | Vos tutoriels et astuces | Faites des libs statiques, bon sang !
Cakeisalie5
En ligne
Administrateur
Niveau: Confirmé
Points: 1573
Défis: 9
Message
Posté le 23/05/2016 10:49

Faites des libs statiques, bon sang ! :


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 ?)





Hackcell
En ligne
Membre
Niveau: Intermédiaire
Points: 595
Défis: 4
Message
Citer : Posté le 23/05/2016 13:42 | #
Du coup gint pourrait occuper moins de place, non?
----------------------------------
I only need black tea and sweets to survive...
But no matter what I eat, I need love to live...
So please, don't leave me alone...
Cakeisalie5
En ligne
Administrateur
Niveau: Confirmé
Points: 1573
Défis: 9
Message
Citer : Posté le 23/05/2016 13:45 | #
gint a un statut un peu particulier à cause de son interrupt handler (et du linker script qu'il impose).

M'enfin, j'ai cru comprendre que c'était réglé, donc à voir.
----------------------------------
Informatichien au poil. Je fais danser des bytes quand ça me chante.
Besoin d'utilitaires de transfert vers et depuis la calculatrice sous GNU/Linux ?
Dark storm
Hors ligne
Administrateur
Niveau: Aucun
Points: 10134
Défis: 170
Message
Citer : Posté le 23/05/2016 14:43 | #
Oui, si tu n'utilise pas toutes les fonctions de gint, tu n'aura pas à tout trimballer. Après il faut savoir que le gestionnaire d'interruption et les fonctions essentielles (getkey, dessin, etc.) sont celles qui prennent le plus de place.
Mais dans tout les cas, c'est développé de manière propre, faut pas s'en faire pour ça
----------------------------------
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Páranÿe quetë Quendya
Hackcell
En ligne
Membre
Niveau: Intermédiaire
Points: 595
Défis: 4
Message
Citer : Posté le 23/05/2016 19:50 | #
Étant donné que c'est léphé qui d'en occupe je ne m'inquiète pas pour ça, c'est juste que j'avais mal compris et que je pensai que quand il disait que ça prenais de la place qu'il voulait dire que ça compilait tout gint.
----------------------------------
I only need black tea and sweets to survive...
But no matter what I eat, I need love to live...
So please, don't leave me alone...
-florian66-
Hors ligne
Rédacteur
Niveau: Aucun
Points: 2264
Défis: 19
Message
Citer : Posté le 23/05/2016 20:22 | #
Si je comprends bien, ça permet de séparer les fonctions et le compilo ne choisi que celle dont il a besoin et ne compile pas toute les fonctions ?
----------------------------------
In Arch, I trust ! And you ?
Dark storm
Hors ligne
Administrateur
Niveau: Aucun
Points: 10134
Défis: 170
Message
Citer : Posté le 23/05/2016 20:27 | #
En soit, GCC le fait déjà. Il n'ajoute à l'écécutable que les fonctions qui sont utilisées. Vous pouvez faire le test, là dessus il est bon. Par contre, c'est le compilo d'Hitachi qui est moins performant. Donc ça prend pas forcément moins de place, c'est juste que c'est en effet un chouille plus propre.
----------------------------------
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Páranÿe quetë Quendya
Cakeisalie5
En ligne
Administrateur
Niveau: Confirmé
Points: 1573
Défis: 9
Message
Citer : Posté le 23/05/2016 20:32 | #
Attention à la nuance : le linker va prendre les fichiers objets contenant les fonctions que le programme utilise. Une lib statique n'est pas fait pour être suffisante, elle permet juste de proposer des fonctions à l'utilisateur. (par exemple, la libc, contenant entre autres printf, malloc, etc)

(un fichier source donne exactement un fichier objet, donc s'il y a plusieurs fonctions dans un fichier source, et que lors du link, le linker se rend compte que le programme utilisateur reprend une des fonctions du fichier objet, il va prendre tout le fichier objet)
----------------------------------
Informatichien au poil. Je fais danser des bytes quand ça me chante.
Besoin d'utilitaires de transfert vers et depuis la calculatrice sous GNU/Linux ?
Dark storm
Hors ligne
Administrateur
Niveau: Aucun
Points: 10134
Défis: 170
Message
Citer : Posté le 23/05/2016 22:26 | #
Ce que je dis juste au dessus, c'est que si tu compile la bibliothèque depuis son .c (comme ce qui est fait actuellement), GCC n'ajoute au binaire que le code des fonctions qu'il utilise. Ce qui n'est pas le cas des .a compilés depuis un unique .c, on est d'accord.
----------------------------------
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Páranÿe quetë Quendya
Lephenixnoir
Hors ligne
Administrateur
Niveau: Confirmé
Points: 11077
Défis: 130
Message
Citer : Posté le 27/05/2016 21:21 | #
De toute façon gint est une lib statique, par essence. Si vous n'utilisez pas du tout un module, vous n'inclurez pas toute la lib. Mais en fait, vous devrez utiliser tous les modules. À moins que vous ne puissiez vous passer de dessiner à l'écran, d'afficher du texte ou d'utiliser le clavier.

L'interrupt handler n'est qu'un module comme un autre, excepté que vous ne pouvez pas linker sans. Le linker script définit un point d'entrée dont les dépendances incluent le gestionnaire.

Le tuto est pas mauvais, mais je pense qu'on peut faire un peu plus clair : peut-être en étant un peu plus factuel. Tu ne devrais pas insister sur le lien entre la répartition des fonctions dans les fichiers et la manière dont le compilateur lie les objets ?
----------------------------------
Watch me, as I build my empire with my own hands.
Cakeisalie5
En ligne
Administrateur
Niveau: Confirmé
Points: 1573
Défis: 9
Message
Citer : Posté le 28/05/2016 02:01 | #
J'ai refait le tutoriel en détaillant un peu plus tout ce qui est ELF etc du coup.
----------------------------------
Informatichien au poil. Je fais danser des bytes quand ça me chante.
Besoin d'utilitaires de transfert vers et depuis la calculatrice sous GNU/Linux ?
Lephenixnoir
Hors ligne
Administrateur
Niveau: Confirmé
Points: 11077
Défis: 130
Message
Citer : Posté le 28/05/2016 14:01 | #
C'est plus clair et plus joli je trouve !
Pense à utiliser [ justify ] aussi
----------------------------------
Watch me, as I build my empire with my own hands.
Nemhardy
Hors ligne
Grand maître des Traits d'Esprit
Niveau: Confirmé
Points: 1160
Défis: 54
Message
Citer : Posté le 18/12/2016 13:32 | #
Ça vaudrait peut-être le coup de passer ce sujet dans la liste des tutoriels utiles non ?
Ça m'évitera d'avoir à endurer le fait d'aller sur le profil de Cake à chaque fois pour le retrouver.
----------------------------------
Mes programmes
Cliquer pour enrouler
Équilibrer des coefficients stœchiométriques en moins de 2500 octets sur ta Prizm : Ekisto
Ma version du moteur de calcul symbolique libre Eigenmath
C'est hyper important
Oui
«Ceux qui exercent la profession d'herboriste-botaniste, lesquels sont de tous temps en possession de vendre des herbes ou plantes, seront soumis à la visite et inspection des gardes des apothicaires»
-- Arrêté du Conseil d'État, 30 oct. 1767

Dark storm
Hors ligne
Administrateur
Niveau: Aucun
Points: 10134
Défis: 170
Message
Citer : Posté le 18/12/2016 22:07 | #
Fait
----------------------------------
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Páranÿe quetë Quendya


Index du Forum | Vos tutoriels et astuces | Faites des libs statiques, bon sang !

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

Casio Education Casiopeia CodeWalrus

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