Link to home
Start Free TrialLog in
Avatar of goloap
goloap

asked on

Multiple Definition in build process

Hi,

I'm having a strange problem with a makefile. I have multiple files that include a .h file which includes another .h file. During compilation, each c file is compiled separately using the "-c" flag. Even so, i get a multiple definition of all the function defined in the second .h file during linking. This is the structure of the program:

foo.h
#ifndef _foo_
#define _foo_

<some variable declaration>
#include "bar.h"

#endif

bar.h
#ifndef _bar_
#define _bar_

<some definition of inline functions>
#endif

c1.c
#include foo.h
<stuff>

c2.c
#include foo.h
<stuff>

I don't get why it shouldn't work since it works fine when compiling with Visual C 8, but I want to use GCC to compile it now and it won't work.

Any help would be appreciated.
Avatar of Infinity08
Infinity08
Flag of Belgium image

>> <some variable declaration>

You shouldn't put variable declarations in header files. Instead put it in the corresponding .c file, and use extern to reference it :

---- foo.h ----

#ifndef FOO_H
#define FOO_H

extern int value;

#endif /* FOO_H */

---- ----

---- foo.c ----

#influde "foo.h"

int value = 5;

---- ----

That way, the int value is accessible everywhere (as long as you include foo.h), but it's still only defined once, namely in foo.c
Avatar of goloap
goloap

ASKER

Sorry my bad. I meant structure declaration

So the foo.h file only has a bunch of typedef and #defines

No actual variable declaration

My mistake.
>> <some definition of inline functions>

Are these explicitly defined as inline ? Can you show some actual code, and the lines the errors refer to ?
Avatar of goloap

ASKER

The functions are explicitely defined as inline as follows

// This is defined at line 45
__inline__ uint8_T func1( volatile uint8_T * arg )
{

}

And the corresponding error is

./objs/AtSource_Grounds.o: In function `func1':
$PATH/bar.h:45: multiple definition of `func1'
./objs/STARE018.o:$PATH/bar.h:45: first defined here

Thanks
What's __inline__ supposed to mean ?
Avatar of goloap

ASKER

it's the same as "inline" from what i've read (i didn't write the code)
>> it's the same as "inline" from what i've read (i didn't write the code)

Well, it's not part of standard C++ ... Is there a define or something that translates __inline__ to inline ?


Can you just try it with inline instead ?
Avatar of goloap

ASKER

Tried with simply inline and same problem. This is annoying, why would it compile perfectly fine with Visual Studio and not gcc.
Can you post a bit more code ? Or even better, create a minimal example that illustrates the problem ?
ASKER CERTIFIED SOLUTION
Avatar of fli1103
fli1103

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of goloap

ASKER

Thanks,

the introduction of static solved the problem. But can you explain what difference it makes and why it would work with Visual Studio and not gcc?

Also there is another strange point. If I compile with visual Studio and then look for the symbol func1 in the object file created (using grep) no occurence are found. However, with gcc the symbol func1 appears in all the object files.

Any idea?
A minimal example that illustrates the problem would still be handy ... ;)
Avatar of goloap

ASKER

Ok, here is an example of my problem

FOO.H
#ifndef FOO_H_
#define FOO_H_

#include "bar.h"

#endif /*FOO_H_*/

BAR.H
#ifndef BAR_H_
#define BAR_H_

inline int func1(int a, int b)
{
      return a+b;
}
#endif /*BAR_H_*/

FOO.C
#include <stdlib.h>
#include <stdio.h>

#include "foo.h"

int main(int argc, char *argv[]) {
      printf("test program");
      return EXIT_SUCCESS;
}

FOO2.C
#include "foo.h"

int useless()
{
      int tmp;
      
      tmp = fun1(2,3);
      
      return tmp;
}


When i compile this I get the following output


gcc -c -Wc,-Wall -Wc,-Wno-parentheses -g   -DVARIANT_g  ../foo.c
gcc -c -Wc,-Wall -Wc,-Wno-parentheses -g   -DVARIANT_g  ../foo2.c
gcc -o../foo_g    foo.o    foo2.o -g    
foo2.o: In function `func1':
../foo2.c:5: multiple definition of `func1'
foo.o:../foo.c:5: first defined here
cc: ld caught signal 1
make[2]: *** [../foo_g] Error 1
make[2]: Target `all' not remade because of errors.
make[1]: [all] Error 2 (ignored)
make[1]: Leaving directory `../x86'
Avatar of goloap

ASKER

Ok

After some more research, I figured out that it has to do with how VS and GCC handle the inline call. From this web site (http://msdn2.microsoft.com/en-us/library/feffc7b5(vs.80).aspx) I understood that VS always expands the inline function at each call, so the function effectively disapears (which would explain why the symbol is not present anymore in the object file).

While GCC (refer to http://gcc.gnu.org/onlinedocs/gcc/Inline.html) only expands the function when there is optimization (which I'm not using at the moment) and as such would require the static keyword.

Also, the __inline__ reserved word is prefered to be more compatible since "inline" is not available for programs compile with the -ansi or -std flags set.
Ah, I seem to have misunderstood your question ... That would indeed be fixed with the static keyword (credit goea to fli1103). More info here :

        http://www.greenend.org.uk/rjk/2003/03/inline.html