~skeeto/public-inbox

1

LDLIBS in portable makefiles

Details
Message ID
<20200419221129.bpppejhwuni6udzc@begriffs.com>
DKIM signature
pass
Download raw message
Hi Chris, I notice that your makefile article [1] uses the macro name
LDLIBS for -l options like -lm. That's reminiscent of GNU make's .c
suffix rule [2]:

	LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)

	.c:
		$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@

Do you know why they separate the -L flags in LDFLAGS vs -l flags in
LDLIBS? I realize that GCC's linker has trouble if the -l flags precede
the source file(s), but my question is why don't they put all the flags
(both -L and -l) together into LDFLAGS and put that macro at the end?

For instance, using this suffix rule:

	.c:
		$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

POSIX make [3] doesn't recognize LDLIBS in its default rules. And its .c
suffix rule puts the LDFLAGS before the source name:

	.c:
		$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<

The clang compiler is fine with the -l flags going before the source
file actually, which makes it work with the POSIX defaults.

Do you know the background behind GNU's divergence?

1: https://nullprogram.com/blog/2017/08/20/
2: https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
3: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html#tag_20_76_13_09
Details
Message ID
<20200420135740.fyky7dkb64mgyxe7@nullprogram.com>
In-Reply-To
<20200419221129.bpppejhwuni6udzc@begriffs.com> (view parent)
DKIM signature
missing
Download raw message
> why don't they put all the flags (both -L and -l) together into 
> LDFLAGS and put that macro at the end?

That's a really good question, and I don't know the reason behind it. As 
you pointed out, as long as the -L option precedes the corresponding -l 
option, I believe it shouldn't matter that -L comes later, even for gcc.

I suspect it's a historical accident. Dynamic linking came relatively 
late, and along with it linker sensitivity to argument order (at least 
when invoked via some compilers). By convention, options go before file 
arguments so the POSIX make documentation put LDFLAGS first. However, 
with dynamic linking we needed some arguments passed after the source 
file names. Rather than override the established inference rules to put 
LDFLAGS last, introduce a new variable, LDLIBS, to hold just the 
arguments that must go last.

Perhaps whoever decided to create LDLIBS thought moving LDFLAGS was too 
disruptive, and that introducing LDLIBS was a softer fix. Unfortunately 
this history predates GNU Make's use of source control, as LDLIBS first 
appears in a January 1992 commit titled "Initial revision".

However, it turns out this isn't a GNU-ism! Digging around the Unix 
History Repository, I see LDLIBS makes its first appearance in April 
1986 in BSD 4.3 (commit 7887d35c750). It's in its modern form: at the 
end of the command with a separate LDFLAGS. This predates GNU Make, 
which was announced in February 1988 and released in June 1988. So GNU 
Make was just following conventions established by BSD.

It may just be rationalization, but I actually prefer that these are 
separate since they configure two different sorts of knobs. It's common 
for the default LDFLAGS to be empty, and LDLIBS populated with the 
necessary libraries. I can override LDFLAGS independently of LDLIBS, 
meaning I don't need to worry about preserving anything about LDLIBS:

make LDFLAGS='-pie -Wl,-rpath=$HOME/.local/lib' CFLAGS='-fpie'

I do want to override LDFLAGS on occasion, but I rarely want or need to 
override LDLIBS. Makefiles are also a little tidier with them separated.