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