Migrate to Swift5 & Change APIs.

This commit is contained in:
YOCKOW 2019-04-14 11:08:03 +09:00
parent 2db7d4147c
commit 8923a2458c
10 changed files with 244 additions and 508 deletions

View File

@ -1,20 +1,28 @@
matrix:
include:
- os: linux
dist: trusty
sudo: required
language: ruby
before_install:
- export SWIFT_ARCHIVE_URL="https://swift.org/builds/swift-4.0-release/ubuntu1404/swift-4.0-RELEASE/swift-4.0-RELEASE-ubuntu14.04.tar.gz"
- curl ${SWIFT_ARCHIVE_URL} -o ../swift.tar.gz
- mkdir ../swift
- tar xzf ../swift.tar.gz -C ../swift --strip-components 1
- export PATH="$(pwd)/../swift/usr/bin:${PATH}"
- os: osx
osx_image: xcode9
sudo: required
language: objective-c
branches:
except:
- /^\d+\.\d+\.\d+(-\S*)?$/
os:
- linux
- osx
language: generic
sudo: required
osx_image: xcode10.2
dist: xenial
env:
- SWIFT_BUILD_OPTION="-Xswiftc -swift-version -Xswiftc 4"
- SWIFT_BUILD_OPTION="-Xswiftc -swift-version -Xswiftc 4.2"
- SWIFT_BUILD_OPTION="-Xswiftc -swift-version -Xswiftc 5"
before_install:
- |
if [ $(uname) = "Linux" ]; then
export SWIFT_ARCHIVE_URL="https://swift.org/builds/swift-5.0-release/ubuntu1604/swift-5.0-RELEASE/swift-5.0-RELEASE-ubuntu16.04.tar.gz"
curl ${SWIFT_ARCHIVE_URL} -o ../swift.tar.gz
mkdir ../swift
tar xzf ../swift.tar.gz -C ../swift --strip-components 2
export PATH="$(dirname $(pwd))/swift/bin:$PATH"
fi
script:
- swift build
- swift test
- swift build ${SWIFT_BUILD_OPTION}
- swift build --configuration release ${SWIFT_BUILD_OPTION}
- swift test ${SWIFT_BUILD_OPTION}

View File

@ -1,15 +1,23 @@
// swift-tools-version:4.0
// swift-tools-version:5.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "TimeSpecification",
products: [.library(name: "SwiftTimeSpecification", type:.dynamic, targets: ["TimeSpecification"])],
dependencies: [],
targets: [
.target(name: "TimeSpecification", dependencies: [], path:".", sources:["Sources"]),
.testTarget(name: "TimeSpecificationTests", dependencies: ["TimeSpecification"])
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(name: "SwiftTimeSpecification", type: .dynamic, targets: ["TimeSpecification"]),
],
swiftLanguageVersions:[3, 4]
dependencies: [
// Dependencies declare other packages that this package depends on.
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(name: "TimeSpecification", dependencies: []),
.testTarget(name: "TimeSpecificationTests", dependencies: ["TimeSpecification"]),
],
swiftLanguageVersions: [.v4, .v4_2, .v5]
)

View File

@ -1,8 +0,0 @@
// swift-tools-version:3.1
import PackageDescription
let package = Package(
name: "TimeSpecification",
swiftLanguageVersions:[3]
)

View File

@ -1,42 +1,29 @@
# What is SwiftTimeSpecification?
SwiftTimeSpecification is an implementation of `struct timespec` (`struct mach_timespec` on OS X) in Swift Programming Language.
SwiftTimeSpecification is an implementation of `struct timespec` (`struct mach_timespec` on OS X) in Swift.
Its prototype is [YOCKOW's Gist](https://gist.github.com/YOCKOW/12d9607cb30f40b79fb2).
[![Build Status](https://travis-ci.org/YOCKOW/SwiftTimeSpecification.svg?branch=master)](https://travis-ci.org/YOCKOW/SwiftTimeSpecification)
## Class, Structure, Enumeration
```
public struct TimeSpecification {
public var seconds:Int64 = 0
public var nanoseconds:Int32 = 0
/* ... */
}
public enum Clock {
case calendar
case system
public var timeSpecification: TimeSpecification? {
/* ... */
}
}
```
# How to use
Build and install:
`./build-install.rb --install-prefix=/path/to/your/system --install`
Then, you can use it in your project:
`swiftc ./your/project/main.swift -I/path/to/your/system/include -L/path/to/your/system/lib -lSwiftTimeSpecification`
# Sample Code
## Sample Code
```
import TimeSpecification
func time(_ body:() -> Void) {
guard let start = Clock.system.timeSpecification else { return }
let start = TimeSpecification(clock:.stystem)
body()
guard let end = Clock.system.timeSpecification else { return }
let end = TimeSpecification(clock:.stystem)
let duration = end - start
print("\(duration)")
}
```
# Requirements
- Swift 5 (including compatibility mode for 4, 4.2)
- macOS or Linux
# License
MIT License.
See "LICENSE.txt" for more information.

View File

@ -1,131 +0,0 @@
/***************************************************************************************************
TimeSpecification.swift
© 2016-2017 YOCKOW.
Licensed under MIT License.
See "LICENSE.txt" for more information.
**************************************************************************************************/
#if os(Linux)
import Glibc
private typealias CTimeSpec = timespec
#elseif os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
private let mach_task_self:() -> mach_port_t = { return mach_task_self_ }
private typealias CTimeSpec = mach_timespec_t
#else
// UNKNOWN OS
#endif
public struct TimeSpecification {
public var seconds:Int64 = 0
public var nanoseconds:Int32 = 0 {
didSet { self.normalize() }
}
public init(seconds:Int64, nanoseconds:Int32) {
self.seconds = seconds
self.nanoseconds = nanoseconds
self.normalize()
}
public mutating func normalize() {
// `nanoseconds` must be always zero or positive value and less than 1_000_000_000
if self.nanoseconds >= 1_000_000_000 {
self.seconds += Int64(self.nanoseconds / 1_000_000_000)
self.nanoseconds = self.nanoseconds % 1_000_000_000
} else if self.nanoseconds < 0 {
// For example,
// (seconds:3, nanoseconds:-2_123_456_789)
// -> (seconds:0, nanoseconds:876_543_211)
self.seconds += Int64(self.nanoseconds / 1_000_000_000) - 1
self.nanoseconds = self.nanoseconds % 1_000_000_000 + 1_000_000_000
}
}
}
/// Comparable
extension TimeSpecification: Comparable {
public static func ==(lhs:TimeSpecification, rhs:TimeSpecification) -> Bool {
return (lhs.seconds == rhs.seconds && lhs.nanoseconds == rhs.nanoseconds) ? true : false
}
public static func <(lhs:TimeSpecification, rhs:TimeSpecification) -> Bool {
if lhs.seconds < rhs.seconds { return true }
if lhs.seconds > rhs.seconds { return false }
// then, in the case of (lhs.seconds == rhs.seconds)
if (lhs.nanoseconds < rhs.nanoseconds) { return true }
return false
}
}
/// ExpressibleByIntegerLiteral
extension TimeSpecification: ExpressibleByIntegerLiteral {
public typealias IntegerLiteralType = Int64
public init(integerLiteral value:Int64) {
self.seconds = value
self.nanoseconds = 0
}
}
/// ExpressibleByFloatLiteral
extension TimeSpecification: ExpressibleByFloatLiteral {
public typealias FloatLiteralType = Double
public init(floatLiteral value:Double) {
self.seconds = Int64(floor(value))
self.nanoseconds = Int32((value - Double(self.seconds)) * 1.0E+9)
}
}
/// Sum And Difference
extension TimeSpecification {
public static func +(lhs:TimeSpecification, rhs:TimeSpecification) -> TimeSpecification {
var result = lhs
result.seconds += rhs.seconds
result.nanoseconds += rhs.nanoseconds // always normalized
return result
}
public static func -(lhs:TimeSpecification, rhs:TimeSpecification) -> TimeSpecification {
var result = lhs
result.seconds -= rhs.seconds
result.nanoseconds -= rhs.nanoseconds // always normalized
return result
}
public static func +=(lhs:inout TimeSpecification, rhs:TimeSpecification) {
lhs = lhs + rhs // always normalized
}
public static func -=(lhs:inout TimeSpecification, rhs:TimeSpecification) {
lhs = lhs - rhs // always normalized
}
}
/* Clock */
extension TimeSpecification {
fileprivate init(_ cts:CTimeSpec) {
self.seconds = Int64(cts.tv_sec)
self.nanoseconds = Int32(cts.tv_nsec)
}
}
public enum Clock {
case calendar
case system
public var timeSpecification: TimeSpecification? {
var c_timespec:CTimeSpec = CTimeSpec(tv_sec:0, tv_nsec:0)
let clock_id:CInt
var retval:CInt = -1
#if os(Linux)
clock_id = (self == .calendar) ? CLOCK_REALTIME : CLOCK_MONOTONIC
retval = clock_gettime(clock_id, &c_timespec)
#elseif os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
var clock_name: clock_serv_t = 0
clock_id = (self == .calendar) ? CALENDAR_CLOCK : SYSTEM_CLOCK
retval = host_get_clock_service(mach_host_self(), clock_id, &clock_name)
guard retval == 0 else { return nil }
retval = clock_get_time(clock_name, &c_timespec)
_ = mach_port_deallocate(mach_task_self(), clock_name)
#endif
return (retval == 0) ? TimeSpecification(c_timespec) : nil
}
}

View File

@ -0,0 +1,153 @@
/***************************************************************************************************
TimeSpecification.swift
© 2016-2019 YOCKOW.
Licensed under MIT License.
See "LICENSE.txt" for more information.
**************************************************************************************************/
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
private let mach_task_self:() -> mach_port_t = { return mach_task_self_ }
private typealias CTimeSpec = mach_timespec_t
#else
import Glibc
private typealias CTimeSpec = timespec
#endif
/// The representation for the time in nanoseconds.
public struct TimeSpecification {
public var seconds: Int64 = 0
private var _nanoseconds: Int32 = 0
}
extension TimeSpecification {
private mutating func _normalize() {
//`nanoseconds` must be always zero or positive value and less than 1_000_000_000
if self._nanoseconds >= 1_000_000_000 {
self.seconds += Int64(self._nanoseconds / 1_000_000_000)
self._nanoseconds = self._nanoseconds % 1_000_000_000
} else if self._nanoseconds < 0 {
// For example,
// (seconds:3, nanoseconds:-2_123_456_789)
// -> (seconds:0, nanoseconds:876_543_211)
self.seconds += Int64(self._nanoseconds / 1_000_000_000) - 1
self._nanoseconds = self._nanoseconds % 1_000_000_000 + 1_000_000_000
}
}
public var nanoseconds: Int32 {
get {
return self._nanoseconds
}
set {
self._nanoseconds = newValue
self._normalize()
}
}
}
extension TimeSpecification {
public init(seconds:Int64, nanoseconds:Int32) {
self.seconds = seconds
self.nanoseconds = nanoseconds // will be normalized
}
}
extension TimeSpecification: Equatable {
public static func ==(lhs:TimeSpecification, rhs:TimeSpecification) -> Bool {
return lhs.seconds == rhs.seconds && lhs.nanoseconds == rhs.nanoseconds
}
}
extension TimeSpecification: Comparable {
public static func < (lhs: TimeSpecification, rhs: TimeSpecification) -> Bool {
if lhs.seconds < rhs.seconds { return true }
if lhs.seconds > rhs.seconds { return false }
// Then, in the case of (lhs.seconds == rhs.seconds) ...
return lhs.nanoseconds < rhs.nanoseconds
}
}
extension TimeSpecification: Hashable {
public func hash(into hasher:inout Hasher) {
hasher.combine(self.seconds)
hasher.combine(self.nanoseconds)
}
}
extension TimeSpecification: ExpressibleByIntegerLiteral {
public typealias IntegerLiteralType = Int64
public init(integerLiteral value: Int64) {
self.init(seconds: value, nanoseconds: 0)
}
}
extension TimeSpecification: ExpressibleByFloatLiteral {
public typealias FloatLiteralType = Double
public init(floatLiteral value:Double) {
let double_seconds = floor(value)
self.init(seconds: Int64(double_seconds), nanoseconds: Int32((value - double_seconds) * 1.0E+9))
}
}
// sum and difference
extension TimeSpecification {
public static func +(lhs:TimeSpecification, rhs:TimeSpecification) -> TimeSpecification {
var result = lhs
result.seconds += rhs.seconds
result.nanoseconds += rhs.nanoseconds // always normalized
return result
}
public static func -(lhs:TimeSpecification, rhs:TimeSpecification) -> TimeSpecification {
var result = lhs
result.seconds -= rhs.seconds
result.nanoseconds -= rhs.nanoseconds // always normalized
return result
}
public static func +=(lhs:inout TimeSpecification, rhs:TimeSpecification) {
lhs = lhs + rhs // always normalized
}
public static func -=(lhs:inout TimeSpecification, rhs:TimeSpecification) {
lhs = lhs - rhs // always normalized
}
}
extension TimeSpecification {
public enum Clock {
/// Calendar Clock
///
/// Note: This means `CLOCK_REALTIME` on Linux, `CALENDAR_CLOCK` on macOS.
case calendar
/// System Clock
///
/// Note: This means `CLOCK_MONOTONIC` on Linux, `SYSTEM_CLOCK` on macOS.
case system
}
private init(_ cts:CTimeSpec) {
self.init(seconds:Int64(cts.tv_sec), nanoseconds:Int32(cts.tv_nsec))
}
/// Initialze with an instance of `Clock`.
public init(clock:Clock) {
var c_timespec:CTimeSpec = CTimeSpec(tv_sec:0, tv_nsec:0)
let clock_id:CInt
#if os(Linux)
clock_id = (clock == .calendar) ? CLOCK_REALTIME : CLOCK_MONOTONIC
_ = clock_gettime(clock_id, &c_timespec)
#elseif os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
var clock_name: clock_serv_t = 0
clock_id = (clock == .calendar) ? CALENDAR_CLOCK : SYSTEM_CLOCK
_ = host_get_clock_service(mach_host_self(), clock_id, &clock_name)
_ = clock_get_time(clock_name, &c_timespec)
_ = mach_port_deallocate(mach_task_self(), clock_name)
#endif
self.init(c_timespec)
}
}

View File

@ -1,6 +1,8 @@
import XCTest
@testable import TimeSpecificationTests
XCTMain([
testCase(TimeSpecificationTests.allTests),
])
import TimeSpecificationTests
var tests = [XCTestCaseEntry]()
tests += TimeSpecificationTests.__allTests()
XCTMain(tests)

View File

@ -1,6 +1,6 @@
/***************************************************************************************************
SwiftTimeSpecificationTests.swift
© 2016-2017 YOCKOW.
© 2016-2019 YOCKOW.
Licensed under MIT License.
See "LICENSE.txt" for more information.
**************************************************************************************************/
@ -11,7 +11,7 @@ import XCTest
@testable import TimeSpecification
class TimeSpecificationTests: XCTestCase {
func testNormalization() {
func test_normalization() {
let N1 = TimeSpecification(seconds:0, nanoseconds:1_234_567_890)
let N2 = TimeSpecification(seconds:-1, nanoseconds:-1_234_567_890)
@ -19,7 +19,7 @@ class TimeSpecificationTests: XCTestCase {
XCTAssertTrue(N2.seconds == -3 && N2.nanoseconds == 765_432_110, "Normalization Test 2")
}
func testComparison() {
func test_comparison() {
let C1 = TimeSpecification(seconds:100, nanoseconds:100)
let C2 = TimeSpecification(seconds: 98, nanoseconds:2_000_000_100)
let C3 = TimeSpecification(seconds:200, nanoseconds:100)
@ -29,31 +29,22 @@ class TimeSpecificationTests: XCTestCase {
XCTAssertTrue(C2 < C4, "Comparison Test 3")
}
func testIntegerLiteral() {
func test_integerLiteral() {
let I1: TimeSpecification = 100
let I2: TimeSpecification = -100
XCTAssertEqual(I1, TimeSpecification(seconds:100, nanoseconds:0), "ExpressibleByIntegerLiteral Test 1")
XCTAssertEqual(I2, TimeSpecification(seconds:-100, nanoseconds:0), "ExpressibleByIntegerLiteral Test 2")
}
func testFloatLiteral() {
func test_floatLiteral() {
let F1: TimeSpecification = 1.1
XCTAssertEqual(F1, TimeSpecification(seconds:1, nanoseconds:100_000_000), "ExpressibleByFloatLiteral Test 1")
}
func testSumAndDifference() {
func test_sumAndDifference() {
let L1 = TimeSpecification(seconds:100, nanoseconds:123_456_789)
let R1 = TimeSpecification(seconds:100, nanoseconds:987_654_321)
XCTAssertEqual(L1 + R1, TimeSpecification(seconds:201, nanoseconds:111_111_110), "Sum Test 1")
XCTAssertEqual(L1 - R1, TimeSpecification(seconds:0, nanoseconds:-864_197_532), "Difference Test 1")
}
static var allTests = [
("Normalization", testNormalization),
("Comparison", testComparison),
("ExpressibleByIntegerLiteral", testIntegerLiteral),
("ExpressibleByFloatLiteral", testFloatLiteral),
("+/-", testSumAndDifference)
]
}

View File

@ -0,0 +1,22 @@
#if !canImport(ObjectiveC)
import XCTest
extension TimeSpecificationTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__TimeSpecificationTests = [
("test_comparison", test_comparison),
("test_floatLiteral", test_floatLiteral),
("test_integerLiteral", test_integerLiteral),
("test_normalization", test_normalization),
("test_sumAndDifference", test_sumAndDifference),
]
}
public func __allTests() -> [XCTestCaseEntry] {
return [
testCase(TimeSpecificationTests.__allTests__TimeSpecificationTests),
]
}
#endif

View File

@ -1,296 +0,0 @@
#!/usr/bin/env ruby
=begin
build-install.rb
© 2016-2017 YOCKOW.
Licensed under MIT License.
See "LICENSE.txt" for more information.
=end
ModuleName = 'TimeSpecification'
ModuleVersion = "0.0.0"
# Requirements #####################################################################################
require 'fileutils'
require 'json'
require 'optparse'
require 'pathname'
require 'open3'
require 'shellwords'
# Constants ########################################################################################
OS = case RbConfig::CONFIG['host_os']
when /darwin/i then :macOS
when /linux/i then :Linux
else :Other
end
SharedLibraryPrefix = 'lib'
SharedLibrarySuffix = (OS == :macOS) ? '.dylib' : '.so'
ModuleLinkName = 'Swift' + ModuleName
RootDirectory = Pathname(__FILE__).dirname.expand_path
## Default Values ##
Defaults = {
:swift => Pathname('swift'),
:build_directory => Pathname('./.build'),
:install => false,
:prefix => Pathname('/usr/local'),
:debug => false,
:skip_build => false,
:skip_test => false,
:clean => false
}
## Options ##
Options = {
:swift => nil,
:build_directory => nil,
:install => nil,
:prefix => nil,
:debug => nil,
:skip_build => nil,
:skip_test => nil,
:sdk => nil,
:clean => nil
}
## Canceled ##
Canceled = {
:debug => nil,
:skip_build => nil,
:skip_test => nil
}
### Qualifications ###
UnsavableOptions = [:build_directory, :sdk, :clean]
PathnameOptions = [:swift, :build_directory, :prefix]
# Functions ########################################################################################
## Error ##
def failed(message)
$stderr.puts("!!ERROR!! #{message}")
exit(false)
end
## Run Shell Script
def try_exec(command, indent = 0)
puts(' ' * indent + "Execute: #{command}")
Open3.popen3(command) {|stdin, stdout, stderr, wait_thread|
stdin.close
stdout.each {|line| $stdout.puts(' ' * indent * 2 + line) }
stderr.each {|line| $stderr.puts(' ' * indent * 2 + line) }
status = wait_thread.value.exitstatus
failed("Command exited with status #{status}") if status != 0
}
end
# Extends Class(es) ################################################################################
## Pathname ##
class Pathname
def escaped(type = :shell)
return Shellwords.shellescape(self.to_s) if type == :shell
return self.to_s.gsub(/\$/, '$$').gsub(/\s/, '$\&') if type == :ninja
return self.to_s
end
def exit_if_i_am_file
failed("#{self.to_s} is not directory.") if self.exist? && !self.directory?
end
end
# Parse Options ####################################################################################
OptionParser.new(__FILE__){|parser|
parser.on('--swift=PATH',
'Path to `swift` which you want to use.') {|path|
path = Pathname(path)
path += 'swift' if path.directory?
Options[:swift] = Pathname(path)
}
parser.on('--build-dir=PATH', '--build-directory=PATH',
'Name of the directory where the build products will be placed. ' +
'Default: ' + Defaults[:build_directory].to_s) {|path|
Options[:build_directory] = Pathname(path)
}
parser.on('--install',
'Whether to install products or not.') {|value|
Options[:install] = value
}
parser.on('--prefix=PATH', '--install-prefix=PATH',
'The installation prefix. (Only used when `--install` is specified.) ' +
'Default: ' + Defaults[:prefix].to_s) {|path|
Options[:prefix] = Pathname(path)
Options[:prefix]= Options[:prefix].expand_path if path =~ /\A~\//
if !Options[:prefix].absolute?
failed(%Q[The installation prefix must be absolute path.])
end
Options[:prefix].exit_if_i_am_file
Options[:install] = true # install library if prefix is specified.
}
parser.on('--debug',
'Debug builds') {|value|
Options[:debug] = value
}
parser.on('--release',
'Release builds; default is on') {|value|
Canceled[:debug] = value
}
parser.on('--skip-build',
'Whether to skip building or not.') {|value|
Options[:skip_build] = value
}
parser.on('--do-build',
'Cancel skipping building') {|value|
Canceled[:skip_build] = value
}
parser.on('--skip-test',
'Whether to skip testing or not.') {|value|
Options[:skip_test] = value
}
parser.on('--do-test',
'Cancel skipping testing') {|value|
Canceled[:skip_test] = value
}
parser.on('--clean',
'Whether to clean up or not.') {|value|
Options[:clean] = value
}
begin
parser.parse!(ARGV)
rescue OptionParser::ParseError => error
failed(error.message + "\n" + parser.help)
end
}
# Determine Options ################################################################################
UnsavableOptions.each{|key| Options[key] = Defaults[key] if Options[key].nil?}
## Build Directory
Options[:build_directory] = Defaults[:build_directory] if Options[:build_directory].nil?
Options[:build_directory] = RootDirectory + Options[:build_directory] if Options[:build_directory].relative?
Options[:build_directory].exit_if_i_am_file
FileUtils.rm_r(Options[:build_directory].to_s) if Options[:clean]
FileUtils.mkdir_p(Options[:build_directory].to_s)
## Save/Read Cache
cache_json = Options[:build_directory] + 'build_options-cache.json'
saved_defaults = nil
if cache_json.exist?
saved_defaults = JSON.parse(File.read(cache_json.to_s), {:symbolize_names => true})
saved_defaults.each_key{|key|
saved_defaults[key] = Pathname(saved_defaults[key]) if PathnameOptions.include?(key)
}
end
Defaults.each_pair{|key, value|
next if UnsavableOptions.include?(key)
if Options[key].nil?
if !saved_defaults.nil? && !saved_defaults[key].nil?
Options[key] = saved_defaults[key]
else
Options[key] = Defaults[key]
end
end
}
Canceled.each_pair{|key, value|
Options[key] = false if !value.nil? && value
}
File.write(cache_json.to_s, JSON.dump(Options))
Options.each_pair {|key, value| Options[key] = Defaults[key] if value.nil? }
# Swift? ###########################################################################################
failed("#{Options[:swift]} is not found.") if !system(%Q[which #{Options[:swift].escaped()} >/dev/null])
# Build! ###########################################################################################
configuration = Options[:debug] ? 'debug' : 'release'
binPath = Pathname(%x[#{Options[:swift].escaped()} build --build-path #{Options[:build_directory].escaped()} --configuration #{configuration} --show-bin-path].chomp)
libFilename = Pathname(SharedLibraryPrefix + ModuleLinkName + SharedLibrarySuffix)
libPath = binPath + libFilename
moduleFilename = Pathname(ModuleName + '.swiftmodule')
modulePath = binPath + moduleFilename
# Build
if !Options[:skip_build]
puts("[Start Building...]")
try_exec(["#{Options[:swift].escaped()} build --build-path #{Options[:build_directory].escaped()}",
"--configuration #{configuration}",
"-Xswiftc -emit-library -Xswiftc -o#{libPath.escaped()}",
"-Xswiftc -module-link-name -Xswiftc #{ModuleLinkName}",
"-Xswiftc -module-name -Xswiftc #{ModuleName}",
"-Xswiftc -emit-module-path -Xswiftc #{modulePath.escaped()}"].join(" "),
2)
puts()
end
# Test
if !Options[:skip_test]
puts("[Start Testing...]")
if !Options[:debug]
$stderr.puts("** WARNING ** No tests will be executed unless debug mode is specified.")
else
try_exec(["#{Options[:swift].escaped()} test --build-path #{Options[:build_directory].escaped()}",
"--configuration #{configuration}"].join(" "), 2)
end
puts()
end
# Install
if Options[:install]
puts("[Installing...]")
if Options[:debug]
$stderr.puts("** WARNING ** DEBUG MODE. Products to be installed may not be optimized.\n")
end
if ModuleVersion =~ /^([0-9]+)\.([0-9]+)\.([0-9]+)(?:\-(.+))?/
majorVersion = $1
minorVersion = $2
patchVersion = $3
prereleaseIdentifiers = $4
suffixes = [
".#{majorVersion}.#{minorVersion}",
".#{majorVersion}",
""
]
if prereleaseIdentifiers
suffixes.unshift(".#{majorVersion}.#{minorVersion}.#{patchVersion}")
end
libInstallDirPath = Options[:prefix] + Pathname('lib')
moduleInstallDirPath = Options[:prefix] + Pathname('include')
originalLibFilename = Pathname(SharedLibraryPrefix + ModuleLinkName + SharedLibrarySuffix + '.' + ModuleVersion)
originalModuleFilename = Pathname(ModuleName + '.swiftmodule' + '.' + ModuleVersion)
originalLibInstallPath = libInstallDirPath + originalLibFilename
originalModuleInstallPath = moduleInstallDirPath + originalModuleFilename
try_exec("mkdir -p #{libInstallDirPath.escaped()}", 2)
try_exec("rm -f #{originalLibInstallPath.escaped()}", 2)
try_exec("cp -f #{libPath.escaped()} #{originalLibInstallPath.escaped()}", 2)
try_exec("mkdir -p #{moduleInstallDirPath.escaped()}", 2)
try_exec("rm -f #{originalModuleInstallPath.escaped()}", 2)
try_exec("cp -f #{modulePath.escaped()} #{originalModuleInstallPath.escaped()}", 2)
suffixes.each_with_index{|suffix, ii|
sourceSuffix = (ii == 0) ? ('.' + ModuleVersion) : suffixes[ii - 1]
libSourceFilename = Pathname(SharedLibraryPrefix + ModuleLinkName + SharedLibrarySuffix + sourceSuffix)
moduleSourceFilename = Pathname(ModuleName + '.swiftmodule' + sourceSuffix)
libDestFilename = Pathname(SharedLibraryPrefix + ModuleLinkName + SharedLibrarySuffix + suffix)
moduleDestFilename = Pathname(ModuleName + '.swiftmodule' + suffix)
libSourcePath = libInstallDirPath + libSourceFilename
moduleSourcePath = moduleInstallDirPath + moduleSourceFilename
libDestPath = libInstallDirPath + libDestFilename
moduleDestPath = moduleInstallDirPath + moduleDestFilename
try_exec("ln -fs #{libSourcePath.escaped()} #{libDestPath.escaped}", 2)
try_exec("ln -fs #{moduleSourcePath.escaped()} #{moduleDestPath.escaped}", 2)
}
else
$stderr.puts("Invalid Version")
end
end