Обсуждение: changes in pgport etc doesn't cause client programs to be relinked

Поиск
Список
Период
Сортировка

changes in pgport etc doesn't cause client programs to be relinked

От
Andres Freund
Дата:
Hi,

our make dependencies currently are insufficient to trigger client binaries to
be relinked when pgport/pgcommon/libpq/... changes.

To reproduce, you can use something like:
touch ~/src/postgresql/src/port/snprintf.c && make -j48 2>&1|grep 'gcc.*pgbench'
which won't show anything, whereas e.g.
touch ~/src/postgresql/src/include/postgres_fe.h && make -j48 2>&1|grep 'gcc.*pgbench'
will.

The reason for that is that currently client programs only have order-only
dependencies on pgport:

pgbench: $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
    $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)

which will dutifully cause pgport to be rebuilt. But then we won't actually
rebuild $client_program, because it's just an order-only dependency [1].


The same problem does *not* exist for the backend, because there we add
pgport/pgcommon to OBJS, which will cause them to be proper dependencies.

This does explain some mysterious issues I had over the years with changes
occasionally requiring a clean/build cycle to fully take. It's especially
confusing because after a build cycle one ends up with a build partially using
the old and partially the new libraries.


I unfortunately don't see a localized fix for this. Afaict we'd need to change
all client build rules to also have a dependency on the library?

Greetings,

Andres Freund


[1] https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html



Re: changes in pgport etc doesn't cause client programs to be relinked

От
Andres Freund
Дата:
Hi,

On 2021-10-26 11:04:54 -0700, Andres Freund wrote:
> pgbench: $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
>     $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)

> I unfortunately don't see a localized fix for this. Afaict we'd need to change
> all client build rules to also have a dependency on the library?

For a second I thought I had an elegant solution to this: Many linkers these
days support --dependency-file, similar to the way we deal with dependencies
for compilation.

But that doesn't work easily either, because we use $^ in at least some of the
recipes for building executables. Which will contain the generated library
dependencies after the first build. That's easy enough to fix for things like
pgbench, where $^ is used directly, but there's also some binaries that we
build using prefix rules.

Like

# Replace gmake's default rule for linking a single .o file to produce an
# executable.  The main point here is to put LDFLAGS after the .o file,
# since we put -l switches into LDFLAGS and those are order-sensitive.
# In addition, include CFLAGS and LDFLAGS_EX per project conventions.
%: %.o
    $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)

which, despite the comment, we not just use with a single object file, but
also with multiple ones, afaict. E.g. in src/bin/scripts/Makefile. With a
single object file we could just replace $^ with $@.o, but...

Of course we could filter $^ to only contain .o's, but at some point this
isn't a simple solution anymore :(

Greetings,

Andres Freund