Re: Discussion about why GNU/Linux system upgrades cause old programs to break

Eli Zaretskii <[email protected]> Thu, 13 Aug 2026 08:43:50 +0300
Newsgroups gmane.emacs.devel
Message-ID <[email protected]>
> From: Arsen Arsenović <[email protected]>
> Cc: Eli Zaretskii <[email protected]>,  [email protected],  [email protected]
> Date: Wed, 12 Aug 2026 19:31:09 +0200
> 
>   /tmp/emacs-24.1/lib-src/emacsclient.c: In function ‘main’:
>   /tmp/emacs-24.1/lib-src/emacsclient.c:1606:9: error: implicit declaration of function ‘get_current_dir_name’ [-Wimplicit-function-declaration]
>    1606 |   cwd = get_current_dir_name ();
>         |         ^~~~~~~~~~~~~~~~~~~~
>   /tmp/emacs-24.1/lib-src/emacsclient.c:1606:7: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
>    1606 |   cwd = get_current_dir_name ();
>         |       
> 
> The latter is a case where Emacs blatantly violates the rules of C99: it
> calls a function that is not declared.

First, Emacs 24 was not a C99 program.  We switched to C99 in Emacs
25.1, see NEWS.25.  So no, the above was not a violation of the C
standard we were adhering to back then, certainly not a "blatant"
violation.  I'm old enough to remember the old C rules, whereby a
function without a prior declaration (a.k.a. "prototype") had very
specific semantics for its return type.

And second, I don't really understand the above warnings at all,
because emacsclient.c in Emacs 24.1 says this starting at line 232,
way before line 1606:

  char *get_current_dir_name (void);

  /* Return the current working directory.  Returns NULL on errors.
     Any other returned value must be freed with free.  This is used
     only when get_current_dir_name is not defined on the system.  */
  char*
  get_current_dir_name (void)
  {

> Unfortunately, that's not at all a simple answer, especially not for an
> old codebase.  If I kept attempting to fix the above, I'm sure I'd have
> ran into many more problems.

I'm sure you would.  And I would naïvely ask: why shouldn't we have an
easily-discoverable option to avoid such problems when we need to
compile old source code?

> > Would there be a subset of dependencies such that there is greater
> > longevity anticipated for, by way of illustration, Emacs compiled
> > without GTK.  Namely, a subset of e.g. terminal-based Emacs?
> 
> I certainly expect Emacs compiled with fewer dependencies to live for
> longer, because that means, by proxy, that it is smaller.

That's impractical to expect.  People expect Emacs to do everything
including coffee, so most of the users want as rich Emacs as possible,
not as lean as possible.

And anyway, some compatibility problems are in system libraries such
as libc and basic GUI stuff, and those dependencies cannot be removed
from Emacs.

> >>> See above: that's not what happens.  In reality, the build invokes the
> >>> compiler without specifying the dialect, so whatever is the default C
> >>> dialect is being used.  So when the default changes to be
> >>> backward-incompatible, it's bound to break old programs.
> >>
> >> Indeed, the default dialect can change.  This is why I find the
> >> autotools choice to only provide -std=... conditionally dubious.
> >
> > Do you have a suggestion to improve this?
> 
> Yes.  Pass it always when possible, ensure that it has an effect.
> 
> I've seen some projects do the following for C++:
> 
>   AC_DEFUN([NMS_CXX_11],
>   [AC_MSG_CHECKING([whether $CXX is for C++11])
>   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
>   [#if __cplusplus != 201103
>   #error "C++11 is required"
>   #endif
>   ]])],
>   [AC_MSG_RESULT([yes])],
>   [CXX_ORIG="$CXX"
>   CXX="$CXX -std=c++11"
>   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
>   [#if __cplusplus != 201103
>   #error "C++11 is required"
>   #endif
>   ]])],
>   AC_MSG_RESULT([adding -std=c++11]),
>   [CXX="$CXX_ORIG"
>   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
>   [#if __cplusplus > 201103
>   #error "C++11 is required"
>   #endif
>   ]])],
>   AC_MSG_RESULT([> C++11]),
>   AC_MSG_RESULT([no])
>   AC_MSG_ERROR([C++11 is required])]))
>   unset CXX_ORIG])])
> 
> ... i.e. ensure that the compiler is *truly* a C++11 compiler, at least
> by adding -std=c++11.
> 
> Analogously this goes for every C version.

That's harsh: it requires one to install a compiler that adheres to
the particular version of the standard even if that is not required by
the code.  We in Emacs use a different approach: we use features from
newer standards when they are available, and have workarounds and
replacements for when they are not.  This is why our configure script
checks for various -std=gnuXX and -std=cXX options, starting from the
most advanced one and going back to the oldest one we want to support,
and uses the first one that's supported (and compiles the test program
with features from that version of the standard).