Make, GIT y Doxygen

Para programar hacen falta herramientas

Ing. Ignacio Javier Bonelli

Programar es dificil...

¡Necesitamos ayuda!

  • Compilar muchos archivos se complica...
    • ¡Necesitamos a make!
  • ¿Como llevamos un registro de que hicimos?
    • Puedo usar un sistema de versionado como GIT...
  • Por que lo programé así?!?
    • Necesito escribir notas, documentar...
    • Doxygen me puede ayudar :)

MAKE

Automatización del proceso decompilación

  • Nos permite "programar" el proceso de compilación y linkeo.
  • Ademas permite automatizar otros tipos de tareas (similar a shell scripting).
  • Una diferencia importante (con shell scripting) es que make tiene registro de los cambios que se hacen en los archivos que debe utilizar. Si no hay cambios, no realiza ninguna tarea.
  • No está limitado por lenguajes de programación, tiene mas que ver con procesos con archivos de entrada (fuentes) y salida (binarios).
  • El make ejecuta ciertas reglas que obtiene de un archivo llamado “Makefile”

Ejemplo sencillo

hellomake.c


#include "hellomake.h"

int main() {
  // call a function in another file
  myPrintHelloMake();

  return(0);
}
						

hellomake.h


/* Example include file */

void myPrintHelloMake(void);
						

Ejemplo sencillo

hellofunc.c


#include "hellomake.h"
#include <stdio.h>

void myPrintHelloMake(void) {

  printf("Hello makefiles!\n");

  return;
}
						

Normalmente esto lo compilariamos haciendo:


$ gcc -o hellomake hellomake.c hellofunc.c -Wall
						

Nuestro primer makefile

Compilar de esta manera tiene dos desventajas:

  1. Cada vez que compilamos tenemos que tipear todo ese largo string/comando.
  2. Si solo cambiamos un fuente (.c) debemos recompilar todo cada vez. Dependiendo de la cantidad de codigo esto puede resultar lento e ineficiente.



Makefile

hellomake: hellomake.c hellofunc.c
	gcc -o hellomake hellomake.c hellofunc.c -Wall
						

Explicando lo que hicimos...


target: dependencia/s
	comando/s
						
  • Los target seran nuestros productos (archivos de salida).
  • Para poder crearlos deberemos respetar las dependencia/s (que existan los archivos).
  • Si las dependencias se cumplen make ejecutara comando/s.
  • Es importante que antes de comando/s deber ser un TAB (no espacios).
  • Una vez guardado en el archivo Makefile para compilar solo ejecutaremos make.

$ make ; ls -l hellomake
gcc -o hellomake hellomake.c hellofunc.c -Wall
-rwxr-xr-x 1 ignacio ignacio 4997 Jul  4 18:49 hellomake
						

Haciendo las cosas mas flexibles...

Makefile 2

CC=gcc
CFLAGS=-Wall

hellomake: hellomake.c hellofunc.c
	$(CC) -o hellomake hellomake.c hellofunc.c $(CFLAGS)
						

Ahora al compilador lo llamamos por referencia en una variable y los flags del compilador los pasamos de la misma manera.

Usemos mas dependecias

Makefile 3

CC = gcc
CFLAGS = -Wall
DEPS = hellomake.h

all: hellomake.o hellofunc.o
	$(CC) hellomake.o hellofunc.o -o app $(CFLAGS)

hellomake.o: hellomake.c $(DEPS)
	$(CC) -c -o hellomake.o hellomake.c $(CFLAGS)

hellofunc.o: hellofunc.c $(DEPS)
	$(CC) -c -o hellofunc.o hellofunc.c $(CFLAGS)
						

Tenemos mas targets, y mas dependencias:

  • Ahora para hacer all necesitamos antes compilar hellomake y hellofunc.
  • Y para hacer hellomake y hellofunc necesitamos hellomake.h declarado ahora como una variable.

¿Y si limpiamos tambien?

Makefile 4

CC = gcc
CFLAGS = -Wall
DEPS = hellomake.h

all: hellomake.o hellofunc.o
	$(CC) hellomake.o hellofunc.o -o app $(CFLAGS)
hellomake.o: hellomake.c $(DEPS)
	$(CC) -c -o hellomake.o hellomake.c $(CFLAGS)
hellofunc.o: hellofunc.c $(DEPS)
	$(CC) -c -o hellofunc.o hellofunc.c $(CFLAGS)
clean:
	rm -f *.o app
						

Podemos tener targets sin dependencias. El mas comun es el que limpia todo lo creado.

Lo podemos ejecturar invocando directamente el target:


$ make clean
						

Complicando el asunto...

Makefile 5

CC=gcc
CFLAGS=-Wall
DEPS = hellomake.h

%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)

hellomake: hellomake.o hellofunc.o 
	gcc -o hellomake hellomake.o hellofunc.o $(CFLAGS)
						

Es muy similar al Makefile 3, pero ahora parametrizamos las dependencias...

Complicando el asunto...

Makefile 5
  • Utilizamos %.o y %.c donde % es: La expresion regular para coincidir con los nombres de los archivos con la extension deseada.
  • El $@ es una macro que devuelve el nombre del target donde se lo utiliza.
  • Luego $<: nos devuelve el nombre de la primer dependencia de un determinado target.
  • No lo usamos en el ejemplo, pero $^ nos devuelve el nombre de todas las dependencias de un determinado target.

Para cerrar:

Makefile 6

CC=gcc
CFLAGS=-Wall
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o
LIBS = -lm

%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)
hellomake: $(OBJ)
	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
clean:
	rm -f *.o hellomake
						

Que es similar al Makefile 5, pero ahora parametrizamos todo y agregamos la librería math.h.


Ejemplos: make_files.zip

Compilando siempre



Sin importar el estado del archivo fuente



							make -B <target>
						

o también:



							make --always-make <target>
						

GIT

Sistema de control de versiones

El problema:

Problema: Necesitamos control de versiones!

Si trabajamos en equipo y en un repositorio comun es muy fácil tener conflictos y "pisar" el trabajo de otros.

GIT

Hay varias razones para usar un sistema de control de versiones:

  • Para trabajar en equipo sin pisar el trabajo de otros y delegar en el sistema la detección de conflictos.
  • Mantener un historial de como fue cambiando el código, y poder explicar por que se hicieron los cambios.
  • Tener una herramienta que nos ayude a resolver los conflictos cuando estos ocurran.
  • Poder hacer cambios drasticos respetando el trabajo de otros (a esto se llama branching).

GIT

Como trabajamos con versiones:

Como funciona GIT 1 Como funciona GIT 2

GIT

Comandos para arrancar

  • Install:
  • 
    $ sudo apt-get install git gitk
    								
  • CheckOut:
  • 
    $ git clone https://github.com/ibonelli/info1_presentations.git
    								
  • Ver el historial:
  • 
    $ gitk
    								
  • Estado del repositorio / ver cambios:
  • 
    $ git status
    								

GIT

Subiendo cambios

  • Traerse los cambios:
  • 
    $ git pull
    								
  • Agregar archivos / cambios:
  • 
    $ git add .
    								
  • Incorporar esos cambios al repositorio:
  • 
    $ git commit -m "Descripción del cambios"
    								
  • Enviar los cambios del repositorio local al remoto:
  • 
    $ git push
    								

GIT

Usando branches

  • Crear un branch:
  • 
    $ git branch mi-new-branch
    								
  • Enviar branch al repo remoto:
  • 
    $ git push -u origin mi-new-branch
    								
  • Volviendo al master
  • 
    $ git checkout master
    								
  • Volviendo a mi branch:
  • 
    $ git checkout mi-new-branch
    								

Documentación


Doxygen

Usaremos los apuntes del Ing. Jerónimo F. Atencio:

doxygen_atencio_v1.2.2_IBmod.odp


Para instalarlo:


$ sudo apt-get install doxygen doxygen-gui
		

Ejemplo: doxygen_template.zip

Corriendo el GUI: doxywizard

Doxygen para C: doxygen_QuickReferenceLenguajeC.pdf

Herramientas

  • Debugging: gdb, ddd, kdbg, etc...
  • Compiler/Linker: gcc
  • Editor: geany, kate, gedit, etc...
  • Proyecto: make
  • Control Versiones: git, svn, cvs, etc...
  • Documentación: doxygen
  • Logging: librerías vistas...

Debuggers


GDB


$ sudo apt-get install cgdb
		


Instalando KDBG:


$ sudo apt-get install kdbg
		

Problemas en Ubuntu 14.04 LTS (trusty)

Interface

CLI vs GUI


INSTALL


  • apt install build-essential cmake qtcreator
  • QTcreator es piola para crear entornos gráficos (usa las librerias QT de KDE).

  • apt install openjdk-11-jdk
  • Ese es el paquete básico (corre sobre Java)
    y luego bajarse eclipse para Linux desde el sitio oficial.

    Eclise es un framework para generar IDEs y se usó para crear el IDE del LPCxpresso



Otros:

  • apt-get install kdevelop
  • apt-get install codeblocks

Ejemplos de uso

  • Geany:
    • Uso simple: ejemplos/getline.c
    • Muchos Archivos: ejemplos/punto3D/main.cpp
  • QTCreator: Armar un proyecto con QT y ver opciones
  • Eclipse CDT: Armar un proyecto y mostrar debugging factorial

Otros

  • Agregar pantallas: snapshot*
  • Alt+Enter sobre el proyecto creado factorial: Clase25b_IDE_eclipse_allegr.png