est ici une solution qui ne utilise GNU make fonctions. Même s'il est récursif, il devrait être plus efficace que d'appeler un programme externe. L'idée est assez simple: le chemin relatif sera zéro ou plus ... pour remonter à l'ancêtre le plus commun, puis un suffixe pour descendre au 2ème répertoire. La partie difficile est de trouver le plus long préfixe commun dans les deux chemins.
# DOES not work if path has spaces
OneDirectoryUp=$(patsubst %/$(lastword $(subst /, ,$(1))),%,$(1))
# FindParentDir2(dir0, dir1, prefix) returns prefix if dir0 and dir1
# start with prefix, otherwise returns
# FindParentDir2(dir0, dir1, OneDirectoryUp(prefix))
FindParentDir2=
$(if
$(or
$(patsubst $(3)/%,,$(1)),
$(patsubst $(3)/%,,$(2))
),
$(call FindParentDir2,$(1),$(2),$(call OneDirectoryUp,$(3))),
$(3)
)
FindParentDir=$(call FindParentDir2,$(1),$(2),$(1))
# how to make a variable with a space, courtesy of John Graham-Cumming
# http://blog.jgc.org/2007/06/escaping-comma-and-space-in-gnu-make.html
space:=
space+=
# dir1 relative to dir2 (dir1 and dir2 must be absolute paths)
RelativePath=$(subst
$(space),
,
$(patsubst
%,
../,
$(subst
/,
,
$(patsubst
$(call FindParentDir,$(1),$(2))/%,
%,
$(2)
)
)
)
)
$(patsubst
$(call FindParentDir,$(1),$(2))/%,
%,
$(1)
)
# example of how to use (will give ..)
$(call RelativePath,/home/yale,/home/yale/workspace)
J'ai récemment traduit un grand nombre de makefiles récursifs dans un projet tout faire comme il est bien connu que faire récursive est mauvais en raison de ne pas exposer l'ensemble de graphe de dépendance (http://aegis.sourceforge.net/auug97.pdf). Tous les chemins de code source et de bibliothèque sont définis par rapport au répertoire makefile actuel. Au lieu de définir un nombre fixe de règles de génération% génériques, je crée un ensemble de règles pour chaque paire (répertoire de code source, répertoire de sortie), ce qui évite l'ambiguïté d'utiliser vpath. Lors de la création des règles de construction, j'ai besoin d'un chemin canonique pour chaque répertoire de code source. Bien que le chemin absolu puisse être utilisé, il est généralement trop long et moins portable (j'utilisais Cygwin GNU make où les chemins absolus ont un préfixe/cygdrive et ne sont pas reconnus par les programmes Windows).Par conséquent, j'utilise cette fonction fortement pour générer des chemins canoniques.
Cette méta-réponse est le meilleur - éviter le problème! Notez aussi que '--directory' n'est pas portable:' cd $ (rootdir)/src/libs/libfoo; $ (MAKE) ... 'serait plus fiable. –
@Norman Gray: qu'est-ce qui ne va pas avec '$ (MAKE) -C ...'? – Beta
Je ne pense pas que j'irais aussi loin que _wrong_, mais toutes les commandes 'make' ne le supportent pas (et ce n'est pas dans [posix] (http://www.opengroup.org/onlinepubs/009695399/utilities/make .html), par exemple), donc si ce makefile est pour la distribution, alors cela pourrait créer des problèmes. En tout cas, j'ai tendance à penser que cd foo; $ (MAKE) ... 'exprime l'intention plus clairement. –