AVRSack/AVRsack/ASBuilder.swift

180 lines
7.8 KiB
Swift
Raw Normal View History

2014-11-28 13:18:53 +00:00
//
// ASBuilder.swift
// AVRsack
//
// Created by Matthias Neeracher on 11/24/14.
// Copyright © 2014 Aere Perennius. All rights reserved.
//
import Foundation
class ASBuilder {
2014-12-01 02:34:53 +00:00
var dir = NSURL()
var task : NSTask?
2014-12-08 04:35:58 +00:00
var continuation: (()->())?
var termination : AnyObject?
init() {
termination = NSNotificationCenter.defaultCenter().addObserverForName(NSTaskDidTerminateNotification,
object: nil, queue: nil, usingBlock:
{ (notification: NSNotification!) in
2014-12-10 14:30:51 +00:00
if notification.object as? NSTask == self.task {
if self.task!.terminationStatus == 0 {
if let cont = self.continuation {
self.continuation = nil
cont()
}
} else {
2014-12-08 04:35:58 +00:00
self.continuation = nil
}
}
})
}
func finalize() {
NSNotificationCenter.defaultCenter().removeObserver(termination!)
}
2014-11-28 13:18:53 +00:00
func setProjectURL(url: NSURL) {
dir = url.URLByDeletingLastPathComponent!.standardizedURL!
}
2014-12-01 02:34:53 +00:00
func stop() {
task?.terminate()
task?.waitUntilExit()
}
2014-12-01 03:26:55 +00:00
func cleanProject() {
NSFileManager.defaultManager().removeItemAtURL(dir.URLByAppendingPathComponent("build"), error: nil)
}
2014-11-28 13:18:53 +00:00
func buildProject(board: String, files: ASFileTree) {
2014-12-15 01:49:33 +00:00
let toolChain = (NSApplication.sharedApplication().delegate as ASApplication).preferences.toolchainPath
2014-11-28 13:18:53 +00:00
task = NSTask()
task!.currentDirectoryPath = dir.path!
task!.launchPath = NSBundle.mainBundle().pathForResource("BuildProject", ofType: "")!
2014-12-01 02:34:53 +00:00
let fileManager = NSFileManager.defaultManager()
2014-11-28 13:18:53 +00:00
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
var args = [NSString]()
let boardProp = ASHardware.instance().boards[board]!
2014-11-30 21:32:14 +00:00
var corePath = ""
var variantPath : NSString?
for hw in ASHardware.instance().directories {
2014-12-08 04:35:33 +00:00
corePath = hw+"/cores/"+boardProp["build.core"]!
2014-11-30 21:32:14 +00:00
if fileManager.fileExistsAtPath(corePath) {
2014-12-08 04:35:33 +00:00
if let variantName = boardProp["build.variant"] {
variantPath = hw+"/variants/"+variantName
if fileManager.fileExistsAtPath(variantPath!) {
args.append("variant="+variantName)
} else {
2014-11-30 21:32:14 +00:00
variantPath = nil
}
}
break
} else {
corePath = ""
}
}
if corePath == "" {
2014-12-08 04:35:33 +00:00
NSLog("Unable to find core %s\n", boardProp["build.core"]!)
2014-11-30 21:32:14 +00:00
return
}
2014-12-15 01:49:33 +00:00
args.append("toolchain="+toolChain)
2014-12-01 00:20:48 +00:00
args.append("project="+dir.lastPathComponent)
2014-11-28 13:18:53 +00:00
args.append("board="+board)
2014-12-08 04:35:33 +00:00
args.append("mcu="+boardProp["build.mcu"]!)
args.append("f_cpu="+boardProp["build.f_cpu"]!)
args.append("max_size"+boardProp["upload.maximum_size"]!)
args.append("core="+boardProp["build.core"]!)
2014-11-28 13:18:53 +00:00
args.append("libs="+libPath)
2014-11-30 21:32:14 +00:00
args.append("core_path="+corePath)
if variantPath != nil {
args.append("variant_path="+variantPath!)
}
2014-12-29 06:35:07 +00:00
args.append("usb_vid="+(boardProp["build.vid"] ?? "null"));
args.append("usb_pid="+(boardProp["build.pid"] ?? "null"));
2014-11-28 13:18:53 +00:00
args.append("--")
2014-12-01 02:34:53 +00:00
args += files.paths
task!.arguments = args;
2014-11-28 13:18:53 +00:00
task!.launch()
}
2014-12-08 02:59:47 +00:00
func uploadProject(board: String, programmer: String, port: String) {
2014-12-15 01:49:33 +00:00
let toolChain = (NSApplication.sharedApplication().delegate as ASApplication).preferences.toolchainPath
2014-12-08 02:59:47 +00:00
task = NSTask()
task!.currentDirectoryPath = dir.path!
2014-12-15 01:49:33 +00:00
task!.launchPath = toolChain+"/bin/avrdude"
2014-12-08 02:59:47 +00:00
let fileManager = NSFileManager.defaultManager()
let logURL = dir.URLByAppendingPathComponent("build/upload.log")
fileManager.createFileAtPath(logURL.path!, contents: NSData(), attributes: nil)
let logOut = NSFileHandle(forWritingAtPath: logURL.path!)!
task!.standardOutput = logOut
task!.standardError = logOut
2014-12-29 06:35:07 +00:00
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
let boardProp = ASHardware.instance().boards[board]!
let progProp = ASHardware.instance().programmers[programmer]
let hasBootloader = boardProp["upload.protocol"] != nil
let leonardish = hasBootloader && (boardProp["bootloader.path"] ?? "").hasPrefix("caterina")
let proto = hasBootloader ? boardProp["upload.protocol"] : progProp?["protocol"]
let speed = hasBootloader ? boardProp["upload.speed"] : progProp?["speed"]
let verbosity = NSUserDefaults.standardUserDefaults().integerForKey("UploadVerbosity")
var args = Array<String>(count: verbosity, repeatedValue: "-v")
args += [
2014-12-15 01:49:33 +00:00
"-C", toolChain+"/etc/avrdude.conf",
2014-12-08 04:35:58 +00:00
"-p", boardProp["build.mcu"]!, "-c", proto!, "-P", port,
2014-12-08 02:59:47 +00:00
"-U", "flash:w:build/"+board+"/"+dir.lastPathComponent+".hex:i"]
2014-12-08 04:35:58 +00:00
if speed != nil {
args.append("-b")
args.append(speed!)
}
2014-12-29 06:35:07 +00:00
//
// For Leonardo & the like, reset by opening port at 1200 baud
//
if leonardish {
if verbosity > 0 {
logOut.writeData("Opening \(port) at 1200 baud\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
}
if let dummyConnection = ASSerial.openPort(port, withSpeed: 1200) {
2015-01-02 06:26:10 +00:00
close(dummyConnection.fileDescriptor)
for (var retry=0; retry < 40; ++retry) {
usleep(250000)
2014-12-29 06:35:07 +00:00
if (NSFileManager.defaultManager().fileExistsAtPath(port)) {
if verbosity > 0 {
logOut.writeData("Found port \(port) after \(retry) attempts.\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
}
break;
}
}
}
}
2014-12-08 04:41:00 +00:00
let cmdLine = task!.launchPath+" "+(args as NSArray).componentsJoinedByString(" ")+"\n"
logOut.writeData(cmdLine.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
2014-12-08 02:59:47 +00:00
task!.arguments = args;
task!.launch()
}
2014-12-10 14:30:51 +00:00
func disassembleProject(board: String) {
2014-12-15 01:49:33 +00:00
let toolChain = (NSApplication.sharedApplication().delegate as ASApplication).preferences.toolchainPath
2014-12-10 14:30:51 +00:00
task = NSTask()
task!.currentDirectoryPath = dir.path!
2014-12-15 01:49:33 +00:00
task!.launchPath = toolChain+"/bin/avr-objdump"
2014-12-10 14:30:51 +00:00
let fileManager = NSFileManager.defaultManager()
let logURL = dir.URLByAppendingPathComponent("build/disasm.log")
fileManager.createFileAtPath(logURL.path!, contents: NSData(), attributes: nil)
let logOut = NSFileHandle(forWritingAtPath: logURL.path!)!
task!.standardOutput = logOut
task!.standardError = logOut
2014-12-15 01:49:33 +00:00
let showSource = NSUserDefaults.standardUserDefaults().boolForKey("ShowSourceInDisassembly")
var args = showSource ? ["-S"] : []
args += ["-d", "build/"+board+"/"+dir.lastPathComponent+".elf"]
let cmdLine = task!.launchPath+" "+(args as NSArray).componentsJoinedByString(" ")+"\n"
2014-12-10 14:30:51 +00:00
logOut.writeData(cmdLine.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
task!.arguments = args;
task!.launch()
}
2014-11-28 13:18:53 +00:00
}