Start work on ASBuilder
This commit is contained in:
parent
7ae5a4b215
commit
9b770623a7
|
@ -13,6 +13,8 @@
|
|||
9501D8091A17025C0034C530 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9501D8081A17025C0034C530 /* Images.xcassets */; };
|
||||
9501D80C1A17025C0034C530 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9501D80A1A17025C0034C530 /* MainMenu.xib */; };
|
||||
9501D8181A17025C0034C530 /* AVRsackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9501D8171A17025C0034C530 /* AVRsackTests.swift */; };
|
||||
951CD1741A23C9FC0066C1A1 /* ASBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951CD1731A23C9FC0066C1A1 /* ASBuilder.swift */; };
|
||||
951CD1771A2615000066C1A1 /* BuildProject in Resources */ = {isa = PBXBuildFile; fileRef = 951CD1761A2615000066C1A1 /* BuildProject */; };
|
||||
95468DDF1A228BE600668EE2 /* ASHardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95468DDE1A228BE600668EE2 /* ASHardware.swift */; };
|
||||
95468DE31A228E1300668EE2 /* Defaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = 95468DE21A228E1300668EE2 /* Defaults.plist */; };
|
||||
95BF80EB1A185C9E0004A693 /* ASFileTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BF80EA1A185C9E0004A693 /* ASFileTree.swift */; };
|
||||
|
@ -69,6 +71,8 @@
|
|||
9501D8111A17025C0034C530 /* AVRsackTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AVRsackTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9501D8161A17025C0034C530 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9501D8171A17025C0034C530 /* AVRsackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVRsackTests.swift; sourceTree = "<group>"; };
|
||||
951CD1731A23C9FC0066C1A1 /* ASBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASBuilder.swift; sourceTree = "<group>"; };
|
||||
951CD1761A2615000066C1A1 /* BuildProject */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = BuildProject; sourceTree = "<group>"; };
|
||||
95468DDE1A228BE600668EE2 /* ASHardware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASHardware.swift; sourceTree = "<group>"; };
|
||||
95468DE21A228E1300668EE2 /* Defaults.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Defaults.plist; sourceTree = "<group>"; };
|
||||
958D76811A17DA1C00917D96 /* AVRsack-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AVRsack-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
|
@ -120,11 +124,7 @@
|
|||
9501D7FE1A17025C0034C530 /* AVRsack */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
958D76811A17DA1C00917D96 /* AVRsack-Bridging-Header.h */,
|
||||
9501D8011A17025C0034C530 /* ASApplication.swift */,
|
||||
9501D8031A17025C0034C530 /* ASProjDoc.swift */,
|
||||
95BF80EA1A185C9E0004A693 /* ASFileTree.swift */,
|
||||
95468DDE1A228BE600668EE2 /* ASHardware.swift */,
|
||||
951CD1751A2614C40066C1A1 /* Source */,
|
||||
95BF80EC1A185CD90004A693 /* Resources */,
|
||||
9501D7FF1A17025C0034C530 /* Supporting Files */,
|
||||
95EA32671A17BAA600F66EB0 /* Frameworks */,
|
||||
|
@ -136,6 +136,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
9501D8001A17025C0034C530 /* Info.plist */,
|
||||
958D76811A17DA1C00917D96 /* AVRsack-Bridging-Header.h */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
|
@ -157,6 +158,19 @@
|
|||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
951CD1751A2614C40066C1A1 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9501D8011A17025C0034C530 /* ASApplication.swift */,
|
||||
9501D8031A17025C0034C530 /* ASProjDoc.swift */,
|
||||
95BF80EA1A185C9E0004A693 /* ASFileTree.swift */,
|
||||
95468DDE1A228BE600668EE2 /* ASHardware.swift */,
|
||||
951CD1731A23C9FC0066C1A1 /* ASBuilder.swift */,
|
||||
951CD1761A2615000066C1A1 /* BuildProject */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
95BF80EC1A185CD90004A693 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -302,6 +316,7 @@
|
|||
9501D8071A17025C0034C530 /* ASProjDoc.xib in Resources */,
|
||||
9501D8091A17025C0034C530 /* Images.xcassets in Resources */,
|
||||
9501D80C1A17025C0034C530 /* MainMenu.xib in Resources */,
|
||||
951CD1771A2615000066C1A1 /* BuildProject in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -321,6 +336,7 @@
|
|||
files = (
|
||||
9501D8041A17025C0034C530 /* ASProjDoc.swift in Sources */,
|
||||
95468DDF1A228BE600668EE2 /* ASHardware.swift in Sources */,
|
||||
951CD1741A23C9FC0066C1A1 /* ASBuilder.swift in Sources */,
|
||||
9501D8021A17025C0034C530 /* ASApplication.swift in Sources */,
|
||||
95BF80EB1A185C9E0004A693 /* ASFileTree.swift in Sources */,
|
||||
);
|
||||
|
|
40
AVRsack/ASBuilder.swift
Normal file
40
AVRsack/ASBuilder.swift
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// ASBuilder.swift
|
||||
// AVRsack
|
||||
//
|
||||
// Created by Matthias Neeracher on 11/24/14.
|
||||
// Copyright © 2014 Aere Perennius. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class ASBuilder {
|
||||
var dir = NSURL()
|
||||
var task : NSTask?
|
||||
|
||||
func setProjectURL(url: NSURL) {
|
||||
dir = url.URLByDeletingLastPathComponent!.standardizedURL!
|
||||
}
|
||||
|
||||
func buildProject(board: String, files: ASFileTree) {
|
||||
task = NSTask()
|
||||
task!.currentDirectoryPath = dir.path!
|
||||
task!.launchPath = NSBundle.mainBundle().pathForResource("BuildProject", ofType: "")!
|
||||
|
||||
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
|
||||
var args = [NSString]()
|
||||
let boardProp = ASHardware.instance().boards[board]!
|
||||
args.append("board="+board)
|
||||
args.append("mcu="+boardProp["build.mcu"])
|
||||
args.append("f_cpu="+boardProp["build.f_cpu"])
|
||||
args.append("core="+boardProp["build.core"])
|
||||
args.append("variant="+boardProp["build.variant"])
|
||||
args.append("libs="+libPath)
|
||||
args.append("--")
|
||||
args += files.paths
|
||||
task!.arguments = args;
|
||||
task!.launch()
|
||||
|
||||
files.paths
|
||||
}
|
||||
}
|
|
@ -76,6 +76,9 @@ class ASFileNode {
|
|||
assertionFailure("Undefined item type in file hierarchy")
|
||||
}
|
||||
}
|
||||
func paths(rootPath: NSString) -> [NSString] {
|
||||
return [NSString]()
|
||||
}
|
||||
}
|
||||
|
||||
class ASFileGroup : ASFileNode {
|
||||
|
@ -109,7 +112,6 @@ class ASFileGroup : ASFileNode {
|
|||
child.apply(closure)
|
||||
}
|
||||
}
|
||||
|
||||
func childrenPropertyList(rootPath: NSString) -> [AnyObject] {
|
||||
return children.map() { (node) in node.propertyList(rootPath) }
|
||||
}
|
||||
|
@ -117,6 +119,13 @@ class ASFileGroup : ASFileNode {
|
|||
return [kTypeKey: kNodeType, kNameKey: name, kExpandedKey: expanded,
|
||||
kChildrenKey: childrenPropertyList(rootPath)]
|
||||
}
|
||||
override func paths(rootPath: NSString) -> [NSString] {
|
||||
var allPaths = [NSString]()
|
||||
for child in children {
|
||||
allPaths += child.paths(rootPath)
|
||||
}
|
||||
return allPaths
|
||||
}
|
||||
}
|
||||
|
||||
class ASProject : ASFileGroup {
|
||||
|
@ -168,10 +177,12 @@ class ASFileItem : ASFileNode {
|
|||
let resComp = Array(count: relCount-matchComp, repeatedValue: "..")+pathComp[matchComp..<pathCount]
|
||||
return "/".join(resComp)
|
||||
}
|
||||
|
||||
override func propertyList(rootPath: NSString) -> AnyObject {
|
||||
return [kTypeKey: kNodeTypeFile, kKindKey: type.rawValue, kPathKey: relativePath(rootPath)]
|
||||
}
|
||||
override func paths(rootPath: NSString) -> [NSString] {
|
||||
return [relativePath(rootPath)]
|
||||
}
|
||||
}
|
||||
|
||||
class ASFileTree : NSObject, NSOutlineViewDataSource {
|
||||
|
@ -197,6 +208,9 @@ class ASFileTree : NSObject, NSOutlineViewDataSource {
|
|||
func readPropertyList(prop: NSDictionary) {
|
||||
root = ASFileNode.readPropertyList(prop, rootURL:dir) as ASProject
|
||||
}
|
||||
var paths : [NSString] {
|
||||
return root.paths(dir.path!)
|
||||
}
|
||||
|
||||
// MARK: Outline Data Source
|
||||
func outlineView(outlineView: NSOutlineView, numberOfChildrenOfItem item: AnyObject?) -> Int {
|
||||
|
|
|
@ -8,7 +8,22 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
typealias ASPropertyEntry = [String: String]
|
||||
class ASPropertyEntry {
|
||||
private var storage = [String: String]()
|
||||
subscript(key: String) -> String {
|
||||
get {
|
||||
if let value = storage[key] {
|
||||
return value
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
set (newValue) {
|
||||
storage[key] = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias ASProperties = [String: ASPropertyEntry]
|
||||
|
||||
private func subdirectories(path: NSString) -> [NSString] {
|
||||
|
@ -26,7 +41,7 @@ private func subdirectories(path: NSString) -> [NSString] {
|
|||
return subDirs
|
||||
}
|
||||
|
||||
let hardwareInstance = ASHardware()
|
||||
private let hardwareInstance = ASHardware()
|
||||
class ASHardware {
|
||||
class func instance() -> ASHardware { return hardwareInstance }
|
||||
let directories = [NSString]()
|
||||
|
@ -90,3 +105,33 @@ class ASHardware {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let librariesInstance = ASLibraries()
|
||||
class ASLibraries {
|
||||
class func instance() -> ASLibraries { return librariesInstance }
|
||||
let directories = [NSString]()
|
||||
let libraries = [NSString]()
|
||||
init() {
|
||||
//
|
||||
// Gather hardware directories
|
||||
//
|
||||
let userDefaults = NSUserDefaults.standardUserDefaults()
|
||||
let fileManager = NSFileManager.defaultManager()
|
||||
if let arduinoPath = userDefaults.stringForKey("Arduino") {
|
||||
let arduinoLibrariesPath = arduinoPath + "/Contents/Resources/Java/libraries"
|
||||
let dirs = subdirectories(arduinoLibrariesPath)
|
||||
if dirs.count > 0 {
|
||||
directories.append(arduinoLibrariesPath)
|
||||
libraries += dirs
|
||||
}
|
||||
}
|
||||
for sketchDir in userDefaults.objectForKey("Sketchbooks") as [NSString] {
|
||||
let librariesPath = sketchDir + "/libraries"
|
||||
let dirs = subdirectories(librariesPath)
|
||||
if dirs.count > 0 {
|
||||
directories.append(librariesPath)
|
||||
libraries += dirs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,15 @@ private var keyboardHandler : ACEKeyboardHandler = .Ace
|
|||
class ASProjDoc: NSDocument, NSOutlineViewDelegate {
|
||||
@IBOutlet weak var editor : ACEView!
|
||||
@IBOutlet weak var outline : NSOutlineView!
|
||||
let files : ASFileTree = ASFileTree()
|
||||
let files = ASFileTree()
|
||||
let builder = ASBuilder()
|
||||
var mainEditor : ASFileNode?
|
||||
var currentTheme : UInt = 0
|
||||
var fontSize : UInt = 12
|
||||
var themeObserver : AnyObject?
|
||||
var board : String = "uno"
|
||||
var programmer : String = ""
|
||||
var port : String = ""
|
||||
|
||||
let kVersionKey = "Version"
|
||||
let kCurVersion = 1.0
|
||||
|
@ -25,6 +29,9 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate {
|
|||
let kThemeKey = "Theme"
|
||||
let kFontSizeKey = "FontSize"
|
||||
let kBindingsKey = "Bindings"
|
||||
let kBoardKey = "Board"
|
||||
let kProgrammerKey = "Programmer"
|
||||
let kPortKey = "Port"
|
||||
|
||||
// MARK: Initialization / Finalization
|
||||
|
||||
|
@ -51,6 +58,9 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate {
|
|||
themeObserver = NSNotificationCenter.defaultCenter().addObserverForName(kBindingsKey, object: nil, queue: nil, usingBlock: { (NSNotification) in
|
||||
self.editor.setKeyboardHandler(keyboardHandler)
|
||||
})
|
||||
board = userDefaults.stringForKey(kBoardKey)!
|
||||
programmer = userDefaults.stringForKey(kProgrammerKey)!
|
||||
port = userDefaults.stringForKey(kPortKey)!
|
||||
}
|
||||
override func finalize() {
|
||||
saveCurEditor()
|
||||
|
@ -123,6 +133,7 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate {
|
|||
success = importProject(url.URLByDeletingLastPathComponent!, error: outError)
|
||||
if success {
|
||||
files.setProjectURL(fileURL!)
|
||||
builder.setProjectURL(fileURL!)
|
||||
fileURL = projectURL
|
||||
success = writeToURL(projectURL, ofType: "Project", forSaveOperation: .SaveAsOperation, originalContentsURL: nil, error: outError)
|
||||
}
|
||||
|
@ -136,6 +147,7 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate {
|
|||
return false
|
||||
}
|
||||
files.setProjectURL(fileURL!)
|
||||
builder.setProjectURL(fileURL!)
|
||||
let projectData : NSDictionary = NSPropertyListSerialization.propertyListFromData(data, mutabilityOption: .Immutable, format: nil, errorDescription: nil) as NSDictionary
|
||||
let projectVersion = projectData[kVersionKey] as Double
|
||||
assert(projectVersion <= floor(kCurVersion+1.0), "Project version too new for this app")
|
||||
|
@ -228,6 +240,7 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate {
|
|||
// MARK: Build / Upload
|
||||
|
||||
@IBAction func buildProject(AnyObject) {
|
||||
builder.buildProject(board, files: files)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
100
AVRsack/BuildProject
Executable file
100
AVRsack/BuildProject
Executable file
|
@ -0,0 +1,100 @@
|
|||
#!/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'
|
||||
|
||||
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
|
||||
|
||||
def parseInoFiles
|
||||
$LIBPATH = BUILD['libs'].split(':').reverse
|
||||
$LIBRARIES = []
|
||||
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 unless existingProto[p]
|
||||
}
|
||||
contents.each_line do |line|
|
||||
if line =~ /^\s*#include\s+[<"](.*)[">]\s*(#.*)?$/
|
||||
addLibrary($1)
|
||||
end
|
||||
end
|
||||
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)
|
||||
$LIBPATH.each do |path|
|
||||
Dir.glob("#{path}/*").each do |lib|
|
||||
if File.exists?("#{lib}/#{header}")
|
||||
$LIBRARIES << lib
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parseArguments
|
||||
createBuildDirectory
|
||||
parseInoFiles
|
||||
|
||||
File.open("#{$BUILD_DIR}/Rakefile", 'w') do |rakeFile|
|
||||
rakeFile.print <<END_RAKE
|
||||
LIBRARIES=#{$LIBRARIES.join(':')}
|
||||
FILES = [
|
||||
#{ARGV.join('\n')}
|
||||
]
|
||||
END_RAKE
|
||||
|
||||
end
|
||||
|
|
@ -2,6 +2,12 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Port</key>
|
||||
<string></string>
|
||||
<key>Programmer</key>
|
||||
<string>arduino</string>
|
||||
<key>Board</key>
|
||||
<string>uno</string>
|
||||
<key>Bindings</key>
|
||||
<string>Ace</string>
|
||||
<key>FontSize</key>
|
||||
|
|
Loading…
Reference in New Issue
Block a user