How similar/different are gnu make, microsoft nmake and posix standard make?
Obviously there's things like "which OS?", "which compiler?" and "which linker?", but I'm referring specifically to the syntax, semantics and command-line options of the makefiles themselves.
If I write makefiles based on manuals for gnu make, what are the most important portability issues that I need to be aware of?
GNU Make and POSIX Make share a common core so that GNU Make understands makefiles intended for POSIX Make and interprets them the same way - with very few exceptions. However, many GNU Makefiles use features that are only available in GNU Make. Sometimes this is deliberate and conscious; sometimes it isn't (and "sometimes isn't" is a problem). I'm less familiar with Microsoft nmake; I believe it is likely to hew close to the POSIX Make semantics at its core, but it will have its own divergent set of extensions.
Generally speaking, what the programs like autoconf produce are close to portable Makefiles.
The main things to be beware of using GNU Make are all the extended function notations for mapping file names (macros) into useful values. While they are undoubtedly useful, they are also a trap for portability.
The '%.x' notations for suffix rules are not defined by the POSIX specification for make — they are recognized as a common extension:
The interpretation of targets containing the characters '%' and '"' is implementation-defined.
Related
The GNU Makefile has a documentation page which lists standard implicit variables for various compilation contexts, such as CC, CFLAGS, etc. They are well defined, and pretty safe to employ (I use them all the time).
Looking though extended documentation, beyond the GNU website, I regularly see other variables which are not listed on the GNU documentation, such as COMPILER.c, LINK.o, etc.
Such variables are present in multiple recipes when looking over Github or Internet, and frequently from authors which seem to have a pretty good understanding regarding how make works.
The question is:
How reliable is it to use such variables?
They are not documented on the GNU make documentation website, but they seem stable enough that several authors have decided to rely on them. Is it a sane thing to do?
I'd say that they are documented and are pretty safe to use with GNU make (they are not in POSIX make).
However, the recipes in built-in implicit rules actually use variables such as COMPILE.c, LINK.p, and PREPROCESS.S, whose values contain the recipes listed above.
make follows the convention that the rule to compile a .x source file uses the variable COMPILE.x. Similarly, the rule to produce an executable from a .x file uses LINK.x; and the rule to preprocess a .x file uses PREPROCESS.x.
In the GNU make manual, I see
Simply expanded variables are defined by lines using ‘:=’ or ‘::=’ (see
Setting Variables). Both forms are equivalent in GNU make; however only the
‘::=’ form is described by the POSIX standard (support for ‘::=’ was added to
the POSIX standard in 2012, so older versions of make won’t accept this form
either).
I thought this meant that ::= was part of the standard, and := was vendor dependent. But I rarely see the double colon.
Which should I use for maximum portability?
The ::= syntax has been approved by the POSIX standards group, in 2011, along with ?= and +=. See http://austingroupbugs.net/view.php?id=330 for information on the process and why a new assignment operator was chosen instead of standardizing on :=.
I can't say which versions of make, other than GNU make, support this syntax yet.
I need to write POSIX shell scripts for many platforms and just discovered that at least one of them does not have getopts but it does have getopt.
Is getopt supported everywhere? If not, where is it not?
I don't have any 'long options'. I do have options which take no argument, others which take an integer or a string (usually a path without spaces), and other positional arguments (all placed after the options since I was previously relying on getopts).
As long as I don't need long options, can I always rely on getopt? If not, when not?
Edit: I read a quote from a FAQ about how we should just forget getopt even exists but it was followed by an answer which appeared to disprove the rationale for the quote.
Stéphane Chazelas wrote (emphasis mine) "getopt is a traditional command that comes from System V long before Linux was ever released. getopt was never standardised. None of POSIX, Unix, or Linux (LSB) ever standardized the getopt command."
Is there a way to use getopt on all three? Like a minimal feature set which is common to all three?
Thanks!
The argument against getopt is against versions not from util-linux (i.e. "traditional versions of getopt" from the given Bash FAQ link).
The answer you linked to misses that context (I'd almost argue intentionally misses it as the quoted snippet starts immediately after the crucially important context word "traditional". And follows the sentence that explains what "traditional" in that context means.)
util-linux getopt supports them, traditional getopt does not. That makes it entirely non-portable.
I cannot speak to the general portability of getopt beyond that but I would expect that its basic functionality is likely to work just about everywhere (and more to the point unless you know your code is going to run on "obscure" environments it likely isn't going to).
That being said the non-getopt solutions that should be entirely portable are not particularly complicated and should be able handle everything you care to write the code for.
From what I've read so far, bash seems to fit the defintion of an interpreted language:
it is not compiled into a lower format
every statement ends up calling a subroutine / set of subroutines already translated into machine code (i.e. echo foo calls a precompiled executable)
the interpreter itself, bash, has already been compiled
However, I could not find a reference to bash on Wikipedia's page for interpreted languages, or by extensive searches on Google. I've also found a page on Programmers Stack Exchange that seems to imply that bash is not an interpreted language- if it's not, then what is it?
Bash is definitely interpreted; I don't think there's any reasonable question about that.
There might possibly be some controversy over whether it's a language. It's designed primarily for interactive use, executing commands provided by the operating system. For a lot of that particular kind of usage, if you're just typing commands like
echo hello
or
cp foo.txt bar.txt
it's easy to think that it's "just" for executing simple commands. In that sense, it's quite different from interpreted languages like Perl and Python which, though they can be used interactively, are mainly used for writing scripts (interpreted programs).
One consequence of this emphasis is that its design is optimized for interactive use. Strings don't require quotation marks, most commands are executed immediately after they're entered, most things you do with it will invoke external programs rather than built-in features, and so forth.
But as we know, it's also possible to write scripts using bash, and bash has a lot of features, particularly flow control constructs, that are primarily for use in scripts (though they can also be used on the command line).
Another distinction between bash and many scripting languages is that a bash script is read, parsed, and executed in order. A syntax error in the middle of a bash script won't be detected until execution reaches it. A Perl or Python script, by contrast, is parsed completely before execution begins. (Things like eval can change that, but the general idea is valid.) This is a significant difference, but it doesn't mark a sharp dividing line. If anything it makes Perl and Python more similar to compiled languages.
Bottom line: Yes, bash is an interpreted language. Or, perhaps more precisely, bash is an interpreter for an interpreted language. (The name "bash" usually refers to the shell/interpreter rather than to the language that it interprets.) It has some significant differences from other interpreted languages that were designed from the start for scripting, but those differences aren't enough to remove it from the category of "interpreted languages".
Bash is an interpreter according to the GNU Bash Reference Manual:
Bash is the shell, or command language interpreter, for the GNU operating system.
The GCC docs at http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html say (under -ffreestanding) that a freestanding environment implies -fno-builtin. I might be misunderstanding exactly what a freestanding environment is or how it works, but it seems to me that, since the builtins usually emit inline code instead of calling the library function, this is ideal for a freestanding environment where the standard library may be missing functionality or even missing entirely.
So why would we not want to use the biltins with a freestanding environment?
In freestanding mode the compiler can not rely on semantical considerations.
Most builtins in GCC work silently -- for instance the compiler sees that you are using strcpy() and in hosted mode it may guess that, when you are using strcpy(), you are intending exactly to copy a string. Then it may replace strcpy with an extensionally equivalent builtin, which is better for the given target to copy a string.
In freestanding mode, using strcpy() function means ANYTHING. The idea is just not the standard library absence in linkage. The idea of freestanding mode is that there is no standard library even on definition level, except float.h, iso646.h, limits.h, stdarg.h, stdbool.h, stddef.h, stdint.h (C99 standard 4.6). You may in freestanding mode decide to format your hard drive with strcpy, and this is perfectly legal for the C language. The compiler thus don't know how to use builtins, and it declines to use them at all.