Cette section explique comment compiler MySQL de façon à obtenir un exécutable entièrement statique. L'intérèt principal de cette manipulation est qu'elle permet de créer un package qui fonctionne sur des architectures Linux hétérogènes.
Pour :
Contre :
Les difficultés liées à la glibc2
Un exécutable compilé avec l'option -static
et la glibc2 n'est pas réellement statique. L'appel de certaines fonction, par exemples du type getpw*
ou gethostby*
, provoque le chargement de bibliothèques (libnss_files.so
, libnss_dns.so
et libresolv.so
).
On peut expérimenter ça en tentant de compiler statiquement le programme ci-dessous :
$ gcc -static foo.c $ strace -eopen ./a.out
La raison est liée au service NSS permettant l'authentification et la résolution de noms sous Unix et dont les méthodes peuvent changer selon le contenu du fichier /etc/nsswitch.conf
.
Une alternative
MySQL met à disposition des binaires génériques compilés statiquement. En principe, ils fonctionnent sur n'importe quel système GNU/Linux et profitent d'optimisations assez poussées lors de leur compilation.
Compiler en statique
Pour obtenir un vrai binaire statique, il faut une glibc2 compilée avec l'option --enable-static-nss
.
La démarche est complètement expliquée ci-dessous.
Attention ! En compilant la glibc2 en statique, on renonce à certaines fonctionnalités des services NSS. Notamment, dans le fichier /etc/nsswitch.conf
, le mot clé compat
doit être remplacé.
Cette étape n'est pas forcement indispensable si le système sur lequel on effectue ses compilation est suffisament récent. Elle peut en revanche s'avèrer nécessaire si la compilation de la glibc échoue en raison d'un linker obsolete :
$ tar xfz binutils-2.18 $ cd binutils-2.18 $ export CC=gcc-3.4 $ ./configure --prefix=/home/binutils-2.18 $ make $ make check $ make install
Notes :
make -j
avec la valeur appropriée pour parallèliser la compilation
make check
peut echouer sans que cela soit forcement très grave car certains tests marchent ou échouent selon la version de gcc
utilisée. Dans tous les cas, les logs sont dans ld/ld.log
Choix de la version
Le noyau Linux 2.6
permet plusieurs implémentations des threads. Les NPTL, qui viennent en remplacement des LinuxThreads, sont actuellement préconisés.
Les noyaux Linux 2.4
n'implémentent que les LinuxThreads. Notre glibc2 devra donc implémenter ceux-ci pour rendre nos binaires compatibles sur les différentes versions de noyaux Linux.
A partir de la version 2.4
, la glibc2 n'implémente plus que les NPTL et ne supporte plus les LinuxThreads. Nous sommes donc obligé de choisir la glibc-2.3
.
La commande suivante fournit plus de détails sur ce sujet : man pthreads
Compilation
$ tar xfz glibc-2.3.6.tar.gz $ cd glibc-2.3.6 $ tar xfz ../glibc-linuxthreads-2.3.6.tar.gz
Il faut appliquer le patch suivant :
Ensuite :
$ cd .. $ mkdir glibc-build $ cd glibc-build $ ../glibc-2.3.6/configure --prefix=/home/glibc-2.3.6 \ --enable-static-nss --enable-add-ons=linuxthreads \ --enable-kernel=2.4.18 --with-binutils=/home/binutils-2.18/bin $ make $ make check $ make install
Notes :
make -j
avec la valeur appropriée pour parallèliser la compilation
gcc-3.4
alors qu'elle a réussi avec gcc-3.3
Tester la nouvelle bibliothèque
On peut tester en tentant de recompiler statiquement le programme suivant :
$ gcc -static foo.c -L/home/glibc-2.3.6/lib -lc -lnss_files -lnss_dns -lresolv $ strace -eopen ./a.out $USER
On peut également tester la nouvelle bibliothèque en faisant une compilation dynamique :
$ gcc foo.c -L/home/glibc-2.3.6/lib -lnss_files -lnss_dns -lresolv \ -Wl,-dynamic-linker,/home/glibc-2.3.6/lib/ld-linux.so.2,-rpath,/home/glibc-2.3.6/lib $ strace -eopen ./a.out $USER
$ tar xfz mysql-3.23.58.tar.gz $ cd mysql-3.23.58 $ ./configure --prefix=/home/mysql-3.23.58-static \ --enable-assembler --with-unix-socket-path=/tmp/mysql.sock \ --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static \ --with-other-libc=/home/glibc-2.3.6 $ make $ make test $ make install
$ basedir=/home/mysql-3.23.58-static $ ./scripts/mysql_install_db --datadir=$basedir/var --basedir=$basedir --verbose $ cd /home/mysql-3.23.58-static $ chown -R mysql.mysql var/ $ chgrp -R mysql . $ ./bin/safe_mysqld --basedir=$basedir --datadir=$basedir/var --skip-grant-tables &
Tester le nouveau binaire
$ /home/super-smack -D test.smack 10 100
La compilation et l'installation sont similaires à celles de la version 3.23
.
L'appel au configure
se fait de la façon suivante :
./configure --prefix=/home/mysql-5.0.45-static \ --enable-assembler --with-unix-socket-path=/tmp/mysql.sock \ --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static \ --with-other-libc=/home/glibc-2.3.6 \ --enable-local-infile --enable-static
Un bug au niveau du configure impose d'éditer le fichier ./dbug/Makefile
:
$ vi +209 ./dbug/Makefile #LDFLAGS = -static -L/home/glibc-2.3.6/li LDFLAGS = -all-static -L/home/glibc-2.3.6/lib