Paul Eggert wrote: > > Is something wrong with the m4/time_h.m4 idioms? What was the recipe to > > reproduce a bug here? > > Here's a recipe: > > git clone https://git.savannah.gnu.org/git/diffutils.git > cd diffutils > git checkout 25594ef0d9cda37835499e637a8ec35126aecf72 > ./bootstrap > ./configure > make > > On Ubuntu 23.04 x86-64 this eventually fails with: > > CCLD diff > /usr/bin/ld: context.o: in function `print_context_label': > .../src/context.c:56: undefined reference to `rpl_timespec_get' > collect2: error: ld returned 1 exit status
I reproduce it if and only if I allow this line in diffutils/configure.ac to be effective: AC_DEFINE([GNULIB_PORTCHECK], [1], [enable some gnulib portability checks]) What happens is that m4/time_h.m4 does this: dnl If another module says to replace or to not replace, do that. dnl Otherwise, replace only if someone compiles with -DGNULIB_PORTCHECK; dnl this lets maintainers check for portability. ... REPLACE_TIMESPEC_GET=GNULIB_PORTCHECK; AC_SUBST([REPLACE_TIMESPEC_GET]) So, on the Ubuntu 23.04 system, which has the timespec_get() function in libc, at the shell level, REPLACE_TIMESPEC_GET evaluates to GNULIB_PORTCHECK, which by these lines of modules/timespec_get gl_CONDITIONAL([GL_COND_OBJ_TIMESPEC_GET], [test $HAVE_TIMESPEC_GET = 0 || test $REPLACE_TIMESPEC_GET = 1]) ... Makefile.am: if GL_COND_OBJ_TIMESPEC_GET lib_SOURCES += timespec_get.c endif causes timespec_get.c to *not* be compiled. On the C preprocessing level, on the other hand, @REPLACE_TIMESPEC_GET@ expands to GNULIB_PORTCHECK, which further expands to 1, thus by these lines of lib/time.in.h # if @REPLACE_TIMESPEC_GET@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef timespec_get # define timespec_get rpl_timespec_get # endif causes timespec_get to redirect to rpl_timespec_get. This explains the link error. A bit of background: When we developed the idioms for the function replacement modules, around 2003-2007, I used one set of idioms for most of the modules, whereas you used a slightly different set of idioms for the time-h module. The difference is regarding how a user is supposed to determine which gnulib modules he needs to request in his bootstrap.conf or gnulib-tool invocation. At that time, it wasn't completely clear how to do this, neither with the idioms in most *.in.h files, nor with the idioms in time.in.h. Meanwhile, in 2018, I completed the procedure for this, for the majority of *.in.h files (by creating the module 'posixcheck') and documented it: https://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=68bfa44c8f03e2f554f6fc6c42d637bb72b368fa The question now is: Do you remember how the user was supposed to determine which modules from time.in.h he needs to import? How did the GNULIB_PORTCHECK macro help doing that (or was supposed to help doing that)? I looked at the history of REPLACE_NANOSLEEP and could not find the answer. If the procedure turns out to be simpler than what we have documented at https://www.gnu.org/software/gnulib/manual/html_node/Finding-POSIX-substitutes.html then we have room for improvement on these 44 *.in.h file. If not, then I would suggest to align time.in.h with the other 44 *.in.h files. Bruno