The compile error is in Print.cpp, for this function:
/* default implementation: may be overridden */
void Print::write(const char *str)
{
while (*str)
write(*str++);
}
I found a few threads that suggest declaring&defining __cxa_pure_virtual() for pure virtuals to work. The big question for me now is why does the arduino library compile with the Arduino IDE, but not with the Eclipse build?
in any .cpp file. Without it, it always complains with
./arduino/Print.o: In function `Print::write(char const*)':
../arduino/Print.cpp:32: undefined reference to `__cxa_pure_virtual'
Can you guys download the code and try running the build?
Also, does anyone know where to get a full list of avr-gcc options and their meanings? I can't find a man page, avr-gcc -v --help doesn't seem to list everything ...
Indeed. However, it seems to me the problem is with the Arduino library, and the question is why does your build work.
Someone at AVRFreaks has written a tutorial on coding C++ for the AVR. Part of what needs to be done is definition and implementation of a void __cxa_pure_virtual(void) function. There is no such function in the Arduino library, hence the build error.
However, when building the project with an object archive (not sure about the terminology here), it magically works! The Arduino IDE copies all C and C++ compiled object files into core.a, and then links the main object file against it (and any other libraries outside the core). This I cannot explain.
I went on playing with this, and found even more curious things. For instance, Eclipse's binaries are much larger than the one generated by the IDE, sometimes by a 3-fold. However, the .o files by the IDE are (on average) 5% larger than those of Eclipse ... I wish I had studied compiler design and theory back in the university ...
Eclipse's binaries are much larger than the one generated by the IDE
That could be the results of...
The various build switches. Often there are "optimize for size" and "optimize for speed" options.
Building with debug versions of the CRT files. C(++) compilers generally include "release" and "debug" versions of libraries. Usually debug versions are considerably larger.
Including the wrong CRT files.
Bug(s) in the development tools.
the .o files by the IDE are (on average) 5% larger than those of Eclipse
That only indicates they were built differently. The size of the .o files isn't necessarily going to be related to the size of the final product.
Well, the differences between the Makefile in hardware/cores/arduino and the build process done by the IDE was not my problem, but I'm glad people have noticed. Hopefully it'll be fixed soon.
Anyway, I finally know what is going on here! Thanks westfw for the hint! Probably most of you already knew all about it, but still, here it comes ...
The difference in binary size, as well as the original problem that prevented me from compiling code (see first post) are related to the same thing -- the -ffunction-sections -fdata-sections options passed to the compiler and the -Wl,-gc-sections option passed to the linker. This post has it all. Having unused code stripped out of the final binary makes it way smaller. It also eliminates the need for void __cxa_pure_virtual(void), since it's not called anywhere. Applying some of the other options/tips there, I managed to get a build by Eclipse even smaller than the one build with the Arduino IDE.
The additional step of combining libraries into core.a and then linking against it is just a hack that allows the linker to garbage-collect even more unneeded code, especially in .data
I'll try to come up with an updated Arduino+Eclipse guide.
I don't know if anyone is interested at all -- it seems not too many people use Eclipse to write for Arduino. Nevertheless, I managed to write a Makefile (oh, the pain!) that replicates the build process of the official ide and even adds some additional improvements.
The advantages of my setup (vs. the one described in the Playground) are that you can modify core libraries and have them automatically recompiled with the next build. It also adds all .o files to the object archive, allowing the linker to do it's magical garbage collecting everywhere. I am getting even smaller builds with this than with the official IDE!
LMK if you find it useful or need more details on how it works.
Kiril: it looks like you changed quite a lot. Is it possible to fold your improvements into the existing Makefile? For example, I'd like to keep the automatic generation of the #include "WProgram.h" and the main() function by the Makefile. If you can send a patch to the developers mailing list, I'll try to integrate it.
Yes, I used the Makefile from the distribution as a reference (and quite a few others, for that matter) but wrote mine from scratch. (Just as with HardwareSerial, I feel I get a much deeper grasp of the subject when I do it that way.) Makefiles are a punishment! but I'll take a deeper look and see if I can adapt it to integrate my changes.