user5434231
user5434231

Reputation: 589

GCC "multiple definition" errors when linking with external library

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) { /* ... */ }

Upvotes: 4

Views: 2574

Answers (2)

Craig Estey
Craig Estey

Reputation: 33621

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.

Upvotes: 5

mentat
mentat

Reputation: 2768

Perhaps you need include guards?

Upvotes: 0

Related Questions