In a makefile, how to get the relative path from one absolute path to another?

前端 未结 7 2093
别那么骄傲
别那么骄傲 2021-02-19 20:57

An example to illustrate my question:

Top level makefile

rootdir = $(realpath .)
export includedir = $(rootdir)/include
default:
    @$(MAKE) --directory         


        
7条回答
  •  天涯浪人
    2021-02-19 21:37

    Robust drop-in solution with pure Make:

    override define \s :=
    $() $()
    endef
    
    ifndef $(\s)
    override $(\s) :=
    else
    $(error Defined special variable '$(\s)': reserved for internal use)
    endif
    
    override define dirname
    $(patsubst %/,%,$(dir $(patsubst %/,%,$1)))
    endef
    
    override define prefix_1
    $(if $(or $\
    $(patsubst $(abspath $3)%,,$(abspath $1)),$\
    $(patsubst $(abspath $3)%,,$(abspath $2))),$\
    $(strip $(call prefix_1,$1,$2,$(call dirname,$3))),$\
    $(strip $(abspath $3)))
    endef
    
    override define prefix
    $(call prefix_1,$1,$2,$1)
    endef
    
    override define relpath_1
    $(patsubst /%,%,$(subst $(\s),/,$(patsubst %,..,$(subst /,$(\s),$\
    $(patsubst $3%,%,$(abspath $2)))))$\
    $(patsubst $3%,%,$(abspath $1)))
    endef
    
    override define relpath
    $(call relpath_1,$1,$2,$(call prefix,$1,$2))
    endef
    

    Test cases:

    $(info $(call prefix,/home/user,/home/user))
    $(info $(call prefix,/home/user,/home/user/))
    $(info $(call prefix,/home/user/,/home/user))
    $(info $(call prefix,/home/user/,/home/user/))
    
    $(info $(call relpath,/home/user,/home/user))
    $(info $(call relpath,/home/user,/home/user/))
    $(info $(call relpath,/home/user/,/home/user))
    $(info $(call relpath,/home/user/,/home/user/))
    
    $(info ----------------------------------------------------------------------)
    
    $(info $(call prefix,/home/user,/home/user/.local/share))
    $(info $(call prefix,/home/user,/home/user/.local/share/))
    $(info $(call prefix,/home/user/,/home/user/.local/share))
    $(info $(call prefix,/home/user/,/home/user/.local/share/))
    
    $(info $(call relpath,/home/user,/home/user/.local/share))
    $(info $(call relpath,/home/user,/home/user/.local/share/))
    $(info $(call relpath,/home/user/,/home/user/.local/share))
    $(info $(call relpath,/home/user/,/home/user/.local/share/))
    
    $(info ----------------------------------------------------------------------)
    
    $(info $(call prefix,/home/user/.config,/home/user/.local/share))
    $(info $(call prefix,/home/user/.config,/home/user/.local/share/))
    $(info $(call prefix,/home/user/.config/,/home/user/.local/share))
    $(info $(call prefix,/home/user/.config/,/home/user/.local/share/))
    
    $(info $(call relpath,/home/user/.config,/home/user/.local/share))
    $(info $(call relpath,/home/user/.config,/home/user/.local/share/))
    $(info $(call relpath,/home/user/.config/,/home/user/.local/share))
    $(info $(call relpath,/home/user/.config/,/home/user/.local/share/))
    
    $(info ----------------------------------------------------------------------)
    
    $(info $(call prefix,/home/user/.local/share,/home/user))
    $(info $(call prefix,/home/user/.local/share,/home/user/))
    $(info $(call prefix,/home/user/.local/share/,/home/user))
    $(info $(call prefix,/home/user/.local/share/,/home/user/))
    
    $(info $(call relpath,/home/user/.local/share,/home/user))
    $(info $(call relpath,/home/user/.local/share,/home/user/))
    $(info $(call relpath,/home/user/.local/share/,/home/user))
    $(info $(call relpath,/home/user/.local/share/,/home/user/))
    
    $(info ----------------------------------------------------------------------)
    
    $(info $(call prefix,/home/user/.local/share,/home/user/.config))
    $(info $(call prefix,/home/user/.local/share,/home/user/.config/))
    $(info $(call prefix,/home/user/.local/share/,/home/user/.config))
    $(info $(call prefix,/home/user/.local/share/,/home/user/.config/))
    
    $(info $(call relpath,/home/user/.local/share,/home/user/.config))
    $(info $(call relpath,/home/user/.local/share,/home/user/.config/))
    $(info $(call relpath,/home/user/.local/share/,/home/user/.config))
    $(info $(call relpath,/home/user/.local/share/,/home/user/.config/))
    
    $(info ----------------------------------------------------------------------)
    
    $(info $(call prefix,/root,/home/user))
    $(info $(call prefix,/root,/home/user/))
    $(info $(call prefix,/root/,/home/user))
    $(info $(call prefix,/root/,/home/user/))
    
    $(info $(call relpath,/root,/home/user))
    $(info $(call relpath,/root,/home/user/))
    $(info $(call relpath,/root/,/home/user))
    $(info $(call relpath,/root/,/home/user/))
    

    Expected results:

    /home/user
    /home/user
    /home/user
    /home/user
    
    
    
    
    ----------------------------------------------------------------------
    /home/user
    /home/user
    /home/user
    /home/user
    ../..
    ../..
    ../..
    ../..
    ----------------------------------------------------------------------
    /home/user
    /home/user
    /home/user
    /home/user
    ../../.config
    ../../.config
    ../../.config
    ../../.config
    ----------------------------------------------------------------------
    /home/user
    /home/user
    /home/user
    /home/user
    .local/share
    .local/share
    .local/share
    .local/share
    ----------------------------------------------------------------------
    /home/user
    /home/user
    /home/user
    /home/user
    ../.local/share
    ../.local/share
    ../.local/share
    ../.local/share
    ----------------------------------------------------------------------
    
    
    
    
    ../../root
    ../../root
    ../../root
    ../../root
    

提交回复
热议问题