I’ve been doing some refactoring on the build system for our transcoding package (http://wiki.sangoma.com/media-transcoding-download) for the Sangoma Transcoding D-Series cards. It is just a simple Makefile, however, there are some non-open source bits that also need to be built and integrated into the public release, we used to have a convoluted release.sh script that copied source files, makefiles, binaries and other stuff into the proper release structure that is made available to customers. I’ve never liked such approach, because you end up with 2 different file trees, the one for development and the one released. While there might be situations where that is necessary, in this case was not and it was confusing from a developer point of view because the same source file may be under /some/public/path/to/file.c and /other/private/file.c depending on whether you are on the svn tree or the release .tar.gz tree. The public tree should be simply a subset of the private one (which contains the non-open source bits).
Anyhow, I had never really spent some quality time understanding Makefiles, I knew the basics to create targets and stuff, but this time I decided it was time to really dig into the fascinating and sometimes frustrating world of Makefiles. While I was doing this refactoring, I had the need to arbitrarily find the topmost directory of our svn tree. I’ve seen some projects require you to execute a shell script at the top directory to set such variables, something like:
Then it is required that you execute that setup.sh script before building anything. Then makefiles that can be included from different directory levels can use that variable to refer to the root directory of the project and not depend on their location using relative paths (which can change depending on who is including that file).
I had to ask myself, do I really need a setup.sh script before building just to figure out what the topmost svn directory is? Being an amateur Makefile writer it took me one hour figure out a function to do it, and this is what I came out with:
find_root = $(if $(wildcard $1/.svn),$(if $(filter-out /,$1),$(call find_root,$(realpath $1/..),$1),$1),$2) SVN_ROOT := $(call find_root,$(shell pwd),$(shell pwd))
That should recursively look for the topmost directory with an .svn entry in it, if / is reached, then / is returned. It is easily changed to look for any other file (like .git).
I could not find any solution using google, so I thought in dropping this here.
I use the native Makefile functions $(if ), $(wildcard ), $(filter-out ) and $(realpath ), you can find documentation for such functions in the Make documentation here: http://www.gnu.org/software/hello/manual/make/Functions.html