Commit 72168af5 authored by Johannes Schriewer's avatar Johannes Schriewer

Convert to atfoundation (WIP, tests failing)

parent ce4c27c4
Pipeline #1652 failed with stage
{
"folders":
[
{
"path": ".",
"folder_exclude_patterns": [ ".atllbuild", "bin", "user" ],
"file_exclude_patterns": [ ".gitignore", ".gitlab-ci.yml", "Dockerfile", "LICENSE" ]
},
]
}
// 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.
......@@ -12,9 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
let version = "0.9.0"
import Foundation
import atfoundation
import atpkg
import attools
......@@ -40,7 +46,7 @@ enum Options: String {
}
}
let defaultPackageFile = "build.atpkg"
let defaultPackageFile = Path(string: "build.atpkg")
var focusOnTask : String? = nil
......@@ -48,7 +54,7 @@ var packageFile = defaultPackageFile
var toolchain = Platform.buildPlatform.defaultToolchainPath
for (i, x) in Process.arguments.enumerated() {
if x == Options.CustomFile.rawValue {
packageFile = Process.arguments[i+1]
packageFile = Path(string: Process.arguments[i+1])
}
if x == Options.Toolchain.rawValue {
toolchain = Process.arguments[i+1]
......
Subproject commit 4ca50369f4da65e629ca3adf7441bd30d7bab6e5
Subproject commit 9a6d4437013e7577b998c096bbbb2b8eb28b1a6c
......@@ -24,7 +24,7 @@ final class CustomTool: Tool {
}
cmd += "--\(key) \"\(evaluateSubstitutions(input: value, package: task.package))\" "
}
setenv("ATBUILD_USER_PATH", userPath(), 1)
setenv("ATBUILD_USER_PATH", userPath().description, 1)
anarchySystem(cmd)
}
}
\ No newline at end of file
// 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.
import Foundation
//SR-138
extension String {
var toNSString: NSString {
#if os(Linux)
return self.bridge()
#elseif os(OSX)
return (self as NSString)
#endif
}
}
extension NSString {
var toString: String {
#if os(Linux)
return self.bridge()
#elseif os(OSX)
return (self as String)
#endif
}
}
// MARK: NSFileManager.copyItemAtPath
// https://github.com/apple/swift-corelibs-foundation/pull/248
enum CopyError: ErrorProtocol {
case CantOpenSourceFile(Int32)
case CantOpenDestFile(Int32)
case CantReadSourceFile(Int32)
case CantWriteDestFile(Int32)
}
extension NSFileManager {
func copyItemAtPath_SWIFTBUG(srcPath: String, toPath dstPath: String) throws {
let fd_from = open(srcPath, O_RDONLY)
if fd_from < 0 {
throw CopyError.CantOpenSourceFile(errno)
}
defer { precondition(close(fd_from) >= 0) }
let permission_ = (try! attributesOfItem(atPath: srcPath)[NSFilePosixPermissions] as! NSNumber)
#if os(OSX) || os(iOS)
let permission = permission_.uint16Value
#elseif os(Linux)
let permission = permission_.unsignedIntValue
#endif
let fd_to = open(dstPath, O_WRONLY | O_CREAT | O_EXCL, permission)
if fd_to < 0 {
throw CopyError.CantOpenDestFile(errno)
}
defer { precondition(close(fd_to) >= 0) }
var buf = [UInt8](repeating: 0, count: 4096)
while true {
let nread = read(fd_from, &buf, buf.count)
if nread < 0 { throw CopyError.CantReadSourceFile(errno) }
if nread == 0 { break }
var writeSlice = buf[0..<nread]
while true {
var nwritten: Int! = nil
writeSlice.withUnsafeBufferPointer({ (ptr) -> () in
nwritten = write(fd_to, ptr.baseAddress, ptr.count)
})
if nwritten < 0 {
throw CopyError.CantWriteDestFile(errno)
}
writeSlice = writeSlice[writeSlice.startIndex.advanced(by: nwritten)..<writeSlice.endIndex]
if writeSlice.count == 0 { break }
}
}
}
}
//These parts of Swift 3 Renaming are not yet implemented on Linux
#if os(Linux)
extension NSFileManager {
func enumerator(atPath path: String) -> NSDirectoryEnumerator? {
return self.enumeratorAtPath(path)
}
func createSymbolicLink(atPath path: String, withDestinationPath destPath: String) throws {
return try self.createSymbolicLinkAtPath(path, withDestinationPath: destPath)
}
func createDirectory(atPath path: String, withIntermediateDirectories createIntermediates: Bool, attributes: [String : AnyObject]? = [:]) throws {
return try self.createDirectoryAtPath(path, withIntermediateDirectories: createIntermediates, attributes: attributes)
}
func attributesOfItem(atPath path: String) throws -> [String : Any] {
return try self.attributesOfItemAtPath(path)
}
func removeItem(atPath path: String) throws {
return try self.removeItemAtPath(path)
}
func fileExists(atPath path: String) -> Bool {
return self.fileExistsAtPath(path)
}
}
extension String {
func componentsSeparated(by separator: String) -> [String] {
return self.componentsSeparatedByString(separator)
}
func write(toFile path: String, atomically useAuxiliaryFile:Bool, encoding enc: NSStringEncoding) throws {
return try self.writeToFile(path, atomically: useAuxiliaryFile, encoding: enc)
}
func replacingOccurrences(of str: String, with: String) -> String {
return self.stringByReplacingOccurrencesOfString(str, withString: with)
}
func cString(usingEncoding encoding: NSStringEncoding) -> [CChar]? {
return self.cStringUsingEncoding(encoding)
}
init?(cString: UnsafePointer<CChar>, encoding: NSStringEncoding) {
precondition(encoding == NSUTF8StringEncoding)
self.init(validatingUTF8: cString)
}
func cString(using: NSStringEncoding) -> [CChar]? {
return self.cString(usingEncoding: using)
}
}
#endif
//These parts are possibly? not yet implemented on OSX
#if os(OSX)
extension String {
func componentsSeparated(by string: String) -> [String] {
return self.components(separatedBy: string)
}
}
#endif
\ No newline at end of file
......@@ -12,8 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
import atfoundation
import atpkg
import Foundation
private enum ModuleMapType: String {
case Synthesized = "synthesized"
}
......@@ -55,41 +62,40 @@ class PackageFramework: Tool {
}
//rm framework if it exists
let frameworkPath = "bin/\(name).framework"
let manager = NSFileManager.defaultManager()
let _ = try? manager.removeItem(atPath: frameworkPath)
try! manager.createDirectory(atPath: frameworkPath, withIntermediateDirectories: false, attributes: nil)
let frameworkPath = Path(string: "bin/\(name).framework")
let _ = try? FS.removeItem(path: frameworkPath)
try! FS.createDirectory(path: frameworkPath)
//'a' version
let AVersionPath = "\(frameworkPath)/Versions/A"
let relativeAVersionPath = "Versions/A"
try! manager.createDirectory(atPath: AVersionPath, withIntermediateDirectories: true, attributes: nil)
let relativeAVersionPath = Path(string: "Versions/A")
let AVersionPath = frameworkPath.join(path: relativeAVersionPath)
try! FS.createDirectory(path: AVersionPath, intermediate: true)
//'current' (produces code signing failures if absent)
try! manager.createSymbolicLink(atPath: "\(frameworkPath)/Versions/Current", withDestinationPath: "A")
try! FS.symlinkItem(from: frameworkPath.join(path: Path(string: "Versions/Current")), to: Path(string: "A"))
//copy payload
let payloadPath = task.importedPath + "bin/" + name + Platform.targetPlatform.dynamicLibraryExtension
let payloadPath = task.importedPath.appending("bin").appending(name + Platform.targetPlatform.dynamicLibraryExtension)
print(payloadPath)
try! manager.copyItemAtPath_SWIFTBUG(srcPath: payloadPath, toPath: "\(AVersionPath)/\(name)")
try! manager.createSymbolicLink(atPath: "\(frameworkPath)/\(name)", withDestinationPath: "\(relativeAVersionPath)/\(name)")
try! FS.copyItem(from: payloadPath, to: AVersionPath.appending(name))
try! FS.symlinkItem(from: frameworkPath.appending(name), to: relativeAVersionPath.appending(name))
//copy modules
let modulePath = "\(AVersionPath)/Modules/\(name).swiftmodule"
try! manager.createDirectory(atPath: modulePath, withIntermediateDirectories: true, attributes: nil)
try! manager.copyItemAtPath_SWIFTBUG(srcPath: "bin/\(name).swiftmodule", toPath: "\(modulePath)/\(Platform.targetPlatform.architecture).swiftmodule")
try! manager.copyItemAtPath_SWIFTBUG(srcPath: "bin/\(name).swiftdoc", toPath: "\(modulePath)/\(Platform.targetPlatform.architecture).swiftdoc")
try! manager.createSymbolicLink(atPath: "\(frameworkPath)/Modules", withDestinationPath: "\(relativeAVersionPath)/Modules")
let modulePath = AVersionPath.appending("Modules").appending(name + ".swiftmodule")
try! FS.createDirectory(path: modulePath, intermediate: true)
try! FS.copyItem(from: Path(string: "bin/\(name).swiftmodule"), to: modulePath.appending(Platform.targetPlatform.architecture + ".swiftmodule"))
try! FS.copyItem(from: Path(string: "bin/\(name).swiftdoc"), to: modulePath.appending(Platform.targetPlatform.architecture + ".swiftdoc"))
try! FS.symlinkItem(from: frameworkPath.appending("Modules"), to: relativeAVersionPath.appending("Modules"))
//copy resources
let resourcesPath = AVersionPath + "/Resources"
try! manager.createDirectory(atPath: resourcesPath, withIntermediateDirectories: true, attributes: nil)
let resourcesPath = AVersionPath.appending("Resources")
try! FS.createDirectory(path: resourcesPath, intermediate: true)
for resource in resources {
try! manager.copyItemAtPath_SWIFTBUG(srcPath: task.importedPath + resource, toPath: "\(resourcesPath)/\(resource)")
try! FS.copyItem(from: task.importedPath.join(path: Path(string: resource)), to: resourcesPath.join(path: Path(string: resource)))
}
try! manager.createSymbolicLink(atPath: "\(frameworkPath)/Resources", withDestinationPath: "\(relativeAVersionPath)/Resources")
try! FS.symlinkItem(from: frameworkPath.appending("Resources"), to: relativeAVersionPath.appending("Resources"))
//codesign
let cmd = "codesign --force --deep --sign - --timestamp=none \(AVersionPath)"
let cmd = "codesign --force --deep --sign - --timestamp=none '\(AVersionPath)'"
print(cmd)
if system(cmd) != 0 {
fatalError("Codesign failed.")
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import Foundation
import atfoundation
public enum Platform {
case OSX
......@@ -103,29 +103,28 @@ public enum Platform {
public static var buildPlatform: Platform = Platform.hostPlatform
}
func findToolPath(toolName: String, toolchain: String) -> String {
func findToolPath(toolName: String, toolchain: String) -> Path {
if Platform.buildPlatform == Platform.hostPlatform {
//poke around on the filesystem
//look in /usr/bin
let manager = NSFileManager.defaultManager()
let usrBin = "\(toolchain)/usr/bin/\(toolName)"
if manager.fileExists(atPath: usrBin) { return usrBin }
let usrBin = Path(string: "\(toolchain)/usr/bin/\(toolName)")
if FS.fileExists(path: usrBin) { return usrBin }
//look in /usr/local/bin
let usrLocalBin = "\(toolchain)/usr/local/bin/\(toolName)"
if manager.fileExists(atPath: usrLocalBin) { return usrLocalBin }
let usrLocalBin = Path(string: "\(toolchain)/usr/local/bin/\(toolName)")
if FS.fileExists(path: 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 = "\(Platform.hostPlatform.defaultToolchainPath)/usr/bin/\(toolName)"
if manager.fileExists(atPath: sbtPath) { return sbtPath }
let sbtPath = Path(string: "\(Platform.hostPlatform.defaultToolchainPath)/usr/bin/\(toolName)")
if FS.fileExists(path: sbtPath) { return sbtPath }
}
}
else {
//file system isn't live; hope the path is in a typical place
return "\(Platform.buildPlatform.defaultToolchainBinaryPath)\(toolName)"
return Path(string: "\(Platform.buildPlatform.defaultToolchainBinaryPath)\(toolName)")
}
fatalError("Can't find a path for \(toolName)")
......
......@@ -12,8 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
import Foundation
import atfoundation
import atpkg
/**
......@@ -23,16 +28,26 @@ import atpkg
*/
final class Shell : Tool {
func run(task: Task, toolchain: String) {
setenv("ATBUILD_USER_PATH", userPath(), 1)
setenv("ATBUILD_USER_PATH", userPath().description, 1)
guard var script = task["script"]?.string else { fatalError("Invalid 'script' argument to shell tool.") }
script = evaluateSubstitutions(input: script, package: task.package)
do {
let oldPath = NSFileManager.defaultManager().currentDirectoryPath
defer { NSFileManager.defaultManager().changeCurrentDirectoryPath(oldPath) }
let oldPath = try FS.getWorkingDirectory()
defer {
do {
try FS.changeWorkingDirectory(path: oldPath)
} catch {
print("Can not revert to previous working directory '\(oldPath)': \(error)")
exit(42)
}
}
NSFileManager.defaultManager().changeCurrentDirectoryPath(task.importedPath)
try FS.changeWorkingDirectory(path: task.importedPath)
anarchySystem("/bin/sh -c \"\(script)\"")
} catch {
print("Can not change working directory to '\(task.importedPath)': \(error)")
exit(42)
}
}
}
\ No newline at end of file
......@@ -12,8 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
import atfoundation
import atpkg
import Foundation
/** The builtin tools. */
let tools: [String:Tool] = [
......@@ -48,12 +54,11 @@ private var userPathCreated = false
/**Returns the "user" path. This is a path that the user may use to store artifacts or for any other purposes. This path is shared for all tasks built as part of the same `atbuild` invocation.
- postcondition: The path exists at this absolute locaton on disk.
- warning: This path is cleared between atbuild invocations. */
func userPath() -> String {
let manager = NSFileManager.defaultManager()
let userPath = manager.currentDirectoryPath + "/user"
func userPath() -> Path {
let userPath = try! FS.getWorkingDirectory().appending("user")
if !userPathCreated {
let _ = try? manager.removeItem(atPath: userPath)
try! manager.createDirectory(atPath: userPath, withIntermediateDirectories: false, attributes: nil)
let _ = try? FS.removeItem(path: userPath, recursive: true)
try! FS.createDirectory(path: userPath)
userPathCreated = true
}
return userPath
......
......@@ -11,8 +11,9 @@
// 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.
import atfoundation
import atpkg
import Foundation
class XCTestRun : Tool {
enum Option: String {
......@@ -25,14 +26,11 @@ class XCTestRun : Tool {
}
switch (Platform.targetPlatform) {
case .OSX:
var workingDirectory = "/tmp/XXXXXXXXXXX"
var template = workingDirectory.cString(using: NSUTF8StringEncoding)!
workingDirectory = String(cString: mkdtemp(&template), encoding: NSUTF8StringEncoding)!
let workingDirectory = try! FS.temporaryDirectory(prefix: "XCTest-\(task)")
let manager = NSFileManager.defaultManager()
let executablePath = workingDirectory + "/XCTestRun.xctest/Contents/MacOS"
try! manager.createDirectory(atPath: executablePath, withIntermediateDirectories: true, attributes: nil)
try! manager.copyItemAtPath_SWIFTBUG(srcPath: testExecutable, toPath: executablePath + "/XCTestRun")
let executablePath = workingDirectory.join(path: Path(string: "XCTestRun.xctest/Contents/MacOS"))
try! FS.createDirectory(path: executablePath, intermediate: true)
try! FS.copyItem(from: Path(string: testExecutable), to: executablePath.appending("XCTestRun"))
var s = ""
s += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
s += "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
......@@ -62,7 +60,7 @@ class XCTestRun : Tool {
s += "<string>1</string>\n"
s += "</dict>\n"
s += "</plist>\n"
try! s.write(toFile: workingDirectory + "/XCTestRun.xctest/Contents/Info.plist", atomically: false, encoding: NSUTF8StringEncoding)
try! s.write(to: workingDirectory.join(path: Path(string: "XCTestRun.xctest/Contents/Info.plist")))
anarchySystem("xcrun xctest \(workingDirectory)/XCTestRun.xctest")
case .Linux:
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import Foundation
import atfoundation
import atpkg
/**Synthesize a module map.
......@@ -72,8 +72,8 @@ final class ATllbuild : Tool {
* - 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], linkOptions: [String], outputType: OutputType, linkWithProduct:[String], swiftCPath: String) -> String {
let productPath = workdir + "products/"
func llbuildyaml(sources: [Path], workdir: Path, modulename: String, linkSDK: Bool, compileOptions: [String], linkOptions: [String], outputType: OutputType, linkWithProduct:[String], swiftCPath: Path) -> String {
let productPath = workdir.appending("products")
//this format is largely undocumented, but I reverse-engineered it from SwiftPM.
var yaml = "client:\n name: swift-build\n\n"
......@@ -95,7 +95,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 + "objects/" + source.toNSString.lastPathComponent + ".o"
workdir.appending("objects").appending(source.basename() + ".o").description
}
yaml += " objects: \(objects)\n"
//this crazy syntax is how llbuild specifies outputs
......@@ -111,19 +111,19 @@ final class ATllbuild : Tool {
}
yaml += " module-name: \(modulename)\n"
let swiftModulePath = "\(productPath + modulename).swiftmodule"
let swiftModulePath = productPath.appending(modulename + ".swiftmodule")
yaml += " module-output-path: \(swiftModulePath)\n"
yaml += " temps-path: \(workdir)/llbuildtmp\n"
var args : [String] = []
args.append(contentsOf: ["-j8", "-D","ATBUILD","-I",workdir+"products/"])
args += ["-j8", "-D", "ATBUILD", "-I", workdir.appending("products").description + "/"]
if linkSDK {
if let sdkPath = Platform.targetPlatform.sdkPath {
args.append(contentsOf: ["-sdk",sdkPath])
args += ["-sdk", sdkPath]
}
}
args.append(contentsOf: compileOptions)
args += compileOptions
yaml += " other-args: \(args)\n"
......@@ -134,17 +134,17 @@ final class ATllbuild : Tool {
yaml += " tool: shell\n"
//this crazy syntax is how sbt declares a dependency
var llbuild_inputs = ["<atllbuild-swiftc>"]
llbuild_inputs.append(contentsOf: objects)
let builtProducts = linkWithProduct.map {workdir+"products/"+$0}
llbuild_inputs.append(contentsOf: builtProducts)
let executablePath = productPath+modulename
llbuild_inputs += objects
let builtProducts = linkWithProduct.map { workdir.join(path: Path(string: "products/"+$0)).description }
llbuild_inputs += builtProducts
let executablePath = productPath.appending(modulename)
yaml += " inputs: \(llbuild_inputs)\n"
yaml += " outputs: [\"<atllbuild>\", \"\(executablePath)\"]\n"
//and now we have the crazy 'args'
args = [swiftCPath, "-o",executablePath]
args.append(contentsOf: objects)
args.append(contentsOf: builtProducts)
args.append(contentsOf: linkOptions)
args = [swiftCPath.description, "-o", executablePath.description]
args += objects
args += builtProducts
args += linkOptions
yaml += " args: \(args)\n"
yaml += " description: Linking executable \(executablePath)\n"
return yaml
......@@ -155,7 +155,7 @@ final class ATllbuild : Tool {
var llbuild_inputs = ["<atllbuild-swiftc>"]
llbuild_inputs.append(contentsOf: objects)
yaml += " inputs: \(llbuild_inputs)\n"
let libPath = productPath + modulename + ".a"
let libPath = productPath.appending(modulename + ".a")
yaml += " outputs: [\"<atllbuild>\", \"\(libPath)\"]\n"
//build the crazy args, mostly consisting of an `ar` shell command
......@@ -171,16 +171,16 @@ final class ATllbuild : Tool {
case .DynamicLibrary:
yaml += " tool: shell\n"
var llbuild_inputs = ["<atllbuild-swiftc>"]
llbuild_inputs.append(contentsOf: objects)
let builtProducts = linkWithProduct.map {workdir+"products/"+$0}
llbuild_inputs.append(contentsOf: builtProducts)
llbuild_inputs += objects
let builtProducts = linkWithProduct.map { workdir.join(path: Path(string: "products/"+$0)).description }
llbuild_inputs += builtProducts
yaml += " inputs: \(llbuild_inputs)\n"
let libPath = productPath + modulename + Platform.targetPlatform.dynamicLibraryExtension
let libPath = productPath.appending(modulename + Platform.targetPlatform.dynamicLibraryExtension)
yaml += " outputs: [\"<atllbuild>\", \"\(libPath)\"]\n"
var args = [swiftCPath, "-o", libPath, "-emit-library"]
args.append(contentsOf: objects)
args.append(contentsOf: builtProducts)
args.append(contentsOf: linkOptions)
var args = [swiftCPath.description, "-o", libPath.description, "-emit-library"]
args += objects
args += builtProducts
args += linkOptions
yaml += " args: \(args)\n"
yaml += " description: \"Linking Library: \(libPath)\""
return yaml
......@@ -252,25 +252,24 @@ final class ATllbuild : Tool {
}
//create the working directory
let workDirectory = ".atllbuild/"
let manager = NSFileManager.defaultManager()
let workDirectory = Path(string: ".atllbuild")
//NSFileManager is pretty anal about throwing errors if we try to remove something that doesn't exist, etc.
//We just want to create a state where .atllbuild/objects and .atllbuild/llbuildtmp and .atllbuild/products exists.
//and in particular, without erasing the product directory, since that accumulates build products across
//multiple invocations of atllbuild.
if Process.arguments.contains("--clean") {
let _ = try? manager.removeItem(atPath: workDirectory + "/objects")
let _ = try? manager.removeItem(atPath: workDirectory + "/llbuildtmp")
let _ = try? FS.removeItem(path: workDirectory.appending("objects"))
let _ = try? FS.removeItem(path: workDirectory.appending("llbuildtmp"))
}
let _ = try? manager.removeItem(atPath: workDirectory + "/include")
let _ = try? FS.removeItem(path: workDirectory.appending("include"))
let _ = try? manager.createDirectory(atPath: workDirectory, withIntermediateDirectories: false, attributes: nil)
let _ = try? manager.createDirectory(atPath: workDirectory + "/products", withIntermediateDirectories: false, attributes: nil)
let _ = try? manager.createDirectory(atPath: workDirectory + "/objects", withIntermediateDirectories: false, attributes: nil)
let _ = try? manager.createDirectory(atPath: workDirectory + "/include", withIntermediateDirectories: false, attributes: nil)
let _ = try? FS.createDirectory(path: workDirectory)
let _ = try? FS.createDirectory(path: workDirectory.appending("products"))
let _ = try? FS.createDirectory(path: workDirectory.appending("objects"))
let _ = try? FS.createDirectory(path: workDirectory.appending("include"))
//parse arguments
var linkWithProduct: [String] = []
......@@ -317,7 +316,7 @@ final class ATllbuild : Tool {
for path_s in includePaths {
guard let path = path_s.string else { fatalError("Non-string path \(path_s)") }
compileOptions.append("-I")
compileOptions.append(userPath() + "/" + path)
compileOptions.append(userPath().join(path: Path(string: path)).description)
}
}
var linkOptions: [String] = []
......@@ -330,17 +329,17 @@ final class ATllbuild : Tool {
//check for modulemaps
for product in linkWithProduct {
let productName = product.componentsSeparated(by: ".")[0]
let moduleMapPath = workDirectory + "/products/\(productName).modulemap"
if manager.fileExists(atPath: moduleMapPath) {
let productName = product.split(character: ".")[0]
let moduleMapPath = workDirectory.join(path: Path(string: "products/\(productName).modulemap"))
if FS.fileExists(path: moduleMapPath) {
/*per http://clang.llvm.org/docs/Modules.html#command-line-parameters, pretty much
the only way to do this is to create a file called `module.modulemap`. That
potentially conflicts with other modulemaps, so we give it its own directory, namespaced
by the product name. */
let pathName = workDirectory + "/include/\(productName)"
try! manager.createDirectory(atPath: pathName, withIntermediateDirectories:false, attributes: nil)
try! manager.copyItemAtPath_SWIFTBUG(srcPath: moduleMapPath, toPath: pathName + "/module.modulemap")
compileOptions.append(contentsOf: ["-I",pathName])
let pathName = workDirectory.join(path: Path(string: "include/\(productName)"))
try! FS.createDirectory(path: pathName)
try! FS.copyItem(from: moduleMapPath, to: pathName.appending("module.modulemap"))
compileOptions.append(contentsOf: ["-I", pathName.description])
}
}
......@@ -364,13 +363,9 @@ final class ATllbuild : Tool {
switch Platform.targetPlatform {
case .OSX:
//inject XCTestCaseProvider.swift
var xcTestCaseProviderPath = "/tmp/XXXXXXX"
var template = xcTestCaseProviderPath.cString(using: NSUTF8StringEncoding)!
xcTestCaseProviderPath = String(cString: mkdtemp(&template), encoding: NSUTF8StringEncoding)!
xcTestCaseProviderPath += "/XCTestCaseProvider.swift"
let xcTestCaseProviderPath = try! FS.temporaryDirectory(prefix: "XCTestCase")
try! ATllbuild.xcTestCaseProvider.write(toFile: xcTestCaseProviderPath, atomically: false, encoding: NSUTF8StringEncoding)
try! ATllbuild.xcTestCaseProvider.write(to: xcTestCaseProviderPath.appending("XCTestCaseProvider.swift"))
sources.append(xcTestCaseProviderPath)
case .Linux:
......@@ -400,10 +395,10 @@ final class ATllbuild : Tool {
if let umbrellaHeader = task[Options.UmbrellaHeader.rawValue]?.string {
precondition(moduleMap == .Synthesized, ":\(Options.ModuleMap.rawValue) \"synthesized\" must be used with the \(Options.UmbrellaHeader.rawValue) option")
let s = synthesizeModuleMap(name: name, umbrellaHeader: "Umbrella.h")
try! s.write(toFile: workDirectory