Commit 0476fc3c authored by David Owens II's avatar David Owens II

Significant refactoring to support the new atpkg format.

The bootstrap scripts were also updated to build the entire product properly into libs; no more compiler flags.
Project structure simplified to at* for each of our targets.
The YAML parser completely removed.
parent 67cdcee2
Pipeline #681 passed with stage
bin/ bin/
*xcuserdata*
.atllbuild/ .atllbuild/
atbuild .built/
build.db
*xcuserdata*
.DS_Store
\ No newline at end of file
...@@ -5,7 +5,7 @@ osx: ...@@ -5,7 +5,7 @@ osx:
stage: build stage: build
script: script:
- export PATH=/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin:"${PATH}" - export PATH=/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin:"${PATH}"
- ./bootstrap.sh - ./bootstrap/build.sh
tags: tags:
- openswift - openswift
artifacts: artifacts:
......
;; Copyright (c) 2016 Anarchy Tools Contributors.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
;; You may obtain a copy of the License at
;;
;; http:;;www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.
;; The build file for all of the targets of the Anarchy Tools build tool.
(package
:name "atbuild"
:tasks {:hellworld {:tool "shell"
:script "echo \"Hello world\"" }
:default {:dependencies ["yaml"]
:tool "atllbuild"
:source ["cli/src/**.swift"]
:name "atbuild"
:outputType "executable"
:linkWithProduct: ["yaml.a"]}
:bootstrap-osx {:dependencies ["bootstrap-yaml-osx"]
:tool "atllbuild"
:source ["cli/src/**.swift"]
:name "atbuild"
:bootstrapOnly true
:llbuildyaml: "llbuild-osx.yaml"
:outputType "executable"
:linkWithProduct ["yaml.a"]}
:bootstrap-linux {:dependencies ["bootstrap-yaml-linux"]
:tool "atllbuild"
:source ["cli/src/**.swift"]
:name "atbuild"
:bootstrapOnly true
:llbuildyaml: "llbuild-linux.yaml"
:linkSDK false
:compileOptions ["-D" "CORELIBS_FOUNDATION"]
:outputType "executable"
:linkWithProduct ["yaml.a"]}
:bootstrap {:dependencies ["bootstrap-osx", "bootstrap-linux"]
:tool "nop"}
:yaml {:tool "atllbuild"
:source ["parsers/yaml/**.swift"]
:name "yaml"
:outputType "static-library"}
:atpkg-model {:tool "atllbuild"
:source ["model/src/**.swift"]
:name "atpkgmodel"
:outputType "static-library"}
:atpkg-parser {:dependencies ["atpkg-model"]
:tool "atllbuild"
:source ["parsers/atpkg/src/**.swift"]
:name "atpkgparser"
:outputType "static-library"
:linkWithProduct ["atpkgmodel.a"]}
:atpkg-tests {:dependencies ["atpkg-parser", "atpkg-model"]
:tool "atllbuild"
:source ["parsers/atpkg/tests/**.swift"]
:name "atpkgtests"
:outputType "executable"
:linkWithProduct ["atpkparser.a", "atpkgmodel.a"]}
:run-atpkg-tests {:dependencies ["atpkg-tests"]
:tool "shell"
:script "./.atllbuild/products/atpkgtests"}
:run-tests {:dependencies ["run-atpkg-tests"]
:tool "nop" }
)
package:
name: "atbuild"
tasks:
helloworld:
tool: "shell"
script: "echo \"Hello world\""
default:
dependency: ["yaml"]
tool: "atllbuild"
source: ["cli/src/**.swift"]
name: "atbuild"
outputType: "executable"
linkWithProduct: ["yaml.a"]
bootstrap-yaml-osx:
tool: "atllbuild"
source: ["parsers/yaml/**.swift"]
name: "yaml"
llbuildyaml: "yaml-osx-llbuild.yaml"
outputType: "static-library"
bootstrapOnly: true
bootstrap-yaml-linux:
tool: "atllbuild"
source: ["parsers/yaml/**.swift"]
name: "yaml"
llbuildyaml: "yaml-linux-llbuild.yaml"
outputType: "static-library"
linkSDK: false
compileOptions: ["-D","CORELIBS_FOUNDATION"]
bootstrapOnly: true
bootstrap-osx:
tool: "atllbuild"
source: ["cli/src/**.swift"]
name: "atbuild"
bootstrapOnly: true
llbuildyaml: "llbuild-osx.yaml"
outputType: "executable"
linkWithProduct: ["yaml.a"]
dependency: ["bootstrap-yaml-osx"]
bootstrap-linux:
tool: "atllbuild"
source: ["cli/src/**.swift"]
name: "atbuild"
bootstrapOnly: true
llbuildyaml: "llbuild-linux.yaml"
linkSDK: false
compileOptions: ["-D","CORELIBS_FOUNDATION"]
outputType: "executable"
linkWithProduct: ["yaml.a"]
dependency: ["bootstrap-yaml-linux"]
bootstrap:
tool: "nop"
dependency: ["bootstrap-osx", "bootstrap-linux"]
yaml:
tool: "atllbuild"
source: ["parsers/yaml/**.swift"]
name: "yaml"
outputType: "static-library"
atpkg:
tool: "atllbuild"
source: ["atpkg/src/**.swift"]
name: "atpkg"
outputType: "static-library"
atpkg-tests:
dependency: ["atpkg"]
tool: "atllbuild"
source: ["atpkg/tests/**.swift"]
name: "atpkgtests"
outputType: "executable"
linkWithProduct: ["atpkg.a"]
run-atpkg-tests:
dependency: ["atpkg-tests"]
tool: "shell"
script: "./.atllbuild/products/atpkgtests"
run-tests:
tool: "nop"
dependency: ["run-atpkg-tests"]
// main.swift // Copyright (c) 2016 Anarchy Tools Contributors.
// © 2016 Anarchy Tools Contributors. //
// This file is part of atbuild. It is subject to the license terms in the LICENSE // Licensed under the Apache License, Version 2.0 (the "License");
// file found in the top level of this distribution // you may not use this file except in compliance with the License.
// No part of atbuild, including this file, may be copied, modified, // You may obtain a copy of the License at
// propagated, or distributed except according to the terms contained //
// in the LICENSE file. // http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
let version = "0.2.0-dev" let version = "0.2.0-dev"
import Foundation import Foundation
import atpkg
import attools
#if ATBUILD let defaultBuildFile = "build.atpkg"
import yaml
#endif
func loadPackageFile() -> Package {
guard let package = Package(filepath: defaultBuildFile) else {
print("Unable to load build file: \(defaultBuildFile)")
exit(1)
}
return package
}
//usage message //usage message
if Process.arguments.count > 1 && Process.arguments[1] == "--help" { if Process.arguments.count > 1 && Process.arguments[1] == "--help" {
...@@ -23,26 +37,22 @@ if Process.arguments.count > 1 && Process.arguments[1] == "--help" { ...@@ -23,26 +37,22 @@ if Process.arguments.count > 1 && Process.arguments[1] == "--help" {
print("") print("")
print("Usage:") print("Usage:")
print("atbuild [task]") print("atbuild [task]")
if let yaml = try? loadyaml() {
if let taskNames = yaml["tasks"]?.dictionary?.keys.map({$0.string!}) { let package = loadPackageFile()
print(" task: \(Array(taskNames)) ") print("tasks:")
} for (key, task) in package.tasks {
print(" \(key)")
} }
exit(1) exit(1)
} }
//load configuration let package = loadPackageFile()
let yaml = try! loadyaml() print("Building package \(package.name)...")
guard let package = yaml["package"]?.dictionary else { fatalError("No package in YAML") }
guard let name = package["name"]?.string else { fatalError("No package name") }
print("Building package \(name)...")
func runtask(taskName: String) { func runtask(taskName: String) {
guard let task = yaml["tasks"]?.dictionary else { fatalError("No tasks in YAML") } guard let task = package.tasks[taskName] else { fatalError("No \(taskName) task in build configuration.") }
guard let defaultTask = task[Yaml(stringLiteral: taskName)]?.dictionary else { fatalError("No \(taskName) task in YAML") } TaskRunner.runTask(task, package: package)
let t = try! Task(yaml: defaultTask, name: taskName, entireConfig: yaml)
try! t.run()
} }
//choose which task to run //choose which task to run
...@@ -54,4 +64,4 @@ else { ...@@ -54,4 +64,4 @@ else {
} }
//success message //success message
print("Built package \(name).") print("Built package \(package.name).")
\ No newline at end of file \ No newline at end of file
...@@ -12,117 +12,33 @@ ...@@ -12,117 +12,33 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
public enum OutputType { final public class Task {
case Executable public var key: String = ""
case StaticLibrary public var dependencies: [String] = []
case DynamicLibrary
}
public class FilePath {
public var path: String
public init(path: String) {
self.path = path
}
init?(value: ParseValue) {
guard let str = value.stringLiteral else { return nil }
self.path = str
}
}
public class Dependency {
public var name: String
public init(name: String) {
self.name = name
}
init?(value: ParseValue) {
guard let str = value.stringLiteral else { return nil }
self.name = str
}
}
public class Task {
// The required properties.
public var name: String
// The optional properties. All optional properties must have a default value.
public var dependencies: [Dependency] = []
public var tool: String = "atllbuild" public var tool: String = "atllbuild"
public var sources: [FilePath] = []
public var bootstrapOnly: Bool = false
public var llbuildyaml: String = ""
public var linkSDK: Bool = false
public var compilerOptions: [String] = []
public var outputType: OutputType = OutputType.StaticLibrary
public var linkWithProduct: [String] = []
public init(name: String) {
self.name = name
}
private var kvp: [String:ParseValue]
init?(value: ParseValue, name: String) { init?(value: ParseValue, name: String) {
guard let kvp = value.map else { return nil } guard let kvp = value.map else { return nil }
if let value = kvp["name"]?.stringLiteral { self.name = value }
else {
print("ERROR: Name is a required property on task.")
return nil
}
if let value = kvp["tool"]?.stringLiteral { self.tool = value } self.kvp = kvp
if let value = kvp["bootstrapOnly"]?.boolLiteral { self.bootstrapOnly = value } self.key = name
if let value = kvp["llbuildyaml"]?.stringLiteral { self.llbuildyaml = value } self.tool = kvp["tool"]?.string ?? self.tool
if let value = kvp["linkSDK"]?.boolLiteral { self.linkSDK = value }
if let value = kvp["outputType"]?.stringLiteral {
switch value {
case "lib": self.outputType = .StaticLibrary
case "static-library": self.outputType = .StaticLibrary
case "dylib": self.outputType = .DynamicLibrary
case "dynamic-library": self.outputType = .DynamicLibrary
case "exe": self.outputType = .Executable
case "executable": self.outputType = .Executable
default: print("ERROR: unsupported outputType: \(value), defaulting to: \(self.outputType)")
}
}
if let values = kvp["dependencies"]?.vector { if let values = kvp["dependencies"]?.vector {
for value in values { for value in values {
if let dep = Dependency(value: value) { self.dependencies.append(dep) } if let dep = value.string { self.dependencies.append(dep) }
}
}
if let values = kvp["sources"]?.vector {
for value in values {
if let filepath = FilePath(value: value) { self.sources.append(filepath) }
}
}
if let values = kvp["source"]?.vector {
for value in values {
if let filepath = FilePath(value: value) { self.sources.append(filepath) }
}
}
if let values = kvp["compilerOptions"]?.vector {
for value in values {
if let value = value.stringLiteral { self.compilerOptions.append(value) }
}
}
if let values = kvp["linkWithProduct"]?.vector {
for value in values {
if let value = value.stringLiteral { self.linkWithProduct.append(value) }
} }
} }
} }
public subscript(key: String) -> ParseValue? {
return kvp[key]
}
} }
public class Package { final public class Package {
// The required properties. // The required properties.
public var name: String public var name: String
...@@ -134,15 +50,28 @@ public class Package { ...@@ -134,15 +50,28 @@ public class Package {
self.name = name self.name = name
} }
public convenience init?(filepath: String) {
guard let parser = Parser(filepath: filepath) else { return nil }
do {
let result = try parser.parse()
self.init(type: result)
}
catch {
print("error: \(error)")
return nil
}
}
public init?(type: ParseType) { public init?(type: ParseType) {
if type.name != "package" { return nil } if type.name != "package" { return nil }
if let value = type.properties["name"]?.stringLiteral { self.name = value } if let value = type.properties["name"]?.string { self.name = value }
else { else {
print("ERROR: No name specified for the package.") print("ERROR: No name specified for the package.")
return nil return nil
} }
if let value = type.properties["version"]?.stringLiteral { self.version = value } if let value = type.properties["version"]?.string { self.version = value }
if let parsedTasks = type.properties["tasks"]?.map { if let parsedTasks = type.properties["tasks"]?.map {
for (key, value) in parsedTasks { for (key, value) in parsedTasks {
......
...@@ -31,22 +31,22 @@ public enum ParseValue { ...@@ -31,22 +31,22 @@ public enum ParseValue {
} }
extension ParseValue { extension ParseValue {
public var stringLiteral: String? { public var string: String? {
if case let .StringLiteral(value) = self { return value } if case let .StringLiteral(value) = self { return value }
return nil return nil
} }
public var integerLiteral: Int? { public var integer: Int? {
if case let .IntegerLiteral(value) = self { return value } if case let .IntegerLiteral(value) = self { return value }
return nil return nil
} }
public var floatLiteral: Double? { public var float: Double? {
if case let .FloatLiteral(value) = self { return value } if case let .FloatLiteral(value) = self { return value }
return nil return nil
} }
public var boolLiteral: Bool? { public var bool: Bool? {
if case let .BoolLiteral(value) = self { return value } if case let .BoolLiteral(value) = self { return value }
return nil return nil
} }
...@@ -63,12 +63,12 @@ extension ParseValue { ...@@ -63,12 +63,12 @@ extension ParseValue {
} }
public class ParseType { final public class ParseType {
public var name: String = "" public var name: String = ""
public var properties: [String:ParseValue] = [:] public var properties: [String:ParseValue] = [:]
} }
public class Parser { final public class Parser {
let lexer: Lexer let lexer: Lexer
private func next() -> Token? { private func next() -> Token? {
......
...@@ -18,7 +18,7 @@ public struct ScannerInfo { ...@@ -18,7 +18,7 @@ public struct ScannerInfo {
public let column: Int public let column: Int
} }
public class Scanner { final public class Scanner {
var content: String var content: String
var index: String.Index var index: String.Index
......
...@@ -75,8 +75,7 @@ func isWhitespace(c: Character?) -> Bool { ...@@ -75,8 +75,7 @@ func isWhitespace(c: Character?) -> Bool {
return isCharacterPartOfSet(c, set: NSCharacterSet.whitespaceCharacterSet()) return isCharacterPartOfSet(c, set: NSCharacterSet.whitespaceCharacterSet())
} }
public class Lexer { final public class Lexer {
var scanner: Scanner var scanner: Scanner
var current: Token? = nil var current: Token? = nil
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:tasks {:build {:tool "lldb-build" :tasks {:build {:tool "lldb-build"
:name "json-swift" :name "json-swift"
:output-type "lib" :output-type "lib"
:source [ "src/**.swift" ]}} :source [ "src/**.swift" "lib/**.swift" ]}}
) )
; End of the sample. ; End of the sample.
\ No newline at end of file
...@@ -41,23 +41,11 @@ class PackageTests: Test { ...@@ -41,23 +41,11 @@ class PackageTests: Test {
for (key, task) in package.tasks { for (key, task) in package.tasks {
try test.assert(key == "build") try test.assert(key == "build")
try test.assert(task.tool == "lldb-build") try test.assert(task.tool == "lldb-build")
try test.assert(task.name == "json-swift") try test.assert(task["name"]?.string == "json-swift")
try test.assert(task.outputType == .StaticLibrary) try test.assert(task["output-type"]?.string == "lib")
try test.assert(task.sources.count == 1) try test.assert(task["source"]?.vector?.count == 2)
try test.assert(task.sources[0].path == "src/**.swift") try test.assert(task["source"]?.vector?[0].string == "src/**.swift")
try test.assert(task["source"]?.vector?[1].string == "lib/**.swift")
} }
// (package
// :name "basic"
// :version "0.1.0-dev"
// :tasks {:build {:tool "lldb-build"
// :name "json-swift"
// :output-type "lib"
// :source [ "src/**.swift" ]}}
// )
// ; End of the sample.
} }
} }
This diff is collapsed.
...@@ -34,11 +34,11 @@ class ParserTests: Test { ...@@ -34,11 +34,11 @@ class ParserTests: Test {
let name = result.properties["name"] let name = result.properties["name"]
try test.assert(name != nil) try test.assert(name != nil)
try test.assert(name?.stringLiteral == "basic") try test.assert(name?.string == "basic")
let version = result.properties["version"] let version = result.properties["version"]
try test.assert(version != nil) try test.assert(version != nil)
try test.assert(version?.stringLiteral == "0.1.0-dev") try test.assert(version?.string == "0.1.0-dev")
let tasks = result.properties["tasks"] let tasks = result.properties["tasks"]
try test.assert(tasks != nil) try test.assert(tasks != nil)
...@@ -48,19 +48,20 @@ class ParserTests: Test { ...@@ -48,19 +48,20 @@ class ParserTests: Test {
let tool = build?.map?["tool"] let tool = build?.map?["tool"]
try test.assert(tool != nil) try test.assert(tool != nil)
try test.assert(tool?.stringLiteral == "lldb-build") try test.assert(tool?.string == "lldb-build")
let buildName = build?.map?["name"] let buildName = build?.map?["name"]
try test.assert(buildName != nil) try test.assert(buildName != nil)
try test.assert(buildName?.stringLiteral == "json-swift") try test.assert(buildName?.string == "json-swift")
let outputType = build?.map?["output-type"] let outputType = build?.map?["output-type"]
try test.assert(outputType != nil) try test.assert(outputType != nil)
try test.assert(outputType?.stringLiteral == "lib") try test.assert(outputType?.string == "lib")
let source = build?.map?["source"] let source = build?.map?["source"]
try test.assert(source != nil) try test.assert(source != nil)
try test.assert(source?.vector != nil) try test.assert(source?.vector != nil)
try test.assert(source?.vector?[0].stringLiteral == "src/**.swift") try test.assert(source?.vector?[0].string == "src/**.swift")
try test.assert(source?.vector?[1].string == "lib/**.swift")
} }
} }
\ No newline at end of file
...@@ -299,6 +299,21 @@ class ScannerTests: Test { ...@@ -299,6 +299,21 @@ class ScannerTests: Test {
try test.assert(scanner.next()?.character == "t") try test.assert(scanner.next()?.character == "t")
try test.assert(scanner.next()?.character == "\"") try test.assert(scanner.next()?.character == "\"")
try test.assert(scanner.next()?.character == " ") try test.assert(scanner.next()?.character == " ")
try test.assert(scanner.next()?.character == "\"")
try test.assert(scanner.next()?.character == "l")
try test.assert(scanner.next()?.character == "i")
try test.assert(scanner.next()?.character == "b")
try test.assert(scanner.next()?.character == "/")
try test.assert(scanner.next()?.character == "*")
try test.assert(scanner.next()?.character == "*")
try test.assert(scanner.next()?.character == ".")
try test.assert(scanner.next()?.character == "s")
try test.assert(scanner.next()?.character == "w")
try test.assert(scanner.next()?.character == "i")
try test.assert(scanner.next()?.character == "f")
try test.assert(scanner.next()?.character == "t")
try test.assert(scanner.next()?.character == "\"")
try test.assert(scanner.next()?.character == " ")
try test.assert(scanner.next()?.character == "]") try test.assert(scanner.next()?.character == "]")
try test.assert(scanner.next()?.character == "}") try test.assert(scanner.next()?.character == "}")
try test.assert(scanner.next()?.character == "}") try test.assert(scanner.next()?.character == "}")
......
// Copyright (c) 2016 Anarchy Tools Contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at