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.


Reply via email to