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.
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.
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.
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 ?
Are these explicitly defined as inline ? Can you show some actual code, and the lines the errors refer to ?
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/ba r.h:45: first defined here
Thanks
// This is defined at line 45
__inline__ uint8_T func1( volatile uint8_T * arg )
{
}
And the corresponding error is
./objs/AtSource_Grounds.o:
$PATH/bar.h:45: multiple definition of `func1'
./objs/STARE018.o:$PATH/ba
Thanks
What's __inline__ supposed to mean ?
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 ?
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 ?
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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?
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 ... ;)
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'
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'
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.
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
http://www.greenend.org.uk/rjk/2003/03/inline.html
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