Aquí es una solución que única utiliza GNU make funciones. Aunque es recursivo, debería ser más eficiente que llamar a un programa externo. La idea es bastante directa: la ruta relativa será cero o más ... para subir al ancestro más común, luego un sufijo para bajar al segundo directorio. La parte difícil es encontrar el prefijo común más largo en ambas rutas.
# 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)
Recientemente he traducido un gran conjunto de archivos make recursivas en un proyecto conjunto hacen, ya que es bien sabido que marca recursiva es mala debido a no exponer todo el grafo de dependencias (http://aegis.sourceforge.net/auug97.pdf). Todo el código fuente y las rutas de la biblioteca se definen en relación con el directorio actual del archivo MAKE. En lugar de definir un número fijo de% de reglas genéricas de compilación, creo un conjunto de reglas para cada par (directorio de código fuente, directorio de salida), lo que evita la ambigüedad de usar vpath. Al crear las reglas de compilación, necesito una ruta canónica para cada directorio de código fuente. Aunque se puede usar la ruta absoluta, suele ser demasiado larga y menos portátil (he utilizado Cygwin GNU make donde las rutas absolutas tienen un prefijo/cygdrive y no son reconocidas por los programas de Windows).Por lo tanto, utilizo esta función en gran medida para generar rutas canónicas.
Este meta-respuesta es el mejor - evitar el problema! Tenga en cuenta también que '--directory' no es portable:' cd $ (rootdir)/src/libs/libfoo; $ (MAKE) ... 'sería más confiable. –
@Norman Gray: ¿qué pasa con '$ (MAKE) -C ...'? – Beta
No creo que vaya tan lejos como _wrong_, pero no todos los comandos 'make' lo soportan (y no está en [posix] (http://www.opengroup.org/onlinepubs/009695399/utilities/make) .html), por ejemplo), por lo que si este archivo MAKE es para distribución, entonces podría crear problemas. En cualquier caso, tiendo a pensar que 'cd foo; $ (MAKE) ... 'expresa la intención más claramente. –