Qu'est-ce que Makefile et l'analyse de la syntaxe makefile d'uboot (1)

1. Qu'est-ce que Makefile

Il y a longtemps, les gens n'utilisaient pas Makefile pour produire un programme, ils ne pouvaient taper des commandes que manuellement.

Au début, le programme était très petit, avec un seul fichier, il suffit de taper dans le shell:

   gcc main.c -o main

Plus tard, le programme est devenu de plus en plus gros, il y avait beaucoup de fichiers, vous devez taper ceci:

    gcc main.c 1.c 2.c 3.c ... ... ... -o main

Chaque fois que vous modifiez un fichier, vous devez recompiler tous les fichiers. Cela prend beaucoup de temps et l'efficacité de la compilation est très faible.

Existe-t-il un moyen d'augmenter l'efficacité?

    gcc -c main.c 1.c 2.c 3.c ... ... ... 分别生成 所有的.o文件;

    gcc main.o 1.o 2.o 3.o ... ... ... -o main 再把生成的.o文件链接成目标文件main;

Si vous modifiez 1.c, il vous suffit de

    gcc -c 1.c  生成 1.o 文件;

    gcc main.o 1.o 2.o 3.o ... ... ... -o main 

Ensuite, liez les fichiers 1.o nouvellement générés et les autres fichiers .o précédemment générés dans le fichier cible principal

L'efficacité de la compilation est améliorée par quelle compilation et laquelle est modifiée. Cependant, taper des commandes suffit. Si vous modifiez beaucoup de fichiers, vous devez vous rappeler ceux que vous avez modifiés. Si vous compilez un projet relativement volumineux, vous devrez simplement taper des commandes. J'ai eu des crampes, alors ça a vu le jour.

Mécanisme de Make: Le mécanisme de make est similaire à "quelle édition qui". Make vérifiera automatiquement l'heure de dernière modification du fichier source .c et le fichier correspondant .o. Si l'heure de dernière modification d'un fichier source .c est supérieure au fichier correspondant .o doit être nouveau, indiquant que ce fichier a été modifié et doit être recompilé, make compilera automatiquement le fichier correspondant, puis liera le nouveau fichier correspondant .o généré par la nouvelle compilation avec le fichier .o précédemment généré Fichier cible xxxx.

Alors, comment savoir quels fichiers je veux compiler? Est-ce pour ne compiler que 1.c 2.c? Ou compiler tout? Ou autre chose?

Cela dépend du Makefile. Make est un chef, et le Makefile est la recette. La recette comprend le nom du plat, les matières premières et les méthodes de traitement.

2. Qu'est-ce que Makefile

Supposons que nous ayons trois fichiers source.

hellomake.c hellofunc.c hellomake.h
“#Include <hellomake.h> int main () {// appelle une fonction dans un autre fichier myPrintHelloMake (); retour (0); } " "#Include <stdio.h> #include <hellomake.h> void myPrintHelloMake (void) {printf (" "Hello makefiles! \ N" "); return;}" "/ * Example include file * / void myPrintHelloMake (void);"

Si nous utilisons la ligne de commande pour compiler, c'est comme ça

gcc -o hellomake hellomake.c hellofunc.c

Si vous écrivez un makefile simple, c'est le cas, le nom du fichier est enregistré sous Makefile.

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

Exigences de format de base:

target ... : prerequisites ...
    command
    ....
    ....

target : Le fichier cible peut être un fichier objet, un fichier exécutable ou une étiquette;

prerequisites: Générer des fichiers ou des cibles requis par la cible;

command: La commande qui doit être exécutée peut être n'importe quelle commande shell.

Dans l'environnement shell Linux, entrez directement make, et un fichier nommé "Makefile" ou "makefile" sera trouvé dans le répertoire courant. S'il est trouvé, il utilisera la première cible du fichier comme fichier cible final.

Nous savons qu'après l'écriture d'un fichier programme, le processus de compilation suivant est ( .c .S) -> ( .o .a) -> ( .bin), mais le processus d'analyse de Makefile par l'outil make est inversé. Afin de générer ( .bin) besoin de s'appuyer sur (* .o .a), afin de générer ( .o .a) indirects et besoins ( .c .S), on peut dire que ( .c * .S) dépend de l'original.

3. La déclaration et l'affectation des variables Makefile.

PS:Makefile里所有变量都是字符串

变量的声明,方法有:
=、?=、:=、+=、
define  endef

变量的使用方法:$(var)

=、?=、define Variable de retard, la valeur n'est déterminée que lorsqu'elle est utilisée

:= Variable immédiate, la valeur est déterminée lorsqu'elle est définie

+= Regarde devant, le front c'est le delay c'est le delay, le front c'est l'immédiat c'est l'immédiat

    var1=abc

    var2=$(var1)def

    var1=ghi

    echo $(var2) 

输出 ghidef

=、?=、define是延时变量,所以,在 echo $(var2) 时,才确定 var2的值是 $(var1)def,var1的值是 ghi



    var1=abc

    var2:=$(var1)def

    var1=ghi

    echo $(var2) 

输出 abcdef

:= 是立即变量,所以,在var2:=$(var1)def 时,就已经确定了var2的值是 abcdef



?=只有在变量第一次赋值的时候有效,也就是说,如果前面变量没被赋值,就赋值,如果有赋值,则不执行赋值,跳过。



    var1?=abc 或者 var1=abc 或者 var1:=abc

    var1?=def

    echo $(var1) 

输出 abc



    var1?=def

    echo $(var1) 

输出 def



+=字符串连接,在原有的字符串上加上后续内容,不过中间会有空格喔,呵呵哒



    var1=abc

    var1+=def

    echo $(var1) 

输出 abc def

4. La structure de Makefile

Prenons d'abord un exemple: si nous avons un fichier exécutable nommé edit, cela dépend de 8 fichiers objets, qui à leur tour dépendent de 8 fichiers c et de 3 fichiers d'en-tête.

edit : main.o kbd.o command.o display.o \
       insert.o search.o files.o utils.o
       
        cc -o edit main.o kbd.o command.o display.o \
                   insert.o search.o files.o utils.o
                   
//每一个目标文件的依赖关系
main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
command.o : command.c defs.h command.h
        cc -c command.c
display.o : display.c defs.h buffer.h
        cc -c display.c
insert.o : insert.c defs.h buffer.h
        cc -c insert.c
search.o : search.c defs.h buffer.h
        cc -c search.c
files.o : files.c defs.h buffer.h command.h
        cc -c files.c
utils.o : utils.c defs.h
        cc -c utils.c
clean :
        rm edit main.o kbd.o command.o display.o \
           insert.o search.o files.o utils.o

Nous shell en ligne de commande makepour exécuter ce makefile,
si l'entrée make cleanexécutée simultanément le fichier exécutable éditera et supprimera tous les fichiers objets.

Si un fichier est écrit de cette manière, c'est évidemment trop compliqué et trop long, on peut le simplifier au moyen de définitions de variables.

objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
        cc -o edit $(objects)

$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h

//这里类似伪代码,指明clean并不是一个文件,而是一个执行语句的缩写
.PHONY : clean
clean :
        rm edit $(objects)

5. Caractères génériques dans Makefile

Pour faciliter l'écriture, makefile prend en charge de nombreuses syntaxes génériques, telles que

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

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

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

% .o:% .c $ (DEPS) Cette phrase définit une règle, ce qui signifie que tous les .cfichiers qui dépendent de hellomake.h sont compilés pour générer des .ofichiers.
% Est appelé ici un caractère générique.

On peut aussi voir ce joker

out.o: src.c src.h
$@signifie "out.o" (cible)
$< signifie "src.c" (premier prérequis)
$^signifie "src.c src.h" (tous les prérequis)
Par exemple:

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

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

Cela signifie utiliser le fichier compilé du premier fichier .c comme fichier cible.
-I Moyens d'opérer sous le chemin actuel.

6. Fonctions couramment utilisées de Makefile.

Fonctions de remplacement et d'analyse des chaînes:

$ ( substde, à, texte)

Remplacez de par à dans le texte.

echo $ (sous-ee, EE, faible dans la rue!) 输出 fEEet sur la rue!

$ ( patsubstmotif, répétition, texte)

Trouvez un mot qui correspond au format du motif dans le texte et remplacez-le par repace.

$ (patsubst% .c,%. o, aa.cc bb.c) sortie aa.co bb.o

$ ( stripstring) supprime le début et la fin, et compresse plusieurs espaces entre les deux en un

$ (strip je suis un homme riche !!) 输出 Je suis un homme riche !!

$ ( findstringfind, string) Recherche de find dans la chaîne, retourne find s'il n'y en a pas, retourne vide si non

$ (findstring homme riche, je suis un homme riche !!) 输出 homme riche

$ ( filterpat ..., text) renvoie les mots qui "correspondent à pat ..." séparés par des espaces dans le texte, et supprime les mots sans correspondance.

$ (filtre% h% n, je suis un homme riche) 输出 homme riche

$ (filter-out pat ..., text) renvoie les mots qui "correspondent à pat ..." séparés par des espaces dans le texte, et supprime les mots sans correspondance.

$ (filtrage% h% n, je suis un homme riche) 输出 Je suis un

$ ( sortliste…) Supprimez les mots répétés séparés par des espaces dans la liste… et triez-les par ordre alphabétique, avec les symboles d'abord, puis les chiffres, puis les lettres, sensible à la casse

$ (sorte 1. Je suis un homme riche! homme Un homme riche) 输出! homme 1. Je suis un homme un homme riche

Fonction de nom de fichier:

$ ( dirdirs…) extrait la partie répertoire de chaque partie, le répertoire commence du premier caractère du nom de fichier au dernier caractère / fin

$ (dir /mnt/src.c hack / ddr / aab.a kko.c) sortie / mnt / hack / ddr / ./

Le répertoire de /mnt/src.c est / mnt /

Le répertoire de hack / ddr / aab.a est hack / ddr /

Le répertoire de kko.c est ./

$ ( notdirnames…) extraire le nom du fichier

$ (notdir /mnt/src.c hack / ddr / aab.a kko.c) sortie src.c aab.a kko.c

$ (suffixes…) extraire le suffixe du nom du fichier

$ ( suffix/mnt/src.c hack / ddr / aab.a kko.d rich-man) output.c .a .d

$ ( basenamenoms…) extrait d'autres caractères sauf le suffixe

$ (basename /mnt/src.c hack / ddr / aab.a kko.d rich-man) 输出 / mnt / src hack / ddr / aab kko rich-man

$ ( addsuffixsuffixe, nom…) plus le suffixe du nom de fichier

$ (adduffix .c, 1413 1314 rich-man) renvoie 1413.c 1314.c rich-man.c

$ (addprefix prefix, names…) add prefix, tel que src /, hack.c bb.c output src / hack.c

$ ( addprefixriche-, homme femme garçon fille) 输出 homme riche femme riche femme riche garçon riche fille riche

$ ( wildcard* .c) renvoie le fichier .c dans le dossier courant, sortie 1.c 2.c main.c

Autres fonctions:

$ ( foreachvar, list, text) développe list et var, puis affecte chaque liste à var et le texte fait référence à var pour développer.

dirs: = abcde

fichiers: = $ (pour chaque tmp, $ (dirs), $ (tmp) .txt)

echo $ (fichiers)

输出 : a.txt b.txt c.txt d.txt e.txt

dir première expansion = a, tmp = a

dir deuxième expansion = b, tmp = b

…………

最后 tmp.txt 就是 a.txt b.txt c.txt d.txt e.txt

$ ( ifcondition, alors, sinon)

Développez d'abord la condition, si elle n'est pas vide, exécutez puis, si elle est vide, exécutez autrement.

fichier: = abcd

$ (if $ (file), havefile, nothavefile) 返回 havefile

#fichier: =

$ (if $ (file), havefile, nothavefile) 返回 nothavefile

Je suppose que tu aimes

Origine blog.csdn.net/malcolm_110/article/details/108357146
conseillé
Classement