Commit 6e5ab155 authored by Drew's avatar Drew

build yaml as a module

See #6
parent 2d6a8f41
......@@ -7,10 +7,12 @@ tasks:
script: "echo \"Hello world\""
default:
dependency: ["yaml"]
tool: "atllbuild"
source: ["cli/src/**.swift", "parsers/yaml/**.swift"]
source: ["cli/src/**.swift"]
name: "atbuild"
outputType: "executable"
linkWithProduct: ["yaml.a"]
bootstrap-osx:
tool: "atllbuild"
......
......@@ -8,6 +8,10 @@
import Foundation
#if ATBUILD
import yaml
#endif
///Nop is a tool that has no effect
final class Nop: Tool {
func run(args: [Yaml : Yaml]) throws {
......
......@@ -6,6 +6,10 @@
// propagated, or distributed except according to the terms contained
// in the LICENSE file.
#if ATBUILD
import yaml
#endif
import Foundation
///The Shell tool runs a shell script. It expects a zero return code.
......
......@@ -6,6 +6,10 @@
// propagated, or distributed except according to the terms contained
// in the LICENSE file.
#if ATBUILD
import yaml
#endif
///A Task is a CLI entry point to `atbuild`. If you call `atbuild` with no arguments, we run a task called "default".
final class Task {
let tool: String ///The tool that implements this task. See Tools.swift
......
......@@ -5,6 +5,9 @@
// No part of atbuild, including this file, may be copied, modified,
// propagated, or distributed except according to the terms contained
// in the LICENSE file.
#if ATBUILD
import yaml
#endif
///A tool is a function that performs some operation, like building, or running a shell command.
///We provide several builtin tools, but users can build new ones out of the existing ones.
......
......@@ -8,6 +8,10 @@
import Foundation
#if ATBUILD
import yaml
#endif
/**The ATllbuild tool builds a swift module via llbuild.
For more information on this tool, see `docs/attllbuild.md` */
final class ATllbuild : Tool {
......@@ -45,8 +49,8 @@ final class ATllbuild : Tool {
- parameter sources: A resolved list of swift sources
- parameter workdir: A temporary working directory for `atllbuild` to use
- parameter modulename: The name of the module to be built.
- returns: The string contents for llbuild.yaml suitable for processing by swift-build-tool */
func llbuildyaml(sources: [String], workdir: String, modulename: String, linkSDK: Bool, compileOptions: [String], outputType: OutputType) -> String {
- returns: The string contents for llbuild.yaml suitable for processing by swift-build-tool, along with a list of products */
func llbuildyaml(sources: [String], workdir: String, modulename: String, linkSDK: Bool, compileOptions: [String], outputType: OutputType, linkWithProduct:[String]) -> (yaml: String, products: [String]) {
//this format is largely undocumented, but I reverse-engineered it from SwiftPM.
var yaml = "client:\n name: swift-build\n\n"
......@@ -68,7 +72,7 @@ final class ATllbuild : Tool {
//swiftPM wants "objects" which is just a list of %.swift.o files. We have to put them in a temp directory though.
let objects = sources.map { (source) -> String in
workdir + (source as NSString).lastPathComponent + ".o"
workdir + "objects/" + (source as NSString).lastPathComponent + ".o"
}
yaml += " objects: \(objects)\n"
//this crazy syntax is how llbuild specifies outputs
......@@ -88,7 +92,7 @@ final class ATllbuild : Tool {
yaml += " temps-path: \(workdir)/llbuildtmp\n"
var args : [String] = []
args.appendContentsOf(["-j8"])
args.appendContentsOf(["-j8", "-D","ATBUILD","-I",workdir+"products/"])
if linkSDK {
args.appendContentsOf(["-sdk", SDKPath])
......@@ -105,14 +109,19 @@ final class ATllbuild : Tool {
//this crazy syntax is how sbt declares a dependency
var llbuild_inputs = ["<atllbuild-swiftc>"]
llbuild_inputs.appendContentsOf(objects)
let builtProducts = linkWithProduct.map {workdir+"products/"+$0}
llbuild_inputs.appendContentsOf(builtProducts)
yaml += " inputs: \(llbuild_inputs)\n"
yaml += " outputs: [\"<atllbuild>\", \"\(workdir + modulename)\"]\n"
//and now we have the crazy 'args'
args = [SwiftCPath, "-o",workdir + modulename]
args.appendContentsOf(objects)
args.appendContentsOf(builtProducts)
yaml += " args: \(args)\n"
yaml += " description: Linking executable \(modulename)\n"
return (yaml: yaml, products: [workdir + modulename])
case .StaticLibrary:
yaml += " tool: shell\n"
......@@ -130,22 +139,30 @@ final class ATllbuild : Tool {
let args = "[\"/bin/sh\",\"-c\",\(shellCmd)]"
yaml += " args: \(args)\n"
yaml += " description: \"Linking Library: \(libPath)\""
return (yaml: yaml, products: [libPath, "\(workdir + modulename).swiftmodule"])
}
return yaml
}
func run(args: [Yaml : Yaml]) throws {
//create the working directory
let workDirectory = ".atllbuild/"
let manager = NSFileManager.defaultManager()
if manager.fileExistsAtPath(workDirectory) {
try manager.removeItemAtPath(workDirectory)
}
try manager.createDirectoryAtPath(workDirectory, withIntermediateDirectories: false, attributes: nil)
try? manager.removeItemAtPath(workDirectory + "/objects")
try? manager.removeItemAtPath(workDirectory + "/llbuildtmp")
try? manager.createDirectoryAtPath(workDirectory, withIntermediateDirectories: false, attributes: nil)
try? manager.createDirectoryAtPath(workDirectory + "/products", withIntermediateDirectories: false, attributes: nil)
try manager.createDirectoryAtPath(workDirectory + "/objects", withIntermediateDirectories: false, attributes: nil)
//parse arguments
var linkWithProduct: [String] = []
if let arr = args["linkWithProduct"]?.array {
for product in arr {
guard let p = product.string else { throw AnarchyBuildError.CantParseYaml("non-string product \(product)") }
linkWithProduct.append(p)
}
}
let outputType: OutputType
if args["outputType"]?.string == "static-library" {
outputType = .StaticLibrary
......@@ -193,7 +210,8 @@ final class ATllbuild : Tool {
llbuildyamlpath = workDirectory + "llbuild.yaml"
}
try llbuildyaml(sources, workdir: workDirectory, modulename: name, linkSDK: sdk, compileOptions: compileOptions, outputType: outputType).writeToFile(llbuildyamlpath, atomically: false, encoding: NSUTF8StringEncoding)
let (yaml, products) = llbuildyaml(sources, workdir: workDirectory, modulename: name, linkSDK: sdk, compileOptions: compileOptions, outputType: outputType, linkWithProduct: linkWithProduct)
try yaml.writeToFile(llbuildyamlpath, atomically: false, encoding: NSUTF8StringEncoding)
if bootstrapOnly { return }
//now we try running sbt
......@@ -203,5 +221,12 @@ final class ATllbuild : Tool {
if sbt.terminationStatus != 0 {
throw AnarchyBuildError.ExternalToolFailed("\(SwiftBuildToolpath) " + args.joinWithSeparator(" "))
}
//move the output to our build products
for product in products {
let productName = (product as NSString).lastPathComponent
try? manager.removeItemAtPath(workDirectory + "products/\(productName)")
try manager.moveItemAtPath(product, toPath: workDirectory + "products/\(productName)")
}
}
}
\ No newline at end of file
......@@ -7,6 +7,9 @@
// in the LICENSE file.
///Load the contents of atbuild.yaml
#if ATBUILD
import yaml
#endif
func loadyaml() throws -> [Yaml:Yaml] {
guard let yamlContents = try? String(contentsOfFile: "atbuild.yaml") else { throw AnarchyBuildError.CantParseYaml("Can't load atbuild.yaml") }
let yaml = Yaml.load(yamlContents)
......
......@@ -10,6 +10,11 @@ let version = "0.2.0-dev"
import Foundation
#if ATBUILD
import yaml
#endif
//usage message
if Process.arguments.count > 1 && Process.arguments[1] == "--help" {
print("atbuild - Anarchy Tools Build Tool \(version)")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment