Ok - thats clearer. Long explanation coz its a C thing rather than a WebbotLib thing. Here is what is happening....
In C you should only declare the body of a function, or create a variable, with the same name ONCE. The best practice is that you do this inside a C file and then you create a H file to expose the functions/variables to the outside world (ie other code) via a .H file.
EXAMPLE OF BAD STUFF
---- test.h ----
int foo=1; // Declare a variable
void bar(int p){ // Declare a function
-- do something --
}
--- test1.c ----
#include "test.h"
void something1(void){
bar(foo);
}
--- test2.c ----
#include "test.h"
void something2(void){
bar(foo);
}
This will compile the individual C files into O files without errors. Effectively:-
- test1.o will contain the code to define the foo variable and the bar function and the something1 function. The something1 function accesses both foo and bar.
- test2.o will contain the code to define the foo variable and the bar function and the something2 function. The something2 function accesses both foo and bar.
But when the linker tries to amalgamate test1.o and test2.o to produce the whole program it gives you a multi-defined error nas you now have 2 things called 'foo' and two things called 'bar'. Since these are both accessed by the 2 C files then it has no idea which one the C files is trying to use.
Wrapping stuff with #ifdef pre-processor commands ain't gonna help since each C file is compiled as a standalone thing. ie when compiling test2.c the compiler has no idea that test.h was used by test1.c
SO HOW DO YOU FIX IT
foo and bar are accessed by various C files so they should be placed into a new C file - lets call it test.c
---- test.c ----
int foo=1; // Declare a variable
void bar(int p){ // Declare a function
-- do something --
}
Then change the H file to let all other C files know that these variable exist somewhere....
---- test.h ----
extern int foo; // Let the compiler know that there is an int variable called foo that has been declared externally (ie somewhere else)
// Also let it know that there is a function called 'bar' that is defined somewhere else.
// Note that the keyword 'extern' is optional for a function.
// So long as you dont supply the body of the function (ie you just have a ;) then it knows that its defined somewhere else.
extern void bar(int p);
This will compile the individual C files into O files without errors. Effectively:-
- test.o will contain the code to define the foo variable and the bar function.
- test1.o will contain the code for the something1 function. It uses foo and bar but knows they exist elsewhere.
- test2.o will contain the code for the something2 function. It uses foo and bar but knows they exist elsewhere.
The linker will now stitch the 3 .o files together quite happily as everything has only been defined once.
WHAT ABOUT 'static' AND '__inline__' (Advanced Topic!!)
The __inline__ keyword is often used at the start of a function declaration in H files (look at the WebbotLib files). It gives a hint to the compiler that this function is a candidate to be used inline. Which basically means 'dont generate the code as a standard function but rather, every time it is called, then cut and paste the code from the function to the place that is calling it'. Why would you do this? Well one benefit is that if the code is never called then no code ever gets generated so your program is smaller. Also: it can never be multi-defined since the function doesn't exist as a stand alone thing.But you need to be careful: if the body of the function is quite large and is used quite often then its like cut'n'pasting the code all over the place - so your program gets very large. Thats why I called it a 'hint' since depending on various factors: including the optimise for speed vs optimise for size settings the compiler may choose to ignore your hint all together and still create it as a standalone function. In which case: and you've called it from lots of C files, then each C file now has a function with that name so its back to the linker bombing out with a multi-defined error. The cure is to use 'static' ....
The static keyword in front of a function declaration or variable declaration means that this function/variable is only visible within the current C file and its name is hidden from the linker. So if you declare something in an H file as static and include the H file from, say, 3 C files then the code for the function, or variable, will exist 3 times. You won't get a multi-defined error as each one is hidden from the other in the linker. But this makes it impossible for test1.c to read/write/call the variable/function with the same name in any other C file. This is a good thing! It means that if you have a C file to do a specific job and you have a variable called 'myVar' which is only ever used by the code in that file, and you dont want to have other C files accidentally stuffing its value, then you can declare it as static. But also beware: this only applies to variables defined outside of functions - declaring a variable as static inside a function has a whole different meaning....
WEBBOTLIB
Looking at your error log then some of the stuff looks like your code and its hard to tell but some of the stuff may be things you declared in Project Designer but I'm not sure.
If you are using WebbotLib V1 then make sure you only ever include 'hardware.h' from your main C file so that your devices are only defined once. All other C files should include 'xhardware.h'. This version of the file declares all the devices as being 'extern' to stop them being multi defined. Version 2 doesn't need you to do this.
KISS
This added complexity, bought about by the C language, has resulted in the general KISS principal of having one C file and having everything else in H files. That way nothing can EVER be multi-defined as everything is effectively just one file that is cut'n'past together. Follow the above steps and you can split stuff out. WebbotLib has no problem with it - the only observation is to make sure, in Version 1, that you only include hardware.h once (from your main C file) and use xhardware.h in other C files.