In a makefile, how to get the relative path from one absolute path to another?
Didier's answer is the best one, but the following might give you some ideas:
includedir=/a/b/c/d
currentdir=/a/b/e/f/g
up=; while ! expr $includedir : $currentdir >/dev/null; do up=../$up; currentdir=`dirname $currentdir`; done; relative=$up`expr $includedir : $currentdir'/*\(.*\)'`
echo "up=$up currentdir=$currentdir, relative=$relative"
Sorted!
(no-one said it had to be pretty...)
Doing what you want does not look easy. It may be possible using a lot of combined $(if
in the makefile but not portable (gmake only) and cumbersome.
IMHO, you are trying to solve a problem that you create yourself. Why don't you send the correct value of includedir
as a relative path from the Top-level Makefile? It can be done very easily as follows:
rootdir = $(realpath .)
default:
@$(MAKE) --directory=$(rootdir)/src/libs/libfoo includedir=../../../include
Then you can use $(includedir)
in the sub-makefiles. It is already defined as relative.
You can use the shell function, and use realpath(1) (which is part of coreutils) and the --relative-to flag.
Here is an example:
RELATIVE_FILE1_FILE2:=$(shell realpath --relative-to $(FILE1) $(FILE2))
You can even process a whole list of files with one invocation of realpath(1) since it knows how to process many file names.
Here is an example:
RELATIVES:=$(shell realpath --relative-to $(RELATIVE) $(FILES))
Python is portable! So, I would suggest you this simple example in your submakefile
With current_dir
and destination_dir
paths os.path.relpath()
does the job for you so you do not have to re-invent the wheel.
submakefile.mk
current_dir=$(CURDIR)
makefile_target:
(echo "import os"; echo "print(os.path.relpath('$(destination_dir)', '$(current_dir)'))" )| python