como hacer un makefile

10

Click here to load reader

Upload: hichokei-yuki

Post on 24-Jun-2015

9.329 views

Category:

Documents


0 download

DESCRIPTION

Guia del Club.net para utilizar otros IDE como Visual Studio, y poder compilar lo programado en Linux con un Makefile

TRANSCRIPT

Page 1: Como Hacer Un Makefile

Como hacer un

Makefile

Guías Granada.NET

(Junio 2008)

Óscar Valor [email protected]

Vicepresidente de club .Net de Granada

Page 2: Como Hacer Un Makefile

- 2 -

A lo largo de este breve documento, vamos a intentar explicaos de la forma más sencilla posible como lograr hacer un makefile que funcione y no morir en el intento (o borrarnos la practica por el camino, que no sé que es peor). Partamos de un programa muy sencillo llamado, en un alarde de originalidad, programa.cpp tal que así: #include <iostream> using namespace std; int main() { cout << "\n Estudiando para conquistar el mundo... \n"; }

Bueno amigos, veamos como es eso que dicen que es tan difícil, vamos a empezar por lo más sencillo, compilar programa.cpp desde consola: [consola]$> make programa

Hasta aquí todo muy bonito, se crea el ejecutable programa (en algunas consolas de Linux para ejecutar el programa es necesario poner [consola]$>./programa indicando con el ./ que es en este fichero). Vamos a hacerlo usando g++ [consola]$> g++ programa.cpp

De esta manera ha creado el ejecutable, pero con el nombre a.out que es mucho mas feo que programa. Así que vamos a ponerle el nombre que nosotros queramos [consola]$> g++ programa.cpp -o cmundo

De esta manera le decimos al compilador el fichero de salida (-o) se va a llamar cmundo (palabra en clave de conquistar el mundo).

Ahora vamos a crear un fichero objeto, que se llamará programa.o (Los ficheros objeto son los ficheros compilados con nuestro código que más adelante nos sirven para poder enlazar programas entre sí, y que nadie sepa que hemos escrito en los ficheros fuentes, pero puedan usar nuestros programas). Para hacer esto hay que usar la palabra -c [consola]$> g++ -c programa.cpp

Ahora nos ha creado el objeto programa.o, pero mira por donde se me ha olvidado poner -o programa y esta vez linux está de nuestro lado, ha hecho el programa con el nombre bien (un aplauso para linux). Vamos a probar poniendo todas las opciones anteriores: [consola]$> g++ -c programa.cpp -o programa

Y ahora nos sale un archivo llamada programa, que no lo podemos ejecutar, ya la hemos liado. Nooo, vamos a ver, hemos dicho que con -c se sacan objetos, pues hemos creado un objeto con un nombre un poco conflictivo, el nombre del ejecutable que queríamos sacar. Así que habrá que ponerlo bien: [consola]$> g++ -c programa.cpp -o programa.o

Ahora ya no se lía nadie. Bien vamos a ver que hemos visto. Cuando se genera un archivo con g++ el compilador por defecto va a sacar el ejecutable como a.out, así que usaremos -o para decirle como queremos que se llame y cuando le ponemos el -c va a sacar por defecto el objeto programa.o.

Page 3: Como Hacer Un Makefile

- 3 -

Bueno, llegamos a lo que todos temíamos: El Makefile, Asesino de Almas. Vamos a empezar por algo sencillo, un fichero llamado Makefile tal que así: . g++ programa.cpp -o cmundo

Y yasta, hemos puesto lo que habíamos hecho en consola. Fijaos en un detalle. He puesto un punto al principio, pero no porque haya que ponerlo, sino para representar que las instrucciones en consola SIEMPRE hay que ponerlas con una tabulación dentro del makefile. Vale, ahora vamos a ejecutarlo desde consola: [consola]$>make

Makefile:1: *** las instrucciones comenzaron antes del primer objetivo. Alto.

Ya la hemos liado. Mira que sabía que era complicado. ¡¿¡¿Y que me está contando de noseque objetivos?!?!. Vale, que no cunda el pánico, en una línea de código no nos podemos haber equivocado mucho. Aquí pasa lo siguiente tenemos que añadirle una etiqueta (su nombre de verdad es objetivo, pero con etiqueta creo que es mas como para todos). Probablemente no sepáis que es una etiqueta si usáis lenguajes de alto nivel como C++, C#, Java, porque usar las etiquetas en estos lenguajes es vender tu alma al diablo y luego vas al infierno, como todo el mundo sabe. Pero en otros lenguajes como ensamblador (ese lenguaje que todos queremos tanto) es imprescindible. Una etiqueta se describe con un nombre con dos puntos, por ejemplo, etiqueta : , que sirve para que desde cualquier otra parte del programa si se llama a la etiqueta (poniendo su nombre sin los dos puntos) el programa sigue ejecutándose desde la etiqueta (y en los makefiles terminará de ejecutarse cuando empiece una nueva etiqueta), se podría decir que es como una función, a la que llamas para ejecutar un código. Así que esto quedaría así: programa : g++ -c programa.cpp -o cmundo

Expliquemos un poco lo que pone, la etiqueta programa (también conocida en este caso como regla explícita, ya que impone unas reglas de compilación) va a compilar programa.cpp, y en la siguiente línea con un tabulador empezamos a escribir la línea de código que habíamos escrito en consola, y a partir de ahora desde consola sólo habrá que poner make para que se ejecute. [consola]$> make

Y todo va bien y funciona de maravilla. Uff, casi parece difícil. Bueno, ahora vamos a complicarlo un poco. Alguien en un arranque de euforia quiere añadir un fichero .h que ha creado, llamado funciones.h y es tal que así: #include <iostream> using namespace std; void imprimir(char* c) { cout << c; }

Y a programa.cpp lo cambiamos por: #include <funciones.h> using namespace std; int main() { Imprimir("\n Estudiando para conquistar el mundo... \n"); }

Page 4: Como Hacer Un Makefile

- 4 -

Ejecutamos el make por consola: [consola]$> make

g++ programa.cpp -o cmundo programa.cpp:2:23: error: funciones.h: No existe el fichero ó directorio programa.cpp: In function ‘int main()’: programa.cpp:7: error: ‘imprimir’ no se declaró en este ámbito make: *** [programa] Error 1

Y nos vuelve a reventar. No encuentra funciones.h. Entonces es cuando llega el listo y dice: pues ponle comillas (“ ”) en vez de menor mayor (< >). Y claro, funciona, pero voy a ser malo y voy a poneros un caso en el que eso no sirve, vamos a añadirlo en otro directorio, llamado inc de esta manera: ./ // Directorio actual |- programa.cpp |- Makefile |- inc // Carpeta |- funciones.h

Ahora hemos metido la pata, ya si que no se puede hacer nada contra el sistema. No os preocupéis, todavía hay esperanza. Hay una opción que nos sacará de este atolladero, la opción -I, que indica en que carpetas tiene que buscar el compilador para enlazar, es decir, donde hemos metido el código, que no se va a poner a buscar por todo el disco duro el g++, no gana para tanto. Así queda el makefile de esta manera: programa : . g++ programa.cpp -I inc -o cmundo

(Recordad que el punto es para indicar que hay una tabulación, no porque haya que poner un punto). Ejecutamos en consola y: [consola]$> make g++ programa.cpp -I inc -o cmundo

Voilá, funciona. Y ya da igual si es con comillas (“ ”) o con menor mayor el include (< >) porque g++ ya sabe donde tenemos escondidos los archivos.

Bueno, vamos a complicar esto para darle emoción. Supongamos ahora que nos preguntamos, ¿tanto lío al principio con los objetos y el -c y no lo usamos para nada? Bueno, vamos a usarlos. Vamos a hacer la compilación por partes. Probablemente aquí no le veáis ahora mucha utilidad, pero pensad que estamos compilando un solo fichero, cuando hay muchos más la cosa se complica y hay que organizarse, así que vamos a ir preparándonos. Vamos a ver la versión más sencilla:

programa : . g++ -c programa.cpp -I inc . g++ programa.o -o cmundo

Si ejecutamos make sale todo a la perfección. Fijaros que donde se pone el -I es cuando se hace el objeto, y que no hemos puesto -o programa.o en la primera instrucción porque ya sabemos que el compilador le pone el nombre bonito a los objetos automáticamente (aunque si queréis aseguraros podéis ponerlo, que no cambia nada). Pero esto plante un problema. Todo es un bloque, y a mi me gustaría que pudiera hacer sólo el objeto sin tener que hacer también el ejecutable. Así que habrá que arreglarlo. La primera idea sería esta: programa_o : . g++ -c programa.cpp -I inc

Page 5: Como Hacer Un Makefile

- 5 -

programa : . g++ programa.o -o cmundo

Si ahora ejecutamos make nos sale: [consola]$> make

g++ -c programa.cpp -I inc

Aquí nos falta algo...., ostras, la línea del ejecutable. ¿Que ha pasado? Bien, seamos por un momento la máquina que ejecuta el makefile. Abrimos el fichero, leemos la primera etiqueta, ejecutamos la instrucción, no hay más instrucciones, pues nos salimos.

¿¿No debería de leer todo?? Pues no. Ahora mismo con lo que he contado no se entiende el porqué. Así que os voy a contar la auténtica historia de las etiquetas (cuyo nombre real son objetivos):

Una etiqueta, sirve para llamar desde consola a las líneas de instrucción que van precedidas de una tabulación. es decir, podemos ejecutar desde consola el makefile de esta manera: [consola]$> make programa

g++ programa.o -o cmundo

Y hace lo que nos faltaba de instrucción. Pero claro, no nos vamos a poner a llamar al make cada vez que queramos ejecutar cada parte del programa. Por eso las etiquetas están definidas de esta forma: etiquetas : otras etiquetas Instrucciones de consola precedidas de tabulación

Las otras etiquetas son las listas de dependencias, que es sólo la forma de decir que otras etiquetas tenemos que hacer antes de ejecutar las instrucciones. Y abusando de esto, se puede hacer un pequeño truco, que es como lo hace todo el mundo para lanzar el make. Crear una etiqueta sin instrucciones y así llamar a las etiquetas que nos hacen falta. He aquí como quedaría: todo : programa_o programa programa_o : g++ -c programa.cpp -I inc programa : g++ programa.o -o cmundo

Ahora si lanzamos el make si nos lanza las dos instrucciones, porque la primera etiqueta que lee es todo, y esta a su vez llama a generar el objeto y el ejecutable. El orden es importante, porque no puedes crear el ejecutable a partir del objeto, si no tienes el objeto. Así que aquí se sigue viendo un problema, si hacemos: [consola]$> make programa

g++ programa.o -o cmundo g++: programa.o: No existe el fichero ó directorio g++: no hay ficheros de entrada make: *** [programa] Error 1

No encuentra a programa.o (si lo probáis sin haber borrado el programa.o que habíais generado antes no os dará este error, pero siempre estaréis compilando el programa que compilasteis en el .o). Así que hay que decirle que cuando haga programa haga también el objeto. Esto es fácil, ya somos casi unos expertos: todo : programa_o programa programa_o : g++ -c programa.cpp -I inc

Page 6: Como Hacer Un Makefile

- 6 -

programa : programa_o g++ programa.o -o cmundo

Lo lanzamos y: [consola]$> make programa

g++ -c programa.cpp -I inc g++ programa.o -o cmundo

Perfecto. Ya hemos terminado de aprender cómo compilar un fichero sencillo, y conocer porqué puede estar dándonos errores el makefile. Ahora un detalle. Si ahora ejecutamos sólo make y lo lanzamos debería de ejecutarse: programa_o, programa (y cuando empiece se vuelve a ejecutar programa_o) y luego las instrucciones de programa. Entonces, ¿Lo estamos ejecutando dos veces? La verdad es que no, porque la instrucción make ejecuta la etiqueta cuando hace falta, es decir, no la ejecuta si:

- Ya la ha ejecutado antes - El fichero del nombre de la etiqueta no ha sido creado en esta ejecución del makefile

Esto último sólo pasaría si generamos con dos reglas distintas la misma instrucción. Se detiene si la etiqueta tiene el nombre del fichero. Lo que pasa es que ponerle a la etiqueta el nombre del fichero es un poco peligroso si no se sabe que pasa en realidad. Hay que tener cuidado con lo que se pone, ya que una etiqueta llamada como un fichero, sin ejecutar ninguna acción, lanza un conjunto de acciones de compilación básicas, que puede desbocar en un error si hay que añadirle información al g++. Así que si se usa una etiqueta con el nombre de un fichero (o el nombre de un fichero.cpp sin .cpp) siempre hay que ponerle una acción, que sino se pasa de listo el makefile y nos da un disgusto.

Vamos a ver ahora algunos detalles, como por ejemplo, si quisiéramos crear un makefile que tuviera otro nombre que no fuera Makefile, sino makefil, o make2 o algo así, para llamarlo habría que poner: [consola]$> make -f makefil

O si quisiéramos llamar a otro makefile que está en otra carpeta desde nuestro makefile, hay que poner la orden -C <directorio> para saber que se ejecuta. etiqueta : . make -C ./carpeta/

Bueno, sigamos aprendiendo más cosas interesantes. Supongo que conoceréis o al menos os sonarán las macros en c++, del tipo: #DEFINE paco_pepe 25 y que cada vez que pongáis paco_pepe es como si pusierais 25, (si a alguien les resulta extrañas, se pueden ver como unas variables que no vas a cambiar de valor) pues el makefile no es menos y también tiene macros, si, si, y además luego nos serán de ayuda, porque ahorran trabajo, ya lo veréis. Bueno, hagamos las macros más conocidas: INC = inc SRC = src OBJ = obj LIB = lib BIN = bin GPP = g++ # g plus plus, lo ponemos como macro porque existen otro tipo # de compiladores, aunque de momento sólo vamos a usar gcc, # que es muy bonito

Page 7: Como Hacer Un Makefile

- 7 -

Declarar las macros no ha sido doloroso, ni algo superdifícil, tal vez algo largo porque hay muchas carpetas. Las macros se definen así <nombre> = <valor>. Se puede considerar para hacer un símil más sencillo, con que las macros son variables string (cadenas de caracteres) fijas. El símbolo # es vuestro amigo porque significa comentario (hay que tener cuidado al ponerlo a la derecha de las definiciones que no coge bien la variable), y seguro que os sirve de ayuda para recordar porqué pusisteis algo en ese sitio (y ## sirve para doxygen) Así que vamos a aprender a utilizarlas en el programa. Volvamos a escribir lo que teníamos con las macros: todo : programa.o programa programa.o: $(GPP) -c programa.cpp -I $(INC) programa : programa.o $(GPP) programa.o -o cmundo

Tampoco nos vamos a matar, la verdad es que ese símbolo $ es un poco feo, pero si lo piensas, es el símbolo del dinero, y si tener dinero es bueno, porqué no lo es tener muchos dólares en el makefile, se puede decir que es un makefile apoderado y rico. Pero todavía no es multimillonario, porque todavía nos faltan macros por crear. Si sabemos que siempre vamos a poner -c, y vamos a incluir siempre los archivos del include, entonces vamos a crear más macros que nos hagan más ricos, y así algún día conquistaremos el mundo: FLAGS = -c -I$(INC)

Así el programa se queda de la forma: todo : programa.o programa programa.o: $(GPP) $(FLAGS) programa.cpp programa : programa.o $(GPP) programa.o -o cmundo

Además de rico, elegante. Aunque tenemos los mismos dólares, hay menos código que nos estorbe a la vista. Algún avispado se habrá dado cuenta que de esta manera hemos cambiado el orden, bien visto, pero lo que no sabe es que el único orden que importa es que g++ sea lo primero que pone, el resto no importa (es obvio que -o fichero_salida va junto al igual que -I inc también, pero no importa si uno va delante de otro) Ahora podemos añadir a nuestra amiga @, una a repeinada conocida en los correos electrónicos, que a nosotros nos va a servir para que cuando compilemos quitemos esa línea fea que nos recuerda lo que hemos escrito. Así si ponemos: todo : programa.o programa programa.o: @$(GPP) $(FLAGS) programa.cpp programa : programa.o @$(GPP) programa.o -o cmundo

Ya no nos sale la línea recordándonos que habíamos escrito, pero tampoco me gusta que no salga nada, ¿y si hacemos que salga lo que nosotros queramos?, bueno, pues usaremos echo: todo : programa.o programa programa.o: @echo Creando programa.o

Page 8: Como Hacer Un Makefile

- 8 -

@$(GPP) $(FLAGS) programa.cpp programa : programa.o @echo Creando el ejecutable cmundo @$(GPP) programa.o -o cmundo

Ahora sí sale exactamente lo que queríamos, una línea bonita que dice lo que hace pero en español y no el lenguaje máquina. Si lo miráis bien, si le hemos puesto una @ no debería de salir nada... Este nos está tomando otra vez el pelo. Pues no, porque con la instrucción echo si pones una @ delante sólo tapa el echo, y lo que quieres escribir sale sin decir: echo Creando el ejecutable programa

Ahora vamos a dar el último paso para que nuestro pequeño proyecto esté terminado, es generar cada archivo y leerlo de su carpeta correspondiente. Es decir, si tenemos los .cpp dentro de la carpeta src (source), los .h en inc (include), los .o en obj (objetcs), y los ejectables en bin. Lo primero que hay que hacer es crear las carpetas aunque estén vacías, porque el makefile no tiene permisos para crear carpetas. Una vez creadas, y metidos los ficheros de código en su sitio, al makefile sólo hay que decirle delante de cada archivo donde está o donde va, así que queda tal que así: INC = inc SRC = src OBJ = obj LIB = lib BIN = bin GPP = g++ FLAGS = -c -I$(INC) todo : programa.o programa programa.o: @echo Creando programa.o @$(GPP) $(FLAGS) $(SRC)/programa.cpp -o $(OBJ)/programa.o programa : programa.o @echo Creando el ejecutable cmundo @$(GPP) $(OBJ)/programa.o -o $(BIN)/cmundo

Bueno, ahora viene la parte buena, esa en la que todo esto parece tontería al lado del todo lo que tenéis luego que escribir. Pero no os asustéis, yo lo he escrito y sólo he estado al borde de destrozar el ordenador 3 veces por culpa del makefile, no entendía como lo explicaban en los otros documentos, como podía hacerlo siempre mal y no tenía solución. Pero vosotros tenéis este manual, que ayuda bastante, y la verdad es que hay mucho más de lo que voy a explicar, pero con lo que hay aquí es suficiente para programar casi todo. Bueno, vamos a explicar primero que es una librería (en verdad es library, que significa biblioteca, pero luego veréis que hay que usar instrucciones en las que nos ayudará llamarla librería en vez de biblioteca). Una librería es un conjunto de objetos, es decir, que en vez de tener que crear un ejecutable con todos los objetos que queremos, podemos hacer una bola con ellos y meterlos en 1, creando una librería. Se puede ver también como una forma de poder comercializar tu librería, y que otras personas la usen. El código del makefile para crear una librería es: libMiLibreria.a : @echo Creando biblioteca libMiLibreria.a @ar rvs $(LIB)/libMiLibreria.a $(OBJ)/objeto1.o $(OBJ)/objeto2.o ...

Se puede ver que se necesita el fichero objeto a meter en la librería y luego usamos en vez de g++ el compilador ar y le ponemos los flags r, v y s, que significan:

Page 9: Como Hacer Un Makefile

- 9 -

r : reemplazar en caso de que se haya actualizado el objeto, v : imprime por consola si se ha actualizado o no s : crea un índice en la biblioteca para enlazarla. Ahora vemos que usamos más macros, pero su explicación es bastante intuitiva, el archivo claseAparte.o se encuentra en la carpeta OBJ, va a crear la librería libClaseAparte.a en la carpeta LIB con el objeto claseAparte.o que como ya dijimos se encuentra en OBJ, y lleva la / delante porque es el archivo ./lib/libClaseAparte.a el que se va a crear. Ahora también sabemos hacer librerías, veamos como se crea un ejecutable con librerías: programa : @echo Creando ejecutable programa @$(GPP) $(OBJ)/ programa.o $(LIBFLAGS) -o $(BIN)/programa

Aquí hemos cambiado de nuevo como hacer un ejecutable. Ya sabemos hacerlo con el cpp, el objeto y con las librerías. Sabemos hacer de todo. Pero hay aquí una macro LIBFLAG a la que no nos han presentado. Bueno, esta macro es tal que así: LIBFLAG = -L$(LIB) –lClaseAparte

Tenemos la instrucción –L, parecida a –I , que se refiere a lo mismo, -L indica en que directorio hay que buscar las librerías. Y –lClaseAparte, que nombre más raro, se parece a libClaseAparte.a pero no empieza por lib ni tiene el .a, pues es porque para incluir las librerías hay que transformar el nombre. Las librerías en un makefile deben de empezar por lib, con extensión .a, y para indicar cuáles vamos a usar se preceden por –l y se les quita la extensión. Dicho así no es tan difícil, ¿verdad?. Bueno otra cosa MUY IMPORTANTE, el orden en que se incluyen las librerías es crucial para que funcione bien o mal. Se deben de incluir de derecha a izquierda, estando a la derecha aquellas librerías que no dependen de nadie y a la izquierda las que dependen de las de la derecha. También es importante saber que aquí $(LIBFLAGS) tiene que ir después que la declaración del objeto, sino no funciona. Aquí no pasa como con los flags –I y –c que pueden ir al principio o al final, este si tiene que respetar un orden. ATENCION AL NAVEGANTE: Si ya has llegado hasta aquí te recomendamos que crees una copia de seguridad de todo lo que lleves, porque vamos a empezar a borrar (y borrando nunca se sabe), y a nadie le haría gracia que por faltarnos un simple ‘.’ se nos fuera todo al garete. ¿Qué es el borrado?, pues es algo que no se le presta importancia pero que es bastante importante. Yo aconsejo encarecidamente que lo primero que hagas antes de compilar sea borrar los archivos creados, porque muchísimas veces te dirá que no está actualizado, o tiene un warning en vez de un error, y te deja el último objeto creado, y tienes errores de un archivo que has modificado hace media hora y no sabes que le pasa, y es que no se ha actualizado el objeto y te sigue dando los mismos errores. Así que perder medio segundo más borrando y volviendo a ejecutar de nuevo merece la pena antes de buscar errores en un código que no refleja lo que has creado en el objeto. Para borrar se crea una etiqueta llamada clean, por ejemplo, de esta manera: ## Borrar ficheros ejecutables y intermedios mrproper : clean cleanexe ## Borrar ficheros innecesarios clean : @echo Borrando ficheros innecesarios @rm -rf $(OBJ)/*.o $(LIB)/libMiLibreria.a $(SRC)/*~ $(INC)/*~ ./*~

Page 10: Como Hacer Un Makefile

- 10 -

## Borrar ejecutables cleanexe : @echo Borrando los ejecutables @rm -rf $(BIN)/*

-rf indica que se borra sin preguntar y si hay subdirectorios también se borran estos. Mi consejo es que no pongáis esta etiqueta hasta que no estéis seguros que lo que habéis puesto funciona, y la primera vez que lancéis el borrado, tened hecha una copia de seguridad de los ficheros fuentes, por si acaso (y si usáis -rf no dentro de la misma carpeta, por si hacéis rm -rf ./). Si nos fijamos borramos los ficheros que genera Linux de seguridad (los que acaban en ~) y los puntos objeto y de las librerías no las borramos todas porque las librerías prestadas no la volveríamos a crear con este makefile, y hay que conservarla para que luego podamos enlazarla.

Nos queda el Doxygen, que es la documentación en formato html, latex ó xml que nos saca doxygen de lo que hayamos documentado en nuestros programas. Para ejecutar doxygen primero hay que crear un fichero llamado Doxyfile, donde se detallarán todos los datos acerca de la presentación de la documentación: formato, nombre del proyecto, versión , autor, idioma.... y muchas más cosas. Para crearlo tecleamos en consola: [consola]$> doxygen –g

Y te dirá que ya tienes creado el Doxyfile, ahora con un editor de textos, lo abres y modificas todas las opciones importantes para que la documentación sea correcta, el único inconveniente es que está en inglés, pero bueno, hay que acabar acostumbrándose. Así en el Makefile añadimos estas líneas para que doxygen (con –s para evitar que nos salga una ristra gigante de instrucciones (porque aún así salen bastantes)) cree la documentación a partir de lo que le hemos indicado: doxygen : @echo Creando documentación con Doxygen @doxygen Doxyfile -s

Es importante el orden para crear los archivos. Primero las clases que no dependen de nadie, luego las clases que dependan de clases ya creadas, y así hasta terminar las clases. Luego lo objetos de los ejecutables, pues estos dependen de las clases (por norma general, porque no haríamos una clase si no la vamos a utilizar). Una vez creados todos los objetos, pasaos a enlazar las clases en librerías, y cuando ya tienes las librerías crea los ejecutables. Ese es el orden para llamar a las funciones. Y se pude mantener gracias a las dependencias, es decir, poniendo al lado de cada etiqueta de que depende lo que estás ejecutando para que lo ejecute antes. La prueba de fuego es hacer make con todas las etiquetas que tengas y comprobar que con ninguna te da error. Ahora se puede resumir más el código, pero eso ya lo dejo a vuestra imaginación y creatividad. La pista que os dejo es que hay muchas macros que están escritas seguidas y que se pueden juntar en una macro gigante, los nombres de las macros pueden ser mas cortos (cuidado porque puede volverse muy lioso) y hay algunas cosas como lo era la @ que aparecen cerca y siempre se pueden añadir a la macro. A divertirse.