1ifdef _RELPATH_MK_
2$(if $D,$(info =-= Avoiding redundant include ($(MAKEFILE_LIST))))
3else
4unexport _RELPATH_MK_	# in case of make -e
5_RELPATH_MK_ := 1
6
7# Protection against process recursion when this file is
8# included by setting MAKEFILES.
9ifneq (,$(filter %$(notdir $(lastword $(MAKEFILE_LIST))),$(MAKEFILES)))
10MAKEFILES := $(filter-out %$(notdir $(lastword $(MAKEFILE_LIST))),$(MAKEFILES))
11ifndef MAKEFILES
12unexport MAKEFILES
13endif
14endif
15
16# Usage: $(call relpath,[<from-dir>,]<to-dir>)
17# Returns the relative path from <from-dir> to <to-dir>; <from-dir>
18# may be elided in which case it defaults to $(CURDIR).
19
20_rp_space :=
21_rp_space +=
22_rp_uname_s := $(shell uname -s)
23
24# Utility functions.
25_rp_compose = $(subst ${_rp_space},$(strip $1),$(strip $2))
26_rp_endlist = $(wordlist $1,$(words $2),$2)
27_rp_canonpath = $(if $(findstring CYGWIN,$(_rp_uname_s)),$(shell cygpath -a -u $1),$(abspath $1))
28
29# ----relpath(): Self-recursive function which compares the first element
30#                of two given paths, then calls itself with the next two
31#                elements, and so on, until a difference is found.  At each
32#                step, if the first element of both paths matches, that
33#                element is produced.
34----relpath = $(if $(filter $(firstword $1),$(firstword $2)), \
35                $(firstword $1) \
36                $(call $0,$(call _rp_endlist,2,$1),$(call _rp_endlist,2,$2)) \
37               )
38# ---relpath():  This function removes $1 from the front of both $2 and
39#                $3 (removes common path prefix) and generates a relative
40#                path between the locations given by $2 and $3, by replacing
41#                each remaining element of $2 (after common prefix removal)
42#                with '..', then appending the remainder of $3 (after common
43#                prefix removal) to the string of '..'s
44---relpath  = $(foreach e,$(subst /, ,$(patsubst $(if $1,/)$1/%,%,$2)),..) \
45              $(if $3,$(patsubst $(if $1,/)$1/%,%,$3))
46# --relpath():   This function runs the output of ----relpath() through
47#                ---relpath(), and turns the result into an actual relative
48#                path string, separated by '/'.
49--relpath   = $(call _rp_compose,/, \
50                $(call -$0,$(call _rp_compose,/,$(call --$0,$3,$4)),$1,$2) \
51               )
52# -relpath():    This function makes a determination about the two given
53#                paths -- does one strictly prefix the other?  If so, this
54#                function produces a relative path between the two inputs,
55#                without calling --relpath() and taking the "long road".
56#                If $1 prefixes $2, the result is the remainder of $2 after
57#                removing $1.  If $2 prefixes $1, the result is the remainder
58#                of $1 after removing $2, but with each element in that
59#                remainder converted to '..'.
60-relpath    = $(if $(filter $1,$2),., \
61                $(if $(filter $1/%,$2), \
62                 $(patsubst $1/%,%,$2), \
63                 $(if $(filter $2/%,$1), \
64                   $(call _rp_compose,/, \
65                     $(foreach e,$(subst /, ,$(patsubst $2/%,%,$1)),..) \
66                    ), \
67                   $(call -$0,$1,$2,$(subst /, ,$1),$(subst /, ,$2)) \
68                  ) \
69                ) \
70              )
71
72# relpath():     This function loops over each element in $2, calculating
73#                the relative path from $1 to each element of $2.
74relpath     = $(if $1,,$(error Error: missing first parameter to $0))$(strip \
75                $(if $2, \
76                  $(foreach d,$2,$(call -$0,$(call _rp_canonpath,$1),$(call _rp_canonpath,$d))), \
77                  $(foreach d,$1,$(call -$0,$(call _rp_canonpath,${CURDIR}),$(call _rp_canonpath,$d))) \
78                 ) \
79               )
80
81endif #_RELPATH_MK_
82