I've written in the past about the GNU Make Standard Library open source project. This article outlines the changes made between v1.0.2 and the current release (v1.0.9) and discusses some of the techniques used to implement the GMSL.
As of v1.0.5 GMSL has switched from the GNU GPL to the BSD license. This change was made by popular demand so that commercial users feel good about using the GMSL in their Makefiles.
Two new functions have been added since I last wrote about GMSL: strlen (in v1.0.8) and substr (in v1.0.9).
strlen returns the length of a string as an integer. It works by splitting the string into space separated characters (every character is actually convered to an x) and the the built-in GNU Make function $(words) is used to return the length of the resulting list.
$(call strlen,quick brown) -> 11
$(call strlen,) -> 0
substr returns a sub-string of a string given a start point (first character is at position 1) and an end point (this will be included in the sub-string). It works by first splitting the string into space separated characters (just like strlen but preserving the characters instead of changing them to x) and then it uses the built-in GNU Make function $(wordlist) to extract the sub-string. Finally, the list if turned back into a string by removing the spaces.
$(call substr,quick brown,5,7) -> k b
$(call substr,quick brown,1,1) -> q
Detecting native or, and, and lastword
Another GMSL improvement in v1.0.7 was the automatic detection of the new GNU Make built-in functions or, and, and lastword. GMSL itself implements or, and, and lastword (which it calls simply last), but it seems more efficient to use the native implementations if they are present.
From v1.0.7 GMSL detects the native functions and doesn't define its own or or and and makes last last call lastword directly. Detecting the native implementations is done as follows:
# See if we have $(lastword) (GNU Make 3.81 and above)
__gmsl_have_lastword := $(lastword $(true))
# See if we have native or and and (GNU Make 3.81 and above)
__gmsl_have_or := $(if $(filter-out undefined, \
$(origin or)),$(call or,$(true),$(false)))
__gmsl_have_and := $(if $(filter-out undefined, \
$(origin and)),$(call and,$(true),$(true)))
Since GMSL already defines $(true) the __gmsl_have_lastword function just tries to get the last element of the singleton list $(true). If lastword is present then the result is $(true), otherwise it's the empty string (which is the same as $(false).
__gmsl_have_or works by first seeing if or is defined, and if it is it tries oring true and false. Similarly, __gmsl_have_and tries anding true and true.
Location independent include
One criticism of GMSL was that writing, for example, include /foo/gmsl could result in an error about not being able to find __gmsl (which is included by gmsl). To solve this I made gmsl figure out where it's located (using MAKEFILE_LIST) and then prepend the appropriate path to the include __gmsl.
# Try to determine where this file is located. If the caller did
# include /foo/gmsl then extract the /foo/ so that __gmsl gets
# included transparently
__gmsl_root := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
# If there are any spaces in the path in __gmsl_root then give up
ifeq (1,$(words $(__gmsl_root)))
__gmsl_root := $(patsubst %gmsl,%,$(__gmsl_root))
That's a handy technique if you are trying to make your Makefiles location independent.
If you have an idea for a new GMSL function please visit http://gmsl.sf.net/ and request it. I'm always on the lookout for new ideas.