Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Make écrase mes fichiers !

4 réponses
Avatar
Alain Ketterlin
Salut,

J'ai un problème étrange avec le makefile suivant :

# --------
name: name.tab.o name.o

name.tab.c: name.y
bison name.y
# --------

J'ai deux fichiers source, name.y (la grammaire Yacc) et name.c (un
main) -- vous avez un contenu "minimal" après ma signature.

Avec ces trois fichiers, si name.c est plus récent que name.y, "make"
(GNUmake 4.1) fait :

| cc -c -o name.o name.c
| bison name.y
| cc -c -o name.tab.o name.tab.c
| cc name.o name.tab.o -o name

Exactement ce que je veux. Si maintenant je fais "touch name.y ; make"
(ou si name.y est le plus récent des deux au départ), voilÍ  ce qui se
passe :

| yacc name.y
| mv -f y.tab.c name.c
| cc -c -o name.o name.c
| bison name.y
| ...

WHAT THE FUCK ! Make commence par écraser mon fichier name.c (par
yacc+mv) juste parce qu'il a une règle pour le faire.

Je veux bien croire que make a un peu de boulot avec toutes ces règles
implicites Í  appliquer, mais lÍ  il écrase mon fichier... (ajouter une
dépendance "name.o: name.c" avec ou sans commande ne règle pas le
problème).

Y a-t-il un moyen de lister les fichiers source ? Ou en tout cas les
fichiers Í  ne pas écraser ?

make --version dit

| GNU Make 4.1
| Built for x86_64-pc-linux-gnu
| ... (licence omise)

Vous avez un avis ? (Inutile de dépiauter les règles implicites, je me
pose une question de principe dans ce cas.)

-- Alain.

PS : deux fichiers minimaux (qui compilent) si vous voulez répéter
l'expérience

// name.y
%{
int yylex() { return 0; }
int yyerror (const char * msg) {}
%}
%%
input: %empty;
%%

//name.c
extern int yyparse();
int main (void) { return yyparse (); }

4 réponses

Avatar
Olivier Miakinen
Bonjour,
Le 12/10/2021 22:02, Alain Ketterlin a écrit :
Salut,
J'ai un problème étrange avec le makefile suivant :
# --------
name: name.tab.o name.o
name.tab.c: name.y
bison name.y
# --------
J'ai deux fichiers source, name.y (la grammaire Yacc) et name.c (un
main) -- vous avez un contenu "minimal" après ma signature.

Bon, déjÍ  on pourrait argͼer que ce n'est pas une bonne idée d'avoir
deux fichiers sources qui ne diffèrent que par une extension connue
de make. Mais voyons plus loin.
[...]
| yacc name.y
| mv -f y.tab.c name.c
| cc -c -o name.o name.c
| bison name.y
| ...

Donc oui, c'est clairement une règle implicite pour faire un fichier .c
Í  partir d'un fichier .y -- implicite puisque dans ton makefile tu ne
définis qu'une règle avec bison et aucune avec yacc.
Si tu veux conserver name.y et name.c comme deux fichiers *sources*
indépendants, alors je vois ceci :
man make
...
-r, --no-builtin-rules
Eliminate use of the built-in implicit rules. Also clear
out the default list of suffixes for suffix rules.
...
Cordialement,
--
Olivier Miakinen
Avatar
Olivier Miakinen
Le 12/10/2021 Í  22:14, je répondais Í  Alain Ketterlin plusieurs choses,
parmi lesquelles :
man make
...
-r, --no-builtin-rules
Eliminate use of the built-in implicit rules. Also clear
out the default list of suffixes for suffix rules.
...

Tu as reçu ma réponse ?
--
Olivier Miakinen
Avatar
Alain Ketterlin
Je réponds ici Í  (l'autre message de) Olivier pour garder un peu de
contexte.
Olivier Miakinen <om+ writes:
# --------
name: name.tab.o name.o
name.tab.c: name.y
bison name.y
# --------

Bon, déjÍ  on pourrait argͼer que ce n'est pas une bonne idée d'avoir
deux fichiers sources qui ne diffèrent que par une extension connue
de make. Mais voyons plus loin.

On pourrait, mais d'une part c'est un projet o͹ j'ai plusieurs sources
yacc/bison et je suis allé au plus simple, d'autre part la règle make
"%.y: %.c" est contraire aux conventions de yacc (qui produit par défaut
y.tab.c) ou de bison (qui produit %.tab.c). D'o͹ ma surprise.
[...]
| yacc name.y
| mv -f y.tab.c name.c
| cc -c -o name.o name.c
| bison name.y
| ...

Donc oui, c'est clairement une règle implicite pour faire un fichier .c
Í  partir d'un fichier .y -- implicite puisque dans ton makefile tu ne
définis qu'une règle avec bison et aucune avec yacc.
Si tu veux conserver name.y et name.c comme deux fichiers *sources*
indépendants, alors je vois ceci :
man make
...
-r, --no-builtin-rules
Eliminate use of the built-in implicit rules. Also clear
out the default list of suffixes for suffix rules.
...

Ben oui, mais les règles implicites pour C sont bien pratiques (avec
CFLAGS etc.) J'ai finalement changé mes conventions de nommage.
Je me demande si on ne pourrait pas imaginer une contrainte qui
empêcherait make d'utiliser une règle implicite quand les prérequis sont
mentionnés explicitement dans une règle avec une commande... Bref.
(Au passage, j'ai été piégé par une autre règle implicite, parce que
j'avais la règle suivante :
name.lex.c: name.lex
flex -o $@ $<
mais lÍ  make m'indique une circularité, Í  cause de sa règle "%: %.c". Ma
cible s'appelle maintenant name.dfa.c.)
Merci en tout cas pour ta réponse.
-- Alain.
Avatar
Thomas
In article ,
Alain Ketterlin wrote:
Olivier Miakinen <om+ writes:
Bon, déjÍ  on pourrait argͼer que ce n'est pas une bonne idée d'avoir
deux fichiers sources qui ne diffèrent que par une extension connue
de make. Mais voyons plus loin.

On pourrait, mais d'une part c'est un projet o͹ j'ai plusieurs sources
yacc/bison et je suis allé au plus simple, d'autre part la règle make
"%.y: %.c" est contraire aux conventions de yacc (qui produit par défaut
y.tab.c) ou de bison (qui produit %.tab.c). D'o͹ ma surprise.

je comprend ton agacement :-)
Donc oui, c'est clairement une règle implicite pour faire un fichier .c
Í  partir d'un fichier .y -- implicite puisque dans ton makefile tu ne
définis qu'une règle avec bison et aucune avec yacc.
Si tu veux conserver name.y et name.c comme deux fichiers *sources*
indépendants, alors je vois ceci :
man make
...
-r, --no-builtin-rules
Eliminate use of the built-in implicit rules. Also clear
out the default list of suffixes for suffix rules.
...

Ben oui, mais les règles implicites pour C sont bien pratiques (avec
CFLAGS etc.)
Je me demande si on ne pourrait pas imaginer une contrainte qui
empêcherait make d'utiliser une règle implicite quand les prérequis sont
mentionnés explicitement dans une règle avec une commande... Bref.
(Au passage, j'ai été piégé par une autre règle implicite, parce que
j'avais la règle suivante :
mais lÍ  make m'indique une circularité, Í  cause de sa règle "%: %.c". Ma
cible s'appelle maintenant name.dfa.c.)

je n'ai que survolé les règles implicites, parce que c'est éloigné de
mes besoins.
mais je me souviens qu'il y a qqch pour afficher toutes les règles
implicites
(il faut éventuellement veiller Í  débrancher tout fichier makefile pour
ne pas être pollué par son contenu)
de cette façon, tu auras juste Í  recopier ce dont tu as besoin dans ton
makefile,
- sans avoir besoin de les réécrire toi même,
- sans être dérangé par toutes celles dont tu n'as pas besoin :-)
--
RAPID maintainer
http://savannah.nongnu.org/projects/rapid/