I came upon a situation where I had to flip a boolean quantity inside Makefile. I.e. change 1 to 0, or a 0 to 1. GNU Make doesn't have any builtins to do just this, and one has to find their own way.
What struck me immediately was to use the shell function from the Makefile. The shell function will execute a shell snippet and returns its output to Makefile. So I could easily get by with this:
flipped := $(shell [ $(boolean) -eq 0 ] && echo 1 || echo 0)
That should have done the trick and I could have stopped there. But I had a feeling that this is so simple a thing to invoke a separate shell for, and there could be a way to get this done using builtin functions. I'm glad I managed to pull this silly feat off without having to look up the Internet (I swear)! And that would be below:
flipped := $(if $(patsubst 0,,$(boolean)),0,1)
This uses patsubst and if builtin functions. If anyone wondered, it works as follows: First, the patsubst (trimmed name for pattern substitution) function is used here to substitute 0 with an empty string, effectively deleting the 0. That means if the input was 0, the result would be empty; otherwise the result would the same as input (i.e. the only other input, 1). Next, this result is fed to the if builtin. The if builtin takes 3 arguments and works just like the ternary operator in C: If the first argument evaluates to true (in its case, being non-empty is true), it returns the second argument; otherwise returns the third argument.
So their combined effect flips a boolean for me: For an input 0, patsubst returns empty string, which makes if return 1. For an input 1, patsubst returns 1 intact and makes if return 0. Done.
While I was at it, I stumbled on a lengthy post on how to do arithmetic using make builtin functions. I haven't read it in full, but it does look pretty contrived, far-fetched and insane to be placed into any public-facing Makefile, but fun nevertheless. I'd rather dive straight into the shell builtin if using pure builtins spans more than a line.
I'd be glad to hear about even easier ways to do this using only builtins.
Happy makeing!
No comments:
Post a Comment