Aún así, ¿por qué necesitas hacer?



Parece que todo comenzó con una simple pregunta que primero me llevó a un estupor: "¿Por qué necesito hacer? ¿Por qué no puedo llevarme bien con los scripts de bash ?". Y pensé: En serio, ¿por qué necesito hacer? (y lo más importante) ¿Qué problemas resuelve?


Entonces decidí pensar un poco: ¿cómo recolectaríamos nuestros proyectos si no tuviéramos que hacer? Digamos que tenemos un proyecto con códigos fuente. De ellos necesitas obtener un archivo ejecutable (o biblioteca). A primera vista, la tarea parece ser simple, pero fuimos más allá. Supongamos que en la etapa inicial el proyecto consta de un archivo.



Para compilarlo, solo ejecuta un comando:


$ gcc main.c -o main 

Fue muy simple. Pero pasa un tiempo, el proyecto se desarrolla, aparecen algunos módulos y los archivos de origen se hacen más grandes.



Para compilar, debe ejecutar condicionalmente el siguiente número de comandos:


 $ gcc -c src0.c $ gcc -c src1.c $ gcc -c main.c $ gcc -o main main.o src0.o src1.o 

De acuerdo, este es un proceso bastante largo y laborioso. Para hacer esto manualmente, no lo haría. Creo que este proceso puede automatizarse simplemente creando un script build.sh que contenga estos comandos. De acuerdo, eso es mucho más fácil:


 $ ./build.sh 

¡Seguimos adelante! El proyecto está creciendo, la cantidad de archivos fuente está aumentando y también hay más líneas en ellos. Estamos comenzando a notar que el tiempo de compilación ha aumentado notablemente. Aquí vemos una falla significativa en nuestro script: compila todos nuestros 50 archivos con las fuentes, aunque solo modificamos uno.



¡No funcionará! El tiempo del desarrollador es un recurso demasiado valioso. Bueno, podemos intentar modificar el script de compilación para que antes de la compilación verifiquemos la hora de modificación de los archivos fuente y objeto. Y compile solo aquellas fuentes que han sido cambiadas. Y condicionalmente, puede verse así:


 #!/bin/bash function modification_time { date -r "$1" '+%s' } function check_time { local name=$1 [ ! -e "$name.o" ] && return $? [ "$(modification_time "$name.c")" -gt "$(modification_time "$name.o")" ] && return $? } check_time src0 && gcc -c src0.c check_time src1 && gcc -c src1.c check_time main && gcc -c main.c gcc -o main main.o src0.o src1.o 

Y ahora solo se compilarán las fuentes que han sido modificadas.



Pero qué sucede cuando el proyecto se convierte en algo como esto:



Tarde o temprano, llegará un momento en que será muy difícil entender el proyecto y el apoyo de tales guiones en sí mismo se convertirá en un proceso laborioso. Y no es un hecho que este script verificará adecuadamente todas las dependencias. Además, podemos tener varios proyectos y cada uno tendrá su propio script para ensamblar.


Por supuesto, vemos que surge una solución general a este problema. Una herramienta que proporcionaría un mecanismo para verificar las dependencias. Y aquí estamos llegando lentamente a la invención de la marca . Y ahora, sabiendo qué problemas enfrentaremos en el proceso de construcción del proyecto, al final formularía los siguientes requisitos:


  • análisis de marcas de tiempo de dependencias y objetivos
  • Cantidad mínima de trabajo requerida para garantizar la relevancia de los archivos derivados
  • (bueno, + ejecución paralela de comandos)

Makefile


Los Makefiles se usan para describir las reglas de ensamblaje del proyecto. Al crear un Makefile, declaramos declarativamente un cierto estado de las relaciones entre archivos. La naturaleza declarativa de la determinación del estado es conveniente porque decimos que tenemos una lista de archivos y que necesitamos obtener un nuevo archivo de ellos ejecutando una lista de comandos. En el caso de usar un lenguaje imperativo (por ejemplo, shell), tendríamos que realizar una gran cantidad de verificaciones diferentes, obteniendo código complejo y confuso en la salida, mientras que make lo hace por nosotros. Lo principal es construir el árbol de dependencia correcto.


 <  > : <  ... > <  > ... ... 

No hablaré sobre cómo escribir Makefiles. En Internet hay muchos manuales sobre este tema y, si lo desea, puede consultarlos. Y además, pocas personas escriben Makefiles manualmente. Y los Makefiles muy complejos pueden ser una fuente de complicaciones en lugar de simplificar el proceso de compilación.

Source: https://habr.com/ru/post/477656/


All Articles