Under the hood in the Arduino GUI

October 2, 2012

For curiousity sake, I decided to dig a bit into how the Arduino GUI is engineered. When I install it on my Fedora 17 system via "yum install arduino", I get the following set of packages.

Oct 02 11:42:13 Installed: avr-libc-1.7.1-3.fc17.noarch
Oct 02 11:42:14 Installed: 1:avr-binutils-2.20-3.fc17.x86_64
Oct 02 11:42:18 Installed: avr-gcc-4.6.3-1.fc17.x86_64
Oct 02 11:42:19 Installed: avr-gcc-c++-4.6.3-1.fc17.x86_64
Oct 02 11:42:20 Installed: rxtx-2.2-0.6.20100211.fc17.1.x86_64
Oct 02 11:42:20 Installed: ttmkfdir-3.0.9-35.fc17.x86_64
Oct 02 11:42:22 Installed: xorg-x11-fonts-Type1-7.5-5.fc17.noarch
Oct 02 11:42:23 Installed: libftdi-0.19-3.fc17.x86_64
Oct 02 11:42:24 Installed: avrdude-5.11.1-1.fc17.x86_64
Oct 02 11:42:26 Installed: 1:arduino-core-1.0.1-1.fc17.noarch
Oct 02 11:42:26 Installed: 1:arduino-doc-1.0.1-1.fc17.noarch
Oct 02 11:42:27 Installed: 1:arduino-1.0.1-1.fc17.noarch
For good measure, I also install the "uisp" package, which gives me:
Oct 02 11:42:49 Installed: uisp-20050207-9.fc17.x86_64

Looking at the java source

The arduino gui is written in Java. When you type "arduino" on the command line, you run the shell script /bin/arduino, which does the following to start the GUI:
. /usr/share/java-utils/java-functions

MAIN_CLASS=processing.app.Base

set_classpath ecj jna RXTXcomm
for lib in /usr/share/arduino/*.jar; do
    CLASSPATH="$CLASSPATH:$lib"
done

set_flags -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel

cd /usr/share/arduino
run "$@"
To look at the source, I get the source rpm and unpack it. Fedora 17 initially shipped the arduino-1.0 package, but later released 1.0.1 as an update, so I do this:
rpm -i arduino-1.0.1-1.fc17.src.rpm
This one source RPM builds to 3 target binary packages (arduino, arduino-core, and arduino-doc).

For some reason, the arduino folks use the offbeat "xz" compression for the tarball, so to extract the files, you do:

tar -xJf arduino-1.0.1.tar.xz
This places the source files into "arduino-1.0.1" in the current directory. There are on the order of 1000 source files.
The output from the tar -tJf command is here.

The fedora build applies five patches, which are not of immediate interest here.
Here is the spec file used to build the fedora packages.
Here is the output from rpmbuild.

A key aspect of the build process involves the "ant" utility, which is a java-specific build tool (like the make utility, but driven by XML files named "build.xml" in the source directories). The build process yields a variety of .jar files, such as pde.jar, core.jar, RXTXcomm.jar, ecj.tar, jna.tar.

Where do the Arduino files get installed

The bulk of it goes to /usr/share/arduino, in fact if you look at the script above that runs the arduino gui, you will see that the gui is run from there.

Documentation goes to /usr/share/doc/arduino-1.0.1 and /usr/share/doc/arduino-core-1.0.1 In fact /usr/share/doc/arduino-1.0.1/reference is an html reference guide to the arduino API. Man pages go into /usr/share/man/man1

The directory /etc/arduino holds three files:

It appears that files by the same name in /home/user/.arduino can override these system wide settings.

A file /usr/share/applications/arduino.desktop provides a desktop entry and icon.

So, how does all this work (from sketch to download)?

For a sketch named "Yada", it all begins with the file "Yada.pde". This file is an incomplete fragment of C++ code. The arduino build system adds some boilerplate header stuff to this (including among other things the line:
#include "Arduino.h"
producing an intermediate file Yada.cpp.

This gets compiled using avr-g++ with many interesting switches, producing Yada.cpp.o

Various files in the directory /usr/share/arduino/hardware/arduino/cores/arduino get compiled with either avr-g++ or avr-gcc, then are bundled using avr-ar into a library /tmp/core.a.

The file Yada.cpp.o gets linked with the library "core.a" (which gets discarded afterwards), along with avr libraries (avr-libc), to obtain Yada.cpp.elf.

avr-objcopy is run with the elf file as input, two times. The first yields Yada.cpp.eep (content destined for eeprom). The second yields Yada.cpp.hex (executable code).

Finally avrdude is used to download the hex file into the target system. It is not yet clear (to me) what happens to the eep file.

I think you are lying, show me!

Take a look at these 3 files in the source code: If you are wondering just how the arduino GUI starts up (and you should be), here is how it goes.

The following line in the startup script:

MAIN_CLASS=processing.app.Base
Is fingering the file app/src/processing/app/Base.java, which does contain a method "main". The final line in the script:
run "$@"
is actually just the command "run". $@ would be additional arguments after the word "arduino" and there ain't none if you just type arduino as most folks do.

If you take a look at /usr/share/java-utils/java-functions, you can find the "run" function, and do as I just did and set the VERBOSE variable to obtain:

java virtual machine used: /usr/lib/jvm/java/bin/java
classpath used: /usr/share/java/ecj.jar:/usr/share/java/jna.jar:/usr/share/java/RXTXcomm.jar::/usr/share/arduino/core.jar:/usr/share/arduino/pde.jar
main class used: processing.app.Base
flags used: -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel
options used: 
arguments used: 
So, what is happening is that the run command is looking for a method called main() in the processing.app.Base class and starting things up with it.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org