Skip to content

Commit

Permalink
FW-177. Add cross-platform builds for simulation library.
Browse files Browse the repository at this point in the history
* Supports x86-linux, amd64-windows, and x86-windows target build from an
  amd64-linux host, using MinGW-w64.
* Added two SCons build variables:
  * simhost   - simulation host architecture/OS to build
  * simhostpy - location of simulation host Python headers and library
* Added Scons tool module for MinGW-w64 support, and added SCons utils
  module.
* Reformatted SCons help text and provided more informative descriptions.
  • Loading branch information
kb2ma committed Dec 26, 2013
1 parent a49b4b3 commit d3a051c
Show file tree
Hide file tree
Showing 7 changed files with 382 additions and 35 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ settings
*.so
*.a
*.pyd
*.pyc
path.txt
/build
/.sconsign.dblite
/firmware/openos/bsp/boards/python/*.def
.directory
/firmware/openos/projects/common/03oos_openwsn_prog
/firmware/openos/projects/common/03oos_openwsn/03oos_openwsn_obj.*
/firmware/openos/projects/common/oos_openwsn.*
/firmware/openos/bsp/boards/python/openwsnmodule_obj.c
/firmware/openos/bsp/boards/python/openwsnmodule_obj.os
/firmware/openos/bsp/boards/python/openwsnmodule_obj.os
50 changes: 41 additions & 9 deletions SConscript
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import os
import threading
import subprocess
import platform
import distutils.sysconfig
import sconsUtils

Import('env')

Expand Down Expand Up @@ -172,16 +174,30 @@ elif env['toolchain']=='iar-proj':
else:
if env['board'] in ['telosb','wsn430v13b','wsn430v14','gina','z1']:
raise SystemError('toolchain {0} can not be used for board {1}'.format(env['toolchain'],env['board']))

if env['fastsim']==1:
env.Append(CPPDEFINES = {'FASTSIM': None})
#env.Append(CPPDEFINES = {'TRACE_ON': None})
env.Append(CPPDEFINES = 'FASTSIM')
#env.Append(CPPDEFINES = 'TRACE_ON')

# enabling shared library to be reallocated
if os.name!='nt':
env.Append(CCFLAGS = '-fPIC')
env.Append(SHLINKFLAGS = '-Wl,-Bsymbolic-functions') # per FW-176
env.Append(SHCFLAGS = '-Wl,-Bsymbolic-functions') # per FW-176
if env['simhost'].endswith('linux'):
# enabling shared library to be reallocated
env.Append(CCFLAGS = '-fPIC')
env.Append(SHLINKFLAGS = '-Wl,-Bsymbolic-functions') # per FW-176
env.Append(SHCFLAGS = '-Wl,-Bsymbolic-functions') # per FW-176

if platform.architecture()[0]=='64bit' and env['simhost']=='x86-linux':
# Cross-compile x86 Linux target from 64-bit host. Also see
# firmware/openos/projects/python/SConscript.env.
env.Append(CCFLAGS = '-m32')
# Resolves a conflict between Python's pyconfig.h, which uses
# '200112'L, and libc's features.h, which uses '200809L'.
env.Append(CPPDEFINES = [('_POSIX_C_SOURCE','200112L')])
env.Append(SHLINKFLAGS = '-m32')

if env['simhost'] == 'amd64-windows':
# Used by Python includes
env.Append(CPPDEFINES = 'MS_WIN64')

# converts ELF to iHex
env.Append(BUILDERS = {'Elf2iHex' : dummyFunc})
Expand Down Expand Up @@ -400,10 +416,26 @@ def sconscript_scanner(localEnv):
)

# prepare environment for this build
if os.name!='nt' and localEnv['simhost'].endswith('-windows'):
# Cross-build handling -- find DLL, rather than hardcode version,
# like 'python27.dll'
pathnames = sconsUtils.findPattern('python*.dll', localEnv['simhostpy'])
if pathnames:
pathname = pathnames[0]
else:
raise SystemError("Can't find python dll in provided simhostpy")

# ':' means no prefix, like 'lib', for shared library name
pysyslib = ':{0}'.format(os.path.basename(pathname))
pylibExt = '.pyd'
else:
pysyslib = 'python' + distutils.sysconfig.get_config_var('VERSION')
pylibExt = distutils.sysconfig.get_config_var('SO')

target = targetName
source = [localEnv.ObjectifiedFilename(s) for s in sources_c]
libs = buildLibs(projectDir)
libs += [['python' + distutils.sysconfig.get_config_var('VERSION')]]
libs += [[pysyslib]]

buildIncludePath(projectDir,localEnv)

Expand All @@ -414,7 +446,7 @@ def sconscript_scanner(localEnv):
source,
LIBS = libs,
SHLIBPREFIX = '',
SHLIBSUFFIX = distutils.sysconfig.get_config_var('SO'),
SHLIBSUFFIX = pylibExt,
)

Alias(targetName, [targetAction])
Expand Down
124 changes: 108 additions & 16 deletions SConstruct
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys
import platform
import SCons

#============================ banner ==========================================
Expand All @@ -15,6 +16,68 @@ banner += [""]
banner = '\n'.join(banner)
print banner

#===== help text

Help('''
Usage:
scons [<variable>=<value> ...] <project>
scons docs
scons [help-option]
project:
A project is represented by a subdirectory of the
firmware{0}openos{0}projects directory, for a particular board. For
example, the 'oos_openwsn' project may be built for telosb. To specify a
project, exclude the leading digits in the directory name, like '03' for
oos_openwsn.
variable=value pairs
These pairs qualify how the project is built, and are organized here into
functional groups. Below each variable's description are the valid
options, with the default value listed first.
board Board to build for. 'python' is for software simulation.
telosb, wsn430v14, wsn430v13b, gina, z1, pc, python
toolchain Toolchain implementation. The 'python' board requires gcc
(MinGW on Windows build host).
mspgcc, iar, iar-proj, gcc
Connected hardware variables:
bootload Location of the board to bootload the binary on.
COMx for Windows, /dev entries for Linux
Supports parallel operation with a comma-separated list,
for example 'COM5,COM6,COM7'.
jtag Location of the board to JTAG the binary to.
COMx for Windows, /dev entry for Linux
fet_version Firmware version running on the MSP-FET430uif for jtag.
2, 3
Simulation variables:
fastsim Compiles the firmware for fast simulation.
1 (on), 0 (off)
These simulation variables are for a cross-platform build, and are valid
only from an amd64-linux build host.
simhost Host platform and OS for simulation. Default selection is
the current platform/OS, which of course is not a cross-
build. x86-windows cross-build requires MinGW-w64 toolchain.
amd64-linux, x86-linux, amd64-windows, x86-windows
simhostpy Home directory for simhost cross-build Python headers and
shared library.
Common variables:
verbose Print each complete compile/link comand.
0 (off), 1 (on)
docs:
Generate source documentation in build{0}docs{0}html directory
help-option:
--help Display help text. Also display when no parameters to the
scons scommand.
'''.format(os.sep))

#============================ options =========================================

#===== options
Expand All @@ -25,81 +88,110 @@ command_line_options = {
'fet_version': ['2','3'],
'verbose': ['0','1'],
'fastsim': ['1','0'],
'simhost': ['amd64-linux','x86-linux','amd64-windows','x86-windows'],
'simhostpy': [''] # No reasonable default
}

def validate_option(key, value, env):
if key not in command_line_options:
raise ValueError("Unknown switch {0}.".format(key))
if value not in command_line_options[key]:
raise ValueError("Unknown {0} \"{1}\". Options are {2}.\n\n".format(key,value,','.join(command_line_options[key])))


# Define default value for simhost option
if os.name=='nt':
defaultHost = 2
else:
defaultHost = 0 if platform.architecture()[0]=='64bit' else 1

command_line_vars = Variables()
command_line_vars.AddVariables(
(
'board', # key
'Board to build for.', # help
'', # help
command_line_options['board'][0], # default
validate_option, # validator
None, # converter
),
(
'toolchain', # key
'Toolchain to use.', # help
'', # help
command_line_options['toolchain'][0], # default
validate_option, # validator
None, # converter
),
(
'jtag', # key
'Location of the board to JTAG the binary to.', # help
'', # help
'', # default
None, # validator
None, # converter
),
(
'fet_version', # key
'Firmware version running on the MSP-FET430uif.', # help
'', # help
command_line_options['fet_version'][0], # default
validate_option, # validator
int, # converter
),
(
'bootload', # key
'Location of the board to bootload the binary on.',# help
'', # help
'', # default
None, # validator
None, # converter
),
(
'verbose', # key
'Print complete compile/link comand.', # help
'', # help
command_line_options['verbose'][0], # default
validate_option, # validator
int, # converter
),
(
'fastsim', # key
'Compiles the firmware for fast simulation.', # help
'', # help
command_line_options['fastsim'][0], # default
validate_option, # validator
int, # converter
),
(
'simhost', # key
'', # help
command_line_options['simhost'][defaultHost], # default
validate_option, # validator
None, # converter
),
(
'simhostpy', # key
'', # help
command_line_options['simhostpy'][0], # default
None, # validator
None, # converter
),
)

if os.name=='nt':
env = Environment(
tools = ['mingw'],
variables = command_line_vars,
variables = command_line_vars
)
else:
env = Environment(
variables = command_line_vars,
)

#===== help text
simhost = ARGUMENTS.get('simhost', 'none')
board = ARGUMENTS.get('board', 'none')
if board=='python' and simhost.endswith('-windows'):
# Cross-compile for simulation on Windows
env = Environment(
# crossMingw64 requires 'mingw_prefer_amd64' key
tools = ['crossMingw64'],
mingw_prefer_amd64 = simhost.startswith('amd64-'),
variables = command_line_vars
)
else:
env = Environment(
variables = command_line_vars
)

Help("\nUsage: scons board=<b> toolchain=<tc> project\n\nWhere:")
Help(command_line_vars.GenerateHelpText(env))
def default(env,target,source): print SCons.Script.help_text
Default(env.Command('default', None, default))

Expand Down
14 changes: 7 additions & 7 deletions firmware/openos/bsp/boards/python/openwsnmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@ static PyObject* OpenMote_getState(OpenMote* self) {
returnVal = PyDict_New();

// callbacks
uart_icb_tx = PyInt_FromLong((long)self->uart_icb.txCb);
uart_icb_tx = PyInt_FromLong((intptr_t)self->uart_icb.txCb);
PyDict_SetItemString(returnVal, "uart_icb_tx", uart_icb_tx);
uart_icb_rx = PyInt_FromLong((long)self->uart_icb.rxCb);
uart_icb_rx = PyInt_FromLong((intptr_t)self->uart_icb.rxCb);
PyDict_SetItemString(returnVal, "uart_icb_rx", uart_icb_rx);
bsp_timer_icb_cb = PyInt_FromLong((long)self->bsp_timer_icb.cb);
bsp_timer_icb_cb = PyInt_FromLong((intptr_t)self->bsp_timer_icb.cb);
PyDict_SetItemString(returnVal, "bsp_timer_icb_cb", bsp_timer_icb_cb);
radio_icb_startFrame_cb = PyInt_FromLong((long)self->radio_icb.startFrame_cb);
radio_icb_startFrame_cb = PyInt_FromLong((intptr_t)self->radio_icb.startFrame_cb);
PyDict_SetItemString(returnVal, "radio_icb_startFrame_cb", radio_icb_startFrame_cb);
radio_icb_endFrame_cb = PyInt_FromLong((long)self->radio_icb.endFrame_cb);
radio_icb_endFrame_cb = PyInt_FromLong((intptr_t)self->radio_icb.endFrame_cb);
PyDict_SetItemString(returnVal, "radio_icb_endFrame_cb", radio_icb_endFrame_cb );
radiotimer_icb_overflow_cb = PyInt_FromLong((long)self->radiotimer_icb.overflow_cb);
radiotimer_icb_overflow_cb = PyInt_FromLong((intptr_t)self->radiotimer_icb.overflow_cb);
PyDict_SetItemString(returnVal, "radiotimer_icb_overflow_cb", radiotimer_icb_overflow_cb);
radiotimer_icb_compare_cb = PyInt_FromLong((long)self->radiotimer_icb.compare_cb);
radiotimer_icb_compare_cb = PyInt_FromLong((intptr_t)self->radiotimer_icb.compare_cb);
PyDict_SetItemString(returnVal, "radiotimer_icb_compare_cb", radiotimer_icb_compare_cb);

// ohlone_vars
Expand Down
34 changes: 32 additions & 2 deletions firmware/openos/projects/python/SConscript.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import os
import datetime
import re
import platform
import sconsUtils

import distutils.sysconfig

Expand All @@ -17,10 +19,38 @@ buildEnv['ENV'] = os.environ
# configuration for the same board.
buildEnv['BSP'] = buildEnv['board']

# Define locations for Python headers and shared library. A cross-platform build
# requires environment variables for these locations.
isCrossBuild = False
if os.name!='nt':
if platform.architecture()[0]=='64bit' and buildEnv['simhost']=='x86-linux':
# Search for a well-known file in the include directory tree to avoid
# hard-coding the intervening directories, which may refer to the build host
# or Python version. For example, on the author's system, the file is in the
# 'i386-linux-gnu/python2.7' directory.
isCrossBuild = True
pathnames = sconsUtils.findPattern('Python.h',
'{0}/include'.format(buildEnv['simhostpy']))
if pathnames:
pathname = pathnames[0]
else:
raise SystemError("Can't find python header in 'include' directory below provided simhostpy")
pythonInc = os.path.dirname(pathname)
pythonLib = '{0}/lib'.format(buildEnv['simhostpy'])

elif buildEnv['simhost'].endswith('-windows'):
isCrossBuild = True
pythonInc = buildEnv['simhostpy']
pythonLib = buildEnv['simhostpy']

if not isCrossBuild:
pythonInc = distutils.sysconfig.get_python_inc()
pythonLib = distutils.sysconfig.PREFIX+"/libs"

# update C include path
buildEnv.Append(
CPPPATH = [
distutils.sysconfig.get_python_inc(),
pythonInc,
os.path.join('#','build','python_gcc','bsp','boards'),
os.path.join('#','build','python_gcc','bsp','boards','python'),
os.path.join('#','build','python_gcc','drivers','common'),
Expand Down Expand Up @@ -56,7 +86,7 @@ buildEnv.Append(

# update library include path
buildEnv.Append(
LIBPATH = [distutils.sysconfig.PREFIX+"/libs"],
LIBPATH = [pythonLib],
)

#============================ objectify functions =============================
Expand Down
Loading

0 comments on commit d3a051c

Please sign in to comment.