lunes, 22 de octubre de 2012

Proyectos C/C++ de Eclipse a Autotools

La problemática de preparar proyectos de C/C++ para que se compilen en cualquier sistema compatible con el estándar POSIX, con las herramientas recomendadas por GNU conocidas como Autotools (autoconf, autoheader, automake, autoreconf, aclocal, libtoolize) es un procedimiento que puede llegar a ser exhaustivo, confuso y agobiante si no se cuenta con sugerencias prácticas y aspectos básicos sobre estas herramientas. Como Eclipse es uno de los ambientes de desarrollo más populares sobre todo en Linux, cuenta con un tipo de proyecto llamado GNU Autotools que da un buen nivel de integración con dichos programas e incluye un eficaz resaltado de sintaxis. Sin embargo, por defecto no permite ejecución o depuración, además de dar un cascarón vacío que carece de una información que bien pudiera deducirse automáticamente a partir de los proyectos originales de C/C++. Este artículo trata de cómo crear proyectos GNU Autotools en Eclipse que reutilicen los proyectos Executable, Shared library y Static library sin perder la posibilidad de depurarlos, ejecutarlos y mantenerlos. Supongamos que nuestro proyecto original se llame ProjectX.
  1. Creamos un directorio llamado gnu-ProjectX (puede ser otro nombre) al mismo nivel que nuestro proyecto en el espacio de trabajo de Eclipse.
  2. Movemos la carpeta del proyecto original hacia dentro gnu-ProjectX. Es importante aclarar que con un enlace simbólico FUNCIONAN ERRÓNEAMENTE las Autotools, por lo que desechamos esta variante.
  3. Desde Eclipse, eliminamos el proyecto ProjectX del workspace. ¡Es importante haber realizado el paso 2 antes de hacer esto!
  4. Creamos un nuevo proyecto de C/C++, en el wizard especificamos el nombre gnu-ProjectX (que coincide con el directorio que creamos anteriormente) como proyecto GNU Autotools, y según nuestro objetivo seleccionamos:
    • Hello World C++ Autotools Project, si lo que vamos a generar es un ejecutable.
    • Autotools Shared Library Project, si lo que vamos a generar es una biblioteca (estática o dinámica).
  5. Seguidamente, especificamos los datos de autor, copyright y demás. En el campo Source, entramos el nombre del proyecto original, ProjectX.
  6. Una vez creado el proyecto, podemos ver nuestro proyecto original dentro del nuevo proyecto. Podemos eliminar el archivo .cpp que se crea nuevo, pues no lo utilizaremos. ¡Cuidado no eliminar un archivo del proyecto original!
  7. Si lo que se ha creado es una biblioteca, deberá especificarse en el archivo configure.ac lo siguiente:
    AC_CONFIG_MACRO_DIR([m4])
    después del comando AC_PROG_LIBTOOL y en Makefile.am de la raíz del proyecto, especificar:
    ACLOCAL_AMFLAGS=-I m4
    para no recibir unas warnings cuando se ejecuten las Autotools.
  8. Verificamos en Makefile.am de la raíz que se incluya la línea:
    SUBDIRS=ProjectX
  9. con el nombre del directorio del proyecto original.
  10. La parte más complicada es modificar Makefile.am del directorio del proyecto ProjectX, por lo que brindaremos una secuencia especial de pasos:
    1. Si su código no está en la raíz del directorio del proyecto, deberá crear tantos Makefile.am como directorios anidados tenga, en los que debe especificar la variable SUBDIRS con los nombres de los directorios hijos necesarios. Luego, debe buscar la directiva AC_CONFIG_FILES en el archivo configure.ac y adicionar un Makefile por cada Makefile.am. Ejemplo:
      AC_CONFIG_FILES(Makefile 
                      ProjectX/Makefile 
                      ProjectX/src/Makefile)
    2. Buscamos una variable llamada bin_PROGRAMS y modificamos su valor al nombre del ejecutable que deseamos generar. Por ejemplo:
      bin_PROGRAMS=projectx.bin
      Si es una biblioteca, el prefijo deberá ser lib en vez de bin.
    3. Usando ese nombre, creamos (o modificamos si existe) una con el sufijo _SOURCES. Por ejemplo:
      projectx_bin_SOURCES=main.cpp tool.cpp write.cpp tools.h
      Para dar el valor de esta variable, podemos buscar el archivo subdir.mk que debe aparecer dentro de la carpeta Debug del proyecto ProjectX original. En este archivo debe aparecer una variable C_SRCS o CPP_SRCS en la que se enumeran los archivos de código fuente a compilar, por lo general uno por línea con \ al final. Copie y pegue el o los archivos aquí enumerados en en Makefile.am y asegúrese de que de ellos quede solo el nombre y extensión, es decir, que no tengan elementos de caminos relativos, como ../ . Al final del backslash que indica cambio de línea NO debe aparecer ningún otro caracter, incluido el espacio.
    4. Si tiene los archivos .c y/o .cpp distribuidos en varios directorios, entonces deberá poner los caminos relativos:
      projectx_bin_SOURCES=dir1/main.cpp dir2/tools.cpp
    5. Si usa alguna biblioteca, deberá definir una variable con el nombre del binario con sufijo _LDADD (o _LIBADD si es una biblioteca), por ejemplo:
      projectx_bin_LDADD=-ldaemon -lMyLib
      Para obtener estos valores, puede buscar el archivo objects.mk que debe aparecer dentro de la carpeta Debug del proyecto ProjectX. En este archivo debe aparecer una variable LIBS cuyo valor puede usar.
  11. Ahora debemos correr las Autotools en orden:
    • aclocal
    • autoheader (solo si se usa la directiva AC_CONFIG_HEADERS en configure.ac)
    • autoconf
    • libtoolize (solo para bibliotecas)
    • automake --add-missing
    • autoreconf (para reconfigurarlo todo, por si acaso)
    Esto se puede hacer desde la línea de comandos en el directorio del proyecto gnu-ProjectX o desde Eclipse, seleccionando el proyecto en el Project Explorer, y luego ir al menú Project / Invoke Autotools. Estas herramientas deben estar instaladas, desde luego. En Debian/Ubuntu por ejemplo, los paquetes autoconf, automake y libtool tienen todo lo necesario. En caso de que Eclipse emita un mensaje de error como:
    sh autoconf
    
    sh: 0: Can't open autoconf
    abra las propiedades del proyecto, busque la sección Autotools / General y en la pestaña Tool Settings especifique cada herramienta con su camino absoluto, por ejemplo: /usr/bin/autoconf. Consulte los manuales de las herramientas automake y autoconf para más información.
  12. Una vez corridas todas las Autotools sin error, deberán haberse creado muchos archivos nuevos, como son: aclocal.m4 config.guess config.status config.sub configure INSTALL install-sh Makefile Makefile.in missing.
  13. Supongamos que en nuestro código usamos encabezados (headers) o bibliotecas no estándares, es decir, que no aparecen por defecto bajo el directorio /usr/include o /lib, /usr/lib que son incluidos por defecto a la hora de compilar. Si es así, podemos optar por la alternativa de definir (o aumentar) las variables de entorno:
    • CPATH para los headers, caminos absolutos separados por dos puntos (:).
    • LIBRARY_PATH para las bibliotecas, caminos absolutos separados por dos puntos (:).
  14. Desde la línea de comandos, en el directorio gnu-ProjectX ejecute:
    ./configure
    
    make
    Chequee si se produjo o no algún error. En caso afirmativo, deberá comprender el mensaje de error para poder darle solución. Deberá determinar si el fallo fue en los archivos del configuración de Autotools, o faltan prerrequisitos, variables de entorno sin definición o incompletas, o errores de compilación. Según sea el caso, consulte los manuales o la Internet.
  15. Si todo terminó felizmente, pruebe a instalar (correr desde una cuenta con permisos de administración):
    make install
    Chequee el o los binarios en /usr/local/bin (por defecto) y las bibliotecas en /usr/local/lib.
  16. Si la instalación se realizó con éxito, trate de probar lo instalado. Una vez comprobado, puede ejecutar el comando:
    make dist
    para crear un paquete .tar.gz, el cual puede distribuir.
  17. Solo falta que volvamos a tener la posibilidad de ejecutar y depurar el proyecto. Esto es sencillo: desde el Project Explorer en Eclipse, haga clic derecho en algún lugar, debe aparecer la opción Import..., busque en General / Existing projects into Worspace, busque la carpeta de ProjectX dentro de gnu-ProjectX y haga clic en el botón Finish y listo.
En conclusión, ya estamos listos para empaquetar, desplegar y compilar nuestro código de C o C++, sin perder la posibilidad de mantenerlo actualizado, depurarlo y probarlo en Eclipse.

No hay comentarios:

Publicar un comentario