Articles avec le tag ‘technique’

Compiler Gimp avec LLVM/Clang et analyse statique

Clang, qui utilise l’infrastructure de LLVM, est un compilateur pour la famille de langage du C. Son but est d’offrir une alternative moderne à GCC. Avec Clang arrive notamment un très sympathique analyseur statique du code source. Nous allons appliquer ça à Gimp.

Pour ça, j’ai lâchement copié et adapté la procédure donné par Campbell Barton, de la team Blender. (http://wiki.blender.org/index.php/User:Ideasman42/BlenderClang).

Voici ce que ça donne à la sauce Gimp:

Etape 1: compiler LLVM/Clang

J’ai d’abord essayé avec la version fournis dans ArchLinux, mais Clang s’arrêtait avec une fatal error. Ça se passe bien mieux avec la version de développement. Pour la récupérer, le script de Campbell Barton fonctionne très bien.

Etape 2: configurer la compilation de Gimp

Déjà, il faut ajouter les binaires de LLVM dans le PATH:

export PATH=$PATH:/opt/llvm/bin

La seule différence avec une compilation classique, c’est qu’on demande explicitement le compilateur de CLang:

CC=ccc-analyzer ./autogen.sh --prefix=/opt/gimp/

Etape 3: compiler

Si vous voulez juste compiler, la procédure ne change pas.

make -j3

Si vous voulez lancer en même temps une analyse statique, il faut utiliser scan-build:

scan-build -o clang make -j3

Attention, une compilation avec analyse statique prend pas mal de temps (3h40 avec mon Core 2 Duo E4500).

Etape 4: profit !

L’analyseur statique de LLVM va probablement trouver tout un tas de bug dans le code. Il y a bien sûr des faux positifs, mais c’est dans l’ensemble remarquablement bien fait ! Vous trouverez le résultat de l’analyse de master que j’ai fait aujourd’hui ici: http://pellelatarte.fr/dawa/gimp-llvm/

Implémenter une machine à état

Si vous avez déjà fait de la programmation événementielle (typiquement, les interfaces graphiques avec tout leurs boutons, qui sont activés n’importe quand), vous avez du tomber sur le problème du code à mettre derrière. Le problème est de gérer tous les cas possibles, sans zone de cas indéterminé, et donc sans bugs.

J’ai récemment réécris la gestion de l’interface de de mon outil de déformation par cage pour Gimp, sous forme de machine à état. Cette approche est à mon avis la plus simple a mettre en œuvre, et présente pas mal d’avantage:

  • On voit très facilement si tout les cas sont gérés
  • S’implémente de façon très simple, presque mécanique
  • Facile à maintenir et à étendre

La première étape est de dessiner un diagramme UML d’état. Voici le diagramme que nous allons implémenter:
State Chart UML
3 états et 6 transitions, c’est un automate relativement simple, mais déjà pas facile à implémenter si on ne suis pas cette approche.

Une fois qu’on a ce diagramme, toute la phase de réflexion pour savoir comment va marcher notre système est terminée. J’ai ici implémenté ce système en Java. On commence par définir un enum qui contient tous les états possibles du système:

public class StateMachine {

  private enum State {STATE1, STATE2, STATE3};

Une variable pour stocker l’état actuel:

  private State state;

L’état initial est défini dans le constructeur:

  public StateMachine() {
    this.state = State.STATE1;
  }

Le traitement sur les évènements se fait avec un switch case:

  public void event1() {
    switch(this.state) {
    case STATE1:
      //Action
      this.state = State.STATE2;
      break;
    default:
      //Nothing
      break;
    }
  }
 
  public void event2() {
    switch(this.state) {
    case STATE1:
      //Action
      this.state = State.STATE3;
      break;
    case STATE2:
      //Action
      this.state = State.STATE3;
      break;
    case STATE3:
      //Action
      this.state = State.STATE2;
      break;
    }
  }

  public void event3() {
    switch(this.state) {
    case STATE1:
      //Action
      this.state = State.STATE1;
      break;
    case STATE3:
      //Action
      this.state = State.STATE1;
      break;
    default:
      //Nothing
      break;
    }
  }
}

Et c’est tout ! Ça juste marche =)

ps: J’ai crée le diagramme UML avec PlantUML, très simple à utiliser et encore plus avec le plugin Eclipse !

Ubuntu/Debian : faire le ménage dans les noyaux

Après quelques mois d’utilisation, mon grub ressemble inévitablement à ça :

grub

Oui, je fais une collection de kernels, et alors? :D
Bref, tout ça pour dire que je fini par me retrouver avec 4 ou 5 noyaux, ce qui est, d’une part, inutile, et d’autre part gênant quand il faut commencer à scroller pour attendre la ligne « Windows » tout en bas de la liste (ok, je n’ai qu’à pas utiliser Windows, mais c’est pas la question :p ). Il y a bien la méthode crade d’adapter simplement grub, mais c’est quand même plus propre de supprimer tous ces noyaux inutiles. Voici comment faire.

Lister tous les noyaux installés

dpkg -l | grep linux-image
ii  linux-image-2.6.31-19-generic        2.6.31-19.56                               Linux kernel image for version 2.6.31 on x86
ii  linux-image-2.6.31-20-generic        2.6.31-20.58                               Linux kernel image for version 2.6.31 on x86
ii  linux-image-2.6.31-21-generic        2.6.31-21.59                               Linux kernel image for version 2.6.31 on x86
ii  linux-image-2.6.31-22-generic        2.6.31-22.60                               Linux kernel image for version 2.6.31 on x86
ii  linux-image-generic                  2.6.31.22.35                               Generic Linux kernel image

On voit à la fin le paquet générique du kernel. Il ne faut pas le supprimer.

En théorie, à chaque paquet « linux-image » est associé 2 paquets « linux-headers ».

dpkg -l | grep linux-headers
ii  linux-headers-2.6.31-19              2.6.31-19.56                               Header files related to Linux kernel version
ii  linux-headers-2.6.31-19-generic      2.6.31-19.56                               Linux kernel headers for version 2.6.31 on x
ii  linux-headers-2.6.31-20              2.6.31-20.58                               Header files related to Linux kernel version
ii  linux-headers-2.6.31-20-generic      2.6.31-20.58                               Linux kernel headers for version 2.6.31 on x
ii  linux-headers-2.6.31-21              2.6.31-21.59                               Header files related to Linux kernel version
ii  linux-headers-2.6.31-21-generic      2.6.31-21.59                               Linux kernel headers for version 2.6.31 on x
ii  linux-headers-2.6.31-22              2.6.31-22.60                               Header files related to Linux kernel version
ii  linux-headers-2.6.31-22-generic      2.6.31-22.60                               Linux kernel headers for version 2.6.31 on x
ii  linux-headers-generic                2.6.31.22.35                               Generic Linux kernel headers

Suppression des noyaux inutiles

Il est recommandé de conserver les 2 noyaux les plus récents (le plus récent pour une utilisation courante, l’autre en cas de problème sur le dernier noyau). Dans mon cas, je veux donc supprimer les versions 2.6.31-19.56 et 2.6.31-20.58 du noyau.
Ensuite, tout se fait classiquement avec apt-get et son option –purge :

sudo apt-get remove linux-image-2.6.31-19-generic linux-headers-2.6.31-19 linux-headers-2.6.31-19-generic linux-image-2.6.31-20-generic linux-headers-2.6.31-20 linux-headers-2.6.31-20-generic --purge

Grub sera (normalement) mis à jour automatiquement.

Quelques photos de Prague

Quelques photos que j’ai prises à Prague, où j’ai passé le weekend. Elles sont pratiquement « brutes de décoffrage », je les ai juste redimensionnées et j’en ai recadrée une.

A ce propos, j’en profite pour vous filer un petit outil sympa que j’ai utilisé pour le redimensionnement « massif » : mogrify. Il fait d’ailleurs plein d’autres choses que le redimensionnement.
Et la super commande :

mogrify -resize 50% *

Attention : il écrase les anciennes images.

La cathédrale Saint Vitus
Prague
Prague
Des tux à Prague !
La cathédrale Saint Vitus, intérieur