270 likes | 450 Views
Herramientas de construcción ( Build ). Utilidad ‘make’ y similares. Contenido. Objetivo y funciones Proceso de compilación y montaje Dependencias y regeneración selectiva Makefile Aplicaciones Generación automática de dependencias Limitaciones de ‘make’
E N D
Herramientas de construcción (Build) Utilidad ‘make’ y similares
Contenido • Objetivo y funciones • Proceso de compilación y montaje • Dependencias y regeneración selectiva • Makefile • Aplicaciones • Generación automática de dependencias • Limitaciones de ‘make’ • Otras herramientas de construcción
Objetivo y funciones • Objetivo: • Generar o actualizar automáticamente ficheros dependientes de otros, de forma selectiva • Modo de operación: • Compara la fecha de actualización de cada fichero con la de los que depende, y si está anticuado lo regenera • Aplicación típica: • Compilación y montaje de programas
Compilación y montaje • Inicialmente hay que compilar todo alfa.c alfa.o prog gcc -c alfa.c -o alfa.o gcc -o prog alfa.o beta.o beta.c beta.o gcc -c beta.c -o beta.o
Recompilación selectiva • Posteriormente sólo se recompila lo que cambia * = modificado * * alfa.c alfa.o * prog gcc -c alfa.c -o alfa.o gcc -o prog alfa.o beta.o beta.c beta.o
Recompilación selectiva • Posteriormente sólo se recompila lo que cambia * = modificado alfa.c alfa.o * prog * * gcc -o prog alfa.o beta.o beta.c beta.o gcc -c beta.c -o beta.o
Comparación de fechas • Proceso automático, comparando fechas 11.15 12.00 alfa.c alfa.o 12.32 12.02 prog 12.31 12.30 12.01 gcc -o prog alfa.o beta.o beta.o beta.c gcc -c beta.c -o beta.o
ajustar parrafo linea palabra Dependencias múltiples • Programa modular, jerarquizado
ajustar.cpp ajustar.o ajustar parrafo.h parrafo.cpp parrafo.o linea.h linea.cpp linea.o palabra.h palabra.cpp palabra.o Dependencias múltiples • Dependencias entre ficheros
ajustar.cpp ajustar.o ajustar (*) parrafo.h parrafo.cpp parrafo.o linea.h linea.cpp (*) linea.o (*) palabra.h palabra.cpp palabra.o Dependencias múltiples • Si cambia algo, se recompila lo que depende de él
ajustar.cpp ajustar.o (*) ajustar (*) parrafo.h parrafo.cpp parrafo.o (*) linea.h (*) linea.cpp linea.o (*) palabra.h palabra.cpp palabra.o Dependencias múltiples • Si cambia algo, se recompila lo que depende de él
Utilidad ‘make’ • Automatiza el proceso de regeneración selectiva • Detecta los ficheros no actualizados mediante la comparación de fechas • Necesita información de las dependencias entre ficheros y las acciones para regenerarlos • Esta información se suministra en un fichero denominado genéricamente ‘makefile’, usando una notación específica, basada en reglas • Cada regla contiene las dependencias de un fichero respecto a los demás, y las acciones para regenerarlo
‘makefile’ • Regla = dependencias + acciones objetivo: dependencia dependencia ... accion accion . . . objetivo: dependencia ... accion . . . • Nota: el símbolo es el carácter de tabulación
Ejemplo de ‘makefile’ ajustar: ajustar.o parrafo.o linea.o palabra.o g++ -o ajustar ajustar.o parrafo.o linea.o \ palabra.o palabra.o: palabra.cpp palabra.h g++ -c palabra.cpp -o palabra.o linea.o: linea.cpp linea.h palabra.h g++ -c linea.cpp -o linea.o . . .
Cómo invocar ‘make’ • Dando la orden: • make [ -fmakefile ] [ opciones ] [ objetivos ] • Algunos parámetros: • makefile – fichero de reglas (por defecto makefile) • opción-k – continuar aunque haya errores • objetivos – objetivos a actualizar (por defecto el de la primera regla que haya en el fichero makefile) • Ejemplo: • make (sin parámetros) • Usa el fichero makefile y actualiza el primer objetivo
Variables y reglas implícitas • Variables – toman valores de texto • Asignación: variable = valor • Uso: … $(variable) … • Reglas implícitas – plantillas genéricas • Dependencias – usando patrones • %.ext1: %.ext2 • Acciones – usando ‘macros’ • $@ - objetivo $< - primera dependencia • $? - dependencias modificadas $^ - dependencias (todas) • $* - lo que se ajusta al patrón % • Las reglas se invocan con una línea de dependencias que se ajuste al patrón de dependencias
Variables y reglas implícitas OBJS = ajustar.o parrafo.o linea.o palabra.o ajustar: $(OBJS) g++ -o ajustar $(OBJS) %.o : %.cpp g++ -c $< -o $@ palabra.o: palabra.cpp palabra.h linea.o: linea.cpp linea.h palabra.h . . .
Otras aplicaciones • Cualquier situación en que unos ficheros se actualizan a partir de otros que cambian • Hacer copias de backup • Generar formatos finales de documentos • Actualizar contenido de sitios web • Ejecutar pruebas de programas • Regenerar instalaciones de software • Borrar ficheros anticuados • … etc. …
Ejemplo • ‘Backup’/’Mirror’ incremental directorio copia fichero1 fichero1 fichero2 fichero2 fichero3 fichero3 • Situación inicial
Ejemplo • ‘Backup’/’Mirror’ incremental directorio copia fichero1 fichero1 fichero2 fichero2 fichero3 fichero3 . . . ficheroN • Modificado fichero2, nuevo ficheroN
Ejemplo • ‘Backup’/’Mirror’ incremental directorio copia fichero1 fichero1 fichero2 fichero2 fichero3 fichero3 . . . . . . ficheroN fichero N • Sólo hay que copiar lo que cambia
Ejemplo • ‘Backup’ incremental (1) BAK/fichero1: fichero1 copy fichero1 BAK BAK/fichero2: fichero2 copy fichero2 BAK . . . • Rudimentario: hay que nombrar cada fichero
Ejemplo • ‘Backup’ incremental (2) copia: *.c *.h copy $? BAK touch copia • ‘touch’ cambia la fecha de actualización del fichero que se indique, poniendo la fecha de ese momento • ‘copia’ es un fichero vacío, que sirve para tener la fecha del último ‘backup’
Dependencias automáticas • La preparación manual del makefile es laboriosa • Es fácil olvidarse de algunas dependencias • Se puede automatizar en parte • Hay herramientas para analizar las dependencias • Para ello se analizan las directivas #include • Utilidad makedepend • Invoca el preprocesador y analiza los #include • Añade las dependencias el final del makefile, precedidas de la marca: # DO NOT DELETE THIS LINE -- make depend depends on it. • Esta marca permite regenerar (reescribir) las dependencias, conservando el resto del makefile.
Dependencias automáticas • Compilador gcc/g++ • Tiene una capacidad equivalente a ‘makedepend’ • Se invoca como gcc –MM (o g++ -MM) • Escribe las dependencias por la salida estándar • Ejemplo: g++ -MM *.cpp > ajustar.o: ajustar.cpp palabra.h ... > linea.o: linea.cpp linea.h palabra.h > palabra.o: palabra.cpp palabra.h > parrafo.o: parrafo.cpp parrafo.h linea.h ...
Desventajas de ‘make’ • La preparación manual del makefile es laboriosa • La reconstrucción no es segura • No se detectan cambios ‘hacia atrás’ • Puede ser poco eficiente • Se reconstruye aunque no cambien objetivos intermedios • Reconstruye más de lo necesario tras ligeros cambios en cabeceras básicas • Ficheros makefile poco transportables • Las acciones son específicas para cada plataforma: ‘shell’, compilador, etc.
Otras herramientas de construcción • Hay muchas herramientas similares a ‘make’ • Algunas muy similares • Otras más elaboradas • Ejemplos • A-a-p: sencilla de usar, basta la lista de fuentes • Jam: sencilla de usar (como la anterior) • Cook: usa una herramienta separada para las dependencias (c_incl), notación tipo Lisp • Ant: muy usado con Java, reglas con marcado XML • SCons: reconstrucción más segura, basado en Python