{"id":372,"date":"2009-11-08T12:54:21","date_gmt":"2009-11-08T10:54:21","guid":{"rendered":"http:\/\/blog.rastersoft.com\/?p=372"},"modified":"2015-08-15T17:49:18","modified_gmt":"2015-08-15T17:49:18","slug":"compilacion-en-masa","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=372","title":{"rendered":"Compilacion en masa"},"content":{"rendered":"<p>En la entrada <a href=\"https:\/\/blog.rastersoft.com\/index.php\/2009\/10\/02\/emergiendo\/\" target=\"_blank\">Emergiendo<\/a> expliqu\u00e9 como generar un entorno de compilaci\u00f3n cruzada basado en Gentoo para poder compilar cosas para nuestro disco duro, pero luego, en <a href=\"https:\/\/blog.rastersoft.com\/index.php\/2009\/10\/12\/ftp-ando\/\" target=\"_blank\">FTP-ando<\/a>, ech\u00e9 todo por tierra al no poner binarios creados por m\u00ed. Ahora ya he sido capaz de compilar, as\u00ed que, para los impacientes, <a href=\"http:\/\/www.rastersoft.com\/blogpic\/ftp_bt4lxmedia_2.0.tar.bz2\">aqu\u00ed est\u00e1 el paquete con las \u00faltimas versiones<\/a> de CTorrent (3.2.2), BFTP (2.6) y YAOD (0.7.2). Las instrucciones de instalaci\u00f3n son las mismas que en el art\u00edculo anterior (<a href=\"https:\/\/blog.rastersoft.com\/index.php\/2009\/10\/12\/ftp-ando\/\" target=\"_blank\">FTP-ando<\/a>). Como gran ventaja, algunos fallos de BFTP han desaparecido, y encima la tasa de transferencia ha subido a 3MBytes\/seg.<\/p>\n<p><span style=\"color: #ff0000;\"><strong>AVISO<\/strong><\/span><span style=\"color: #ff0000;\">:<\/span> <strong>a partir de aqu\u00ed empiezo a tocar en el sistema operativo del disco duro multimedia, lo que significa que estas acciones s\u00f3lo las deben realizar aquellos que sepan muy bien lo que hacen. Si alguien se carga su disco, ser\u00e1 el \u00fanico responsable.<\/strong><\/p>\n<p>Pasando ya a la chicha, la raz\u00f3n de que haya tardado tanto es que la cosa no es tan sencilla, por varias razones:<\/p>\n<ul>\n<li>Para empezar, el disco duro tiene su propia versi\u00f3n de la uClibc, por lo que la \u00fanica manera de garantizar que un programa funcione correctamente es compilarlo contra esa misma versi\u00f3n.<\/li>\n<li>Por otro lado, en algunas versiones del compilador GCC cambia el fomato binario de las bibliotecas en C++, por lo que tambi\u00e9n es conveniente utilizar la misma versi\u00f3n de compilador GCC: para garantizar que la interfaz binaria entre la aplicaci\u00f3n y las bibliotecas es la misma.<\/li>\n<li>Por \u00faltimo, muchos paquetes no se pueden instalar en un sistema mediante compilaci\u00f3n cruzada porque su <em>configure <\/em>hace cosas <em>raras<\/em>, como comprobar si GCC compila correctamente un programa de prueba&#8230; programa que estar\u00e1 en arquitectura MIPS y, por tanto, no correr\u00e1 en un Intel, abortando el proceso de compilaci\u00f3n.<\/li>\n<\/ul>\n<p>Y si ya la cosa se ve\u00eda complicada, encima nos encontramos con que Gentoo no tiene la versi\u00f3n de GCC utilizada en nuestro disco duro (la 3.4.4), y que algunas versiones de uClibc (entre ellas la 0.9.28.3, la de nuestro disco duro) no compilan con seg\u00fan qu\u00e9 compiladores o versiones de binutils. El resultado era desalentador.<\/p>\n<p>La primera idea que consider\u00e9 para resolver el problema fue meter un sistema Gentoo completo en el disco y ejecutar en \u00e9l las aplicaciones usando <a href=\"http:\/\/en.wikipedia.org\/wiki\/Chroot\" target=\"_blank\">chroot<\/a>. Por desgracia esta soluci\u00f3n es muy ineficiente porque necesita mucho espacio en disco y porque las aplicaciones s\u00f3lo tendr\u00edan acceso a los directorios contenidos dentro del chroot, pero nunca a los de fuera.<\/p>\n<p>La segunda idea consist\u00eda en intentar generar un conjunto nativo de compilador GCC, binutils y biblioteca uClibc con las versiones correctas a partir de fuentes oficiales. Por desgracia, el proceso es demasiado complejo y tampoco funciona con todas las versiones de GCC, binutils y uClibc que interesaba.<\/p>\n<p>La tercera idea era usar <a href=\"http:\/\/buildroot.uclibc.org\/\" target=\"_blank\">BuildRoot<\/a>, el entorno de generaci\u00f3n de compiladores cruzados de BusyBox. Por desgracia, una vez m\u00e1s, no s\u00f3lo no ten\u00eda las versiones necesarias, sino que tampoco compilaba cualquier combinaci\u00f3n.<\/p>\n<p>Por \u00faltimo, la cuarta, que ha sido la que decid\u00ed emplear, consiste en compilar est\u00e1ticamente los programas deseados utilizando un compilador nativo en el propio disco duro multimedia. De esta manera, al no depender de ninguna biblioteca de enlazado din\u00e1mico, el programa funcionar\u00e1 en cualquier sistema, ahorr\u00e1ndonos el problema de la incompatibilidad de versiones. Adem\u00e1s, al no importar la versi\u00f3n de binutils, GCC ni uClibc, podemos utilizar versiones m\u00e1s modernas, que siempre tendr\u00e1n mayor seguridad y fiabilidad. Por \u00faltimo, al compilarse en el sistema de manera nativa, no habr\u00e1 problemas con ficheros <em>configure<\/em> que hagan cosas \u00abraras\u00bb. Como inconveniente, necesita m\u00e1s memoria que un programa compilado din\u00e1micamente.<\/p>\n<p>Sin embargo, segu\u00eda con el problema de conseguir un toolchain para MIPS que funcionase correctamente, cosa compleja porque en Gentoo hay nueve versiones de GCC, cuatro de binutils y tres de uClibc (sin contar revisiones), y no todas las combinaciones compilan. Adem\u00e1s, no bastaba con el toolchain, sino que tambi\u00e9n necesitaba instalar en nativo <strong>Bash, GCC, binutils, uClibc, make<\/strong> y el entorno b\u00e1sico con <strong>BusyBox<\/strong>. \u00bfPor donde empezar? Por desgracia la versi\u00f3n m\u00e1s reciente no compilaba, y no pod\u00eda probar las 108 combinaciones posibles&#8230; O al menos, no a mano, as\u00ed que hice un <a href=\"http:\/\/www.rastersoft.com\/blogpic\/crossdev_py.tar.bz2\">peque\u00f1o script en python<\/a> que probase a compilar todas las posibles combinaciones. Lo dej\u00e9 una noche, y el resultado fue que s\u00f3lo compilaba con el GCC 3.4.6-R2 y GCC 4.1.2, las Binutils 2.18-R4, 2.19.1-R1 o 2.20, y s\u00f3lo con uClibc 0.9.30.1-R1. En el resto de casos, o fallaba la generaci\u00f3n del toolchain para compilaci\u00f3n cruzada, o fallaba la compilaci\u00f3n de las utilidades nativas.<\/p>\n<p>Una vez descubiertas las versiones, s\u00f3lo fue necesario generar un toolchain adecuado para compilaci\u00f3n cruzada:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">crossdev --target mipsel-unknown-linux-uclibc --without-headers --gcc 4.1.2 --binutils 2.20 --libc 0.9.30.1-r1\r\nemerge-wrapper --init<\/pre>\n<\/div>\n<p>Luego, compilar e instalar las aplicaciones b\u00e1sicas necesarias para poder compilar (lo he cortado por razones de espacio, pero es una \u00fanica l\u00ednea):<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">emerge-mipsel-unknown-linux-uclibc\u00a0 =binutils-2.20 =gcc-4.1.2 =uclibc-0.9.30.1-r1 bash make gzip bzip2 \r\nunzip tar gnuconfig m4 sys-apps\/texinfo gawk coreutils sed grep shadow procps net-tools iputils \r\ndebianutils cpio attr sys-apps\/acl kbd nano less diffutils<\/pre>\n<\/div>\n<p>Vemos que instalamos las mismas versiones de binutils, gcc y uclibc que las usadas para generar la cadena de compilaci\u00f3n cruzada. Instalamos <strong>coreutils<\/strong> y dem\u00e1s en lugar de <strong>busybox<\/strong> (o <strong>system<\/strong>) porque las utilidades de \u00e9ste son versiones recortadas y dan problemas con algunas compilaciones. Tambi\u00e9n instalamos<strong> tar<\/strong>, <strong>gnuconfig<\/strong>, <strong>m4<\/strong> y <strong>texinfo<\/strong>, los cuales ser\u00e1n necesarios para instalar <a href=\"http:\/\/www.gnu.org\/software\/autoconf\/\" target=\"_blank\"><strong>autoconf<\/strong><\/a>, <a href=\"http:\/\/www.gnu.org\/software\/automake\/\" target=\"_blank\"><strong>automake<\/strong><\/a> y <a href=\"http:\/\/www.gnu.org\/software\/libtool\/\" target=\"_blank\"><strong>libtool<\/strong><\/a>. La raz\u00f3n de no instalar estos \u00faltimos directamente es que la instalaci\u00f3n de Perl por compilaci\u00f3n cruzada no funciona; tendremos que hacerlo luego a mano.<\/p>\n<p>Por \u00faltimo, creamos los directorios <em>\/proc, \/dev<\/em> y <em>\/sys<\/em> en <em>\/usr\/mipsel-unknown-linux-uclibc<\/em>, y ya podemos comprimir ese directorio utilizando<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">tar -cpvf buildchain.tar \/usr\/mipsel-unknown-linux-uclibc<\/pre>\n<\/div>\n<p>copiarlo en el disco duro, en <em>\/tmp\/hdd\/volumes\/HDD1<\/em>, descomprimirlo, y lanzar un entorno de compilaci\u00f3n utilizando este script, que autom\u00e1ticamente montar\u00e1 mediante <em>bind<\/em> los directorios del sistema y utilizar\u00e1 chroot para cambiar al nuevo entorno. Ahora nos bajamos <a href=\"http:\/\/www.perl.org\/\" target=\"_blank\">Perl<\/a>, lo descomprimimos y lo compilamos con<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">sh Configure -de\r\nmake\r\nmake install<\/pre>\n<\/div>\n<p>Cabe recordar que el procesador de este disco duro es MUY LENTO, por lo que es posible que necesite toda la noche para compilarlo. Por otro lado, podemos tener problemas con las fechas de los archivos, por lo que es fundamental cambiarlas utilizando el comando <strong>touch *<\/strong> en cada directorio. Esto se puede hacer m\u00e1s c\u00f3modamente con la l\u00ednea<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">find -type d -exec touch {}\/* ;<\/pre>\n<\/div>\n<p>que har\u00e1 un <strong>touch *<\/strong> de manera recursiva en cada directorio. Una vez hecho esto, instalamos <a href=\"http:\/\/www.gnu.org\/software\/autoconf\/\" target=\"_blank\">autoconf<\/a>, <a href=\"http:\/\/www.gnu.org\/software\/automake\/\" target=\"_blank\">automake<\/a> y <a href=\"http:\/\/www.gnu.org\/software\/libtool\/\" target=\"_blank\">libtool<\/a> (no olvidarse de touch en cada uno), y ya tendremos nuestro sistema de desarrollo completo con el que podremos compilar cualquier utilidad. S\u00f3lo hay que tener en cuenta algunos detalles:<\/p>\n<ul>\n<li>El procesador del disco duro no es gran cosa, as\u00ed que la compilaci\u00f3n tarda BASTANTE tiempo<\/li>\n<li>Es fundamental a\u00f1adir la opci\u00f3n <em>-static<\/em> en las opciones de enlazado. En algunos programas es posible hacerlo a\u00f1adiendo <em>LDFLAGS=-static <\/em>justo antes de <em>.\/configure<\/em> (ejemplo: para configurar <strong>ctorrent<\/strong>, la l\u00ednea ser\u00eda <em>LDFLAGS=-static .\/configure<\/em>); otra opci\u00f3n es lanzar primero <em>.\/configure<\/em> y luego editar el Makefile para a\u00f1adirlo donde se defina LDFLAGS. Como opci\u00f3n final, se puede compilar normalmente y, cuando termine, copiar y pegar las l\u00edneas de enlazado (suele ser la \u00faltima) y a\u00f1adir <em>-static<\/em> a mano antes de ejecutarla.<\/li>\n<li>Es muy recomendable eliminar el par\u00e1metro <em>-g<\/em> durante la compilaci\u00f3n, pues lo que hace es a\u00f1adir informaci\u00f3n de depuraci\u00f3n totalmente innecesaria, adem\u00e1s de impedir que el compilador pueda aplicar muchas optimizaciones. Para hacer esto no queda m\u00e1s remedio que editar manualmente el fichero <em>Makefile<\/em> (no olvidar que puede haber varios Makefiles en otros subdirectorios. Hay que editarlos todos). Tambi\u00e9n es bueno utilizar el comando <em>strip<\/em> en el ejecutable final para eliminar los \u00faltimos restos de datos de depuraci\u00f3n<\/li>\n<li>Algunos programas est\u00e1n preparados para versiones de autoconf o automake anteriores a la que hemos instalado. En ese caso basta con hacer un <em>autoreconf<\/em> para regenerar los ficheros. Este debe hacerse despu\u00e9s de <em>autogen.sh<\/em> si lo hubiera. Una vez hecho esto ya se puede ejecutar <em>.\/configure<\/em> y <em>make<\/em>.<\/li>\n<li>Es necesario ajustar las fechas de los archivos porque, si no, Make se l\u00eda y no sabe qu\u00e9 compilar. Para ello basta con ejecutar el comando <strong>touch *<\/strong> en todos y cada uno de los directorios del programa a compilar (la l\u00ednea <strong>find -type d -exec touch {}\/* ;<\/strong> lo har\u00e1 de manera recursiva por nosotros). No recomiendo cambiar la hora del disco duro porque, por alguna raz\u00f3n, las veces que lo hice el sistema se volvi\u00f3 inestable, llegando a colgarse incluso.<\/li>\n<li>En algunos programas, libtool \u00abse vuelve loco\u00bb y empieza a lanzar copias de s\u00ed mismo indiscriminadamente, llegando a ahogar al procesador y colgando el disco duro. Si, cuando va a enlazar el c\u00f3digo, un PS nos devuelve una gran cantidad de procesos libtool, hay que matarlos r\u00e1pidamente y enlazar \u00aba mano\u00bb el c\u00f3digo.<\/li>\n<\/ul>\n<p>Para aquellos que no quieran pasar todo el trabajo, pueden bajarse el <a href=\"http:\/\/www.rastersoft.com\/blogpic\/buildchain_1.0.zip\">entorno de compilaci\u00f3n completo aqu\u00ed<\/a>. Basta con descomprimir el .zip, copiar el .tar en el directorio <em>\/tmp\/hdd\/volumes\/HDD1<\/em> del disco duro y descomprimirlo mediante<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">tar -xpvf buildchain_1.0.tar<\/pre>\n<\/div>\n<p>entrar en el directorio con <em>cd buildchain<\/em>, montar los sistemas de archivos virtuales (<em>proc, dev<\/em> y <em>sys<\/em>) con <em>.\/mount.sh<\/em> y lanzar un chroot con <em>.\/launch.sh<\/em>. Una vez se haya terminado, salir y desmontar los sistemas de archivos virtuales con <em>.\/umount.sh<\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>En la entrada Emergiendo expliqu\u00e9 como generar un entorno de compilaci\u00f3n cruzada basado en Gentoo para poder compilar cosas para nuestro disco duro, pero luego, en FTP-ando, ech\u00e9 todo por tierra al no poner binarios creados por m\u00ed. Ahora ya he sido capaz de compilar, as\u00ed que, para los impacientes, aqu\u00ed est\u00e1 el paquete con &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=372\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">Compilacion en masa<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,7],"tags":[],"class_list":["post-372","post","type-post","status-publish","format-standard","hentry","category-cacharreo","category-tutoriales"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/372","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=372"}],"version-history":[{"count":2,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/372\/revisions"}],"predecessor-version":[{"id":1893,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/372\/revisions\/1893"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}