Ok, esto es solo un ejercicio un poco divertido, pero no puede ser muy difícil compilar programas para algunos sistemas linux antiguos, ¿o sí?cómo portar aplicaciones c/C++ a versiones heredadas del núcleo de Linux
Tengo acceso a un par de sistemas antiguos que ejecutan Linux y tal vez sería interesante ver cómo funcionan bajo carga. Digamos, por ejemplo, que queremos hacer un poco de álgebra lineal usando Eigen, que es una buena biblioteca de solo encabezado. ¿Alguna posibilidad de compilarlo en el sistema de destino?
[email protected]:~ $ uname -a
Linux local 2.2.16 #5 Sat Jul 8 20:36:25 MEST 2000 i586 unknown
[email protected]:~ $ gcc --version
egcs-2.91.66
Quizás no ... Así que compilemos en un sistema actual. A continuación están mis intentos, principalmente los fallidos. Cualquier otra idea muy bienvenida.
compilar con
-m32 -march=i386
[email protected]:~ $ ./a.out BUG IN DYNAMIC LINKER ld.so: dynamic-link.h: 53: elf_get_dynamic_info: Assertion `! "bad dynamic tag"' failed!
compilar con
-m32 -march=i386 -static
: Se ejecuta en todas las versiones bastante recientes del kernel, pero no si son un poco mayores con el mensaje de error conocido[email protected]:~ $ ./a.out FATAL: kernel too old Segmentation fault
Este es un error
glibc
que tiene una versión mínima del kernel compatible, por ejemplo kernel 2.6.4 en mi sistema:$ file a.out a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.4, not stripped
Compilar
glibc
mismo con soporte para el núcleo más antiguo sea posible. This post lo describe con más detalle pero en esencia es la siguientewget ftp://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.bz2 tar -xjf glibc-2.14.tar.bz2 cd glibc-2.14 mkdir build; cd build ../configure --prefix=/usr/local/glibc_32 \ --enable-kernel=2.0.0 \ --with-cpu=i486 --host=i486-linux-gnu \ CC="gcc -m32 -march=i486" CXX="g++ -m32 -march=i486" make -j 4 make intall
No estoy seguro si los
--with-cpu
y--host
opciones hacen nada, lo más importante es forzar el uso de opciones del compilador-m32 -march=i486
de 32 bits construye (por desgracia-march=i386
fianzas con errores después de un tiempo) y--enable-kernel=2.0.0
para hacer que la biblioteca sea compatible con kernels más antiguos. Incidentially, duranteconfigure
me dieron el avisoWARNING: minimum kernel version reset to 2.0.10
que todavía es aceptable, supongo. Para obtener una lista de cosas que cambian con diferentes kernels, vea
./sysdeps/unix/sysv/linux/kernel-features.h
.Ok, así que vamos enlace en contra de la
glibc
biblioteca recién compilado, un poco desordenado, pero aquí va:$ export LIBC_PATH=/usr/local/glibc_32 $ export LIBC_FLAGS=-nostdlib -L${LIBC_PATH} \ ${LIBC_PATH}/crt1.o ${LIBC_PATH}/crti.o \ -lm -lc -lgcc -lgcc_eh -lstdc++ -lc \ ${LIBC_PATH}/crtn.o $ g++ -m32 -static prog.o ${LIBC_FLAGS} -o prog
Ya que estamos haciendo una compilación estática del link order es importante y bien puede requerir un poco de ensayo y error , pero en el fondo sabemos por qué opciones
gcc
da al enlazador:$ g++ -m32 -static -Wl,-v file.o
Nota,
crtbeginT.o
ycrtend.o
también están vinculados contra el que no necesitaba para m y programas, así que los dejé fuera. La salida también incluye una línea como--start-group -lgcc -lgcc_eh -lc --end-group
que indica interdependencia entre las bibliotecas, consulte this post. Acabo de mencionar-lc
dos veces en la línea de comandosgcc
que también resuelve la interdependencia.derecho, el trabajo duro ha dado sus frutos y ahora conseguir
$ file ./prog ./prog: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.0.10, not stripped
brillante pensé, ahora probarlo en el viejo sistema:
[email protected]:~ $ ./prog set_thread_area failed when setting up thread-local storage Segmentation fault
Esto, de nuevo, es un error de
glibc
mensaje de./nptl/sysdeps/i386/tls.h
. No entiendo los detalles y me rindo.Compilar en el nuevo sistema
g++ -c -m32 -march=i386
y vincular en el anterior. Wow, eso realmente funciona para C y programas sencillos de C++ (sin usar objetos C++), al menos para los pocos que he probado. Esto no es demasiado sorprendente ya que todo lo que necesito delibc
esprintf
(y tal vez algunas matemáticas) cuya interfaz no ha cambiado, pero la interfaz alibstdc++
es muy diferente ahora.Configura una caja virtual con un sistema linux antiguo y la versión 2.95 de gcc. A continuación, compile la versión 4.x.x de gcc ... lo siento, pero demasiado perezoso para eso en este momento ...
???
¿Compilar? ¿Una biblioteca de plantillas solo de encabezado? –
Compile un programa de prueba que use esta biblioteca de plantillas. Este es solo un ejemplo de algún código que no se compilaría en la máquina de destino debido a la versión obsoleta de gcc. – user1059432
Ah, está bien. Lo siento, simplemente incomprendido. –