Comment faire en sorte que GNU / Make arrête de dé-référencer les liens symboliques vers les répertoires

Le manuel GNU / Make §5.7 indique ce qui suit:

5.7 Utilisation récursive de make

L’utilisation récursive de make signifie l’utilisation de make en tant que commande dans un fichier Make. Cette technique est utile lorsque vous voulez des fichiers makefiles séparés pour différents sous-systèmes qui composent un système plus grand. Par exemple, supposons que vous ayez un sous-répertoire subdir qui possède son propre fichier makefile, et que vous souhaitez que le fichier Make du répertoire contenant soit exécuté make sur le sous-répertoire. Vous pouvez le faire en écrivant ceci:

subsystem: cd subdir && $(MAKE) or, equivalently, this (see Summary of Options): subsystem: $(MAKE) -C subdir 

Donc, fondamentalement, cela implique que cd subdir && $(MAKE) est identique à $(MAKE) -C subdir .

Cependant, il s’avère que ce n’est pas vraiment un équivalent. Si vous utilisez l’option -C , le chemin du répertoire, s’il s’agit d’un lien symbolique, est toujours dé-référencé, il est donc impossible d’obtenir un nom de répertoire “logique” (comme dans pwd -L ). Prenons l’exemple suivant. Avoir le Makefile suivant dans le /tmp/b , qui est un lien symbolique vers /tmp/a/ directory:

 foo: @echo PWDL=$(shell pwd -L) @echo PWDP=$(shell pwd -P) @echo CURDIR=$(CURDIR) 

Maintenant, invoquons make autrement:

 $ pwd /tmp $ (cd b && make foo) PWDL=/tmp/b PWDP=/tmp/a CURDIR=/tmp/a $ make -C b foo make: Entering directory `/tmp/a' PWDL=/tmp/a PWDP=/tmp/a CURDIR=/tmp/a make: Leaving directory `/tmp/a' $ make --directory=b foo make: Entering directory `/tmp/a' PWDL=/tmp/a PWDP=/tmp/a CURDIR=/tmp/a make: Leaving directory `/tmp/a' $ 

Comme vous pouvez le voir, pwd -P et $(CURDIR) toujours un lien symbolique sans référence. Mais pwd -L ne fonctionne que lorsque vous changez de répertoire avant de make , ce qui prouve que l’option -C de GNU / Make le fait toujours dé-référencer le chemin du répertoire, sans raison valable. J’essayais de trouver une explication à ce comportement dans la documentation mais je n’ai pas pu. Je ne peux pas non plus trouver de solution pour résoudre ce problème sans changer de répertoire en utilisant cd avant de make (ou sans très mauvais hooks à travers LD_PRELOAD ).

La question est la suivante: est-ce que quelqu’un d’autre a rencontré ce problème avant, a une explication ou une solution de contournement? Merci!

METTRE À JOUR:

En essayant d’aller au fond des choses, j’ai téléchargé le code source de make et je n’ai trouvé aucun traitement spécial des répertoires, seulement des appels à chdir . J’ai donc écrit un petit programme pour mener une expérience, et voici ce que j’ai trouvé.

Lorsque vous vous trouvez dans un répertoire avec lien symbolique ( /tmp/b ) et que vous essayez de changer de répertoire, l’opération n’a aucun effet et le répertoire de travail en cours continue à pointer vers le lien symbolique.

Lorsque vous appelez chdir () et spécifiez un chemin complet ou relatif, il le dé-référence avant de changer de répertoire. Voici une preuve:

 $ cat cd.cpp #include  #include  int main () { chdir ("/tmp/b/"); printf ("Current dir: %s\n", get_current_dir_name ()); /* Forgive my memory leak. */ } $ gcc -o test ./cd.cpp $ pwd /tmp/b $ ./test Current dir: /tmp/b $ cd ../ $ ./b/test Current dir: /tmp/a $ cd / $ /tmp/b/test Current dir: /tmp/a $ 

Il semble donc que libc ou Linux me joue des tours qui ne me préoccupaient pas vraiment auparavant. Et en plus, bash s cd` fonctionne différemment.

Curieusement, la page de manuel de Linux chdir () ne mentionne rien à ce sujet, mais il y a une note dans la documentation de Borland Builder (! Sic), ici . Alors je me demande ce que fait bash à cet égard.

Avec l’ aide de Ephemient , j’ai été capable de résoudre ce problème . Donc, il y a peu de choses qui se passent:

  1. Linux ne supporte pas que le répertoire de travail actuel soit défini sur un lien symbolique. chdir () met toujours dans le répertoire réel.
  2. Il existe une variable appelée PWD qui représente un répertoire de travail en cours, par convention.
  3. Certains appels de fonction / système respectent la variable PWD et d’autres non.
  4. Bash maintient un “faux” chemin construit à l’aide de noms symboliques et définit la variable PWD conséquence.

Il explique le comportement de gmake . Lorsque gmake est gmake par sh , PWD est mis à jour avant l’ gmake processus gmake . Ainsi, PWD est défini sur un chemin “symbolique” et les fonctions qui le respectent continuent à bien fonctionner. Sinon, gmake appelle chdir () , qui modifie le répertoire de travail et définit PWD sans les astuces de sh. Ainsi, toutes les fonctions, y compris celles qui honorent les personnes PWD commencent à retourner le “vrai” chemin.

Dans l’ensemble, je dirais que dépendre du nom de chemin symbolique est une mauvaise idée et que les choses peuvent facilement s’effondrer. Par exemple, l’appel système getcwd () ne se soucie pas de PWD . Invoquer cd avant de make fonctionne comme une solution à court terme.