malloc, free, append
This commit is contained in:
+79
-2
@@ -26,6 +26,19 @@ objetivo: prerrequisitos
|
||||
- **Prerrequisitos**: los ficheros de los que depende.
|
||||
- **Receta**: los comandos de shell que producen el objetivo.
|
||||
|
||||
Es como una receta de cocina: *plato: ingredientes* y, debajo, los pasos.
|
||||
|
||||
```make
|
||||
build/hello: build/hello.o build/escpos.o
|
||||
$(CC) build/hello.o build/escpos.o -o build/hello
|
||||
```
|
||||
|
||||
| Parte | Qué es | Pregunta que responde |
|
||||
|---|---|---|
|
||||
| `build/hello` (antes de `:`) | **Objetivo**: el fichero que sale. No es el nombre de un comando. | ¿Qué quiero tener? |
|
||||
| `build/hello.o build/escpos.o` (después de `:`) | **Prerrequisitos**: los ficheros que necesita. | ¿Qué hace falta antes? |
|
||||
| línea con tabulador | **Receta**: el comando. | ¿Cómo se fabrica? |
|
||||
|
||||
Make rehace un objetivo si no existe o si **algún prerrequisito tiene una fecha
|
||||
de modificación más reciente** que él. No usa hashes como Go: solo compara
|
||||
fechas (`mtime`). Por eso un `touch` basta para forzar una recompilación.
|
||||
@@ -54,8 +67,33 @@ build/escpos.o: src/escpos.c include/escpos.h
|
||||
**En Go** es la diferencia entre llamar a `go build` paquete por paquete desde
|
||||
un script y dejar que `go build` resuelva los imports.
|
||||
|
||||
Make recorre el grafo desde el objetivo que le pides (o el primero del fichero)
|
||||
hacia sus prerrequisitos, en profundidad.
|
||||
### Make va hacia atrás
|
||||
|
||||
Make no ejecuta el Makefile de arriba abajo como un script. Empieza por el
|
||||
objetivo que le pides (o el primero del fichero si no pides ninguno) y va
|
||||
tirando de lo que necesita:
|
||||
|
||||
```
|
||||
all
|
||||
└─ build/hello (enlazar)
|
||||
├─ build/hello.o ← examples/hello.c + escpos.h
|
||||
└─ build/escpos.o ← regla patrón: src/escpos.c + escpos.h
|
||||
```
|
||||
|
||||
1. Le pides `all`, que necesita `build/hello`.
|
||||
2. `build/hello` necesita `build/hello.o` y `build/escpos.o`.
|
||||
3. Para cada prerrequisito busca una regla que lo fabrique y repite lo mismo,
|
||||
hasta llegar a ficheros que ya existen (`examples/hello.c`, `src/escpos.c`).
|
||||
4. Después construye de las hojas hacia arriba. Antes de cada receta compara
|
||||
fechas: si el objetivo existe y es más nuevo que todos sus prerrequisitos,
|
||||
no lo rehace.
|
||||
|
||||
El orden de las reglas en el fichero da igual. Solo importa que `all` sea la
|
||||
primera, porque es la que se construye por defecto.
|
||||
|
||||
Nadie le dice a Make "compila `escpos.o`": llega ahí porque `build/hello` lo
|
||||
pide. Si un objetivo no aparece como prerrequisito de nada, Make no lo
|
||||
construye.
|
||||
|
||||
## Piezas que vas a necesitar
|
||||
|
||||
@@ -103,6 +141,45 @@ cambies compilador o flags: `make clean` y construir de cero.
|
||||
**En Go** los flags y la versión del compilador forman parte del hash de la
|
||||
caché, así que `go build` sí recompila lo necesario.
|
||||
|
||||
### Regla patrón = función con parámetros
|
||||
|
||||
Una regla patrón es como una función de Go, y `$@` y `$<` son sus parámetros:
|
||||
|
||||
```make
|
||||
build/%.o: src/%.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
```
|
||||
|
||||
```go
|
||||
// Equivalente mental en Go
|
||||
func buildObject(target, source string) { // target = $@, source = $<
|
||||
run("gcc -std=c17 ... -c " + source + " -o " + target)
|
||||
}
|
||||
```
|
||||
|
||||
Cuando Make necesita `build/escpos.o`:
|
||||
|
||||
1. Busca una regla para `build/escpos.o`. No hay ninguna escrita a mano.
|
||||
2. Prueba la regla patrón `build/%.o`. Encaja, con `%` = `escpos`.
|
||||
3. Calcula el prerrequisito: `src/%.c` → `src/escpos.c`.
|
||||
4. "Llama a la función": `$@` = `build/escpos.o`, `$<` = `src/escpos.c`.
|
||||
5. Sustituye las variables, **imprime el comando ya sustituido** y lo ejecuta.
|
||||
|
||||
Por eso en la salida de `make` nunca se ve `$<`: Make imprime el comando
|
||||
después de sustituir, igual que `fmt.Printf` imprime los valores y no `%s`.
|
||||
|
||||
Otro ejemplo, para `build/buffer.o`:
|
||||
|
||||
| | Valor | Ojo |
|
||||
|---|---|---|
|
||||
| `%` | `buffer` | Solo la parte que varía: sin carpeta ni extensión. |
|
||||
| `$@` | `build/buffer.o` | El objetivo **completo**, con su carpeta. |
|
||||
| `$<` | `src/buffer.c` | El prerrequisito **completo**, con su carpeta. |
|
||||
|
||||
**La regla patrón es una plantilla, no compila "todo lo que hay en `src`".**
|
||||
Make solo la usa cuando algún objetivo pide un `build/ALGO.o`. Si creas
|
||||
`src/buffer.c` y nadie pide `build/buffer.o`, no se compila.
|
||||
|
||||
## El problema de las cabeceras
|
||||
|
||||
Si `escpos.c` incluye `escpos.h` y cambias solo el `.h`, make no lo sabe:
|
||||
|
||||
Reference in New Issue
Block a user