The official llllloooooo blog

Sunday, September 13, 2020

"Multiple definition" error when compiling with GCC 10 and above. Inetutils WITHOUT "--disable-servers"

In the spirit of the rare and unusual error messages that I occasionally post on this blog that no one but me will probably ever experience, this post is about the "multiple definition" error message that occurs when you try to compile inetutils 1.9.4 with GCC 10. This error will probably occur with a whole heap of other oldish software as well so even if you're not compiling "inetutils" but you are using GCC 10 or later, this might apply to you if you get the "multiple definition" error.

The error is of the form

/sources/inetutils-1.9.4/telnetd/state.c:69: multiple definition of `not42'; utility.o:/sources/inetutils-1.9.4/telnetd/utility.c:66: first defined here

and also

/sources/inetutils-1.9.4/ftpd/extern.h:93: multiple definition of `errcatch'; ftpcmd.o:/sources/inetutils-1.9.4/ftpd/extern.h:93: first defined here

The problem is that going from GCC 9 and below to GCC 10 and above the default GCC behavior changed. If multiple definitions of the same global variable are made without using the extern keyword, GCC 10 will generate an error message. GCC 9 and below would just treat all of these kinds of global variable definitions as the same variable and not complain. Specifically the default in GCC has changed from "-fcommon" to "-fno-common".

There's a neat explanation at

https://wiki.gentoo.org/wiki/Gcc_10_porting_notes/fno_common


The following solutions work for inetutils. You only have to chose one of them. I used the first one.

1) Specify the "-fcommon" flag when using GCC to compile inetutils. In other words add "-fcommon" to the CFLAGS. I did this by appending 

CFLAGS="-O2 -g -fcommon" 

to the end of the "configure" command I was using during the compilation process.

2) You can specify the "--disable-servers" flag when you run "configure". This gets rid of the affected code and the compilation will succeed but it means that you won't have cool old school services like telnet, echo and discard.

3) Fix the code. You can fix the code by making small modifications to 3 files. These modifications add the "extern" keyword to some of the global variables that need fixing. See the following URL for a suggested patch

http://git.yoctoproject.org/cgit.cgi/poky/diff/meta/recipes-connectivity/inetutils/inetutils/0001-ftpd-telnetd-Fix-multiple-definitions-of-errcatch-an.patch?id2=0e09f045738259c49126a792cdf583f335bb29e8


The background here is that I was trying to work my way through "Linux From Scratch" (LFS) as seen at http://www.linuxfromscratch.org/ . LFS lets you go through the experience of creating and compiling the whole GNU/Linux system from bare bones source code. I got to the part where "inetutils" was being compiled and it failed as seen above. Inetutils gives you useful network tools like "ping" and "traceroute" so it's impossible to completely skip.

If you use the standard LFS configuration for inetutils then you won't run into any problems but I wasn't happy with the default. I noticed that the suggested configuration for inetutils in LFS was to include the configure option "--disable-servers". This means that inetutils would not include some of those useful old school services like "telnet" and "echo" which I still wanted to be available.

The documentation says that LFS excludes these services because they are insecure however I disagree. I think that if used properly, while keeping in mind that these services are indeed susceptible to packet sniffing, they're invaluable for basic network troubleshooting at a local network level. Obviously you're going to prefer to use something encrypted like SSH rather than unencrypted telnet when your packets are travelling over an untrusted network.

So when I didn't include "--disable-servers" as part of the configure step I got the compilation error message as seen above.

I'm sad that the maintainers of inetutils haven't updated it to reflect this change in the GCC 10 compiler, but given that the last release of inetutils was in 1995 (v1.9.4) I don't expect anyone cares too much. 

I hope this helps someone! I'd really love to know in the comments if anyone else has come across this problem while going through Linux From Scratch.