Commit 8f7175e3 authored by Drew's avatar Drew

Merge pull request #76 from AnarchyTools/toolchainz

Toolchain support
parents c4b99869 9c18c685
Pipeline #1490 passed with stage
...@@ -71,6 +71,16 @@ How do we build a Swift project? There's a built-in tool called `atllbuild`, wh ...@@ -71,6 +71,16 @@ How do we build a Swift project? There's a built-in tool called `atllbuild`, wh
That's all you need to get started! `atbuild` supports many more usecases than can fit in a README. For more information, browse our [documentation](http://anarchytools.org). That's all you need to get started! `atbuild` supports many more usecases than can fit in a README. For more information, browse our [documentation](http://anarchytools.org).
# Options
`atbuild` supports several command-line options:
* `--use-overlay [overlay]`, which you can read more about in our [overlays](overlays.html) documentation.
* `-f [atpkg-file]` which builds a package file other than `build.atpkg`
* `--help`, which displays a usage message
* `--clean`, which forces a clean build
* `--toolchain` which specifies a nonstandard toolchain (swift installation). By default we try to guess, but you can override our guess here. The special string `xcode` uses "xcode swift" for building. (Swift 2.2 does not contain all the tools we use, so you need to have a 3.x snapshot installed as well. However, this is a "mostly" xcode-flavored buildchain.)
# Building # Building
We publish [binary releases](https://github.com/AnarchyTools/atbuild/releases), which are the easiest way to get started. We publish [binary releases](https://github.com/AnarchyTools/atbuild/releases), which are the easiest way to get started.
...@@ -99,3 +109,6 @@ To declare your project to be compatible with Anarchy Tools, simply ...@@ -99,3 +109,6 @@ To declare your project to be compatible with Anarchy Tools, simply
```markdown ```markdown
[![Anarchy Tools compatible](https://img.shields.io/badge/Anarchy%20Tools-compatible-4BC51D.svg?style=flat)](http://anarchytools.org) [![Anarchy Tools compatible](https://img.shields.io/badge/Anarchy%20Tools-compatible-4BC51D.svg?style=flat)](http://anarchytools.org)
``` ```
*Maintainer note: if you edit this file, edit the one in [this repo](https://github.com/AnarchyTools/anarchytools.github.io) as well.*
\ No newline at end of file
...@@ -26,8 +26,9 @@ enum Options: String { ...@@ -26,8 +26,9 @@ enum Options: String {
case CustomFile = "-f" case CustomFile = "-f"
case Help = "--help" case Help = "--help"
case Clean = "--clean" case Clean = "--clean"
case Toolchain = "--toolchain"
static var allOptions : [Options] { return [Overlay, CustomFile] } static var allOptions : [Options] { return [Overlay, CustomFile, Help, Clean, Toolchain] }
} }
let defaultPackageFile = "build.atpkg" let defaultPackageFile = "build.atpkg"
...@@ -43,10 +44,17 @@ for (i, x) in Process.arguments.enumerated() { ...@@ -43,10 +44,17 @@ for (i, x) in Process.arguments.enumerated() {
} }
} }
var packageFile = defaultPackageFile var packageFile = defaultPackageFile
var toolchain = DefaultToolchainPath
for (i, x) in Process.arguments.enumerated() { for (i, x) in Process.arguments.enumerated() {
if x == Options.CustomFile.rawValue { if x == Options.CustomFile.rawValue {
packageFile = Process.arguments[i+1] packageFile = Process.arguments[i+1]
} }
if x == Options.Toolchain.rawValue {
toolchain = Process.arguments[i+1]
if toolchain == "xcode" {
toolchain = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain"
}
}
} }
let package = try! Package(filepath: packageFile, overlay: overlays, focusOnTask: focusOnTask) let package = try! Package(filepath: packageFile, overlay: overlays, focusOnTask: focusOnTask)
...@@ -57,7 +65,7 @@ if Process.arguments.contains("--help") { ...@@ -57,7 +65,7 @@ if Process.arguments.contains("--help") {
print("© 2016 Anarchy Tools Contributors.") print("© 2016 Anarchy Tools Contributors.")
print("") print("")
print("Usage:") print("Usage:")
print("atbuild [-f packagefile] [task] [--clean]") print("atbuild [--toolchain (/toolchain/path | xcode)] [-f packagefile] [task] [--clean]")
print("tasks:") print("tasks:")
for (key, task) in package.tasks { for (key, task) in package.tasks {
...@@ -66,10 +74,11 @@ if Process.arguments.contains("--help") { ...@@ -66,10 +74,11 @@ if Process.arguments.contains("--help") {
exit(1) exit(1)
} }
func runTask(taskName: String, package: Package) { func runTask(taskName: String, package: Package) {
guard let task = package.tasks[taskName] else { fatalError("No \(taskName) task in build configuration.") } guard let task = package.tasks[taskName] else { fatalError("No \(taskName) task in build configuration.") }
for task in package.prunedDependencyGraph(task) { for task in package.prunedDependencyGraph(task) {
TaskRunner.runTask(task, package: package) TaskRunner.runTask(task, package: package, toolchain: toolchain)
} }
} }
......
...@@ -19,5 +19,5 @@ import atpkg ...@@ -19,5 +19,5 @@ import atpkg
* dependencies together. * dependencies together.
*/ */
final class Nop: Tool { final class Nop: Tool {
func run(task: Task) {} func run(task: Task, toolchain: String) {}
} }
...@@ -31,7 +31,7 @@ class PackageFramework: Tool { ...@@ -31,7 +31,7 @@ class PackageFramework: Tool {
fatalError("packageframework is unsupported on this platform") fatalError("packageframework is unsupported on this platform")
#endif #endif
} }
func run(task: Task) { func run(task: Task, toolchain: String) {
compiler_crash() //work around a compiler crash compiler_crash() //work around a compiler crash
guard let moduleMapType = task[Options.ModuleMapType.rawValue]?.string else { guard let moduleMapType = task[Options.ModuleMapType.rawValue]?.string else {
......
...@@ -14,16 +14,35 @@ ...@@ -14,16 +14,35 @@
import Foundation import Foundation
//todo, support multiple toolchains func findToolPath(toolName: String, toolchain: String) -> String {
//look in /usr/bin
let manager = NSFileManager.defaultManager()
let usrBin = "\(toolchain)/usr/bin/\(toolName)"
if manager.fileExists(atPath: usrBin) { return usrBin }
//look in /usr/local/bin
let usrLocalBin = "\(toolchain)/usr/local/bin/\(toolName)"
if manager.fileExists(atPath: usrLocalBin) { return usrLocalBin }
//swift-build-tool isn't available in 2.2.
//If we're looking for SBT, try in the default location
if toolName == "swift-build-tool" {
let sbtPath = "\(DefaultToolchainPath)/usr/bin/\(toolName)"
if manager.fileExists(atPath: sbtPath) { return sbtPath }
}
fatalError("Can't find a path for \(toolName)")
}
#if os(OSX) #if os(OSX)
let SDKPath = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk" let SDKPath = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk"
let SwiftCPath = "/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swiftc" public let DefaultToolchainPath = "/Library/Developer/Toolchains/swift-latest.xctoolchain"
let SwiftBuildToolpath = "/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swift-build-tool"
let DynamicLibraryExtension = ".dylib" let DynamicLibraryExtension = ".dylib"
let Architecture = "x86_64" let Architecture = "x86_64"
#elseif os(Linux) #elseif os(Linux)
let SwiftCPath = "/usr/local/bin/swiftc" let SwiftCPath = "/usr/local/bin/swiftc"
let SwiftBuildToolpath = "/usr/local/bin/swift-build-tool" public let DefaultToolchainPath = "/"
let DynamicLibraryExtension = ".so" let DynamicLibraryExtension = ".so"
let Architecture = "x86_64" let Architecture = "x86_64"
#endif #endif
\ No newline at end of file
...@@ -22,7 +22,7 @@ import atpkg ...@@ -22,7 +22,7 @@ import atpkg
* If the tool returns with an error code of non-zero, the tool will fail. * If the tool returns with an error code of non-zero, the tool will fail.
*/ */
final class Shell : Tool { final class Shell : Tool {
func run(task: Task) { func run(task: Task, toolchain: String) {
setenv("ATBUILD_USER_PATH", userPath(), 1) setenv("ATBUILD_USER_PATH", userPath(), 1)
guard var script = task["script"]?.string else { fatalError("Invalid 'script' argument to shell tool.") } guard var script = task["script"]?.string else { fatalError("Invalid 'script' argument to shell tool.") }
script = evaluateSubstitutions(script, package: task.package) script = evaluateSubstitutions(script, package: task.package)
......
...@@ -22,10 +22,10 @@ import atpkg ...@@ -22,10 +22,10 @@ import atpkg
final public class TaskRunner { final public class TaskRunner {
private init() {} private init() {}
static public func runTask(task: Task, package: Package) { static public func runTask(task: Task, package: Package, toolchain: String) {
print("Running task \(task.qualifiedName) with overlays \(task.appliedOverlays)") print("Running task \(task.qualifiedName) with overlays \(task.appliedOverlays)")
let tool = toolByName(task.tool) let tool = toolByName(task.tool)
tool.run(task) tool.run(task, toolchain: toolchain)
print("Completed task \(task.qualifiedName).") print("Completed task \(task.qualifiedName).")
} }
} }
\ No newline at end of file
...@@ -30,7 +30,7 @@ let tools: [String:Tool] = [ ...@@ -30,7 +30,7 @@ let tools: [String:Tool] = [
* can build new ones out of the existing ones. * can build new ones out of the existing ones.
*/ */
public protocol Tool { public protocol Tool {
func run(task: Task) func run(task: Task, toolchain: String)
} }
/** /**
......
...@@ -19,7 +19,7 @@ class XCTestRun : Tool { ...@@ -19,7 +19,7 @@ class XCTestRun : Tool {
case TestExecutable = "test-executable" case TestExecutable = "test-executable"
} }
func run(task: Task) { func run(task: Task, toolchain: String) {
guard let testExecutable = task[Option.TestExecutable.rawValue]?.string else { guard let testExecutable = task[Option.TestExecutable.rawValue]?.string else {
fatalError("No \(Option.TestExecutable.rawValue) for XCTestRun task \(task.qualifiedName)") fatalError("No \(Option.TestExecutable.rawValue) for XCTestRun task \(task.qualifiedName)")
} }
......
...@@ -234,11 +234,11 @@ final class ATllbuild : Tool { ...@@ -234,11 +234,11 @@ final class ATllbuild : Tool {
} }
} }
func run(task: Task) { func run(task: Task, toolchain: String) {
run(task, wmoHack: false) run(task, toolchain: toolchain, wmoHack: false)
} }
func run(task: Task, wmoHack : Bool = false) { func run(task: Task, toolchain: String, wmoHack : Bool = false) {
//warn if we don't understand an option //warn if we don't understand an option
var knownOptions = Options.allOptions.map({$0.rawValue}) var knownOptions = Options.allOptions.map({$0.rawValue})
...@@ -428,7 +428,7 @@ final class ATllbuild : Tool { ...@@ -428,7 +428,7 @@ final class ATllbuild : Tool {
swiftCPath = c swiftCPath = c
} }
else { else {
swiftCPath = SwiftCPath swiftCPath = findToolPath("swiftc",toolchain: toolchain)
} }
let yaml = llbuildyaml(sources, workdir: workDirectory, modulename: name, linkSDK: sdk, compileOptions: compileOptions, linkOptions: linkOptions, outputType: outputType, linkWithProduct: linkWithProduct, swiftCPath: swiftCPath) let yaml = llbuildyaml(sources, workdir: workDirectory, modulename: name, linkSDK: sdk, compileOptions: compileOptions, linkOptions: linkOptions, outputType: outputType, linkWithProduct: linkWithProduct, swiftCPath: swiftCPath)
...@@ -444,7 +444,7 @@ final class ATllbuild : Tool { ...@@ -444,7 +444,7 @@ final class ATllbuild : Tool {
} }
//SR-566 //SR-566
let cmd = "\(SwiftBuildToolpath) -f \(llbuildyamlpath)" let cmd = "\(findToolPath("swift-build-tool",toolchain: toolchain)) -f \(llbuildyamlpath)"
if system(cmd) != 0 { if system(cmd) != 0 {
fatalError(cmd) fatalError(cmd)
} }
...@@ -472,7 +472,7 @@ final class ATllbuild : Tool { ...@@ -472,7 +472,7 @@ final class ATllbuild : Tool {
if task[Options.WholeModuleOptimization.rawValue]?.bool == true && !wmoHack { if task[Options.WholeModuleOptimization.rawValue]?.bool == true && !wmoHack {
print("Work around SR-881") print("Work around SR-881")
run(task, wmoHack: true) run(task, toolchain: toolchain, wmoHack: true)
} }
} }
......
(package
:name "xcode_toolchain"
:tasks {
:default {
:tool "atllbuild"
:sources ["test.swift"]
:name "hello"
:output-type "executable"
:publish-product true
}
}
)
//this is an error on Swift 3
//but "xcode" currently ships swift 2.2
//so if we compile successfully, we used Xcode compiler.
enum E : ErrorType { }
\ No newline at end of file
...@@ -10,6 +10,15 @@ pwd ...@@ -10,6 +10,15 @@ pwd
echo "****************SELF-HOSTING TEST**************" echo "****************SELF-HOSTING TEST**************"
$ATBUILD atbuild $ATBUILD atbuild
echo "****************XCODE TOOLCHAIN TEST**************"
if [ -e "/Applications/Xcode.app" ]; then
cd $DIR/tests/fixtures/xcode_toolchain
$ATBUILD --toolchain xcode
else
echo "Xcode is not installed; skipping test"
fi
echo "****************PACKAGE FRAMEWORK TESTS**************" echo "****************PACKAGE FRAMEWORK TESTS**************"
UNAME=`uname` UNAME=`uname`
if [ "$UNAME" == "Darwin" ]; then if [ "$UNAME" == "Darwin" ]; then
......
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