main.swift 5.67 KB
Newer Older
Drew's avatar
Drew committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// 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.

Drew's avatar
Drew committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
import atfoundation

private enum ModuleMapType: String {
    case Synthesized = "synthesized"
}

private enum Options: String {
    case InfoPlist = "info-plist"
    case Name = "name"
}

func env(_ feature: String) -> String? {
    let env = getenv(feature)
    guard let e = env else { return nil }
    return String(validatingUTF8: e)
}

func arg(_ larg: String) -> String? {
    for (x, arg) in Process.arguments.enumerated() {
        if arg == "--\(larg)" { return Process.arguments[x+1] }
    }
    return nil
}

class PackageFramework {
    func run() {

Drew's avatar
Drew committed
42
        guard let atbuildPlatform = env("ATBUILD_PLATFORM") else {
Drew's avatar
Drew committed
43 44
            fatalError("Set $ATBUILD_PLATFORM")
        }
Drew's avatar
Drew committed
45 46
        let platformToArch: [String:String]
        switch (atbuildPlatform) {
Drew's avatar
Drew committed
47
            case "osx":
Drew's avatar
Drew committed
48 49 50
            platformToArch = ["osx":"x86_64"]
            case "ios":
            platformToArch = ["ios-arm64":"arm64","ios-armv7":"armv7","ios-i386":"i386","ios-x86_64":"x86_64"]
Drew's avatar
Drew committed
51
            default:
Drew's avatar
Drew committed
52
            fatalError("Unsupported platform \(atbuildPlatform)")
Drew's avatar
Drew committed
53 54 55 56 57 58 59 60 61
        }

        guard let name = arg(Options.Name.rawValue) else {
            fatalError("Specify a \(Options.Name.rawValue)")
        }

        guard let infoPlist = arg(Options.InfoPlist.rawValue) else {
            fatalError("Specify a \(Options.InfoPlist.rawValue)")
        }
Drew's avatar
Drew committed
62

Drew's avatar
Drew committed
63
        var resources: [String] = [infoPlist]
Drew's avatar
Drew committed
64
         
Drew's avatar
Drew committed
65 66 67 68 69 70 71

        //rm framework if it exists
        let frameworkPath = Path("bin/\(name).framework")
        let _ = try? FS.removeItem(path: frameworkPath, recursive: true)
        let _ = try? FS.createDirectory(path: frameworkPath)

        //'a' version
Drew's avatar
Drew committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
        let relativeAVersionPath: Path!
        let AVersionPath: Path
        switch(atbuildPlatform) {
            case "osx":
            relativeAVersionPath = Path("Versions/A")
            AVersionPath = frameworkPath + relativeAVersionPath
            case "ios":
            relativeAVersionPath = nil
            AVersionPath = frameworkPath
            default:
            fatalError("Unsupported platform \(atbuildPlatform)")
        }

        if atbuildPlatform == "osx" {
            try! FS.createDirectory(path: AVersionPath, intermediate: true)
            //'current' (produces code signing failures if absent)
            try! FS.symlinkItem(from: Path("A"), to: frameworkPath + "Versions/Current")
        }
Drew's avatar
Drew committed
90

Drew's avatar
Drew committed
91 92
        //copy payload
        //atbin path
Drew's avatar
Drew committed
93
        let atbinPath = Path(env("ATBUILD_BIN_PATH")!).appending("\(name).atbin")
Drew's avatar
Drew committed
94 95
        let payloadPath = atbinPath.appending(name + ".dylib")
        try! FS.copyItem(from: payloadPath, to: AVersionPath.appending(name))
Drew's avatar
Drew committed
96 97 98
        if atbuildPlatform == "osx" {
            try! FS.symlinkItem(from: relativeAVersionPath.appending(name), to: frameworkPath.appending(name))
        }
Drew's avatar
Drew committed
99 100 101
        //copy modules
        let modulePath = AVersionPath.appending("Modules").appending(name + ".swiftmodule")
        try! FS.createDirectory(path: modulePath, intermediate: true)
Drew's avatar
Drew committed
102
        for (platform, architecture) in platformToArch {
Drew's avatar
Drew committed
103 104 105 106 107
            //In frameworks, what AT calls "armv7" is called "arm".
            let destArchitecture: String 
            if architecture == "armv7" { destArchitecture = "arm" }
            else { destArchitecture = architecture }

Drew's avatar
Drew committed
108 109
            let swiftModulePath = atbinPath.appending("\(platform).swiftmodule")
            if FS.fileExists(path: swiftModulePath) {
Drew's avatar
Drew committed
110
                try! FS.copyItem(from: swiftModulePath, to: modulePath.appending("\(destArchitecture).swiftmodule"))
Drew's avatar
Drew committed
111 112 113 114
            }

            let swiftDocPath = atbinPath.appending("\(platform).swiftdoc")
            if FS.fileExists(path: swiftDocPath) {
Drew's avatar
Drew committed
115
                try! FS.copyItem(from: swiftDocPath, to: modulePath.appending("\(destArchitecture).swiftdoc"))
Drew's avatar
Drew committed
116
            }
Drew's avatar
Drew committed
117
        }
Drew's avatar
Drew committed
118 119
        if atbuildPlatform == "osx" {
            try! FS.symlinkItem(from: relativeAVersionPath.appending("Modules"), to: frameworkPath.appending("Modules"))
Drew's avatar
Drew committed
120 121 122
        }

        //copy resources
Drew's avatar
Drew committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136
        let resourcesPath: Path
        switch(atbuildPlatform) {
            case "osx":
            resourcesPath = AVersionPath.appending("Resources")
            case "ios":
            resourcesPath = AVersionPath
            default:
            fatalError("Unsupported platform \(atbuildPlatform)")
        }
        do {
            try FS.createDirectory(path: resourcesPath, intermediate: true)
        }
        catch SysError.FileExists { /* */ }
        catch { fatalError("\(error)")}
Drew's avatar
Drew committed
137
        for resource in resources {
Drew's avatar
Drew committed
138 139
            let dest = resourcesPath + Path(resource).basename()
            try! FS.copyItem(from: Path(resource), to: dest)
Drew's avatar
Drew committed
140
        }
Drew's avatar
Drew committed
141 142 143
        if atbuildPlatform == "ios" {
            try! FS.copyItem(from: Path(infoPlist), to: AVersionPath.appending("Info.plist"))
        }
Drew's avatar
Drew committed
144

Drew's avatar
Drew committed
145 146 147
        if atbuildPlatform == "osx" {
            try! FS.symlinkItem(from: relativeAVersionPath + "Resources", to: frameworkPath + "Resources")
        }
Drew's avatar
Drew committed
148 149 150 151 152 153 154 155 156
        //codesign
        let cmd = "codesign --force --deep --sign - --timestamp=none '\(AVersionPath)'"
        if system(cmd) != 0 {
            fatalError("Codesign failed.")
        }
    }
}

PackageFramework().run()