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:
......
This diff is collapsed.
......@@ -24,8 +24,8 @@
:sources ["atbuild/src/**.swift"]
:name "atbuild"
:output-type "executable"
:link-with ["attools.a" "atpkg.a"]
:dependencies ["attools" "atpkg.atpkg"]
:link-with ["attools.a" "atpkg.a" "atfoundation.a"]
:dependencies ["attools" "atpkg.atpkg" "atfoundation.atfoundation"]
:publish-product true
: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