Make Http:// akefile.html.
-
Upload
virginia-gutierrez-miranda -
Category
Documents
-
view
221 -
download
0
Transcript of Make Http:// akefile.html.
Make
Http://www.geocities.com/chuidiang/herramientas/makefile.html
Make
El comando de linux make se usa en proyectos grandes, en los que hay muchos ficheros fuente (.c) y módulos (.o). Make tiene en cuenta las dependencias entre módulos.
Make determina si un conjunto de ficheros debe ser compilados, basándose en las fechas de última modificación de los ficheros destino y en las de los ficheros fuente, es decir, si uno de los ficheros fuente, necesario para crear un fichero destino, es más reciente que el fichero destino, un conjunto de comandos serán ejecutados. El propósito de estos comandos es actualizar el fichero destino.
Make
El fichero destino es el 'objetivo' y los ficheros fuente son los 'prerrequisitos'. Los comandos se ejecutan si uno de los 'prerrequisitos' es más reciente que el fichero destino (o si el destino no existe). Si todos los prerrequisitos son igual o más antiguos que el destino, entonces los comandos no se ejecutan y el fichero destino se considera actualizado.
En el directorio de trabajo actual, se debería crear un fichero con el nombre Makefile, GNUmakefile, makefile. Este fichero contiene la información que necesita make para realizar su trabajo de manera adecuada. Una vez que se tiene el Makefile (con 'M' mayúscula), la única cosa que hay que hacer es: teclear 'make' y los comandos necesarios para crear un nuevo fichero destino se ejecutan automáticamente.
MakeINC-DIR = -I. -I../include -I/usr/X11R6/include -I/usr/local/include
LIB-DIR = -L. -L/usr/X11/lib -L -L/usr/local/lib -L/usr/X11R6/lib
GCC = gcc
CFLAGS = -ansi -pedantic -Wall
all: eem
eem: eem.o feem.o
$(GCC) $(CFLAGS) $(LIB-DIR) -o eem eem.o feem.o -lRai -lforms -lX11 -lm
eem.o: eem.c
$(GCC) $(CFLAGS) $(INC-DIR) -c eem.c
feem.o: feem.c
$(GCC) $(CFLAGS) $(INC-DIR) -c feem.c
clean:
rm -f *.o
Make$make (Busca el objetivo principal)
objetivo principal: la parte izquierda de la primera regla que contiene “:”. Ejm:all que sacamos de la regla “all:eem”
Empieza a procesar el objetivo de la primera regla: all: eem
Encuentra que esta tiene una dependencia eem, por lo que va a buscar si hay un objetivo del tipo eem. En caso de que exista procesa dicho objetivo dejando el anterior a la espera de que termine este último. Y así sucesivamente hasta procesar todas las dependencias. En caso de que una dependencia no este como objetivo hará que el make la busque como fichero en la carpeta actual en caso de que no la encuentre dará un error . En caso de encontrar los archivos ejecutará la orden correspondiente, subiendo en la jerarquía hasta llegar al objetivo principal.
Decir que puede haber objetivos que no tengan ninguna dependencia como clean.
Make
Ventajas: Al compilar con make sólo se recompilarán aquellos ficheros que
dependan del que hemos modificado. Nos guarda los comandos de compilación con todos sus parámetros
para encontrar librerías, ficheros de cabecera (.h), ... No tendremos que escribir largas líneas de compilación con
montones de opciones que debemos saber de memoria, o al menos, sólo tendremos que hacerlo una vez.
Make Ventajas:
Make sólo compila si alguna de las fuentes tiene una fecha superior al ejecutable.
$ls ->Holamundo.c
$make Holamundo
$./Holamundo
less makefile
Holamundo: Holamundo.o
gcc Holamundo.o -o Holamundo
Holamundo.o: Holamundo.c
gcc -c -o Holamundo.o Holamundo.c
Make
Make lee del fichero Makefile que contiene reglas: Cuando tenemos más de un programa fuente, hay que decirle
que queremos que haga:
objetivo: dependencia1 dependencia2 ...
<tab>comando1
<tab>comando2
<tab>...
Make
Objetivo: Es el nombre del ejecutable o librería.
dependencia<i> es el nombre de otro objetivo que debe hacerse antes que el nuestro o bien ficheros de los que depende nuestro objetivo.
<tab> es un tabulador
comando<i> es lo que se tiene que ejecutar para construir nuestro objetivo
MakeEn $HOME/FUNCION1/funcion1.hvoid escribeHolaMundo();
En $HOME/FUNCION1/funcion1.c#include <stdio.h> void escribeHolaMundo()
{printf ("Hola Mundo\n");}
En $HOME/PRINCIPAL/HolaMundo.c#include <funcion1.h> int main(void)
{escribeHolaMundo ();return 0}
Make
Ejm:
HolaMundo: HolaMundo.c ../FUNCION1/funcion1.c ../FUNCION1/funcion1.h
gcc -I../FUNCION1 HolaMundo.c ../FUNCION1/funcion1.c -o HolaMundo
Make
Mejora:
HolaMundo: HolaMundo.o ../FUNCION1/funcion1.o
gcc HolaMundo.o ../FUNCION1/funcion1.o -o HolaMundo
../FUNCION1/funcion1.o: ../FUNCION1/funcion1.c
gcc -c ../FUNCION1/funcion1.c -o ../FUNCION1/funcion1.o
HolaMundo.o: HolaMundo.c
gcc -c -I../FUNCION1 HolaMundo.c -o HolaMundo.o
Make:Variables
Es muy habitual que existan variables en los ficheros Makefile, para facilitar su portabilidad a diferentes plataformas y entornos. La forma de definir una variable es muy sencilla, basta con indicar el nombre de la variable (típicamente en mayúsculas) y su valor, de la siguiente forma:
CC = gcc –O2 Cuando queramos acceder al contenido de esa variable, lo
haremos así:
$(CC) juego.c –o juego
Make:Variables
Es necesario tener en cuenta que la expansión de variables puede dar lugar a problemas de expansiones recursivas infinitas, por lo que a veces se emplea esta sintaxis:
CC := gcc
CC := $(CC) –O2 Empleando “:=” en lugar de “=” evitamos la expansión
recursiva y por lo tanto todos los problemas que pudiera acarrear.
Make:Variables
Ejm: Variables definidas en makefile:
En CFLAGS se escriben los parametros que queremos pasar al compilador. Ejm: CFLAGS = -I<directorio1> -I<directorio2> -g ...
OBJETOS=<objeto1> <objeto2> ... FUENTES=<fuente1> <fuente2> ...
Make:Variables
OBJETOS=HolaMundo.o ../FUNCION1/funcion1.o
CFLAGS=-I../FUNCION1
HolaMundo: $(OBJETOS)
gcc $(OBJETOS) -o HolaMundo
../FUNCION1/funcion1.o: ../FUNCION1/funcion1.c
gcc -c ../FUNCION1/funcion1.c -o ../FUNCION1/funcion1.o
HolaMundo.o: HolaMundo.c
gcc -c $(CFLAGS) HolaMundo.c -o HolaMundo.o
Make:Variables
Además de las variables definidas en el propio Makefile, es posible hacer uso de las variables de entorno, accesibles desde el intérprete de comandos. Esto puede dar pie a formulaciones de este estilo:
SRC = $(HOME)/src
juego:
gcc $(SCR)/*.c –o juego
Make:Variables predefinidas
Variables que tienen un valor por defecto para el make:
AS: Nombre del programa ensamblador .Por defecto: as
CC: Nombre de programa para compilar en C .Por defecto:gcc
CPP: Nombre del preprocesador g++. Por defecto:$(CC) -E
CFLAGS=Opciones del compilador de C
RM=Borrar ficheros .Por defecto: rm –f (sin confirmación)
Make:Variables automáticas
Un tipo especial de variables lo constituyen las variables automáticas, aquellas que se evalúan en cada regla:
$@ Se sustituye por el nombre del objetivo de la presente regla
$* Nombre del archivo objetivo sin extensión
$+ Nombre de todos los archivos de las dependencias
$< Nombre del primer archivo de las dependencias
$? Nombre de todos los archivos de las dependencias que son más modernos que el objetivo, con espacios entre ellos.
Make:Variables automáticas
CC=gcc
CFLAGS=-g
OBJECTS=geometria.o area.o volumen.o
todo all: geometria
geometria: $(OBJECTS)
$(CC) -o $@ $(OBJECTS)
....
eliminar clean:
$(RM) geometria $(OBJECTS)
Resumen:makefile
<directorio1>, <directorio2>, ... son directorios donde tengas ficheros .h de tu proyecto. No hace falta que pongas los del sistema (stdio.h y demás), que esos se ponen solos.
<objeto1>,<objeto2>, ... son los .o de tu proyecto, es decir, todos y cada uno de los .c, pero cambiándoles la extensión por .o. Estos objetos deben incluir el path donde están los .c. Por ejemplo, si tengo ..../directorio1/fichero.c, uno de los objetos será ..../directorio1/fichero.o
Resumen:makefile
<fuente1>, <fuente2>, ... son los fuentes, igual que los <objeto1>, <objeto2>, pero terminados en .c en vez de .o y también con el path.
<tab> es un tabulador. Es importante que esté ahí, si no obtendremos errores.
Cada vez que en tu proyecto generes .h o .c nuevos o cambies los includes de las fuentes ya existentes, actualiza el fichero Makefile (FUENTES, OBJETOS y CFLAGS).
Cuando quieras compilar:$ make
Ejemplo
En define.h
#ifndef _DEFINE_H
#define _DEFINE_H
#define PI 3.1415
#endif
En volumen.h#ifndef _VOLUMEN_H#define _VOLUMEN_Hint cubo (int x);float esfera (int x);#endif
En area.h#ifndef _AREA_H#define _AREA_Hint cuadrado (int x);float circulo (int x);#endif
Ejemplo
En area.c
#include "define.h"
int cuadrado (int x)
{return x*x;}
float circulo (int x)
{return PI*x*x;}
En volumen.c #include "define.h"int cubo (int x){return x*x*x;}float esfera (int x){return 4*PI*x*x*x/3;}
Ejemplo
En geometria.c
#include <stdio.h>
#include "area.h"
#include "volumen.h"
int main(){
int lado,radio;
printf("Introduce el lado \n");
scanf("%d",&lado);
printf("Introduce el radio \n");
scanf("%d",&radio);
printf("El cubo es %d \n",cubo(lado));
printf("La esfera es %f \n",esfera(radio));
printf("El cuadrado es %d \n",cuadrado(lado));
printf("El circulo %f \n",circulo(radio));
return 0;
}
Ejemplo:sin librerías
gcc -I. -c volumen.c -o volumen.o
gcc -I. -c area.c -o area.o
gcc -I. volumen.o area.o geometria.c -o geometria
Ejemplo:librerías estáticas
gcc -I. -c volumen.c -o volumen.o
gcc -I. -c area.c -o area.o
ar -rv libgeneral.a volumen.o area.o
ranlib libgeneral.a
nm –s libgeneral.a
gcc -I. geometria.c libgeneral.a -o geometria
Ejemplo:librerías dinámicas
gcc -I. -c volumen.c -o volumen.o
gcc -I. -c area.c -o area.o
ld -o libgeneral.so volumen.o area.o --shared
gcc -o geometria geometria.c -Bdynamic libgeneral.so
//ldd geometria ->analiza que librerías dinámicas necesita geometria
//dice:libgeneral.so => not found
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/kepa/lana
export LD_LIBRARY_PATH
//ldd geometria ->analiza que librerías dinámicas necesita geometria
./geometria
Ejemplo:Make
vi makefile
geometria: area.o volumen.o geometria.o
gcc geometria.o area.o volumen.o -o geometria
volumen.o:volumen.c define.h
gcc –I . -c volumen.c -o volumen.o
area.o:area.c define.h
gcc –I . -c area.c -o area.o
geometria.o: geometria.c volumen.h area.h
gcc –I . -c geometria.c -o geometria.o