Comme je vous le disais dans le billet précédent, je travaille actuellement sur Qasim, un modeste outil pour gérer vos montages SSHFS.
Ainsi, récemment, j'abordais avec enthousiasme le développement de l'interface de configuration qui lui manque. Sauf que problème... impossible d'utiliser les bindings Qt sur les versions de ruby installées sur mon système !
La moindre installation de qtbindings au sein de rbenv plantait lamentablement, avec une trace comme ceci :
$ gem install qtbindings
[...]
make[3]: entrant dans le répertoire « /home/warbrain/.rbenv/versions/1.9.2-p320/lib/ruby/gems/1.9.1/gems/qtbindings-4.6.3.4/ext/build »
[ 82%] Building CXX object ruby/qtruby/src/CMakeFiles/qtruby4shared.dir/Qt.o
[ 82%] Building CXX object ruby/qtruby/src/CMakeFiles/qtruby4shared.dir/handlers.o
[ 83%] Building CXX object ruby/qtruby/src/CMakeFiles/qtruby4shared.dir/marshall_types.o
Linking CXX shared library libqtruby4shared.so
/usr/bin/ld: /home/warbrain/.rbenv/versions/1.9.2-p320/lib/libruby-static.a(array.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/home/warbrain/.rbenv/versions/1.9.2-p320/lib/libruby-static.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make[3]: *** [ruby/qtruby/src/libqtruby4shared.so.2.0.0] Erreur 1
make[3]: quittant le répertoire « /home/warbrain/.rbenv/versions/1.9.2-p320/lib/ruby/gems/1.9.1/gems/qtbindings-4.6.3.4/ext/build »
Alors la solution ?
Comme expliqué sur cet autre billet, il s'agit du linker qui veut utiliser une bibliothèque dynamique alors qu'il trouve seulement la versions statique de la bibliothèque : libruby-static.a. De plus si vous regardez dans le dossier d'installation de ruby, vous constaterez que libruby.so est absent...
La solution est simplement de recompiler ruby avec l'option de configuration --enable-shared et de le réinstaller. Cela créera la bibliothèque dynamique manquante en plus de la version statique.
Facile, non ?
Le combo rbenv et ruby-build ... et qtbindings
Il faut d'abord savoir que depuis la dernière fois, j'ai amélioré mon environnement de développement pour ruby et ce faisant j'utilise désormais rbenv.
Qu'est ce que c'est ? rbenv, c'est un outil permettant à un utilisateur de faire cohabiter plusieurs versions de ruby, de passer de l'une à l'autre ou d'en définir une par défaut au niveau d'un répertoire. Pour ceux qui connaissent, c'est à peu près comme RVM, mais en plus propre.
Je vous renvoie à ce tutorial pour les détails de son fonctionnement. C'est vraiment pratique et très efficace, je vous le conseille.
ruby-build est le compagnon idéal de rbenv. Il s'intègre dans ce dernier et permet de compiler et installer à peu près n'importe quelle version de ruby dans l'environnement de rbenv, en une ligne de commande.
Si vous avez déjà installé une version de ruby avec rbenv, voila ce qu'il vous reste à faire :
D'abord supprimer la version problématique (par exemple la 1.9.3-p194)
rm -fr ~/.rbenv/versions/1.9.3-p194/
Ensuite la réinstaller avec les bons paramètres de compilation. À cette occasion j'ai découvert que certaines variables d'environnement comme CONFIGURE_OPTS étaient prises en compte par ruby-build, et c'est très pratique pour ce qui nous intéresse... il suffit donc de taper ce qui suit :
$ CONFIGURE_OPTS="--enable-shared" \
rbenv install 1.9.3-p194
Changez ensuite votre version de ruby
$ rbenv local 1.9.3-p194
Et enfin installez le gem qui vous embêtait :
$ gem install qtbindings
Fetching: qtbindings-4.6.3.4.gem (100%)
Building native extensions. This could take a while...
Successfully installed qtbindings-4.6.3.4
1 gem installed
Installing ri documentation for qtbindings-4.6.3.4...
Installing RDoc documentation for qtbindings-4.6.3.4...
Et enfin, ça fonctionne !
Pour les versions anciennes de ruby, préciser quel gcc !
Si vous utilisez la méthode précédente "telle quelle" sur une version plus ancienne de ruby, par exemple la 1.8.7-p358, l'installation de qtbindings risque de mal se passer et vous obtiendrez quelque chose de comme ceci:
$ gem install qtbindings
/home/warbrain/.rbenv/versions/1.8.7-p358/lib/ruby/1.8/timeout.rb:60: [BUG] Segmentation fault
ruby 1.8.7 (2012-02-08 patchlevel 358) [x86_64-linux]
Pas terrible donc.
Afin d'éviter cela, au moment de l'installation de ruby, vous devrez également préciser une version du compilateur gcc compatible, via la variable d'environnement CC.
Voila la commande complète.
$ CONFIGURE_OPTS="--enable-shared" CC=gcc-4.5 \
rbenv install 1.8.7-p358
J'espère que cela vous aura été utile ! N'héstez pas à laisser un petit commentaire si c'est le cas 