4
votes

I'm trying to use a library (Watt-32, if it's relevant), which fails to link for some reason. I've compiled the library and as a quick "hello world" test, I'm trying to compile the following file:

#include <tcp.h>
int main() { sock_init(); } 

This causes GCC to produce a long list of multiple definition errors, in the library's own source files:

D:\projects\test-tcp>c++ -Iinclude test-tcp.cpp -Llib -lwatt

lib\libwatt.a(rs232.o): In function `_ntohl':
D:\msys64\home\JW\watt32\src/../inc/sys/swap.h:63: multiple definition of `__ntohl'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/../inc/sys/swap.h:63: first defined here
lib\libwatt.a(rs232.o): In function `_ntohs':
D:\msys64\home\JW\watt32\src/../inc/sys/swap.h:73: multiple definition of `__ntohs'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/../inc/sys/swap.h:73: first defined here
lib\libwatt.a(rs232.o): In function `get_fs_reg':
D:\msys64\home\JW\watt32\src/misc.h:736: multiple definition of `get_fs_reg'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/misc.h:736: first defined here
lib\libwatt.a(rs232.o): In function `get_gs_reg':
D:\msys64\home\JW\watt32\src/misc.h:744: multiple definition of `get_gs_reg'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/misc.h:744: first defined here
lib\libwatt.a(rs232.o): In function `set_fs_reg':
D:\msys64\home\JW\watt32\src/misc.h:751: multiple definition of `set_fs_reg'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/misc.h:751: first defined here
lib\libwatt.a(rs232.o): In function `set_gs_reg':
D:\msys64\home\JW\watt32\src/misc.h:757: multiple definition of `set_gs_reg'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/misc.h:757: first defined here
lib\libwatt.a(ports.o): In function `_ntohl':
D:\msys64\home\JW\watt32\src/../inc/sys/swap.h:63: multiple definition of `__ntohl'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/../inc/sys/swap.h:63: first defined here
lib\libwatt.a(ports.o): In function `_ntohs':
D:\msys64\home\JW\watt32\src/../inc/sys/swap.h:73: multiple definition of `__ntohs'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/../inc/sys/swap.h:73: first defined here
lib\libwatt.a(ports.o): In function `get_fs_reg':
D:\msys64\home\JW\watt32\src/misc.h:736: multiple definition of `get_fs_reg'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/misc.h:736: first defined here
lib\libwatt.a(ports.o): In function `get_gs_reg':
D:\msys64\home\JW\watt32\src/misc.h:744: multiple definition of `get_gs_reg'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/misc.h:744: first defined here
lib\libwatt.a(ports.o): In function `set_fs_reg':
D:\msys64\home\JW\watt32\src/misc.h:751: multiple definition of `set_fs_reg'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/misc.h:751: first defined here
lib\libwatt.a(ports.o): In function `set_gs_reg':
D:\msys64\home\JW\watt32\src/misc.h:757: multiple definition of `set_gs_reg'
lib\libwatt.a(pctcp.o):D:\msys64\home\JW\watt32\src/misc.h:757: first defined here
lib\libwatt.a(language.o): In function `_ntohl':
[... etc ...]

I must be doing something wrong here, but what exactly? It seems like a problem with the library itself..?

edit: These functions are defined as follows in the library source: (implementation omitted, it's all inline assembly code)

extern __inline__ WORD get_fs_reg (void)     { /* ... */ }
extern __inline__ WORD get_gs_reg (void)     { /* ... */ }
extern __inline__ void set_fs_reg (WORD sel) { /* ... */ }
extern __inline__ void set_gs_reg (WORD sel) { /* ... */ }
/*@unused@*/ extern __inline__ unsigned long __ntohl (unsigned long x)  { /* ... */ }
/*@unused@*/ extern __inline__ unsigned short __ntohs (unsigned short x) { /* ... */ }
2
The problem could be with function definitions in header files. Have a look at the code where get_fs_reg and get_gs_reg are defined, in misc.h (post that code in the question perhaps). Maybe they are not marked as inline when they should be. Also, C and C++ behave differently w.r.t. inline functions. so if this library was a C library it's possible that the headers may need some change to be usable from C++. - M.M
Also try making a C program that includes the header and see if the same errors come up - M.M
@M.M, all these functions are actually marked __inline__, and compiled with -O2. I've added their definitions to the question. Compiling the test file as plain C doesn't make any difference. (which I guess makes the c++ tag somewhat irrelevant) - user5434231
See if there is a newer version of the library and headers. The changelog mentions "misc.h change: Watcom uses 'i64' suffix for 64-bit values.". I wonder if both 32 bit and 64 bit functions are somehow being compiled into the same library. watt-32.net/change.log - Sammy

2 Answers

5
votes

These header files are a bit old/dated. The usage of extern inline has changed with newer compilers. extern inline was the preferred way for many years. It worked fine on gcc but clang needed static inline

Now, even gcc wants static inline even with -O2 or you get what you're seeing. Since you're recompiling from source, you may have to edit the .h and change all of them to static.

I have boilerplate for my code that was #define craigs_inline extern inline and now I've switched it to #define craigs_inline static inline to keep the peace.

Note that I didn't investigate a compiler -foption_whatever that might obviate the need for this. If you find you one, please send me a comment as I'd be interested to know.

0
votes