Ahora que el software está configurado correctamente, sólo falta compilarlo. Generalmente esta parte es fácil, y no presenta problemas serios.
make es la herramienta favorita de la comunidad de software libre para compilar los fuentes. Tiene dos cosas interesantes:
Las acciones a
ejecutar para obtener una versión compilada de los fuentes
generalmente se almacenan en un fichero denominado
Makefile
o GNUMakefile
.
De hecho, cuando se invoca a make, este lee
dicho fichero, si existe, en el directorio corriente. Si no es
así, se puede especificar el fichero usando la opción
-f
con make.
make funciona de acuerdo a un sistema de
dependencias,
razón por la cual la compilación de un fichero binario
(“objetivo”)
necesita pasar por varias etapas (“dependencias”). Por
ejemplo, para crear el fichero binario (imaginario)
glloq
, se deben compilar y luego vincular los
ficheros objeto main.o
e
init.o
(ficheros intermedios de la
compilación). Estos ficheros objeto también son objetivos, cuyas
dependencias son sus ficheros fuente correspondiente.
Este texto sólo es una introducción mínima para sobrevivir en el mundo sin piedad de make. Para una documentación exhaustiva, debe referirse a Managing Projects with Make (Administración de proyectos con Make), segunda edición, de O'Reilly, por Andrew Oram y Steve Talbott.
Por lo general, el uso de make obedece a muchas convenciones. Por ejemplo:
make sin argumentos simplemente ejecuta la compilación del programa, sin instalarlo.
make
install compila el programa (aunque no siempre), y
asegura la instalación de los ficheros necesarios en el lugar
adecuado del sistema de ficheros. Algunos ficheros no siempre se
instalan correctamente (man
,
info
), ellos deben ser copiados por el
usuario. Algunas veces, make install tiene
que volver a ser ejecutado en los subdirectorios. Por lo
general, esto pasa con los módulos desarrollados por
terceros.
make clean borra todos los ficheros temporales creados por la compilación, y, en la mayoría de los casos, el fichero ejecutable.
La primera etapa para compilar un programa es ingresar (ejemplo imaginario):
$ make gcc -c glloq.c -o glloq.o gcc -c init.c -o init.o gcc -c main.c -o main.o gcc -lgtk -lgdk -lglib -lXext -lX11 -lm glloq.o init.o main.o -o glloq
Excelente, el fichero binario está compilado correctamente. Ahora estamos preparados para la etapa siguiente, que es la instalación de los ficheros de la distribución (ficheros binarios, ficheros de datos, etc...). Consulte la sección Sección 5, “Instalación”.
Si
Usted es lo suficientemente curioso para mirar el fichero
Makefile
, encontrará comandos conocidos
(rm, mv, cp, ...), aunque también encontrará
algunas cadenas extrañas, de la forma
$(CFLAGS)
.
Estas son variables,
es decir las cadenas que generalmente se fijan al comienzo del
fichero Makefile
, y luego se reemplazan por
el valor con el cual están asociadas. Esto es bastante útil cuando
quiere usar las mismas opciones de compilación varias
veces a la vez.
Por ejemplo, puede
mostrar la cadena “pepe
” en la
pantalla usando make all:
TEST = pepe all: echo $(TEST)
La mayoría de las veces, se definen las variables siguientes:
CC
:
este es el compilador que va a utilizar. Generalmente es
cc1, que en la mayoría de los sistemas libres, es
sinónimo de gcc. Cuando tenga dudas, ponga aquí
gcc.
LD
:
este es el programa usado para asegurar la fase de la
compilación final (consulte la sección Sección 1.2.2, “Las cuatro fases de la compilación”)
El valor predeterminado es ld.
CFLAGS
:
estos son los argumentos adicionales que se pasarán al
compilador durante las primeras etapas de la compilación. Entre
ellos:
-I<ruta>
:
le especifica al compilador donde buscar algunos ficheros de
encabezado adicionales (por ejemplo:
-I/usr/X11R6/include
permite incluir los
ficheros de encabezado que están en el directorio
/usr/X11R6/include
)
-D<símbolo>
:
define un símbolo adicional, útil para los programas cuya
compilación depende de los símbolos definidos (ejemplo: utilizar el
fichero string.h
si está definida
HAVE_STRING_H
)
Generalmente hay líneas de compilación de la forma:
$(CC) $(CFLAGS) -c pepe.c -o pepe.o
LDFLAGS
(o LFLAGS
): estos son los argumentos que se
usan durante la última etapa de compilación. Entre ellos:
No tenga pánico, le puede pasar a cualquiera. Entre las causas más comunes:
glloq.c:16:
decl.h: No such file or directory
(glloq.c
:16
: decl.h
: no hay fichero o
directorio con ese nombre)
El compilador no pudo encontrar el fichero de encabezado correspondiente. Por lo tanto, la etapa de configuración del software debería haber anticipado este error. Cómo resolver este problema:
verifique que
verdaderamente exista el fichero de encabezado en cuestión en
uno de los directorios siguientes:
/usr/include
,
/usr/local/include
,
/usr/X11R6/include
o en alguno de sus
subdirectorios. De no ser así, búsquelo por todo el disco (con
find o locate), y, si todavía no lo encuentra,
verifique que ha instalado la biblioteca de desarrollo
correspondiente a este fichero de encabezado. Puede encontrar
ejemplos de los comandos find y locate en las
respectivas páginas Man.
Verifique que el fichero de encabezado se pueda leer (para verificarlo, puede ingresar less <ruta>/<fichero>.h)
Si es un
directorio como /usr/local/include
o como
/usr/X11R6/include
, Usted tiene que
agregar, a veces, un argumento nuevo al compilador. Abra el
fichero Makefile
correspondiente (tenga
cuidado de abrir el fichero correcto, los que se encuentran en
el directorio donde falla la compilación[39]) con su editor de
texto favorito (Emacs, Vi, etc). Busque la línea
errónea, y agregue la cadena -I<ruta>
,
donde <ruta>
es la ruta donde se puede
encontrar el fichero de encabezado en cuestión, justo después
de la llamada del compilador (gcc
, o, a
veces, $(CC)
). Si no sabe donde agregar esta
opción, agréguela al comienzo del fichero, después de
CFLAGS=<algo>
o después de
CC=<algo>
.
ejecute make de nuevo, y si todavía sigue sin funcionar, verifique que esta opción (ver el punto anterior) se agrega durante la compilación en la línea errónea.
si todavía sigue sin funcionar, pida ayuda al autor del software, a su gurú local, o a la comunidad de software libre para resolver su problema (consulte la sección Sección 6.2, “Soporte técnico”)
glloq.c:28:
`struct pepe' undeclared (first use this function)
(glloq.c:28
: “struct
pepe
” no está declarada (esta es la primera
utilización en esta función))
Las estructuras son tipos de datos especiales, que usan todos los programas. El sistema define un montón de ellas en los ficheros de encabezados. Eso significa que es muy probable que el problema sea la falta o el mal uso de un fichero de encabezado. El procedimiento correcto para resolver el problema es:
intente verificar si la estructura en cuestión es una estructura definida por el programa o por el sistema. Una solución es usar el comando grep para ver si la estructura está definida en alguno de los ficheros de encabezado.
Por ejemplo, cuando Usted está en la raíz de la distribución:
$ find . -name '*.h'| xargs grep 'struct pepe' | less
Es posible que aparezcan muchas líneas en la pantalla (por ejemplo, cada vez que se define una función que use esta estructura). Elija, si existe, la línea donde se define la estructura mirando el fichero de encabezado obtenido por la utilización del comando grep.
La definición de una estructura es:
struct pepe { <contenido de la estructura pepe> };
Verifique si
ella corresponde a lo que Usted tiene. De ser así, eso
significa que no se incluye el encabezado en el fichero
.c
erróneo. Hay dos soluciones:
si este no es el
caso, haga lo mismo con los ficheros de encabezado del sistema
(que, generalmente, se encuentran en los directorios
siguientes: /usr/include
,
/usr/X11R6/include
y
/usr/local/include
). Pero en este caso,
use la línea #include
<<nombre_de_fichero>.h>
.
si todavía no
existe esta estructura, intente encontrar en que biblioteca
(es decir, conjunto de funciones agrupadas en un solo paquete)
debería estar definida (ver en el fichero
INSTALL
o README
cuales son las bibliotecas que usa este programa y las
versiones necesarias). Si la versión que necesita el programa
no está instalada en el sistema, Usted deberá actualizar esta
biblioteca. Cabe destacar que debe tener sumo cuidado al
manipular los ficheros de encabezado del sistema, ya que estos
son comunes a muchos programas.
si todavía sigue sin funcionar, verifique que el programa funciona adecuadamente sobre su arquitectura (algunos programas todavía no han sido portados a todos los sistemas UNIX®). Verifique también que ha configurado el programa correctamente (por ejemplo, cuando ejecutó configure) para su arquitectura.
parse
error
(error de análisis sintáctico)
Este es un problema que es relativamente complicado de resolver, porque generalmente es un error que aparece en cierta línea, pero después que el compilador lo encontró. A veces, es simplemente un tipo de datos que no está definido. Si Usted encuentra un mensaje de error del tipo:
main.c:1: parse error before `glloq_t main.c:1: warning: data definition has no type or storage class
entonces el
problema es que el tipo glloq_t
no está
definido. La solución al problema es más o menos la misma que en
el problema anterior.
no space
left on device
(no queda espacio en el
dispositivo)
Este problema es simple de resolver: no hay espacio
suficiente en el disco para generar un fichero binario a partir
del fichero fuente. La solución consiste en liberar espacio en
la partición que contiene el directorio de instalación (borrar
ficheros innecesarios, ficheros temporales, desinstalar
programas que no use, cambiar el tamaño de la partición,
etc.). Si descomprimió en /tmp
, mejor
hágalo en /usr/local/src
que evita la
saturación innecesaria de la partición
/tmp
. Verifique si hay ficheros
core
[40] en
su disco. De ser así, elimínelos o haga que el usuario al cual
pertenezcan los elimine.
/usr/bin/ld:
cannot open -lglloq: No such file or directory
(/usr/bin/ld: no puedo abrir -lglloq: no hay fichero o
directorio alguno con ese nombre
).
Esto significa
claramente que el programa ld (usado por gcc
durante la última etapa de la compilación) no puede encontrar
una biblioteca. Para incluir una biblioteca, ld busca un
fichero cuyo nombre está en los argumentos del tipo
-l<biblioteca>
. Este fichero es
lib<biblioteca.so>
. Si ld no puede
encontrarlo, produce un mensaje de error. Para resolver el
problema, siga los pasos que se indican a continuación:
verifique
que el fichero existe en el disco rígido usando el comando
locate. Por lo general, las bibliotecas gráficas se
encuentran en /usr/X11R6/lib
. Por
ejemplo:
$ locate libglloq
Si la búsqueda no tiene resultado, puede buscar con el comando find (ejemplo: find /usr -name "libglloq.so*"). Si Usted no puede encontrar la biblioteca, entonces tendrá que instalarla.
una vez que está
localizada la biblioteca, verifique que ld puede
accederla: el fichero que especifica donde encontrar estas
bibliotecas es /etc/ld.so.conf
. Agregue
el directorio en cuestión al final del mismo y ejecute
ldconfig. También puede agregar este
directorio a la variable de entorno
LD_LIBRARY_PATH
. Por ejemplo, si el
directorio a agregar es /usr/X11R6/lib
,
ingrese:
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/X11R6/lib
si todavía
no funciona, verifique que el formato de la biblioteca en
cuestión es un fichero ejecutable (o ELF) (con el comando
file). Si esta es un vínculo simbólico, verifique que el
vínculo es correcto y no apunta a un fichero inexistente (por
ejemplo, con nm <lib>). Los permisos
pueden ser erróneos (por ejemplo, Usted usa una cuenta que no
es root
y la biblioteca está protegida contra
lectura).
glloq.c(.text+0x34):
undefined reference to
`
(glloq_init
'glloq.c(.text+0x34)
: referencia indefinida
al símbolo `glloq_init
')
Esto significa que no se resolvió un símbolo durante la última etapa de la compilación. Por lo general, este es un problema de biblioteca. Puede haber varias causas:
la primera cosa
a hacer es saber si se supone que el
símbolo esté presente en una biblioteca. Por ejemplo, si es un
símbolo que comienza por gtk
, pertenece a
la biblioteca gtk
. Si el nombre de la
biblioteca es difícil de identificar (como por ejemplo,
zorglub_gloubiboulga
), se pueden listar
los símbolos de una biblioteca con el comando
nm. Por ejemplo,
$ nm libglloq.so 0000000000109df0 d glloq_message_func 000000000010a984 b glloq_msg 0000000000008a58 t glloq_nearest_pow 0000000000109dd8 d glloq_free_list 0000000000109cf8 d glloq_mem_chunk
Agregar la
opción -o
a nm permite
mostrar el nombre de la biblioteca en cada línea, lo cual
facilita la búsqueda. Imaginemos que buscamos el símbolo
bulgroz_max
, una solución cruda es realizar
una búsqueda del tipo:
$ nm /usr/lib/lib*.so | grep bulgroz_max $ nm /usr/X11R6/lib/lib*.so | grep bulgroz_max $ nm /usr/local/lib/lib*.so | grep bulgroz_max /usr/local/lib/libfrobnicate.so:000000000004d848 T bulgroz_max
¡Formidable! El
símbolo bulgroz_max
está definido en la
biblioteca zorglub
(la letra mayúscula
T
se encuentra delante de su nombre)
Entonces, Usted sólo tiene que agregar la cadena
-lzorglub
en la línea de compilación
editando el fichero Makefile
: agréguela
al final de la línea donde se define la variable
LDFLAGS
o LFGLAGS
(o, en
el peor de los casos, CC
), o en la línea
correspondiente a la creación del fichero binario
final.
la compilación
está hecha con una versión de la biblioteca que no es la que
permite el software. Lea el fichero
README
o INSTALL
de
la distribución para saber que versión de la biblioteca debe
usar.
no todos los
ficheros objeto de la distribución están vinculados
correctamente. Falta, o no se menciona, el fichero donde está
definida esta función. Ingrese nm -o *.o,
para saber el nombre del fichero .o
correspondiente y agréguelo en la línea de compilación si es
que falta.
la función o variable en cuestión puede ser fantasiosa. Intente eliminarla: edite el fichero fuente en cuestión (el nombre del mismo se especifica al comienzo del mensaje de error). Esta es una solución desesperada cuya consecuencia ciertamente será un funcionamiento anárquico del software (error de segmentación en el arranque, etc.)
Segmentation
fault (core dumped)
(Error de segmentación (se produjo
un fichero core
)).
A veces, el compilador se cuelga lamentablemente y produce este mensaje de error. No tengo consejo alguno, salvo pedirle que instale una versión más reciente de su compilador.
La compilación necesita espacio temporal durante
las diferentes etapas; si no tiene espacio suficiente,
falla. Por lo tanto, debe limpiar la partición, pero debe tener
cuidado ya que algunos programas en curso de ejecución (servidor
X, tuberías, etc.) se pueden colgar si se borran algunos
ficheros ¡Usted debe saber lo que está haciendo! Si
tmp
es parte de una partición que contiene
otros directorios (por ejemplo, la raíz), busque y borre algunos
ficheros core
eventuales. También se puede
cambiar el tamaño a la partición, si es que hay espacio libre
suficiente o se puede reducir temporalmente alguna otra
partición.
make / configure en bucle infinito
Generalmente, esto es un problema de la hora en su sistema. En efecto, make necesita saber la fecha y la hora de la computadora y de los ficheros que verifica. Este compara las fechas de los ficheros y usa el resultado para saber si el objetivo es más reciente que la dependencia.
Algunos problemas en la fecha pueden inducir a make a reconstruirse a sí mismo indefinidamente (o a construir y reconstruir un subárbol en bucle). Si es así, el uso del comando touch (cuya consecuencia es poner en la hora corriente a los ficheros pasados como argumento) resuelve el problema la mayoría de las veces.
$ touch *
O también (más bruto, pero eficiente):
$ find . | xargs touch
[39] Analice el mensaje de error que devuelve
make. Normalmente, las últimas líneas deberían contener
un directorio (un mensaje como make[1]: Leaving
directory `/home/reina/Proyecto/pepe'
). Elija
aquel que tiene el número más grande. Para verificar que es el
bueno, vaya al directorio y ejecute make de nuevo para
obtener el mismo error.
[40] Fichero generado por el sistema cuando un proceso intenta acceder a una ubicación de memoria a la cual no tiene permiso para acceder. Estos archivos se utilizan para analizar la razón de tal comportamiento para corregir el problema.