Discussion:
autoconf tests and stdcall name mangling
Dimitrios Apostolou
2013-05-22 18:22:32 UTC
Permalink
(Not sure which list is relevant, so I'm cross-posting to both mingw-users
and autoconf lists)

Hello lists,

when I'm cross compiling from linux x86_64 to 32-bit MinGW autoconf
refuses to detect getaddrinfo and define HAVE_GETADDRINFO. I've limited
the case to the following behaviour:

The "getaddrinfo-link.c" attached file is a simplification of what
AC_REPLACE_FUNCS(getaddrinfo) tries to compile and link. It fails to find
the symbol because gcc most probably doesn't use proper calling
conventions (stdcall). This is demonstrated by the build success of the
second attached program. So:

$ i686-w64-mingw32-gcc -o getaddrinfo-link getaddrinfo-link.c -lws2_32
/tmp/cctQtw3q.o:getaddrinfo-link.c:(.text+0xc): undefined reference to `_getaddrinfo'
collect2: ld returned 1 exit status
$ i686-w64-mingw32-gcc -o getaddrinfo-link getaddrinfo-link-2.c -lws2_32
$

In the second case ("getaddrinfo-link-2.c") compilation is successful
because the symbol linked is "***@16" which actually exists in
ws2_32 (verified it with nm). Here is the version of my toolchain:

$ i686-w64-mingw32-gcc --version
i686-w64-mingw32-gcc (GCC) 4.6.3

Any idea what's the proper way to use AC_REPLACE_FUNCS in this case?


Thanks in advance,
Dimitris
Nick Bowler
2013-05-22 20:06:05 UTC
Permalink
Hello,
Post by Dimitrios Apostolou
The "getaddrinfo-link.c" attached file is a simplification of what
AC_REPLACE_FUNCS(getaddrinfo) tries to compile and link. It fails to find
the symbol because gcc most probably doesn't use proper calling
conventions (stdcall). This is demonstrated by the build success of the
[...]
Post by Dimitrios Apostolou
In the second case ("getaddrinfo-link-2.c") compilation is successful
ws2_32 (verified it with nm).
[...]
Post by Dimitrios Apostolou
[getaddrinfo-link-2.c]
int __attribute__((__stdcall__)) getaddrinfo(int,int,int,int);
[...]

The fundamental problem, I think, is that you really need the proper
headers included and AC_REPLACE_FUNCS does not seem to allow you to
specify the includes. So you probably can't use this macro at all.

You can use AC_LINK_IFELSE to fully specify the test program to compile
and link, which is probably what you'll need to do here. This may still
be tricky to get right. Alternately, Gnulib[1] has a getaddrinfo module[2]
which may already do everything you need (although I have not used it).

[1] https://gnu.org/s/gnulib
[2] http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=modules/getaddrinfo

Cheers,
--
Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/)
Zack Weinberg
2013-05-22 20:12:44 UTC
Permalink
Post by Nick Bowler
The fundamental problem, I think, is that you really need the proper
headers included and AC_REPLACE_FUNCS does not seem to allow you to
specify the includes. So you probably can't use this macro at all.
You can use AC_LINK_IFELSE to fully specify the test program to compile
and link, which is probably what you'll need to do here. This may still
be tricky to get right. Alternately, Gnulib[1] has a getaddrinfo module[2]
which may already do everything you need (although I have not used it).
I wrote the attached macro to solve a closely related problem (looking
for ntohl, not getaddrinfo; the way Winsock works, it's equivalent).
Perhaps it will be useful to you.

Going forward I think AC_*_FUNC[S] really need to grow a way to
specify headers. Fake-declaring everything as "char foo();" has been
kinda silly for years now.

zw
Eric Blake
2013-05-22 20:35:00 UTC
Permalink
Post by Zack Weinberg
Post by Nick Bowler
The fundamental problem, I think, is that you really need the proper
headers included and AC_REPLACE_FUNCS does not seem to allow you to
specify the includes. So you probably can't use this macro at all.
You can use AC_LINK_IFELSE to fully specify the test program to compile
and link, which is probably what you'll need to do here. This may still
be tricky to get right. Alternately, Gnulib[1] has a getaddrinfo module[2]
which may already do everything you need (although I have not used it).
I wrote the attached macro to solve a closely related problem (looking
for ntohl, not getaddrinfo; the way Winsock works, it's equivalent).
Perhaps it will be useful to you.
Going forward I think AC_*_FUNC[S] really need to grow a way to
specify headers. Fake-declaring everything as "char foo();" has been
kinda silly for years now.
AC_CHECK_DECL ("can I compile against this function when using the right
headers") is a much better macro than AC_CHECK_FUNC ("can I link against
this symbol, and cross-my-fingers that the library actually exported it
by this name and not some other due to aliasing or stdcall or ...").
There are still a few corner cases where some platforms accidentally
declare a function but fail to export it, so both styles of probes are
still useful in practice; but generally you should try the DECL form first.

Maybe this warrants a patch to the autoconf manual to point this out
more emphatically; anyone want to take a stab at it?
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
Dimitrios Apostolou
2013-05-23 08:55:16 UTC
Permalink
Post by Eric Blake
Post by Zack Weinberg
Post by Nick Bowler
The fundamental problem, I think, is that you really need the proper
headers included and AC_REPLACE_FUNCS does not seem to allow you to
specify the includes. So you probably can't use this macro at all.
You can use AC_LINK_IFELSE to fully specify the test program to compile
and link, which is probably what you'll need to do here. This may still
be tricky to get right. Alternately, Gnulib[1] has a getaddrinfo module[2]
which may already do everything you need (although I have not used it).
I wrote the attached macro to solve a closely related problem (looking
for ntohl, not getaddrinfo; the way Winsock works, it's equivalent).
Perhaps it will be useful to you.
Going forward I think AC_*_FUNC[S] really need to grow a way to
specify headers. Fake-declaring everything as "char foo();" has been
kinda silly for years now.
AC_CHECK_DECL ("can I compile against this function when using the right
headers") is a much better macro than AC_CHECK_FUNC ("can I link against
this symbol, and cross-my-fingers that the library actually exported it
by this name and not some other due to aliasing or stdcall or ...").
There are still a few corner cases where some platforms accidentally
declare a function but fail to export it, so both styles of probes are
still useful in practice; but generally you should try the DECL form first.
The way I'm using autoconf up to now, I first do an AC_CHECK_DECLS and
right afterwards AC_REPLACE_FUNCS. For this case I'll only use
AC_CHECK_DECLS, thanks everyone for helping. :-)
Post by Eric Blake
Maybe this warrants a patch to the autoconf manual to point this out
more emphatically; anyone want to take a stab at it?
The AC_REPLACE_FUNCS comes in really handy, so I believe it should be
updated if AC_CHECK_FUNC is not the recommended way to replace
non-existing functions.


Thanks,
Dimitris
Dimitrios Apostolou
2013-05-23 09:41:55 UTC
Permalink
Post by Zack Weinberg
Post by Nick Bowler
The fundamental problem, I think, is that you really need the proper
headers included and AC_REPLACE_FUNCS does not seem to allow you to
specify the includes. So you probably can't use this macro at all.
You can use AC_LINK_IFELSE to fully specify the test program to compile
and link, which is probably what you'll need to do here. This may still
be tricky to get right. Alternately, Gnulib[1] has a getaddrinfo module[2]
which may already do everything you need (although I have not used it).
I wrote the attached macro to solve a closely related problem (looking
for ntohl, not getaddrinfo; the way Winsock works, it's equivalent).
Perhaps it will be useful to you.
Going forward I think AC_*_FUNC[S] really need to grow a way to
specify headers. Fake-declaring everything as "char foo();" has been
kinda silly for years now.
What I really need from autoconf is to append to config.h the results of
the tests so far right after every test. That way I'd be able to #include
"platform.h" instead of AC_DEFAULT_INCLUDES and I'd get an increasing
number of headers included after every test.

That in combination to checking for the exact prototype I define, would
have resolved many of my problems. Something like:
AC_CHECK_FUNC([int getaddrinfo(NULL,NULL,NULL,NULL)])


Thanks,
Dimitris

Dimitrios Apostolou
2013-05-22 20:11:20 UTC
Permalink
Post by Dimitrios Apostolou
(Not sure which list is relevant, so I'm cross-posting to both mingw-users
and autoconf lists)
Not a cross-post after all since mingw-users requires registration. I'd
appreciate any help from autoconf people, just make sure you don't CC
mingw-users so that you don't get a bounce (or just reply to this
message).
Post by Dimitrios Apostolou
Hello lists,
when I'm cross compiling from linux x86_64 to 32-bit MinGW autoconf refuses
to detect getaddrinfo and define HAVE_GETADDRINFO. I've limited the case to
The "getaddrinfo-link.c" attached file is a simplification of what
AC_REPLACE_FUNCS(getaddrinfo) tries to compile and link. It fails to find the
symbol because gcc most probably doesn't use proper calling conventions
(stdcall). This is demonstrated by the build success of the second attached
$ i686-w64-mingw32-gcc -o getaddrinfo-link getaddrinfo-link.c -lws2_32
/tmp/cctQtw3q.o:getaddrinfo-link.c:(.text+0xc): undefined reference to `_getaddrinfo'
collect2: ld returned 1 exit status
$ i686-w64-mingw32-gcc -o getaddrinfo-link getaddrinfo-link-2.c
-lws2_32
$
In the second case ("getaddrinfo-link-2.c") compilation is successful because
$ i686-w64-mingw32-gcc --version
i686-w64-mingw32-gcc (GCC) 4.6.3
Any idea what's the proper way to use AC_REPLACE_FUNCS in this case?
Thanks in advance,
Dimitris
Loading...