wiki:WimplicitFunctionDeclaration

WimplicitFunctionDeclaration

WimplicitFunctionDeclaration is wiki shorthand for a particular warning message, "Warning: Configuration logfiles contain indications of -Wimplicit-function-declaration; check that features were not accidentally disabled", which MacPorts sometimes displays when configuring a port. This page explains what you as a MacPorts user should understand about this message, and what helpful steps you can take. It also explains to port maintainers, and the adventurer who wants to diagnose the problem behind the warning, the reason why the message appears, and how to pursue the problem to the upstream developers.

The warning

Here is what MacPorts prints to Terminal when building the freeciv-common port. Certain parts of this port's code causes MacPorts to issue the warning message.

% sudo port build freeciv-common
--->  Computing dependencies for freeciv-common
--->  Fetching distfiles for freeciv-common
--->  Verifying checksums for freeciv-common
--->  Extracting freeciv-common
--->  Configuring freeciv-common
Warning: Configuration logfiles contain indications of -Wimplicit-function-declaration; check that features were not accidentally disabled:
  strcmp: found in freeciv-2.6.6/config.log
  exit: found in freeciv-2.6.6/config.log
  at_quick_exit: found in freeciv-2.6.6/config.log
--->  Building freeciv-common
%

MacPorts displays the same warning message, "Warning: Configuration logfiles contain indications of -Wimplicit-function-declaration; check that features were not accidentally disabled", for every port. The following lines summarise each separate indication which MacPorts found. Each indication is of a separate place in the source code which might be using a function name as an "implicit function declaration". The indication gives the function name. It is a clue for investigating the situation. The "implicit function declaration" could potentially cause the port to configure incorrectly, especially on Apple Silicon Macs, or on macOS Big Sur or newer versions.

In this example, there are three indications. They are related to the functions "strcmp", "exit", and "at_quick_exit".

The message "found in freeciv-2.6.6/config.log" gives the final part of the path to the log file which contains the message. This log file is in the port's work directory, which only exists while the port is being built and prepared for installation. Once installation is complete, MacPorts deletes the work directory and the log file. The command port work portname tells MacPorts to print out the path to the work directory. Thus, to open the log file in editor, you can use a command combining port work and the final part of the path:

% edit $(port work freeciv-common)/freeciv-2.6.6/config.log

In the config.log, search for each function name mentioned in the configuration output. This might look like (with line breaks added for legibility):

configure:25690: checking for C11 at_quick_exit()
configure:25713: /usr/bin/clang -o conftest -pipe -Os -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -arch x86_64 
-I/opt/local/include -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -Werror -Wall -Wpointer-arith -Wcast-align 
-Wno-tautological-compare -L/opt/local/lib -Wl,-headerpad_max_install_names -Wl,-syslibroot,/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk 
-arch x86_64 conftest.c  -liconv >&5
conftest.c:99:2: error: implicit declaration of function 'at_quick_exit' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
 at_quick_exit(func);
 ^
1 error generated.
configure:25713: $? = 1
configure: failed program was:
| /* confdefs.h */
| …[lines omitted for brevity]…
| /* end confdefs.h.  */
| #include <stdlib.h>
| static void func(void)
| {}
| 
| int
| main (void)
| {
|  at_quick_exit(func);
|   ;
|   return 0;
| }
configure:25723: result: no

Note: if MacPorts has deleted the work directory, the port work gives no output, and the edit command above will fail.

See the #Diagnosis section below for how to pursue the clues in the logs further.

Respond by filing MacPorts ticket(s)

The -Wimplicit-function-declaration warning could be a serious bug in a port. It is worth reporting such problems. This lets other users of the same port know that the problem is recognised, and it lets port maintainers (and you, if you want) diagnose the problem further, and report it to the upstream developers of the port's source code. So, please consider filing a MacPorts ticket about the problems.

You have a choice of filing a a separate MacPorts ticket for each indication in the message, or a single ticket for all the indications. Each indication is evidence of a separate problem, which might get fixed or languish independent of the others. But, someone who works on one problem might well work on the others at the same time. And filing a single ticket is less work than filing multiple. Choosing to file a single ticket for all the indications is perfectly fine.

Follow the instructions for filing a MacPorts ticket. Be sure to check for existing tickets on this port about the -Wimplicit-function-declaration warnings. There is no point in filing a redundant report.

What it means

MacPorts started generating this message in MacPorts 2.7.0, released in May 2021.

Clemens Lang announced the functionality in an announcement to the MacPorts Dev email list in a message, port maintainers: please test check for implicit decls on Tue Nov 24 22:15:53 UTC 2020:

This will become a significant problem with the release of Big Sur, since Apple has made -Wimplicit-function-declaration an error by default due to details of the calling convention on Apple Silicon.

The problem this warning is designed to catch is as follows:

  1. A configure check tests for presence and usability of a function, but does not include a header declaring the function.
  2. The configure check fails due to -Wimplicit-function-declaration, but would succeed otherwise.
  3. The configure script disables certain functionality based on this incorrect result, and software compiles differently than it used to.

Ryan Schmidt's reply to that thread has a lot more detail. Please read it. It is not easy to summarise it here.

Ryan Schmidt explained it to the MacPorts Users list in a message, "Re: Warning: -Wimplicit-function-declaration" on Thu May 20 06:05:07 UTC 2021:

Sometimes programs are written to use functions before declaring them. This has not been correct ever since the introduction of the 1999 version of the C standard decades ago, but because it was allowed by the earlier 1989 C standard many C99 compilers still allowed this with a warning. But it can cause programs to crash or behave incorrectly on ARM processors, therefore to avoid problems on Apple Silicon Macs, the version of clang in included with Xcode 12 and later considers this to be an error. This causes some ports to fail to build. Worse, many configure tests have this problem, but when they fail, it doesn't cause configure to immediately fail and tell you that; instead, configure just makes wrong determinations about your system. In the best case, the build still succeeds and works fine. Or, the build fails with a bizarre error later. Or the build succeeds but is wrong.

The message you're quoting is a new feature of MacPorts 2.7.0. It now notices when an implicit declaration of function error occurred during configuration, so that the port maintainer can investigate whether this is a problem. The port maintainer can then either fix the problem, or can mark the port to indicate that that particular implicit declaration of function does not represent a problem.

If many programs check for functions which we know are not ever present on certain versions of macOS, then we can mark that in a central location rather than individually in each affected port.

The -Wimplicit-function-declaration warning does not cause the problem. The underlying code, together with the behaviour of Xcode 12 and ARM processors, causes the problem. And the problem might be silent in some cases. The message just makes the problem visible. It is sometimes possible to work around such problems by having the port patch the underlying code at the MacPorts stage. It is far better to have the upstream developers change their code so that it works with Xcode 12 and on ARM processors, along with all the other compilers and processors where it needs to work.

Thus, in the long term, the most helpful response to this message is enough diagnosis to make useful bug report, then filing that bug report with the upstream developers.

Diagnosis

In The warning section above, there was an excerpt from a config.log file with one of the indications reported in the -Wimplicit-function-declaration warning. Here are the first few lines again (with line breaks added for legibility):

configure:25690: checking for C11 at_quick_exit()
configure:25713: /usr/bin/clang -o conftest -pipe -Os -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -arch x86_64 
-I/opt/local/include -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -Werror -Wall -Wpointer-arith -Wcast-align 
-Wno-tautological-compare -L/opt/local/lib -Wl,-headerpad_max_install_names -Wl,-syslibroot,/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk 
-arch x86_64 conftest.c  -liconv >&5
conftest.c:99:2: error: implicit declaration of function 'at_quick_exit' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
 at_quick_exit(func);
 ^
1 error generated.
configure:25713: $? = 1
configure: failed program was:
| /* confdefs.h */
| …[lines omitted for brevity]…
| /* end confdefs.h.  */
| #include <stdlib.h>
| static void func(void)
| {}
| 
| int
| main (void)
| {
|  at_quick_exit(func);
|   ;
|   return 0;
| }
configure:25723: result: no

The notation configure:25690 refers to line 25690 of file configure in the work directory. configure is a shell script generated by the GNU Autoconf tool. For this project, those lines looked like:

  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C11 at_quick_exit()" >&5
printf %s "checking for C11 at_quick_exit()... " >&6; }
if test ${ac_cv_c11_at_quick_exit+y}
then :
  printf %s "(cached) " >&6
else $as_nop

                        fc_save_CPPFLAGS="$CPPFLAGS"
    CPPFLAGS="$CPPFLAGS -Werror $EXTRA_DEBUG_CFLAGS"
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>
static void func(void)
{}

int
main (void)
{
 at_quick_exit(func);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_c11_at_quick_exit=yes
else $as_nop
  ac_cv_c11_at_quick_exit=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
    CPPFLAGS="$fc_save_CPPFLAGS"
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c11_at_quick_exit" >&5
printf "%s\n" "$ac_cv_c11_at_quick_exit" >&6; }
  if test "x${ac_cv_c11_at_quick_exit}" = "xyes" ; then

printf "%s\n" "#define HAVE_AT_QUICK_EXIT 1" >>confdefs.h

  fi

So, the implicit function declaration appears to be in line 25708 of configure: at_quick_exit(func); .

Autoconf generates the configure file as a result of performing an auto-configuration, driven by script files. configure.ac is an often-used name for the script file which drives Autoconf as it generates configure. Looking in configure.ac in the work directory, we see no mention of at_quick_exit(func);.

Searching the entire code base for the distinctive string at_quick_exit, we discover another file, m4/c11.m4, with this code:

AC_DEFUN([FC_C11_AT_QUICK_EXIT],
[
  AC_CACHE_CHECK([for C11 at_quick_exit()], [ac_cv_c11_at_quick_exit], [
    dnl Add -Werror to detect cases where the header does not declare
    dnl at_quick_exit() but linking still work. This situation can happen
    dnl when the header is strict about the fact that at_quick_exit() is
    dnl a C11 feature and the compiler is not in C11 mode.
    dnl $EXTRA_DEBUG_CFLAGS contains -Wmissing-declarations if it's supported.
    fc_save_CPPFLAGS="$CPPFLAGS"
    CPPFLAGS="$CPPFLAGS -Werror $EXTRA_DEBUG_CFLAGS"
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>
static void func(void)
{}
]], [[ at_quick_exit(func); ]])],
[ac_cv_c11_at_quick_exit=yes], [ac_cv_c11_at_quick_exit=no])
    CPPFLAGS="$fc_save_CPPFLAGS"])
  if test "x${ac_cv_c11_at_quick_exit}" = "xyes" ; then
    AC_DEFINE([HAVE_AT_QUICK_EXIT], [1], [C11 at_quick_exit() available])
  fi
])

The file extension, .m4, indicates it is a GNU M4 script. GNU Autoconf is built using M4. It is likely that the upstream developers wrote this code. It includes the specific expression, [[ at_quick_exit(func); ]], which seems to have triggered the warning. The square brackets surrounding it are Autoconf syntax. It seems like this code might be a useful place to point to in a bug report filed with the upstream developers about the implicit declaration problem.

This code, and its counterpart in configure, are a good place to examine closely for incorrect behaviour. Does the configuration come to the wrong conclusion about the capabilities of the compiler? If so, that is exactly the "features were… accidentally disabled" risk which the original warning was bringing to your attention.

Add names to implicit declaration whitelist

In cases where you have confirmed that a function name is not declared by the include file which should declare it, for a certain macOS SDK, then add that name to whitelists in the MacPorts ports tree. This means that, when the compiler generates a -Wimplicit-function-declaration warning for that name, MacPorts will not display that warning in the terminal output. Thus it will not cause concern to MacPorts users who use ports which test for that fucntion name.

The whitelists are in the ports tree. There is a separate whitelist for each version of the macOS SDK: Mac OS X 10.5, macOS 10.14, macOS 11, etc. Each whitelist is a text file containing a list of C language function names, one per line, in lexical order.

To add a name to the whitelist, first convince yourself that the name is in fact not declared by the include file which should declare it, by creating and compiling a brief test program which uses that function. Observe if you get a warning or error message like:

error: implicitly declaring library function '…' with type '…' [-Werror,-Wimplicit-function-declaration]

or:

error: implicit declaration of function '…' is invalid in C99 [-Werror,-Wimplicit-function-declaration]

You may be able to test using multiple different versions of the macOS SDK. That is good. It is desireable to add a function name to all the whitelists to which it applies.

Then create a Pull Request modifying the whitelist file(s) appropriate for the version(s) of the macOS SDK which you have tested. The change will be simple: to add a line to the file, inserting a new line with the function name, in the correct lexical order. This change will take effect when the user updates their ports tree. It applies to all ports, when configured on the version of macOS which corresponds to the whitelist file.

Add names to whitelist via Portfile

Another approach is to add the function name via the Portfile, via a line like:

configure.checks.implicit_function_declaration.whitelist-append strchr

This adds the function name (in this example, strchr) to the whitelist for the current Portfile, regardless of macOS SDK version. Do this if the reason why this function should be ignored is specific to this port, rather than to the macOS version. For example, configure scripts generated with the latest version of autoconf will complain erroneously about the implicit declaration of strchr because the latest version of autoconf deliberately tries to use strchr without including the right header in order to see how the compiler reacts to that.

Respond by filing upstream bug reports

If you can, please report these indications to the upstream developers. It is far better to have the upstream developers change their code so that it works with Xcode 12 and on ARM processors, along with all the other compilers and processors where it needs to work.

Thus, in the long term, the most helpful response to this message is enough diagnosis to make useful bug report, then filing that bug report with the upstream developers.

The details of how to do this differ for each port. The Portfile for the port will probably have a link to the upstream project's website. That website may well have instructions about how best to file bug reports with that project.

See also

Here are some links to other information related to the -Wimplicit-function-declaration warning.

Macports-users email threads

The following are some of the email threads about the -Wimplicit-function-declaration warning on the macports-users email list. Some of these threads have further insight about the problem and how to respond.

Macports-dev email threads

The following are some of the email threads about the -Wimplicit-function-declaration warning on the macports-dev email list. Some of these threads have further insight about the problem and how to respond.

GNU Automake tools

One kind of source code which triggers -Wimplicit-function-declaration warning is configuration code generated with, or by, GNU Autoconf. We have not discovered any information which says that Autoconf is incompatible with Xcode 12 and ARM processors. However, the way a project uses the Autoconf, where the project's configuration test code triggers the warning, may make it appear that Autoconf is the problem. Here are links to the project websites for these tools. You can find more documentation on them there.

MacPorts code

Want to learn now a feature really works? As the wise teachers say, "Read the source, Luke." Here are links to MacPorts source code which relates to the -Wimplicit-function-declaration warning.

Last modified 7 months ago Last modified on Jan 29, 2022, 6:26:25 AM