port maintainers: please test check for implicit decls

Ryan Schmidt ryandesign at macports.org
Wed Nov 25 09:43:39 UTC 2020



On Nov 24, 2020, at 16:15, Clemens Lang wrote:

> 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.

Thanks Clemens. I've been meaning to write about that problem here. I want to elaborate on this issue for our developers who haven't been following it closely.

It's the version of clang shipped with Xcode 12 that introduced the change that made implicit declaration of functions an error rather than a warning, so it also affects Catalina users who have upgraded to Xcode 12 (or the matching CLT). It does not affect our Catalina buildbot worker because I'm keeping it at Xcode 11.x (with the matching CLT).

There are a zillion ports affected by this issue, so we have a lot of work to do to fix them all, and we appreciate all developers who have time to pitch in and fix ports. There's often a tendency for developers to stick to the ports they know and maintain and to ignore tickets about other ports, but with this problem the needed fixes are often pretty similar so once you understand how to fix it once or twice, you can apply that knowledge to fix other ports even if you're not familiar with those ports.

Before trying to patch the problem yourself, check if there's a new version of the software available. Maybe updating the port would fix it. If no new version is available, it can also be worthwhile to see if Debian or another package management system out there has already developed patches that we could use. If you do have to develop a patch yourself, and the software is still being actively developed, you should usually send the patch back to the developers so they can include it in the next version. Add the URL of your bug report to the header of your patch.

The way to fix the problem is usually to include the right headers. Often clang will tell you in the error message what the right header is. If it doesn't, you can look up the function in the manpages using "man 3" or "man 2". For example "man 3 exit" tells you that to use "exit" you need to "#include <stdlib.h>".

There are four ways that this problem typically manifests. First, a port could fail to build in the build phase with an error about implicit function declarations. This is straightforward; you would usually fix the file mentioned in the error. Second, a port could fail in the configure phase because one of the configure tests failed to find something essential because of implicit function declarations in that specific test in the configure script. This is more difficult because MacPorts 2.6.4 and earlier don't show you the error in the main log; you have to look in the config.log. This is the problem that this change from Clemens is designed to address, by looking through config.log for you and pulling relevant errors into the main log. To fix the problem, if your port does not auto(re)conf, patch the configure script tests. If your port does auto(re)conf, patch the tests in their original files (configure.ac/configure.in/any .m4 file, possibly even one installed by another port). A third possibility is that a configure test could get the wrong result due to implicit function declaration but allow configure to succeed, and then the build fails later with any number of unexpected errors. The fourth way is like the third expect that the build succeeds but is built wrong due to wrong configure results; in this case, in addition to fixing the problem, the revision would need to be increased to rebuild it.

There are two possible fixes for implicit declaration of function "exit", and this is a common error because so many configure script tests use it without including the required header. One possible fix is to add "#include <stdlib.h>". The other possible fix, provided that "exit" is being called from "main", is to replace "exit(...)" with "return ...".

Please resist the urge to simply add -Wno-error=implicit-function-declaration to CFLAGS. This returns you to the way that Xcode 11 and earlier worked and while it may allow the build to succeed on x86_64, the build could either fail on arm64 or worse yet succeed but crash at runtime. Apple made this condition an error for a reason: the compiler needs to know whether a function is variadic or non-variadic in order to know how to generate the correct machine code to call the function on arm64, and the way that the compiler knows that is by seeing a function declaration or definition before the function is called. In other words, include the header that contains the declaration.

You can find many of the tickets about ports that need fixing by searching the issue tracker for summary "implicit":

https://trac.macports.org/query?status=!closed&summary=~implicit

If you need examples of how to fix these kinds of problems you can search commits for "implicit":

https://github.com/macports/macports-ports/search?q=implicit&type=commits

We often name the patchfile "implicit.patch" to make it easier to find so you can also search your local ports tree for files of that name. We often put the exact error messages that were encountered that the patch fixes in the header of the patchfile to make it easier for others to find when trying to figure out how to fix these errors.


If you want to participate in experiencing and fixing these problems but you haven't upgraded to Xcode 12, you can fake it by modifying portconfigure.tcl:

--- src/port1.0/portconfigure.tcl.orig
+++ src/port1.0/portconfigure.tcl
         configure.classpath
 # compiler flags section
 default configure.optflags      -Os
-default configure.cflags        {${configure.optflags}}
-default configure.objcflags     {${configure.optflags}}
+default configure.cflags        {${configure.optflags} -Werror=implicit-function-declaration}
+default configure.objcflags     {${configure.optflags} -Werror=implicit-function-declaration}
 default configure.cppflags      {[portconfigure::configure_get_cppflags]}
 proc portconfigure::configure_get_cppflags {} {
     global prefix

This is what I'm doing on High Sierra. Note that this will only be accurate for ports that actually honor MacPorts CFLAGS, but if you encounter a port that does not, that is in and of itself a bug that should be fixed.




More information about the macports-dev mailing list