The GMSLThe GMSL is a library of functions to enhance GNU Make. It provides string and list functions, arithmetic operators, tracing facilities and even associative arrays.
The GMSLThe GMSL is a library of functions to enhance GNU Make. It provides string and list functions, arithmetic operators, tracing facilities and even associative arrays.
Check out the main GMSL site: gmsl.sf.net.
GMSL Background
To use the GMSL in your Makefiles first download it from SourceForge (the latest version is available here).
There are two files to save with your own Makefile: gmsl and __gmsl. To start using the GMSL simply place include gmsl in your own Makefile (the gmsl file decides whether it should include __gmsl to prevent multiple inclusion of the same file).
GMSL functions are called using the standard GNU Make $(call ...) built-in function. For example, to get the last element of the list $(MY_LIST) using the GMSL last function do $(call last,$(MY_LIST)).
New in v1.0.2: Logical Operators
GMSL v1.0.2 introduces the logical operators and, or, xor, nand, nor, xnor and not.
GNU Make's concept of truth values is simple: any non-empty string is considered to be 'true' and an empty string is 'false'. To make this explicit the GMSL define variables $(true) and $(false). $(true) is simply the string T and $(false) is an empty string.
GNU Make's (and the GMSL) boolean values can be used with both GMSL functions and GNU Make's $(if ...) built-in. The GMSL logical operators were designed for use with $(if ...) and the GNU Make preprocessor ifeq directive.
Example: Is DEBUG set to Y?
Imagine that a Makefile has a debug option which is enabled by setting the DEBUG environment variable to Y. Using the GMSL function seq (string equal) and the new or operator it's easy to determine whether debugging is desired or not.
include gmsl
debug_needed := $(call or,$(call seq,$(DEBUG),Y),$(call seq,$(DEBUG),y))
Since the GMSL has a 'lower case' function (lc)it's possible to write this example without the need for the or:
include gmsl
debug_needed := $(call seq,$(call lc,$(DEBUG)),y)
But the logical operator or allows us to be even more generous and accept YES as well as Y for the debug option:
include gmsl
debug_needed := $(call or,$(call seq,$(call lc,$(DEBUG)),y),$(call seq,$(call lc,$(DEBUG)),yes))
And that's case insensitive too.
Example: Is DEBUG set to Y or N?
Another possible use of the logical operators is to force the user of the Makefile to set DEBUG to either Y or N, thus avoiding problems if the debug option is forgotten about.
The GMSL has an assertion function (assert) that will output a fatal error if its argument is not true. So we can use it to assert that DEBUG must be Y or N:
include gmsl
$(call assert,$(call or,$(call seq,$(DEBUG),Y),$(call seq,$(DEBUG),N)),DEBUG must be Y or N)
If the user makes an error and sets DEBUG to Oui then the following error is generated by the assertion:
Make DEBUG=Oui
Makefile:1: *** GNU Make Standard Library: Assertion failure: DEBUG must be Y or N. Stop.
That should keep the French office in check!
Example: Using Logical Operators in the Preprocessor
Since GNU Make's preprocessor (which has ifeq, ifneq and ifdef directives) doesn't have any logical operations it's hard to write a complex statement. For example, to define a section of a Makefile if DEBUG is set to Y or Yes in GNU Make requires either duplicating a section of code (yuck!) or writing the following hard to understand statement:
ifeq ($(DEBUG),$(filter $(DEBUG),Y Yes))
...
endif
This works by filtering the list Y Yes with the value of $(DEBUG) which returns an empty list if $(DEBUG) is not Y or Yes, and the value of $(DEBUG) if it is. The ifeq then compares the resulting value with $(DEBUG). That's pretty ugly, and hard to maintain and contains a subtle bug (what happens if $(DEBUG) is empty?). Fixing the bug means doing something like:
include gmsl
ifeq (x$(DEBUG)x,$(filter x$(DEBUG)x,xYx xYesx))
...
endif
Using the GMSL or operator this becomes much clearer:
ifeq ($(true),$(call or,$(call seq,$(DEBUG),Y),$(call seq,$(DEBUG),Yes)))
...
endif
That's much more maintainable. It works by before the or on two calls to seq and then comparing the result with $(true).
New in v1.0.2: uniq
The final new function in GMSL v1.0.2 is uniq which removes duplicates from a list (recall that in GNU Make terms a list is a string with spaces separating list elements).
GNU Make has a built-in sort function that both sorts a list and removes duplicates; uniqremoves duplicates without sorting the list (which can be handy if list order is important).
So, for example, $(sort c b a a c) will return a b c, whereas as $(call uniq,c b a a c) returns c b a.
For example, suppose you need to simplify the PATH variable by removing duplicate entries while preserving the order. The PATH is typically a colon-separated list of paths (e.g. /usr/bin:/bin:/usr/local/bin:/bin); here simple-path is the PATH with duplicates removed and order preserved:
include gmsl
simple-path := $(call merge,:,$(call uniq,$(call split,:,$(PATH))))
This uses three GMSL functions: uniq, split (which splits a string into a list at a certain separator character; in this case colon) and merge (which merges a list into a string separating list entries with a character; in this case a colon).
Bug Fixes in v1.0.2
Since 1.0.0 was released there have been three bug fixes that make v1.0.2 an important upgrade.
The most serious bug seq function is incorrect was an error in the implementation of the 'string equal' function (called seq).
The `%' character in strings not properly escaped bug meant that the seq function would give incorrect results if the first string argument contain the % character (since % is a GNU Make wildcard character).
The final, very minor, bug Define tracing variables even when GMSL_TRACE not set was fixed so that GNU Make doesn't report an 'undefined variable' error.
Future
The GMSL grows with suggestions from users. If you'd like to see new functionality added (or have a bug to report) please visit the GMSL web site and get involved: gmsl.sf.net.