The Scons arduino tool arduino.py
is loosely based upon the earlier
work of github user tomjnixon and his arduino-scons-alt repository. In
August 2015, I found his work which hadn't been updated since 2013 and which
(1) only ever worked for AVRs, (2) had never been updated to Arduino app
versions later than 1.0, and (3) didn't prevent scons from leaving object
files in the Arduino application directory tree.
arduino.py
has been tested with Arduino 1.5 and 1.6 for both AVR and SAM/ARM
architectures. To prevent object files from being left in the Arduino
application's directory tree, a sleazy symlink trick is used owing to
the restrictive behavior of scons' Repository()
facility.
-
VariantDir()
requires that the source files live in or below the main source tree. So, to use justVariantDir()
the Arduino library sources need to be copied into the source tree so as to provide visibility to a scons build. -
Repository()
makes sources outside the source tree visible for building without leaving object files in that outside source tree. But, when combined withVariantDir()
requires identical directory naming between the "mounted" repository and theVariantDir()
directory. Consider, for example,source directory = src/ build variant directory = BUILD/UNO/ Arduino source directory = /usr/local/arduino/hardware/arduino/avr/
With the commands
VariantDir('BUILD/UNO', 'src') Repository('/usr/local/arduino/hardware/arduino/avr')
there is now a problem. When scons looks for Arduino library sources to build, it will require them to be under
/usr/local/arduino/hardware/arduino/avr/BUILD/UNO/
This can be dealt with by making a symbolic link loop from
UNO/
toavr/
but that may cause problems with unsuspecting programs. Alternatively, we canln -s /usr/local/arduino/hardware/arduino \ /usr/local/arduino/hardware/BUILD \ ln -s /usr/local/arduino/hardware/arduino/avr \ /usr/local/arduino/hardware/arduino/UNO \
Thus, when told to build
cores/arduino/*.cpp
(core library) orlibraries/SPI/*.cpp
(SPI library), scons will find them underBUILD/UNO/cores/arduino
andBUILD/UNO/libraries/SPI
.This tool uses this latter symbolic link approach. It's admittedly sleazy -- it puts sym links into the Arduino tree -- but there's presently no better alternatives. The links are automatically established; you do not need to manually create them. This method can be used with
- No
VariantDir()
, VariantDir('a', )
, andVariantDir('a/b', )
That is, this code works with no variant directory, a single-directory level variant directory, and a two-directory level variant directory.
- No
Copy the arduino.py
file to your project. It can be kept tucked
away in a subdirectory. Scons also has methods for installing it in
site-wide or per-user scons "tool" directories. The examples
provided here keep it in a subdirectory named scons_tools
and
provide that directory's name and location with the Environment()
call.
In you SConstruct file, set into os.environment()
-
The Arduino application version as an single integer (e.g., for 1.5.8beta, use "158"; for 1.6.5, use "165").
os.environ['ARDUINO_VERSION'] = '158'
-
The path to the directory containing the Arduino application's
hardware
folder,os.environ['ARDUINO_HOME'] = '/usr/local/arduino'
Note this is not the path for the
hardware
folder itself: it is the path to the folder containing thehardware
folder. -
For ARM/SAM architectures and Ardiuno 1.6 or later, the path to the directory tree in which the separately installed gcc toolchain is located. E.g.,
os.environ['ARDUINO_TOOLS'] = '/Users/dnewman/Library/Arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1'
See the example SConstruct
files for working examples of effecting
the above three settings.
When creating the scons environment, declare usage of the tool arduino
and the location of the directory containing arduino.py
. For example,
env = Environment(tools = ['default', 'arduino'],
toolpath = ['scons_tools'] )
To then load information about the target Arduino board, issue the command
env.ConfigureBoard(arduino_version, arduino_arch, board, options)
where
-
arduino_version
is an actual integer (not a string) representing the Arduino version number (e.g., 158, 165, etc.). -
arduino_arch
is the string'avr'
or'sam'
and represents the target architecture. Yes, this could be derived fromboard
but that would require either maintaining a table or making guesses in order to find the correctboards.txt
file. (The location ofboards.txt
is dependent on both the target architecture and the version of the Arduino application.) -
board
is the Arduino board name as it appears in the architecture'sboards.txt
(e.g., "uno", "arduino_due_x"). -
options
is used to control how the Arduinoplatform.txt
compile recipes are transformed into CC and C++ commands for use with scons. The Arduino recipes have undesirable (dubious) settings such as-w
which disables all compiler warnings. These options may be used to drop (strip) or replace portions of the recipesoptions
is a dictionary containing any or all of the following keyscc_flags_drop_list
-- strings to drop from CC commandscc_flags_replace_list
-- strings to replace in CC commandscxx_flags_drop_list
-- strings to drop from C++ (CXX) commandscxx_flags_replace_list
-- strings to replace in C++ (CXX) commands
A replace list is a list of 2-tuples, each 2-tuple containing two strings: a substring to look for and a substring to replace it with. E.g., to replace
-w
with-Wall
and-Os
with-O2
, use[ ('-w', '-Wall'), ('-Os', '-O2') ]
Note that depending upon a replace list may cause problems after upgrading the Arduino application: a new Arduino
platform.txt
file may no longer specify a given switch. With the above example, if you need-O2
specified but-Os
is no longer used in the newplatform.txt
, then the replacement will not occur and thus-O2
will not be asserted. It is safer to strip unwanted flags/switches with a drop list and useenv.Append()
to add assert necessary flags or switches forCCFLAGS
orCXXFLAGS
.A drop list is a list of 2-tuples, each 2-tuple containing a string to drop and a count of the subsequent number of tokens following the string to also drop. E.g., the drop list
[ ('-o', 1) ]
drops the
-o
switch and the single argument immediately following it. The following drops both-o
and-w
,[ ('-o', 1), ('-w', 0) ]
Two complete examples are provided. After editing their SConstruct
files to have Arduino version and path information specific to your
computer, they should build with a simple scons command.
-
example_simple/
is a simple Arduino program which requires the Arduino core and SoftwareSerial libraries. It builds in situ rather than to a variant directory. -
example_variant/
builds to a variant directory,build/<board-name>/
. In addition to using Arduino libraries, it also provides a library of its own insrc/libraries/
. Note that library sources do not need to be in a subdirectory. And if placed in a subdirectory, then the name is arbitrary. Libraries do not need to be in a subdirectory namedlibraries
.