Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unclear how CCompiler.has_function works for functions with parameters #3648

Closed
fweimer-rh opened this issue Oct 24, 2022 · 3 comments · Fixed by pypa/distutils#195
Closed

Comments

@fweimer-rh
Copy link
Contributor

This issue is a continuation of python/cpython#98529.

CCompiler.has_function constructs the source code for a linking test for function availability like this:

for incl in includes:
f.write("""#include "%s"\n""" % incl)
f.write(
"""\
int main (int argc, char **argv) {
%s();
return 0;
}
"""
% funcname
)

Let's assume that the checked function actually exists and has one or more arguments. There are two cases to consider:

  1. Include files are specified, and the function is declared in the include files (or a function-like macro is defined).
  2. No include files are specified, or the function is not declared in the specified include files.

In the first case, compilation fails because not enough arguments are specified in the function call. We never get to the linking stage.

In the second case, compilation still fails with strict C compilers (Clang 16, probably future GCC 14) because implicit function declarations are a C89 feature that was removed from C99 and future language standards. Again, no link is attempted.

This means that has_function really can't detect functions successfully (at least if they expect more than one argument).

Autoconf works around this by supplying a char foo(); declaration and calling that (still in a link-only test). That still does not allow the detection of alternative macro implementations. It is incompatible with the header file list that is allegedly supported by has_function: If you supply your own definition, you must not include any header files that potentially conflict with it.

(Found via the Fedora C99 porting project.)

@keszybz
Copy link

keszybz commented Oct 27, 2022

Yep, the current check won't work. Meson's has_function() implementation would be a good start.

fweimer-rh added a commit to fweimer-rh/setuptools that referenced this issue Dec 14, 2022
C99 removed support for implicit function declarations.  This means
that just calling a function, without declaring the function first,
can result in a compilation error.  Today, has_function works with
most compilers because they issue just a warning, create an object
file, and attempt a link, which then detects available of the symbol
at link time, as intended.  With future compilers, compilation will
already fail, and no link test is performed.

The has_function interface provides the caller with a way to supply
a list of header files to include.  However, even with today's
compilers, this only works if the function does not expect any
parameters.  Otherwise, the function call in the C fragment created
by has_function will not supply the correct argument list and fail
compilation.  Therefore, this change supplies and incorrect prototype
without arguments.  This is what autoconf does today in a very
similar situation, so it is quite likely that compilers will support
this construct in this context in the future.

The includes and include_dirs arguments are deprecated because of
the parameter list mismatch issue.

Fixes pypa#3648.
fweimer-rh added a commit to fweimer-rh/setuptools that referenced this issue Dec 14, 2022
C99 removed support for implicit function declarations.  This means
that just calling a function, without declaring the function first,
can result in a compilation error.  Today, has_function works with
most compilers because they issue just a warning, create an object
file, and attempt a link, which then detects available of the symbol
at link time, as intended.  With future compilers, compilation will
already fail, and no link test is performed.

The has_function interface provides the caller with a way to supply
a list of header files to include.  However, even with today's
compilers, this only works if the function does not expect any
parameters.  Otherwise, the function call in the C fragment created
by has_function will not supply the correct argument list and fail
compilation.  Therefore, this change supplies and incorrect prototype
without arguments.  This is what autoconf does today in a very
similar situation, so it is quite likely that compilers will support
this construct in this context in the future.

The includes and include_dirs arguments are deprecated because of
the parameter list mismatch issue.

Fixes pypa#3648.
@fweimer-rh
Copy link
Contributor Author

@jaraco Thanks for merging this into pya/distutils. Can we apply this to pypa/setuptools as well? Should I send another PR?

@jaraco
Copy link
Member

jaraco commented Feb 20, 2023

Yes, was merged in v67.2.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants