MinGW make error "undefined reference" in modbus-tcp.c #163

Closed
ghost opened this Issue Nov 13, 2013 · 10 comments

Comments

Projects
None yet
2 participants
@ghost

ghost commented Nov 13, 2013

when compiling the newest libmodbus master branch
with the newest MinGW (GCC 4.8.1) on Win7 via the steps:

autogen.sh
./configure
make

the libmodbus-5.dll is not created and make breaks with:

modbus-tcp.c: In function '_modbus_tcp_pi_connect':
modbus-tcp.c:371:5: warning: implicit declaration of function 'getaddrinfo' [-Wimplicit-function-declaration]
     rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service,
     ^
modbus-tcp.c:371:5: warning: nested extern declaration of 'getaddrinfo' [-Wnested-externs]
modbus-tcp.c:414:5: warning: implicit declaration of function 'freeaddrinfo' [-Wimplicit-function-declaration]
     freeaddrinfo(ai_list);
     ^
modbus-tcp.c:414:5: warning: nested extern declaration of 'freeaddrinfo' [-Wnested-externs]

.libs/modbus-tcp.o: In function `modbus_tcp_pi_connect':
src/modbus-tcp.c:371: undefined reference to `getaddrinfo'
src/modbus-tcp.c:414: undefined reference to `freeaddrinfo'
.libs/modbus-tcp.o: In function `modbus_tcp_pi_listen':
src/modbus-tcp.c:561: undefined reference to `getaddrinfo'
src/modbus-tcp.c:615: undefined reference to `freeaddrinfo'
src/modbus-tcp.c:615: undefined reference to `freeaddrinfo'

collect2.exe: error: ld returned 1 exit status
make[2]: *** [libmodbus.la] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
@stephane

This comment has been minimized.

Show comment
Hide comment
@stephane

stephane Nov 13, 2013

Owner

I don't use Windows, could you send a patch, please?

Owner

stephane commented Nov 13, 2013

I don't use Windows, could you send a patch, please?

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Nov 14, 2013

hello stephane,

the "undefined reference" errors for "getaddrinfo" and "freeaddrinfo"
can be repaired by the following changes.
"libmodbus-5.dll" is then successfully created by make.

i suggest in src/modbus-tcp.c to replace lines 32-35 with

 * MinGW header ws2tcpip.h checks _WIN32_WINNT before allowing the use of these */
# undef  _WIN32_WINNT
# define _WIN32_WINNT _WIN32_WINNT_WINXP
# undef  WINVER
# define WINVER       _WIN32_WINNT_WINXP

if you prefer i can also send a pull request ?

ghost commented Nov 14, 2013

hello stephane,

the "undefined reference" errors for "getaddrinfo" and "freeaddrinfo"
can be repaired by the following changes.
"libmodbus-5.dll" is then successfully created by make.

i suggest in src/modbus-tcp.c to replace lines 32-35 with

 * MinGW header ws2tcpip.h checks _WIN32_WINNT before allowing the use of these */
# undef  _WIN32_WINNT
# define _WIN32_WINNT _WIN32_WINNT_WINXP
# undef  WINVER
# define WINVER       _WIN32_WINNT_WINXP

if you prefer i can also send a pull request ?

@stephane

This comment has been minimized.

Show comment
Hide comment
@stephane

stephane Nov 14, 2013

Owner

Does it mean _WIN32_WINNT_WINXP is equal to 0x501?

I think you want to say #ifndef and not #undef (I don't intend to unset constants I haven't set).

Owner

stephane commented Nov 14, 2013

Does it mean _WIN32_WINNT_WINXP is equal to 0x501?

I think you want to say #ifndef and not #undef (I don't intend to unset constants I haven't set).

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Nov 14, 2013

hello stephane,

Does it mean WIN32WINNT_WINXP is equal to 0x501?

yes, _ WIN32_WINNT_WINXP = 0x0501 .
it's a microsoft windows symbol and works also with MinGW.

I think you want to say #ifndef and not #undef

first i've tried it with #ifndef , but it did not work: make gave the same compile error.
this is because if _ WIN32_WINNT is not set to 0x0501 , then it defaults
to 0x0500 and the same happens with WINVER .

but in the MinGW header ws2tcpip.h in line 386 is the condition

#if (_WIN32_WINNT >= _WIN32_WINNT_WINXP)

checked before getaddrinfo and freeaddrinfo are managed in ws2tcpip.h .
so if _ WIN32_WINNT is not set to 0x0501 the condition fails and causes
in turn the libmodbus compilation to fail.

ghost commented Nov 14, 2013

hello stephane,

Does it mean WIN32WINNT_WINXP is equal to 0x501?

yes, _ WIN32_WINNT_WINXP = 0x0501 .
it's a microsoft windows symbol and works also with MinGW.

I think you want to say #ifndef and not #undef

first i've tried it with #ifndef , but it did not work: make gave the same compile error.
this is because if _ WIN32_WINNT is not set to 0x0501 , then it defaults
to 0x0500 and the same happens with WINVER .

but in the MinGW header ws2tcpip.h in line 386 is the condition

#if (_WIN32_WINNT >= _WIN32_WINNT_WINXP)

checked before getaddrinfo and freeaddrinfo are managed in ws2tcpip.h .
so if _ WIN32_WINNT is not set to 0x0501 the condition fails and causes
in turn the libmodbus compilation to fail.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Nov 17, 2013

according to the infos from the microsoft developer network

difference between WINVER, _ WIN32_WINNT

windows headers ( WINVER or _ WIN32_WINNT )

with WINVER and _ WIN32_WINNT a developer can set the minimum required
windows system for a project. for example if a project usese functions,
that are available in Win7 and above, but not in earlier windows versions,
then WINVER and _ WIN32_WINNT would need to be set (outside of
libmodbus library code) to 0x0601 (= _ WIN32_WINNT_WIN7).

to take this into account i suggest the tested solution:
to replace in src/modbus-tcp.c the lines 32-35

 * minwg32 headers check WINVER before allowing the use of these */
# ifndef WINVER
# define WINVER 0x0501
# endif

with

 * MinGW header ws2tcpip.h checks _WIN32_WINNT before allowing the use of these */
# if !defined( _WIN32_WINNT ) || ( _WIN32_WINNT < 0x0501 )
#  undef  _WIN32_WINNT
#  define _WIN32_WINNT 0x0501
# endif
# if !defined( WINVER ) || ( WINVER < 0x0501 )
#  undef  WINVER
#  define WINVER 0x0501
# endif

when WINVER and _ WIN32_WINNT are not set by a developer
in a project that includes libmodbus or to a value below WinXP,
it is assured that the minimum required windows version defaults
to WinXP as needed by libmodbus to use getaddrinfo and freeaddrinfo.
but it leaves developers the freedom to require a higher minimum
windows version for a project via WINVER and _ WIN32_WINNT.

ghost commented Nov 17, 2013

according to the infos from the microsoft developer network

difference between WINVER, _ WIN32_WINNT

windows headers ( WINVER or _ WIN32_WINNT )

with WINVER and _ WIN32_WINNT a developer can set the minimum required
windows system for a project. for example if a project usese functions,
that are available in Win7 and above, but not in earlier windows versions,
then WINVER and _ WIN32_WINNT would need to be set (outside of
libmodbus library code) to 0x0601 (= _ WIN32_WINNT_WIN7).

to take this into account i suggest the tested solution:
to replace in src/modbus-tcp.c the lines 32-35

 * minwg32 headers check WINVER before allowing the use of these */
# ifndef WINVER
# define WINVER 0x0501
# endif

with

 * MinGW header ws2tcpip.h checks _WIN32_WINNT before allowing the use of these */
# if !defined( _WIN32_WINNT ) || ( _WIN32_WINNT < 0x0501 )
#  undef  _WIN32_WINNT
#  define _WIN32_WINNT 0x0501
# endif
# if !defined( WINVER ) || ( WINVER < 0x0501 )
#  undef  WINVER
#  define WINVER 0x0501
# endif

when WINVER and _ WIN32_WINNT are not set by a developer
in a project that includes libmodbus or to a value below WinXP,
it is assured that the minimum required windows version defaults
to WinXP as needed by libmodbus to use getaddrinfo and freeaddrinfo.
but it leaves developers the freedom to require a higher minimum
windows version for a project via WINVER and _ WIN32_WINNT.

@SwissKnife

This comment has been minimized.

Show comment
Hide comment
@SwissKnife

SwissKnife Jan 8, 2014

I use libmodbus 3.1.1 on Windows 7 64bit with Qt 5.2 (mingw48 edition).

To successfully link I have added the following to the .pro file:

# for libmodbus
DEFINES += WINVER=0x0501
LIBS += -lwsock32 -lWS2_32

Now the libraries "libws2_32.a" and "libwsock32.a" in the mingw folder "D:\Qt\Qt5.2.0\Tools\mingw48_32\i686-w64-mingw32\lib" are used.

This fixed the issue for me.

I use libmodbus 3.1.1 on Windows 7 64bit with Qt 5.2 (mingw48 edition).

To successfully link I have added the following to the .pro file:

# for libmodbus
DEFINES += WINVER=0x0501
LIBS += -lwsock32 -lWS2_32

Now the libraries "libws2_32.a" and "libwsock32.a" in the mingw folder "D:\Qt\Qt5.2.0\Tools\mingw48_32\i686-w64-mingw32\lib" are used.

This fixed the issue for me.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Jan 9, 2014

hello SwissKnife,

many thanks for your solution !

following your idea, i've successfully tested another alternative,
that works also in a libmodbus/MinGW situation without Qt:

in configure.ac adding

AC_DEFINE(WINVER, 0x0501, _)

somewhere between AC_INIT and AC_OUTPUT, for example after

AM_CONDITIONAL(OS_QNX, test "$os_qnx" = "true")

in the empty line 71

ghost commented Jan 9, 2014

hello SwissKnife,

many thanks for your solution !

following your idea, i've successfully tested another alternative,
that works also in a libmodbus/MinGW situation without Qt:

in configure.ac adding

AC_DEFINE(WINVER, 0x0501, _)

somewhere between AC_INIT and AC_OUTPUT, for example after

AM_CONDITIONAL(OS_QNX, test "$os_qnx" = "true")

in the empty line 71

@stephane stephane closed this in dcfac5a Jan 28, 2014

@stephane

This comment has been minimized.

Show comment
Hide comment
@stephane

stephane Jan 28, 2014

Owner

Thank you @MarjanTomas and @SwissKnife, I've applied the final solution.
I tested only under WinXP with MinGW gcc v4.5 to ensure there is no regression.
Could you test master, please?

Owner

stephane commented Jan 28, 2014

Thank you @MarjanTomas and @SwissKnife, I've applied the final solution.
I tested only under WinXP with MinGW gcc v4.5 to ensure there is no regression.
Could you test master, please?

@ghost ghost assigned stephane Jan 28, 2014

mk8 added a commit to mk8/libmodbus that referenced this issue Jan 29, 2014

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Jan 29, 2014

tested:
compilation of the actual libmodbus master branch 2014-01-29
with MinGW (GCC 4.8.1) on Win7 via the steps:

autogen.sh
./configure
make

result:
libmodbus-5.dll is successfully created and totally
clean at the make step: no warnings, no errors.

ghost commented Jan 29, 2014

tested:
compilation of the actual libmodbus master branch 2014-01-29
with MinGW (GCC 4.8.1) on Win7 via the steps:

autogen.sh
./configure
make

result:
libmodbus-5.dll is successfully created and totally
clean at the make step: no warnings, no errors.

@stephane

This comment has been minimized.

Show comment
Hide comment
@stephane

stephane Jan 29, 2014

Owner

Great, I'll look at usleep() issue in unit-test-server this evening.

Owner

stephane commented Jan 29, 2014

Great, I'll look at usleep() issue in unit-test-server this evening.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment