6 ms·
Updated, thank you. Assigning the results of a command to a variable is not POSIX Make. However, both FreeBSD's Make and GNU Make support it. There's the prop
by git-pull 9y ago
Updated, thank you.
Assigning the results of a command to a variable is not POSIX Make. However, both FreeBSD's Make and GNU Make support it.
There's the proposal to add it to POSIX Make: http://austingroupbugs.net/view.php?id=337 http://austingroupbugs.net/view.php?id=337
Another thing I wanted to add to the main post: since POSIX Make doesn't have conditionals, GNU Make and bmake both have different ways of doing them. If you look through FreeBSD's Make files, you'll see that conditionals exist, but they begin with dots:
https://github.com/freebsd/freebsd/blob/c09174d99/share/mk/bsd.dep.mk#L53 https://github.com/freebsd/freebsd/blob/c09174d99/share/mk/b...
There are going to be some compromises when writing portable scripts where it won't be POSIX, but could still be considered portable.
- wahern 9y agoPOSIX Make supports conditional constructs by way of recursive macro expansion. I've found it to be not much more clunky than GNU Make's conditional constructs. (Recently I've come to appreciate the simplicity and consistency of the BSD extensions, even though I don't use them. GNU Make syntax quickly becomes impenetrable.) And as you say, shell invocation from macros isn't yet supported by POSIX but _can_ be done portably. GNU Make supports $(shell COMMAND), everybody else supports $(COMMAND:sh), nobody supports both, and where not supported they expand to the empty string.[1] Here's a simplified example from my proof-of-concept library from https://github.com/wahern/autoguess/blob/config-guess/config.mk.guess https://github.com/wahern/autoguess/blob/config-guess/config... BOOL,true = true BOOL,1 = true BOOL,false = false BOOL,0 = false BOOL, = false OS.exec = uname -s | tr '[A-Z]' '[a-z]' OS = $(shell $(OS.exec))$(OS.exec:sh) OS.darwin.test,darwin = true OS.is.darwin = $(BOOL,$(OS.darwin.test,$(OS))) # Usage: $(SOFLAGS.shared) - for creating regular shared libraries SOFLAGS.shared.if.darwin.true = -dynamiclib SOFLAGS.shared.if.darwin.false = -shared SOFLAGS.shared = $(SOFLAGS.shared.if.darwin.$(OS.is.darwin)) SOFLAGS = $(SOFLAGS.shared) show: @echo "SOFLAGS=$(SOFLAGS)" I try to keep my stuff portable across AIX, FreeBSD, Linux/glibc, Linux/musl, macOS, NetBSD, OpenBSD, and Solaris. I used to just require GNU Make, with makefiles that looked like: .POSIX: all: +gmake -f GNUmakefile all .DEFAULT: +gmake -f GNUmakefile $< but now I'm moving my projects over to the more portable, dependency-less method. It makes things so much easier to be able to run `make test` without having to worry about first installing unnecessary dependencies, or often any dependencies whatsoever. When you're juggling a dozen VMs, trying to track the latest couple of releases of a platform, simplicity is key. Plus, more easily programmable environments encourage overly complex solutions which become maintenance burdens over months and years. With GNU Make I was always unable to resist the urge to turn every repetitious rule into a template, for example. Sticking to purely portable constructs means I'm forced to be smarter about how to approach something, including recognizing when something is best left un-automated. [1] It's nice that POSIX will be formalizing the "!=" construct, but unfortunately it's not supported by Solaris make, and macOS will be forever stuck on GNU Make 3.81 which also lacks support.