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 @@ ...@@ -12,9 +12,15 @@
// 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.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
let version = "0.9.0" let version = "0.9.0"
import Foundation import atfoundation
import atpkg import atpkg
import attools import attools
...@@ -40,7 +46,7 @@ enum Options: String { ...@@ -40,7 +46,7 @@ enum Options: String {
} }
} }
let defaultPackageFile = "build.atpkg" let defaultPackageFile = Path(string: "build.atpkg")
var focusOnTask : String? = nil var focusOnTask : String? = nil
...@@ -48,7 +54,7 @@ var packageFile = defaultPackageFile ...@@ -48,7 +54,7 @@ var packageFile = defaultPackageFile
var toolchain = Platform.buildPlatform.defaultToolchainPath var toolchain = Platform.buildPlatform.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 = Path(string: Process.arguments[i+1])
} }
if x == Options.Toolchain.rawValue { if x == Options.Toolchain.rawValue {
toolchain = Process.arguments[i+1] toolchain = Process.arguments[i+1]
......
Subproject commit 4ca50369f4da65e629ca3adf7441bd30d7bab6e5 Subproject commit 9a6d4437013e7577b998c096bbbb2b8eb28b1a6c
...@@ -24,7 +24,7 @@ final class CustomTool: Tool { ...@@ -24,7 +24,7 @@ final class CustomTool: Tool {
} }
cmd += "--\(key) \"\(evaluateSubstitutions(input: value, package: task.package))\" " cmd += "--\(key) \"\(evaluateSubstitutions(input: value, package: task.package))\" "
} }
setenv("ATBUILD_USER_PATH", userPath(), 1) setenv("ATBUILD_USER_PATH", userPath().description, 1)
anarchySystem(cmd) 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 @@ ...@@ -12,8 +12,15 @@
// 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.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
import atfoundation
import atpkg import atpkg
import Foundation
private enum ModuleMapType: String { private enum ModuleMapType: String {
case Synthesized = "synthesized" case Synthesized = "synthesized"
} }
...@@ -55,41 +62,40 @@ class PackageFramework: Tool { ...@@ -55,41 +62,40 @@ class PackageFramework: Tool {
} }
//rm framework if it exists //rm framework if it exists
let frameworkPath = "bin/\(name).framework" let frameworkPath = Path(string: "bin/\(name).framework")
let manager = NSFileManager.defaultManager() let _ = try? FS.removeItem(path: frameworkPath)
let _ = try? manager.removeItem(atPath: frameworkPath) try! FS.createDirectory(path: frameworkPath)
try! manager.createDirectory(atPath: frameworkPath, withIntermediateDirectories: false, attributes: nil)
//'a' version //'a' version
let AVersionPath = "\(frameworkPath)/Versions/A" let relativeAVersionPath = Path(string: "Versions/A")
let relativeAVersionPath = "Versions/A" let AVersionPath = frameworkPath.join(path: relativeAVersionPath)
try! manager.createDirectory(atPath: AVersionPath, withIntermediateDirectories: true, attributes: nil) try! FS.createDirectory(path: AVersionPath, intermediate: true)
//'current' (produces code signing failures if absent) //'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 //copy payload
let payloadPath = task.importedPath + "bin/" + name + Platform.targetPlatform.dynamicLibraryExtension let payloadPath = task.importedPath.appending("bin").appending(name + Platform.targetPlatform.dynamicLibraryExtension)
print(payloadPath) print(payloadPath)
try! manager.copyItemAtPath_SWIFTBUG(srcPath: payloadPath, toPath: "\(AVersionPath)/\(name)") try! FS.copyItem(from: payloadPath, to: AVersionPath.appending(name))
try! manager.createSymbolicLink(atPath: "\(frameworkPath)/\(name)", withDestinationPath: "\(relativeAVersionPath)/\(name)") try! FS.symlinkItem(from: frameworkPath.appending(name), to: relativeAVersionPath.appending(name))
//copy modules //copy modules
let modulePath = "\(AVersionPath)/Modules/\(name).swiftmodule" let modulePath = AVersionPath.appending("Modules").appending(name + ".swiftmodule")
try! manager.createDirectory(atPath: modulePath, withIntermediateDirectories: true, attributes: nil) try! FS.createDirectory(path: modulePath, intermediate: true)
try! manager.copyItemAtPath_SWIFTBUG(srcPath: "bin/\(name).swiftmodule", toPath: "\(modulePath)/\(Platform.targetPlatform.architecture).swiftmodule") try! FS.copyItem(from: Path(string: "bin/\(name).swiftmodule"), to: modulePath.appending(Platform.targetPlatform.architecture + ".swiftmodule"))
try! manager.copyItemAtPath_SWIFTBUG(srcPath: "bin/\(name).swiftdoc", toPath: "\(modulePath)/\(Platform.targetPlatform.architecture).swiftdoc") try! FS.copyItem(from: Path(string: "bin/\(name).swiftdoc"), to: modulePath.appending(Platform.targetPlatform.architecture + ".swiftdoc"))
try! manager.createSymbolicLink(atPath: "\(frameworkPath)/Modules", withDestinationPath: "\(relativeAVersionPath)/Modules") try! FS.symlinkItem(from: frameworkPath.appending("Modules"), to: relativeAVersionPath.appending("Modules"))
//copy resources //copy resources
let resourcesPath = AVersionPath + "/Resources" let resourcesPath = AVersionPath.appending("Resources")
try! manager.createDirectory(atPath: resourcesPath, withIntermediateDirectories: true, attributes: nil) try! FS.createDirectory(path: resourcesPath, intermediate: true)
for resource in resources { 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 //codesign
let cmd = "codesign --force --deep --sign - --timestamp=none \(AVersionPath)" let cmd = "codesign --force --deep --sign - --timestamp=none '\(AVersionPath)'"
print(cmd) print(cmd)
if system(cmd) != 0 { if system(cmd) != 0 {
fatalError("Codesign failed.") fatalError("Codesign failed.")
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
// 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.
import Foundation import atfoundation
public enum Platform { public enum Platform {
case OSX case OSX
...@@ -103,29 +103,28 @@ public enum Platform { ...@@ -103,29 +103,28 @@ public enum Platform {
public static var buildPlatform: Platform = Platform.hostPlatform 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 { if Platform.buildPlatform == Platform.hostPlatform {
//poke around on the filesystem //poke around on the filesystem
//look in /usr/bin //look in /usr/bin
let manager = NSFileManager.defaultManager() let usrBin = Path(string: "\(toolchain)/usr/bin/\(toolName)")
let usrBin = "\(toolchain)/usr/bin/\(toolName)" if FS.fileExists(path: usrBin) { return usrBin }
if manager.fileExists(atPath: usrBin) { return usrBin }
//look in /usr/local/bin //look in /usr/local/bin
let usrLocalBin = "\(toolchain)/usr/local/bin/\(toolName)" let usrLocalBin = Path(string: "\(toolchain)/usr/local/bin/\(toolName)")
if manager.fileExists(atPath: usrLocalBin) { return usrLocalBin } if FS.fileExists(path: usrLocalBin) { return usrLocalBin }
//swift-build-tool isn't available in 2.2. //swift-build-tool isn't available in 2.2.
//If we're looking for SBT, try in the default location //If we're looking for SBT, try in the default location
if toolName == "swift-build-tool" { if toolName == "swift-build-tool" {
let sbtPath = "\(Platform.hostPlatform.defaultToolchainPath)/usr/bin/\(toolName)" let sbtPath = Path(string: "\(Platform.hostPlatform.defaultToolchainPath)/usr/bin/\(toolName)")
if manager.fileExists(atPath: sbtPath) { return sbtPath } if FS.fileExists(path: sbtPath) { return sbtPath }
} }
} }
else { else {
//file system isn't live; hope the path is in a typical place //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)") fatalError("Can't find a path for \(toolName)")
......
...@@ -12,8 +12,13 @@ ...@@ -12,8 +12,13 @@
// 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.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
import Foundation import atfoundation
import atpkg import atpkg
/** /**
...@@ -23,16 +28,26 @@ import atpkg ...@@ -23,16 +28,26 @@ import atpkg
*/ */
final class Shell : Tool { final class Shell : Tool {
func run(task: Task, toolchain: String) { 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.") } guard var script = task["script"]?.string else { fatalError("Invalid 'script' argument to shell tool.") }
script = evaluateSubstitutions(input: script, package: task.package) script = evaluateSubstitutions(input: script, package: task.package)
do { do {
let oldPath = NSFileManager.defaultManager().currentDirectoryPath let oldPath = try FS.getWorkingDirectory()
defer { NSFileManager.defaultManager().changeCurrentDirectoryPath(oldPath) } 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)\"") 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 @@ ...@@ -12,8 +12,14 @@
// 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.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
import atfoundation
import atpkg import atpkg
import Foundation
/** The builtin tools. */ /** The builtin tools. */
let tools: [String:Tool] = [ let tools: [String:Tool] = [
...@@ -48,12 +54,11 @@ private var userPathCreated = false ...@@ -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. /**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. - postcondition: The path exists at this absolute locaton on disk.
- warning: This path is cleared between atbuild invocations. */ - warning: This path is cleared between atbuild invocations. */
func userPath() -> String { func userPath() -> Path {
let manager = NSFileManager.defaultManager() let userPath = try! FS.getWorkingDirectory().appending("user")
let userPath = manager.currentDirectoryPath + "/user"
if !userPathCreated { if !userPathCreated {
let _ = try? manager.removeItem(atPath: userPath) let _ = try? FS.removeItem(path: userPath, recursive: true)
try! manager.createDirectory(atPath: userPath, withIntermediateDirectories: false, attributes: nil) try! FS.createDirectory(path: userPath)
userPathCreated = true userPathCreated = true
} }
return userPath return userPath
......
...@@ -11,8 +11,9 @@ ...@@ -11,8 +11,9 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// 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.
import atfoundation
import atpkg import atpkg
import Foundation
class XCTestRun : Tool { class XCTestRun : Tool {
enum Option: String { enum Option: String {
...@@ -25,14 +26,11 @@ class XCTestRun : Tool { ...@@ -25,14 +26,11 @@ class XCTestRun : Tool {
} }
switch (Platform.targetPlatform) { switch (Platform.targetPlatform) {
case .OSX: case .OSX:
var workingDirectory = "/tmp/XXXXXXXXXXX" let workingDirectory = try! FS.temporaryDirectory(prefix: "XCTest-\(task)")
var template = workingDirectory.cString(using: NSUTF8StringEncoding)!
workingDirectory = String(cString: mkdtemp(&template), encoding: NSUTF8StringEncoding)!
let manager = NSFileManager.defaultManager() let executablePath = workingDirectory.join(path: Path(string: "XCTestRun.xctest/Contents/MacOS"))
let executablePath = workingDirectory + "/XCTestRun.xctest/Contents/MacOS" try! FS.createDirectory(path: executablePath, intermediate: true)
try! manager.createDirectory(atPath: executablePath, withIntermediateDirectories: true, attributes: nil) try! FS.copyItem(from: Path(string: testExecutable), to: executablePath.appending("XCTestRun"))
try! manager.copyItemAtPath_SWIFTBUG(srcPath: testExecutable, toPath: executablePath + "/XCTestRun")
var s = "" var s = ""
s += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 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" 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 { ...@@ -62,7 +60,7 @@ class XCTestRun : Tool {
s += "<string>1</string>\n" s += "<string>1</string>\n"
s += "</dict>\n" s += "</dict>\n"
s += "</plist>\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") anarchySystem("xcrun xctest \(workingDirectory)/XCTestRun.xctest")
case .Linux: case .Linux:
......
This diff is collapsed.
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
:sources ["atbuild/src/**.swift"] :sources ["atbuild/src/**.swift"]
:name "atbuild" :name "atbuild"
:output-type "executable" :output-type "executable"
:link-with ["attools.a" "atpkg.a"] :link-with ["attools.a" "atpkg.a" "atfoundation.a"]
:dependencies ["attools" "atpkg.atpkg"] :dependencies ["attools" "atpkg.atpkg" "atfoundation.atfoundation"]
:publish-product true :publish-product true
:overlays { :overlays {
......
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