Oddities building libraries with Eclipse

Hi everybody,

I'm relatively new to the more advanced Arduino world - but I'm a quite experienced programmer in other respects. As I plan to develop quite a few Arduino libraries in the near future, I decided to setup Eclipse for the purpose. It wasn't easy, but I managed to make it work: I can build and upload the demo project found on Github.

I have a lot of different Arduinos, but for testing Eclipse I stick to an Uno to make things a little easier.

I tried creating a template library and after a little struggle I managed to make it work. So far, so good: Like most programmers the code for now is primarily cut-n-paste, so I'm sure it'll look familiar and pretty simple.

The executable has a simple main.ccp like this:

#include <Arduino.h>
#include <rrTest.h>

int main(void) {
	init();

	setup();

	for (;;)
		loop();

	return 0;
}

rrTest Lcd;

void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
	Lcd.blink(500);
}

Next I have an rrTest.h:

#ifndef RRTEST_H
#define RRTEST_H

#include <Arduino.h>

class rrTest {
public:
	rrTest();
	~rrTest();
	void on();
	void off();
	void blink(int time);
};

#endif /* RRTEST_H */

And finally rrTest.cpp:

#include "rrTest.h" //include the declaration for this class
#include <Arduino.h>

const byte LED_PIN = 13; //use the LED @ Arduino pin 13, this should not change so make it const (constant)

//<<constructor>> setup the LED, make pin 13 an OUTPUT
rrTest::rrTest(){
    pinMode(LED_PIN, OUTPUT); //make that pin an OUTPUT
}

//<<destructor>>
rrTest::~rrTest(){/*nothing to destruct*/}

//turn the LED on
void rrTest::on(){
	digitalWrite(LED_PIN,HIGH); //set the pin HIGH and thus turn LED on
}

//turn the LED off
void rrTest::off(){
	digitalWrite(LED_PIN,LOW); //set the pin LOW and thus turn LED off
}

//blink the LED in a period equal to paramterer -time.
void rrTest::blink(int time){
	on(); 			//turn LED on
	delay(time/2);  //wait half of the wanted period
	off();			//turn LED off
	delay(time/2);  //wait the last half of the wanted period
}

Surprisingly, this works. XD

Then I started cleaning up my cut-n-paste: A lot has been cleaned up already, but a single issue remains: The observant reader might have noticed the call to pinMode() in the setup() routine in main.cpp: This initialization is unwanted - so I tried to remove it.

But if I do, I cannot compile the executable any more. Actually, it fails whilst trying to link the rrTest module:

Building target: ttRemote.elf
Invoking: AVR C++ Linker
avr-g++ -Wl,-Map,ttRemote.map,--cref -L"C:\Users\lars\Dropbox\Eclipse\Arduino\rrTest\Debug" -L"C:\Users\lars\Dropbox\Eclipse\Arduino\Arduino-Blink-Eclipse-Project\ArduinoCore\328P_16MHz" -mmcu=atmega328p -o "ttRemote.elf"  ./main.o   -lArduinoCore -lrrTest
C:\Users\lars\Dropbox\Eclipse\Arduino\rrTest\Debug\librrTest.a(rrTest.o): In function `rrTest::~rrTest()':
C:\Users\lars\Dropbox\Eclipse\Arduino\rrTest\Debug/../rrTest.cpp:19: undefined reference to `digitalWrite'
C:\Users\lars\Dropbox\Eclipse\Arduino\rrTest\Debug/../rrTest.cpp:19: undefined reference to `digitalWrite'
C:\Users\lars\Dropbox\Eclipse\Arduino\rrTest\Debug/../rrTest.cpp:19: undefined reference to `pinMode'
C:\Users\lars\Dropbox\Eclipse\Arduino\rrTest\Debug/../rrTest.cpp:19: undefined reference to `pinMode'
make: *** [ttRemote.elf] Error 1

If I reinsert the call to pinMode() in setup() of main.cpp, the code compiles just fine again.

Can anyone explain what goes on here?

Hi, I'm not anywhere near this advanced, but trying to learn.

Maybe related question: I need to call regular Arduino libraries INSIDE my library, specifically Servo. What's the Right Way to do this??

Sorry for the hijack; leave this question until later...

I'm not sure, but it looks to me as if your library rrTest.o has been built with code that calls 'digitalWrite' and 'pinMode' but for some reason the linker is not including those functions in the output file unless you also call them from the main.cpp file. That suggests something wrong with the way rrTest.o was linked, I don't know what but I wonder whether the archive is up to date and how it was built. Maybe if you dumped the symbol table for rrTest.o, that would give you a clue. Alternatively, rebuild everything from scratch in a clean environment just in case objects and libraries have got out of sync with each other.

Hi Peter,

PeterH:
I'm not sure, but it looks to me as if your library rrTest.o has been built with code that calls 'digitalWrite' and 'pinMode' but for some reason the linker is not including those functions in the output file unless you also call them from the main.cpp file.

Just to clarify: My projects look like this -

  • as you can see, the project rrTest has failed. I can right-click the project and clean it - the red marker then disappears, and I can rebuild the project without problems to get a librrTest.a file.

The ttRemote project is using the rrTest library using the main.cpp shown above: If - after a successful build of rrTest - I rebuild ttRemote, I get the above error from the linker if I don't call pinMode() from the setup() routine.

I've cleaned the projects over and over again, I've tried creating a new library from scratch - the problem persists.

That suggests something wrong with the way rrTest.o was linked, I don't know what but I wonder whether the archive is up to date and how it was built. Maybe if you dumped the symbol table for rrTest.o, that would give you a clue. Alternatively, rebuild everything from scratch in a clean environment just in case objects and libraries have got out of sync with each other.

I need a bit of help as to how to dump the symbol table - I haven't tried that from this environment before.