LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-17-2020, 09:55 PM   #1
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Debian64 stable, LFS 7.1
Posts: 497

Rep: Reputation: 163Reputation: 163
Multiple definition errors when linking on arch using gcc 10.1.0


Someone opened an issue reporting "multiple definition" errors when building on arch. I was able to reproduce the problem after updating an arch docker image locally (gcc 10.1.0 was the default after the update).

Here's part of the log:

Quote:
Making all in src
make[1]: Entering directory '/home/murali/Downloads/rmw/build/src'
make all-am
make[2]: Entering directory '/home/murali/Downloads/rmw/build/src'
CCLD rmw
/bin/ld: rmw-restore_rmw.o:/home/murali/Downloads/rmw/build/src/../../src/rmw.h:95: multiple definition of verbose'; rmw-main.o:/home/murali/Downloads/rmw/build/src/../../src/rmw.h:95: first defined here /bin/ld: rmw-config_rmw.o:/home/murali/Downloads/rmw/build/src/../../src/rmw.h:95: multiple definition of verbose'; rmw-main.o:/home/murali/Downloads/rmw/build/src/../../src/rmw.h:95: first defined here
I have this at the top of rmw.h, which in the past has prevented such problems:

Code:
#ifndef _INC_RMW_H
#define _INC_RMW_H
It builds on other distros, and built on arch before I updated (which I hadn't done for over six months).

Here is a successful build log on Ubuntu Bionic that ran 27 days ago (no code changes since then).

Last edited by Andy Alt; 05-17-2020 at 09:57 PM. Reason: add gcc version to post
 
Old 05-18-2020, 07:55 AM   #2
GazL
LQ Guru
 
Registered: May 2008
Posts: 5,497
Blog Entries: 14

Rep: Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328
Previous versions of gcc were more lenient about multiple definitions of uninitialised global variables. In the latest gcc, they changed the default of -fcommon to -fno-common, which does not allow such duplicates.

To be honest, I'd always assumed that it worked the way -fno-common does, so I was kind of surprised to find out that gcc actually tolerated multiple definitions in the first place and that this has become an issue.

Header guards usually only protect declarations, not definitions (which will normally be in the .c file, not the header)


Until devs get around to fixing their code, specifying -fcommon should workaround the issue.
 
1 members found this post helpful.
Old 05-18-2020, 12:06 PM   #3
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Debian64 stable, LFS 7.1
Posts: 497

Original Poster
Rep: Reputation: 163Reputation: 163
Thanks GazL. This is how I fixed it.
 
1 members found this post helpful.
Old 05-18-2020, 02:12 PM   #4
GazL
LQ Guru
 
Registered: May 2008
Posts: 5,497
Blog Entries: 14

Rep: Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328
You're welcome.

Depending on how large your program will get, it might help to create a globals.{c,h} pair to contain them all. That way you can use a #include "globals.h" rather than spread all those extern ... declarations throughout your code base.

Just an unsolicited suggestion; feel free to ignore.
 
Old 05-18-2020, 05:48 PM   #5
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Debian64 stable, LFS 7.1
Posts: 497

Original Poster
Rep: Reputation: 163Reputation: 163
Quote:
Originally Posted by GazL View Post
You're welcome.

Depending on how large your program will get, it might help to create a globals.{c,h} pair to contain them all. That way you can use a #include "globals.h" rather than spread all those extern ... declarations throughout your code base.

Just an unsolicited suggestion; feel free to ignore.
Your advice is welcome, GazL

I don't understand though. That's what I had before, I was including them with rmw.h instead of a "globals.h". So I'm having trouble understanding how the set-up would work. Maybe you could make a pull request on the repo to show me.

Last edited by Andy Alt; 05-20-2020 at 02:53 PM. Reason: grammar
 
Old 05-23-2020, 12:10 PM   #6
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Debian64 stable, LFS 7.1
Posts: 497

Original Poster
Rep: Reputation: 163Reputation: 163
Quote:
Originally Posted by Andy Alt View Post
Your advice is welcome, GazL

I don't understand though. That's what I had before, I was including them with rmw.h instead of a "globals.h". So I'm having trouble understanding how the set-up would work. Maybe you could make a pull request on the repo to show me.
Ok, I fixed it myself Also added "-fno-common" to the default build flags so I can catch problems like that beforehand from now on. Thanks again, GazL. Have a great weekend.
 
1 members found this post helpful.
Old 05-24-2020, 05:41 AM   #7
GazL
LQ Guru
 
Registered: May 2008
Posts: 5,497
Blog Entries: 14

Rep: Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328
Yeah, sorry for not getting back to you till now, but Slackware just added PAM support to its development snapshot (which I'm foolishly using as a daily drive ) and has put the cat amongst the pigeons here.

What I was suggesting was just something like this:

globals.h
Code:
#ifndef GLOBALS_H
#define GLOBALS_H

extern int global_my_int;
extern int global_another_int;

#endif
globals.c
Code:
int global_my_int;
int global_another_int;
Then you just #include "globals.h" wherever you might need to use them (and link globals.c/o of course). But I suspect you've figured this out by now, or come to your own (possibly better) solution.

Last edited by GazL; 05-24-2020 at 05:47 AM.
 
Old 05-24-2020, 11:27 PM   #8
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Debian64 stable, LFS 7.1
Posts: 497

Original Poster
Rep: Reputation: 163Reputation: 163
Quote:
Originally Posted by GazL View Post
Then you just #include "globals.h" wherever you might need to use them (and link globals.c/o of course). But I suspect you've figured this out by now, or come to your own (possibly better) solution.
No apologies necessary for the delay.

Your solution is a little more efficient, as far as I can tell. I put the 2 vars (verbose and HOMEDIR) at the end of the existing rmw.h and and then created a corresponding rmw.c file.

When I go back to working on rmw regularly, I'll separate them into a globals file like you suggested.

Though it all works on my system (Debian 10) when I use -fno-common, `make check` is failing on the Travis OSX build.

Quote:
/Applications/Xcode-11.2.1.app/Contents/Developer/usr/bin/make strings config_test multi_strlen buffer_overrun url_encoding

CC strings.o

CCLD strings

Undefined symbols for architecture x86_64:

"_verbose", referenced from:

_msg_return_code in librmw_test.a(librmw_test_a-messages_rmw.o)

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)
I haven't been able to figure out why yet, but any unsolicited advice is appreciated
 
Old 05-25-2020, 02:06 AM   #9
GazL
LQ Guru
 
Registered: May 2008
Posts: 5,497
Blog Entries: 14

Rep: Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328
I'm a "less is more" kind of guy, as soon as you start involving things like automake and CI build environments I'm not the person to ask. Especially when using them with IDE's on OSX.

Last edited by GazL; 05-25-2020 at 02:13 AM.
 
1 members found this post helpful.
Old 05-25-2020, 05:55 PM   #10
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,572

Rep: Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874
Quote:
Originally Posted by Andy Alt View Post

Code:
Undefined symbols for architecture x86_64:

"_verbose", referenced from:

_msg_return_code in librmw_test.a(librmw_test_a-messages_rmw.o)
Looks like you forgot to #include rmw.h (where verbose is declared) in messages_rmw.c (I would expect you should get at least a compile warning about that though).
 
Old 05-26-2020, 10:05 AM   #11
GazL
LQ Guru
 
Registered: May 2008
Posts: 5,497
Blog Entries: 14

Rep: Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328
I don't think that's it. From the quick look I took, Andy includes rmw.h indirectly via messages_rmw.h. I don't care for that style of nested include, but it should work. And, as you rightly said, the compiler should have complained about "undeclared first use" or some such if it were a header problem.

Also, as Andy said, it's working on linux, which is what makes me think it's more to do with the tools/environment its being built on.
 
Old 05-28-2020, 05:11 PM   #12
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Debian64 stable, LFS 7.1
Posts: 497

Original Poster
Rep: Reputation: 163Reputation: 163
And even on OSX it compiles both the program and the test library. the problem happens when the first test, strings, tries to link against the library. Maybe some flag is needed when building the test library to work around the problem, or when trying to link the tests against the libary.
 
Old 06-03-2020, 10:42 PM   #13
Andy Alt
Member
 
Registered: Jun 2004
Location: Minnesota, USA
Distribution: Slackware64-stable, Debian64 stable, LFS 7.1
Posts: 497

Original Poster
Rep: Reputation: 163Reputation: 163
I actually can't think of a good reason to include the -fno-common build flag for the tests. I think it should be enough that it's on the main build.

Quote:
Originally Posted by GazL View Post
Andy includes rmw.h indirectly via messages_rmw.h. I don't care for that style of nested include,
I'm open to suggestions... I'm not too married to any style yet.
 
Old 06-04-2020, 04:51 PM   #14
GazL
LQ Guru
 
Registered: May 2008
Posts: 5,497
Blog Entries: 14

Rep: Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328Reputation: 3328
Your rmw.h file is a good example of where my approach would differ to yours.

Firstly, whenever I use a .h file with the same basename as a .c file it will contain only the public interface (function prototypes, typedefs, macros, etc. ) needed to make use of the contents of that .c file elsewhere in the code-base. In contrast, your rmw.h doesn't seem to have much to do with the contents of your rmw.c.

If I'm using a header for something other than the public interface of a .c module, for example because I want to keep some related declarations/definitions together in one place and separate from the .c file, then I'll give it a meaningful name that isn't the basename of an existing .c module: in order to differentiate it.


Secondly, I prefer not to nest #include <...> within my own .h files in the way you have with rmw.h. I prefer to put them directly into the .c files.

If I were to decide that it made sense for the project to use some sort of a common-headers.h that included a lot of other #includes for convenience sake, then I wouldn't put any other declarations/definitions inside it. I'd keep it exclusively for the purpose of including a bunch of other headers, though as I said above, this is not my typical approach as I prefer to put includes directly into the .c file rather than indirectly through other headers.

I find this approach helps me avoid header spaghetti, but I'm not going to claim it's better than anyone else's approach. It's just what works for me. YMMV.
 
1 members found this post helpful.
  


Reply

Tags
arch linux, gcc


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
PHP extension and multiple source files results in multiple definition of `XXX' error atelszewski.versades Programming 1 02-16-2016 08:54 AM
linking problem: "multiple definition of .." qanopus Programming 11 05-03-2012 03:04 AM
compiling and linking multiple files using gcc mas123 Programming 6 03-13-2011 12:10 PM
Using makefile - 'Multiple Definition' compile errors OnlySolitaire Linux - Newbie 2 03-02-2011 12:33 AM
c++: gcc barfs with "Multiple definition of ...". What am I doing wrong? map250r Programming 2 02-23-2009 12:59 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:08 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration