Skip to content

Commit

Permalink
merge nhatkhai's 'Update for support Windows, Cygwin environments
Browse files Browse the repository at this point in the history
  • Loading branch information
amoose136 committed Jan 17, 2019
1 parent f530415 commit 7328145
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 53 deletions.
4 changes: 4 additions & 0 deletions ino/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from ino.runner import main

if __name__ == '__main__':
main()
52 changes: 40 additions & 12 deletions ino/commands/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,24 @@ class Build(Command):
name = 'build'
help_line = "Build firmware from the current directory project"

default_make = 'make'
default_cc = 'avr-gcc'
default_cxx = 'avr-g++'
default_ar = 'avr-ar'
default_objcopy = 'avr-objcopy'
if platform.system() == 'Windows':
default_make= 'make.exe'
default_cc = 'avr-gcc.exe'
default_cxx = 'avr-g++.exe'
default_ar = 'avr-ar.exe'
default_objcopy = 'avr-objcopy.exe'
elif platform.system().startswith('CYGWIN'):
default_make= '/usr/bin/make'
default_cc = 'avr-gcc'
default_cxx = 'avr-g++'
default_ar = 'avr-ar'
default_objcopy = 'avr-objcopy'
else:
default_make= 'make'
default_cc = 'avr-gcc'
default_cxx = 'avr-g++'
default_ar = 'avr-ar'
default_objcopy = 'avr-objcopy'

default_cppflags = '-ffunction-sections -fdata-sections -g -Os -w'
default_cflags = ''
Expand Down Expand Up @@ -126,7 +139,8 @@ def discover(self, args):
human_name='Arduino core library')

if self.e.arduino_lib_version.major:
variants_place = os.path.join(board['_coredir'], 'variants')
variants_place = os.path.join( board['_coredir'], 'variants',
board['build']['variant'])
self.e.find_dir('arduino_variants_dir', ['.'], [variants_place],
human_name='Arduino variants directory')

Expand Down Expand Up @@ -165,10 +179,12 @@ def setup_flags(self, args):
self.e['cppflags'].append('-DUSB_PID=%s' % board['build']['pid'])

if self.e.arduino_lib_version.major:
variant_dir = os.path.join(self.e.arduino_variants_dir,
board['build']['variant'])
variant_dir = self.e.arduino_variants_dir
self.e.cppflags.append('-I' + variant_dir)

self.e.cppflags.append('-I' + self.e.src_dir)
self.e.cppflags.append('-I' + self.e.lib_dir)

self.e['cflags'] = SpaceList(shlex.split(args.cflags))
self.e['cxxflags'] = SpaceList(shlex.split(args.cxxflags))

Expand Down Expand Up @@ -207,13 +223,22 @@ def render_template(self, source, target, **ctx):
contents = template.render(**ctx)
out_path = os.path.join(self.e.build_dir, target)
with open(out_path, 'wt') as f:
contents = contents.split('\\')
contents = '/'.join(contents)
f.write(contents)

return out_path

def make(self, makefile, **kwargs):

old_path = os.environ["PATH"]
os.environ['PATH'] = os.path.dirname(os.path.abspath(self.e.make)) + os.pathsep + old_path

makefile = self.render_template(makefile + '.jinja', makefile, **kwargs)
ret = subprocess.call([self.e.make, '-f', makefile, 'all'])
print "*** RUN %s ..." % (makefile)
ret = subprocess.call([self.e.make , '-f', makefile, 'all'])

os.environ['PATH'] = old_path
if ret != 0:
raise Abort("Make failed with code %s" % ret)

Expand All @@ -233,13 +258,16 @@ def _scan_dependencies(self, dir, lib_dirs, inc_flags):
# for this scan dependency file generated by make
# with regexes to find entries that start with
# libraries dirname
regexes = dict((lib, re.compile(r'\s' + lib + re.escape(os.path.sep))) for lib in lib_dirs)
regexes = dict((lib, re.compile(r'\s' + lib + re.escape('/'))) for lib in lib_dirs)
#regexes = dict((lib, re.compile(r'\s' + lib + re.escape(os.path.sep))) for lib in lib_dirs)
used_libs = set()
with open(output_filepath) as f:
for line in f:
for lib, regex in regexes.iteritems():
if regex.search(line) and lib != dir:
used_libs.add(lib)
if regex.search(line) and lib != dir:
lib = os.path.abspath(lib)
lib = os.path.relpath(lib, os.getcwd())
used_libs.add(lib)

return used_libs

Expand Down
9 changes: 8 additions & 1 deletion ino/commands/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import shutil

from ino.commands.base import Command
from ino.exc import Abort


class Clean(Command):
Expand All @@ -15,7 +16,13 @@ class Clean(Command):

name = 'clean'
help_line = "Remove intermediate compilation files completely"
error=0

def run(self, args):
if os.path.isdir(self.e.output_dir):
shutil.rmtree(self.e.output_dir)
shutil.rmtree(self.e.output_dir,onerror=self.onerror)
if self.error > 0:
raise Abort('Can\'t remove the build directory - ' + self.e.output_dir)

def onerror(self, func, path, excinfo):
self.error += 1
42 changes: 28 additions & 14 deletions ino/commands/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,40 +36,51 @@ def setup_arg_parser(self, parser):
self.e.add_arduino_dist_arg(parser)

def discover(self):
self.e.find_tool('stty', ['stty'])
if platform.system() == 'Linux':
self.e.find_tool('stty', ['stty'])
self.e.find_arduino_tool('avrdude', ['hardware', 'tools'])

conf_places = self.e.arduino_dist_places(['hardware', 'tools'])
conf_places.append('/etc/avrdude') # fallback to system-wide conf on Fedora
self.e.find_file('avrdude.conf', places=conf_places)

elif platform.system()== 'Windows':
self.e.find_arduino_tool('avrdude.exe', ['hardware', 'tools', 'avr', 'bin'])
self.e.find_arduino_file('avrdude.conf', ['hardware', 'tools', 'avr', 'etc'])

elif platform.system().startswith('CYGWIN'):
self.e.find_arduino_tool('avrdude', ['hardware', 'tools', 'avr', 'bin'])
self.e.find_arduino_file('avrdude.conf', ['hardware', 'tools', 'avr', 'etc'])

else:
self.e.find_tool('stty', ['stty'])
self.e.find_arduino_tool('avrdude', ['hardware', 'tools', 'avr', 'bin'])
self.e.find_arduino_file('avrdude.conf', ['hardware', 'tools', 'avr', 'etc'])

def run(self, args):
self.discover()

port = args.serial_port or self.e.guess_serial_port()
board = self.e.board_model(args.board_model)

protocol = board['upload']['protocol']
protocol = board['upload']['protocol']
if protocol == 'stk500':
# if v1 is not specifid explicitly avrdude will
# try v2 first and fail
protocol = 'stk500v1'

if not os.path.exists(port):
raise Abort("%s doesn't exist. Is Arduino connected?" % port)
if port is None:
raise Abort("%s doesn't exist. Is Arduino connected?" % args.serial_port)

# send a hangup signal when the last process closes the tty
file_switch = '-f' if platform.system() == 'Darwin' else '-F'
ret = subprocess.call([self.e['stty'], file_switch, port, 'hupcl'])
if ret:
raise Abort("stty failed")
if 'stty' in self.e:
# send a hangup signal when the last process closes the tty
file_switch = '-f' if platform.system() == 'Darwin' else '-F'
ret = subprocess.call([self.e['stty'], file_switch, port[0], 'hupcl'])
if ret:
raise Abort("stty failed")

# pulse on DTR
try:
s = Serial(port, 115200)
s = Serial(port[0], 115200)
except SerialException as e:
raise Abort(str(e))
s.setDTR(False)
Expand All @@ -92,7 +103,7 @@ def run(self, args):
before = self.e.list_serial_ports()
if port in before:
ser = Serial()
ser.port = port
ser.port = port[0]
ser.baudrate = 1200
ser.open()
ser.close()
Expand Down Expand Up @@ -124,13 +135,16 @@ def run(self, args):
"button after initiating the upload.")

port = new_port

print "Used %s for programming." % port[0]
print "Used %s protocol" % protocol

# call avrdude to upload .hex
subprocess.call([
self.e['avrdude'],
self.e['avrdude'] if 'avrdude' in self.e else self.e['avrdude.exe'],
'-C', self.e['avrdude.conf'],
'-p', board['build']['mcu'],
'-P', port,
'-P', port[0],
'-c', protocol,
'-b', board['upload']['speed'],
'-D',
Expand Down
107 changes: 88 additions & 19 deletions ino/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import platform
import hashlib
import re
from serial.tools.list_ports import comports
import serial

try:
from collections import OrderedDict
Expand Down Expand Up @@ -67,22 +69,37 @@ def __str__(self):
class Environment(dict):

templates_dir = os.path.join(os.path.dirname(__file__), 'templates')
output_dir = '.build'
output_dir = '.build_' + sys.platform
src_dir = 'src'
lib_dir = 'lib'
hex_filename = 'firmware.hex'

arduino_dist_dir = None
arduino_dist_dir_guesses = [
'/usr/local/share/arduino',
'/usr/share/arduino',
]

if platform.system() == 'Darwin':
arduino_dist_dir_guesses = []

if platform.system().startswith('CYGWIN'):
arduino_dist_dir_guesses.insert(0, '/cygdrive/c/Arduino')
arduino_dist_dir_guesses.insert(0, '/cygdrive/c/Progra~1/Arduino')
arduino_dist_dir_guesses.insert(0, '/cygdrive/c/Progra~2/Arduino')
arduino_dist_dir_guesses.insert(0, '/cygdrive/c/Progra~3/Arduino')
arduino_dist_dir_guesses.insert(0, '/cygdrive/c/Progra~4/Arduino')
elif platform.system() == 'Windows':
arduino_dist_dir_guesses.insert(0, 'c:\\Arduino')
arduino_dist_dir_guesses.insert(0, 'c:\\Progra~1\\Arduino')
arduino_dist_dir_guesses.insert(0, 'c:\\Progra~2\\Arduino')
arduino_dist_dir_guesses.insert(0, 'c:\\Progra~3\\Arduino')
arduino_dist_dir_guesses.insert(0, 'c:\\Progra~4\\Arduino')
elif platform.system() == 'Darwin':
arduino_dist_dir_guesses.insert(0, '/Applications/Arduino.app/Contents/Resources/Java')
else:
arduino_dist_dir_guesses = [
'/usr/local/share/arduino',
'/usr/share/arduino',
]

default_board_model = 'uno'
ino = sys.argv[0]
default_board_model = 'promicro16'
ino = os.path.abspath(sys.argv[0])
ino = 'python ' + os.path.relpath(ino, os.getcwd())

def dump(self):
if not os.path.isdir(self.output_dir):
Expand Down Expand Up @@ -140,20 +157,35 @@ def _find(self, key, items, places, human_name, join, multi):
return self[key]

human_name = human_name or key

# make sure search on current directy first
#places.insert(0,'.')

# expand env variables in `places` and split on colons
places = itertools.chain.from_iterable(os.path.expandvars(p).split(os.pathsep) for p in places)
places = map(os.path.expanduser, places)

glob_places = itertools.chain.from_iterable(glob(p) for p in places)
glob_places = itertools.chain.from_iterable(glob(os.path.abspath(p)) for p in places)

print 'Searching for', human_name, '...',
test_func = os.path.isfile if join else os.path.exists
results = []
for p in glob_places:
for i in items:
path = os.path.join(p, i)
if os.path.exists(path):
result = path if join else p
#KHAI: Convert to relative path for compatible with
# windows and Linux system
result = os.path.abspath(result)
result = os.path.relpath(result, os.getcwd())

#KHAI added for convert window path to Linux path for
# make.exe work in window
if platform.system() == "Windows":
result = result.split('\\')
result = '/'.join(result)

if not multi:
print colorize(result, 'green')
self[key] = result
Expand Down Expand Up @@ -259,6 +291,18 @@ def board_models(self):
# store spectial `_coredir` value on top level so we later can build
# paths relative to a core directory of a specific board model
self['board_models'][multikey[0]]['_coredir'] = os.path.dirname(boards_txt)

# Convert core and variant path in Arduino specification to system
# paths
subdict = self['board_models']
for model in subdict:
if 'build' in subdict[model]:
modeldict = subdict[model]['build']
for val, dir in (('core','cores'), ('variant','variants')):
if val in modeldict:
a, b, c = modeldict[val].partition(':')
if b==':':
modeldict[val] = os.path.join('..', '..', a, dir, c)

return self['board_models']

Expand All @@ -285,27 +329,52 @@ def serial_port_patterns(self):
return ['/dev/ttyACM*', '/dev/ttyUSB*']
if system == 'Darwin':
return ['/dev/tty.usbmodem*', '/dev/tty.usbserial*']
raise NotImplementedError("Not implemented for Windows")
elif system.startswith('CYGWIN'):
return []
elif system == 'Windows':
return []
raise NotImplementedError("Not implemented for %s" % system)

def list_serial_ports(self):
def list_serial_ports(self, serial_port=None):
ports = []

for p, desc, hwid in comports():
if hwid.startswith('USB'):
if (serial_port==str(p)):
ports.insert(0, (p,"%s: %s" % (p, desc)))
elif serial_port is None:
if ( desc.startswith('Teensy USB Serial')
or desc.startswith('Sparkfun Pro Micro')):
ports.insert(0, (p,"%s: %s" % (p, desc)))
else:
ports.append((p,"%s: %s" % (p, desc)))

for p in self.serial_port_patterns():
matches = glob(p)
ports.extend(matches)
for m in matches:
if m==serial_port:
ports.insert(0, (m,'%s' % m))
elif serial_port is None:
ports.append((m,'%s' % m))

return ports

def guess_serial_port(self):
print 'Guessing serial port ...',
def guess_serial_port(self, serial_port=None):
if serial_port is None:
print 'Guessing serial port ...',
else:
print 'Check serial port %s ...' % serial_port,

ports = self.list_serial_ports()
ports = self.list_serial_ports(serial_port)
if ports:
result = ports[0]
print colorize(result, 'yellow')
print colorize(ports[0][1], 'yellow')
return result

print colorize('FAILED', 'red')
raise Abort("No device matching following was found: %s" %
(''.join(['\n - ' + p for p in self.serial_port_patterns()])))
return None
# raise Abort("No device matching following was found: %s" %
# (''.join(['\n - ' + p for p in self.serial_port_patterns()])))

def process_args(self, args):
arduino_dist = getattr(args, 'arduino_dist', None)
Expand Down
Loading

1 comment on commit 7328145

@amoose136
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From nhatkhai's amperka#280 pull request

Please sign in to comment.