AVRSack/AVRsack/BuildProject

165 lines
5.2 KiB
Ruby
Executable File

#!/usr/bin/ruby
#
# BuildProject board=... mcu=... -- FILE1 FILE2 FILE3
#
# AVRsack
#
# Created by Matthias Neeracher on 11/26/14.
# Copyright © 2014 Aere Perennius. All rights reserved.
#
require 'fileutils.rb'
require 'rake'
BUILD = {
'board' => 'uno',
'mcu' => 'atmega328p',
'f_cpu' => 16000000,
'core' => 'arduino',
'variant' => 'standard',
}
def parseArguments
while ARGV.length > 0 do
param = ARGV.shift
break if param == '--'
param =~ /(\S+?)=(\S*)/
BUILD[$1] = $2
end
end
def createBuildDirectory
$BUILD_DIR = "build/#{BUILD['board']}"
$SKETCH_DIR = "#{$BUILD_DIR}/sketch"
FileUtils::mkdir_p "#{$SKETCH_DIR}", :verbose => true
end
HEADERMAP = {}
def buildHeaderMap
paths = Rake::FileList.new(BUILD['libs'].split(':').reverse)
paths.each do |path|
libs = Rake::FileList.new(path+"/*")
libs.each do |lib|
headers = Rake::FileList.new(lib+"/**/*.h")
headers.each do |h|
name = h[lib.length+1..-1]
next if name =~ %r|^utility/|
if !HEADERMAP[name] or HEADERMAP[name].pathmap('%f') != name.pathmap('%X')
HEADERMAP[name] = lib
end
end
end
end
end
def parseInoFiles
$LIBRARIES = []
$CORES = [BUILD['core_path']]
if BUILD['variant_path']
$CORES << BUILD['variant_path']
end
ARGV.each_index do |arg|
if ARGV[arg] =~ /\.ino$/
outName = "#{$SKETCH_DIR}/"+File.basename(ARGV[arg], '.ino')+".cpp"
outFile = File.open(outName, 'w')
File.open(ARGV[arg], 'r') do |ino|
contents = ino.read
# Find protypes:
prototypes = contents.dup
# - Strip comments, quoted strings, and preprocessor directives
prototypes.gsub!(%r{'(?:[^']|\\')+'|"(?:[^"]|\\")*"|//.*?$|/\*.*?\*/|^\s*?#.*?$}m, ' ')
# Collapse braces
while prototypes.sub!(/(\{)(?:[^{}]+|\{[^{}]*\})/m, '\1') do
end
existingProto = {}
prototypes.scan(/[\w\[\]\*]+\s+[&\[\]\*\w\s]+\([&,\[\]\*\w\s]*\)(?=\s*;)/) {|p|
existingProto[smashSpaces(p)] = true
}
proto = []
prototypes.scan(/[\w\[\]\*]+\s+[&\[\]\*\w\s]+\([&,\[\]\*\w\s]*\)(?=\s*{)/) {|p|
p = smashSpaces(p)
proto << p+";\n" unless existingProto[p]
}
contents.each_line do |line|
if line =~ /^\s*#include\s+[<"](.*)[">]\s*(#.*)?$/
addLibrary($1)
end
end
%r{(?<preamble>(?:\s+|//.*$|/\*.*?\*/)*)(?<rest>.*)}m =~ contents
outFile.print preamble
outFile.puts '#include "Arduino.h"'
outFile.print proto.join('')
outFile.puts "#line #{1+preamble.count("\n")}"
outFile.print rest
end
outFile.close
ARGV[arg] = outName
end
end
end
def smashSpaces(s)
return s.gsub(/(\W)\s+(\W)/, '\1\2').gsub(/\s+/, ' ')
end
def addLibrary(header)
lib = HEADERMAP[header]
if lib && !$LIBRARIES.include?(lib)
$LIBRARIES << lib
end
end
parseArguments
createBuildDirectory
buildHeaderMap
parseInoFiles
File.open("#{$BUILD_DIR}/Rakefile", 'w') do |rakeFile|
SOURCES = Rake::FileList.new(ARGV).select {|f| f =~ /\.(c|cpp|cp|cxx|S)$/}
INCLUDES= ($CORES+$LIBRARIES).map {|l| " +\n \" -I'#{l}'\""}.join('')
rakeFile.print <<END_RAKE
CC = '/usr/local/CrossPack-AVR/bin/avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=#{BUILD['mcu']} -DF_CPU=#{BUILD['f_cpu']} -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=105 -I ../..'#{INCLUDES}
AR = '/usr/local/CrossPack-AVR/bin/avr-ar crsv'
LIBRARIES = [#{$LIBRARIES.map{|l| "'"+l+"'"}.join(' ')}]
def compile(dest, extrainc, *src)
directory dest
archive = dest.ext('.a')
sources = Rake::FileList.new(src)
objects = sources.pathmap(dest+"/%n.o")
objects.each_index do |i|
file objects[i] => [sources[i],dest] do
sh "%s %s '%s' -o '%s'" % [CC, extrainc ? "-I '"+extrainc+"'" : '', sources[i], objects[i]]
end
end
file archive => objects do
sh ("%s '%s' " % [AR, archive])+objects.map {|o| "'"+o+"'"}.join(" ")
end
end
def compile_library(lib)
extrainc = nil
utility = lib+"/utility"
if File::exists?(utility)
extrainc = utility
end
compile(lib.pathmap('lib/%f'), extrainc, *Rake::FileList[lib+"/*.{c,cpp,cp,cxx,S}", lib+"/utility/*.{c,cpp,cp,cxx,S}"])
end
def compile_core(core,variant)
list = Rake::FileList[core+"/*.{c,cpp,cp,cxx,S}"]
list.add(variant+"/*.{c,cpp,cp,cxx,S}") if variant
compile('core', nil, list)
end
compile('sketch', nil, #{SOURCES.map{|f| "'../../"+f+"'"}.join(', ')})
compile_core(#{$CORES.map {|c| "'"+c+"'"}.join(", ")})
END_RAKE
$LIBRARIES.each do |lib|
rakeFile.puts "compile_library('#{lib}')"
end
end