Hi folks,
today I found out that Arduino supports some commandline options to do
compiling and uploading. I decided to explore this further, since the
Arduino-Makefile doesn't properly support 1.5 yet, and because it seems
that the amount of things to configure might be getting too big for
properly supporting from a Makefile without duplicating a lot of code
(e.g., platform.txt options).
In any case, due to some badly-named sketches (that worked fine with
Arduino-Makefile, but not with the IDE) and poor documentation reading,
I quickly ran into null pointer and index out of range exceptions.
Before fixing my code and commandline options, I decided to improve the
error handling instead.
Most of these commits should be fairly straightforward and non-invasive,
but this was my first time around the Arduino java sources, so I might
have missed some conventions or made wrong assumptions...
https://github.com/arduino/Arduino/pull/1639
Okay, regarding the commandline. Here's some more thoughts.
Right now, the GUI opens during compilation / upload, which isn't really
useful when trying to automate things. I could imagine a --no-gui
option, but it might be even more useful to just make the the default
(and only) option with --verify or --upload. Showing a GUI during the
compilation doesn't really seem useful and is potentially confusing
(you can for example open the preferences dialog, which is then forcibly
shut down after compilation is complete). I can see a few options:
1. Never show a GUI with --verify or --upload. Just do what is asked,
and report all output on stdout / stderr.
2. Show a minimal GUI with --verify or --upload, that shows the status
and/or output, but does not allow any other interaction (perhaps not
even shows the code).
3. Add a --no-gui (or --batch) option. If this option is passed, behave
like 1. If this option is no passed, show the GUI as normal and
start verification or upload. After this is complete, don't quit but
just keep the GUI open. This effectively means --verify just means
"pretend the verify button is clicked after startup".
Option 1 or possibly 3 seem sane to me, option 2 seems nice but is
probably too much work for little gain.
When running --verify or --upload, some preferences are changed. At
least the verbose preferences are always changed, the board name and
serial port only when the --board or --port options are passed. However,
it seems that normally, these options are only changed temporarily and
not save to preferences.txt. I suspect this is because with --verify and
--upload, a hard System.exit(0) is done, skipping all regular quit
handlers that call Preferences.save(). However, it seems there is a
corner case: if the user quits the GUI halfway through the compile, the
preferences _are_ saved.
This would automatically be solved if we go for option 1 above. For
option 3, the semantics would change to "Preferences are saved if and
only if --no-gui is not passed", which also seems fine to me.
Furthermore, passing --board, --port and --serial only actually does
something when --verify or --upload is actually passed (options are
silently ignored otherwise). I'd say it would make sense to always
process these options, so you can also create shortcuts to start the gui
for a specific board. Perhaps even a generic --set-preference would make
sense?
Error message handling should also be slightly adapted. My patches
already use showError wherever possible, which should be adapted to
print to stdout/stderr when no gui is shown (there is already some code
for this, but it seems unused now). It might even be useful to do this
even when there _is_ a GUI.
Additionally, it might be useful to write warnings, error messages and
stack traces to stderr instead of stdout (I think I noticed stacktraces
going to stdout. Since Throwable::printStacktrace should AFAIK print to
stderr, I suspect there is some redirection in place to print both
stderr and stdout into the GUI, which also squats everything together in
the real stdout? Not 100% sure, though). In general, getting logging a
bit more cleaned up might be useful, since there is now
Base::showMessage/Warning/Error, System.out/err.print, and
EditorConsole::message, all of which potentially end up in the same
places...
Gr.
Matthijs