mirror of
https://github.com/GLEGram/GLEGram-iOS.git
synced 2026-04-23 19:36:26 +02:00
4647310322
Based on Swiftgram 12.5 (Telegram iOS 12.5). All GLEGram features ported and organized in GLEGram/ folder. Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass, Font Replacement, Fake Profile, Chat Export, Plugin System, and more. See CHANGELOG_12.5.md for full details.
417 lines
17 KiB
Swift
417 lines
17 KiB
Swift
import Foundation
|
|
import JSONUtilities
|
|
import XcodeProj
|
|
import Version
|
|
|
|
public struct LegacyTarget: Equatable {
|
|
public static let passSettingsDefault = false
|
|
|
|
public var toolPath: String
|
|
public var arguments: String?
|
|
public var passSettings: Bool
|
|
public var workingDirectory: String?
|
|
|
|
public init(
|
|
toolPath: String,
|
|
passSettings: Bool = passSettingsDefault,
|
|
arguments: String? = nil,
|
|
workingDirectory: String? = nil
|
|
) {
|
|
self.toolPath = toolPath
|
|
self.arguments = arguments
|
|
self.passSettings = passSettings
|
|
self.workingDirectory = workingDirectory
|
|
}
|
|
}
|
|
|
|
extension LegacyTarget: PathContainer {
|
|
|
|
static var pathProperties: [PathProperty] {
|
|
[
|
|
.string("workingDirectory"),
|
|
]
|
|
}
|
|
}
|
|
|
|
public struct Target: ProjectTarget {
|
|
public var name: String
|
|
public var type: PBXProductType
|
|
public var platform: Platform
|
|
public var supportedDestinations: [SupportedDestination]?
|
|
public var settings: Settings
|
|
public var sources: [TargetSource]
|
|
public var dependencies: [Dependency]
|
|
public var info: Plist?
|
|
public var entitlements: Plist?
|
|
public var transitivelyLinkDependencies: Bool?
|
|
public var directlyEmbedCarthageDependencies: Bool?
|
|
public var requiresObjCLinking: Bool?
|
|
public var preBuildScripts: [BuildScript]
|
|
public var buildToolPlugins: [BuildToolPlugin]
|
|
public var postCompileScripts: [BuildScript]
|
|
public var postBuildScripts: [BuildScript]
|
|
public var buildRules: [BuildRule]
|
|
public var configFiles: [String: String]
|
|
public var scheme: TargetScheme?
|
|
public var legacy: LegacyTarget?
|
|
public var deploymentTarget: Version?
|
|
public var attributes: [String: Any]
|
|
public var productName: String
|
|
public var onlyCopyFilesOnInstall: Bool
|
|
public var putResourcesBeforeSourcesBuildPhase: Bool
|
|
|
|
public var isLegacy: Bool {
|
|
legacy != nil
|
|
}
|
|
|
|
public var filename: String {
|
|
var filename = productName
|
|
if let fileExtension = type.fileExtension {
|
|
filename += ".\(fileExtension)"
|
|
}
|
|
if type == .staticLibrary {
|
|
filename = "lib\(filename)"
|
|
}
|
|
return filename
|
|
}
|
|
|
|
public init(
|
|
name: String,
|
|
type: PBXProductType,
|
|
platform: Platform,
|
|
supportedDestinations: [SupportedDestination]? = nil,
|
|
productName: String? = nil,
|
|
deploymentTarget: Version? = nil,
|
|
settings: Settings = .empty,
|
|
configFiles: [String: String] = [:],
|
|
sources: [TargetSource] = [],
|
|
dependencies: [Dependency] = [],
|
|
info: Plist? = nil,
|
|
entitlements: Plist? = nil,
|
|
transitivelyLinkDependencies: Bool? = nil,
|
|
directlyEmbedCarthageDependencies: Bool? = nil,
|
|
requiresObjCLinking: Bool? = nil,
|
|
preBuildScripts: [BuildScript] = [],
|
|
buildToolPlugins: [BuildToolPlugin] = [],
|
|
postCompileScripts: [BuildScript] = [],
|
|
postBuildScripts: [BuildScript] = [],
|
|
buildRules: [BuildRule] = [],
|
|
scheme: TargetScheme? = nil,
|
|
legacy: LegacyTarget? = nil,
|
|
attributes: [String: Any] = [:],
|
|
onlyCopyFilesOnInstall: Bool = false,
|
|
putResourcesBeforeSourcesBuildPhase: Bool = false
|
|
) {
|
|
self.name = name
|
|
self.type = type
|
|
self.platform = platform
|
|
self.supportedDestinations = supportedDestinations
|
|
self.deploymentTarget = deploymentTarget
|
|
self.productName = productName ?? name
|
|
self.settings = settings
|
|
self.configFiles = configFiles
|
|
self.sources = sources
|
|
self.dependencies = dependencies
|
|
self.info = info
|
|
self.entitlements = entitlements
|
|
self.transitivelyLinkDependencies = transitivelyLinkDependencies
|
|
self.directlyEmbedCarthageDependencies = directlyEmbedCarthageDependencies
|
|
self.requiresObjCLinking = requiresObjCLinking
|
|
self.preBuildScripts = preBuildScripts
|
|
self.buildToolPlugins = buildToolPlugins
|
|
self.postCompileScripts = postCompileScripts
|
|
self.postBuildScripts = postBuildScripts
|
|
self.buildRules = buildRules
|
|
self.scheme = scheme
|
|
self.legacy = legacy
|
|
self.attributes = attributes
|
|
self.onlyCopyFilesOnInstall = onlyCopyFilesOnInstall
|
|
self.putResourcesBeforeSourcesBuildPhase = putResourcesBeforeSourcesBuildPhase
|
|
}
|
|
}
|
|
|
|
extension Target: CustomStringConvertible {
|
|
|
|
public var description: String {
|
|
"\(name): \(platform.rawValue) \(type)"
|
|
}
|
|
}
|
|
|
|
extension Target: PathContainer {
|
|
|
|
static var pathProperties: [PathProperty] {
|
|
[
|
|
.dictionary([
|
|
.string("sources"),
|
|
.object("sources", TargetSource.pathProperties),
|
|
.string("configFiles"),
|
|
.object("dependencies", Dependency.pathProperties),
|
|
.object("info", Plist.pathProperties),
|
|
.object("entitlements", Plist.pathProperties),
|
|
.object("preBuildScripts", BuildScript.pathProperties),
|
|
.object("prebuildScripts", BuildScript.pathProperties),
|
|
.object("postCompileScripts", BuildScript.pathProperties),
|
|
.object("postBuildScripts", BuildScript.pathProperties),
|
|
.object("legacy", LegacyTarget.pathProperties),
|
|
.object("scheme", TargetScheme.pathProperties),
|
|
]),
|
|
]
|
|
}
|
|
}
|
|
|
|
extension Target {
|
|
|
|
static func resolveMultiplatformTargets(jsonDictionary: JSONDictionary) -> JSONDictionary {
|
|
guard let targetsDictionary: [String: JSONDictionary] = jsonDictionary["targets"] as? [String: JSONDictionary] else {
|
|
return jsonDictionary
|
|
}
|
|
|
|
var crossPlatformTargets: [String: JSONDictionary] = [:]
|
|
|
|
for (targetName, target) in targetsDictionary {
|
|
if let platforms = target["platform"] as? [String] {
|
|
for platform in platforms {
|
|
var platformTarget = target
|
|
|
|
/// This value is set to help us to check, in Target init, that there are no conflicts in the definition of the platforms. We want to ensure that the user didn't define, at the same time,
|
|
/// the new Xcode 14 supported destinations and the XcodeGen generation of Multiple Platform Targets (when you define the platform field as an array).
|
|
platformTarget["isMultiPlatformTarget"] = true
|
|
|
|
platformTarget = platformTarget.expand(variables: ["platform": platform])
|
|
|
|
platformTarget["platform"] = platform
|
|
let platformSuffix = platformTarget["platformSuffix"] as? String ?? "_\(platform)"
|
|
let platformPrefix = platformTarget["platformPrefix"] as? String ?? ""
|
|
let newTargetName = platformPrefix + targetName + platformSuffix
|
|
|
|
var settings = platformTarget["settings"] as? JSONDictionary ?? [:]
|
|
if settings["configs"] != nil || settings["groups"] != nil || settings["base"] != nil {
|
|
var base = settings["base"] as? JSONDictionary ?? [:]
|
|
if base["PRODUCT_NAME"] == nil {
|
|
base["PRODUCT_NAME"] = targetName
|
|
}
|
|
settings["base"] = base
|
|
} else {
|
|
if settings["PRODUCT_NAME"] == nil {
|
|
settings["PRODUCT_NAME"] = targetName
|
|
}
|
|
}
|
|
platformTarget["productName"] = targetName
|
|
platformTarget["settings"] = settings
|
|
if let deploymentTargets = target["deploymentTarget"] as? [String: Any] {
|
|
platformTarget["deploymentTarget"] = deploymentTargets[platform]
|
|
}
|
|
crossPlatformTargets[newTargetName] = platformTarget
|
|
}
|
|
} else {
|
|
crossPlatformTargets[targetName] = target
|
|
}
|
|
}
|
|
|
|
var merged = jsonDictionary
|
|
merged["targets"] = crossPlatformTargets
|
|
return merged
|
|
}
|
|
}
|
|
|
|
extension Target: Equatable {
|
|
|
|
public static func == (lhs: Target, rhs: Target) -> Bool {
|
|
lhs.name == rhs.name &&
|
|
lhs.type == rhs.type &&
|
|
lhs.platform == rhs.platform &&
|
|
lhs.deploymentTarget == rhs.deploymentTarget &&
|
|
lhs.transitivelyLinkDependencies == rhs.transitivelyLinkDependencies &&
|
|
lhs.requiresObjCLinking == rhs.requiresObjCLinking &&
|
|
lhs.directlyEmbedCarthageDependencies == rhs.directlyEmbedCarthageDependencies &&
|
|
lhs.settings == rhs.settings &&
|
|
lhs.configFiles == rhs.configFiles &&
|
|
lhs.sources == rhs.sources &&
|
|
lhs.info == rhs.info &&
|
|
lhs.entitlements == rhs.entitlements &&
|
|
lhs.dependencies == rhs.dependencies &&
|
|
lhs.preBuildScripts == rhs.preBuildScripts &&
|
|
lhs.buildToolPlugins == rhs.buildToolPlugins &&
|
|
lhs.postCompileScripts == rhs.postCompileScripts &&
|
|
lhs.postBuildScripts == rhs.postBuildScripts &&
|
|
lhs.buildRules == rhs.buildRules &&
|
|
lhs.scheme == rhs.scheme &&
|
|
lhs.legacy == rhs.legacy &&
|
|
NSDictionary(dictionary: lhs.attributes).isEqual(to: rhs.attributes)
|
|
}
|
|
}
|
|
|
|
extension LegacyTarget: JSONObjectConvertible {
|
|
|
|
public init(jsonDictionary: JSONDictionary) throws {
|
|
toolPath = try jsonDictionary.json(atKeyPath: "toolPath")
|
|
arguments = jsonDictionary.json(atKeyPath: "arguments")
|
|
passSettings = jsonDictionary.json(atKeyPath: "passSettings") ?? LegacyTarget.passSettingsDefault
|
|
workingDirectory = jsonDictionary.json(atKeyPath: "workingDirectory")
|
|
}
|
|
}
|
|
|
|
extension LegacyTarget: JSONEncodable {
|
|
public func toJSONValue() -> Any {
|
|
var dict: [String: Any?] = [
|
|
"toolPath": toolPath,
|
|
"arguments": arguments,
|
|
"workingDirectory": workingDirectory,
|
|
]
|
|
|
|
if passSettings != LegacyTarget.passSettingsDefault {
|
|
dict["passSettings"] = passSettings
|
|
}
|
|
|
|
return dict
|
|
}
|
|
}
|
|
|
|
extension Target: NamedJSONDictionaryConvertible {
|
|
|
|
public init(name: String, jsonDictionary: JSONDictionary) throws {
|
|
let resolvedName: String = jsonDictionary.json(atKeyPath: "name") ?? name
|
|
self.name = resolvedName
|
|
productName = jsonDictionary.json(atKeyPath: "productName") ?? resolvedName
|
|
|
|
let typeString: String = jsonDictionary.json(atKeyPath: "type") ?? ""
|
|
if let type = PBXProductType(string: typeString) {
|
|
self.type = type
|
|
} else {
|
|
throw SpecParsingError.unknownTargetType(typeString)
|
|
}
|
|
|
|
if let supportedDestinations: [SupportedDestination] = jsonDictionary.json(atKeyPath: "supportedDestinations") {
|
|
self.supportedDestinations = supportedDestinations
|
|
}
|
|
|
|
let isResolved = jsonDictionary.json(atKeyPath: "isMultiPlatformTarget") ?? false
|
|
if isResolved, supportedDestinations != nil {
|
|
throw SpecParsingError.invalidTargetPlatformAsArray
|
|
}
|
|
|
|
var platformString: String = jsonDictionary.json(atKeyPath: "platform") ?? ""
|
|
// platform defaults to 'auto' if it is empty and we are using supported destinations
|
|
if supportedDestinations != nil, platformString.isEmpty {
|
|
platformString = Platform.auto.rawValue
|
|
}
|
|
// we add 'iOS' in supported destinations if it contains only 'macCatalyst'
|
|
if supportedDestinations?.contains(.macCatalyst) == true,
|
|
supportedDestinations?.contains(.iOS) == false {
|
|
|
|
supportedDestinations?.append(.iOS)
|
|
}
|
|
|
|
if let platform = Platform(rawValue: platformString) {
|
|
self.platform = platform
|
|
} else {
|
|
throw SpecParsingError.unknownTargetPlatform(platformString)
|
|
}
|
|
|
|
if let string: String = jsonDictionary.json(atKeyPath: "deploymentTarget") {
|
|
deploymentTarget = try Version.parse(string)
|
|
} else if let double: Double = jsonDictionary.json(atKeyPath: "deploymentTarget") {
|
|
deploymentTarget = try Version.parse(String(double))
|
|
} else {
|
|
deploymentTarget = nil
|
|
}
|
|
|
|
settings = try BuildSettingsParser(jsonDictionary: jsonDictionary).parse()
|
|
configFiles = jsonDictionary.json(atKeyPath: "configFiles") ?? [:]
|
|
if let source: String = jsonDictionary.json(atKeyPath: "sources") {
|
|
sources = [TargetSource(path: source)]
|
|
} else if let array = jsonDictionary["sources"] as? [Any] {
|
|
sources = try array.compactMap { source in
|
|
if let string = source as? String {
|
|
return TargetSource(path: string)
|
|
} else if let dictionary = source as? [String: Any] {
|
|
return try TargetSource(jsonDictionary: dictionary)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
} else {
|
|
sources = []
|
|
}
|
|
if jsonDictionary["dependencies"] == nil {
|
|
dependencies = []
|
|
} else {
|
|
let dependencies: [Dependency] = try jsonDictionary.json(atKeyPath: "dependencies", invalidItemBehaviour: .fail)
|
|
self.dependencies = dependencies.filter { [platform] dependency -> Bool in
|
|
// If unspecified, all platforms are supported
|
|
guard let platforms = dependency.platforms else { return true }
|
|
return platforms.contains(platform)
|
|
}
|
|
}
|
|
|
|
if jsonDictionary["buildToolPlugins"] == nil {
|
|
buildToolPlugins = []
|
|
} else {
|
|
self.buildToolPlugins = try jsonDictionary.json(atKeyPath: "buildToolPlugins", invalidItemBehaviour: .fail)
|
|
}
|
|
|
|
if jsonDictionary["info"] != nil {
|
|
info = try jsonDictionary.json(atKeyPath: "info") as Plist
|
|
}
|
|
if jsonDictionary["entitlements"] != nil {
|
|
entitlements = try jsonDictionary.json(atKeyPath: "entitlements") as Plist
|
|
}
|
|
|
|
transitivelyLinkDependencies = jsonDictionary.json(atKeyPath: "transitivelyLinkDependencies")
|
|
directlyEmbedCarthageDependencies = jsonDictionary.json(atKeyPath: "directlyEmbedCarthageDependencies")
|
|
requiresObjCLinking = jsonDictionary.json(atKeyPath: "requiresObjCLinking")
|
|
|
|
preBuildScripts = jsonDictionary.json(atKeyPath: "preBuildScripts") ?? jsonDictionary.json(atKeyPath: "prebuildScripts") ?? []
|
|
postCompileScripts = jsonDictionary.json(atKeyPath: "postCompileScripts") ?? []
|
|
postBuildScripts = jsonDictionary.json(atKeyPath: "postBuildScripts") ?? jsonDictionary.json(atKeyPath: "postbuildScripts") ?? []
|
|
buildRules = jsonDictionary.json(atKeyPath: "buildRules") ?? []
|
|
scheme = jsonDictionary.json(atKeyPath: "scheme")
|
|
legacy = jsonDictionary.json(atKeyPath: "legacy")
|
|
attributes = jsonDictionary.json(atKeyPath: "attributes") ?? [:]
|
|
onlyCopyFilesOnInstall = jsonDictionary.json(atKeyPath: "onlyCopyFilesOnInstall") ?? false
|
|
putResourcesBeforeSourcesBuildPhase = jsonDictionary.json(atKeyPath: "putResourcesBeforeSourcesBuildPhase") ?? false
|
|
}
|
|
}
|
|
|
|
extension Target: JSONEncodable {
|
|
public func toJSONValue() -> Any {
|
|
var dict: [String: Any?] = [
|
|
"type": type.name,
|
|
"platform": platform.rawValue,
|
|
"supportedDestinations": supportedDestinations?.map { $0.rawValue },
|
|
"settings": settings.toJSONValue(),
|
|
"configFiles": configFiles,
|
|
"attributes": attributes,
|
|
"sources": sources.map { $0.toJSONValue() },
|
|
"dependencies": dependencies.map { $0.toJSONValue() },
|
|
"postCompileScripts": postCompileScripts.map { $0.toJSONValue() },
|
|
"prebuildScripts": preBuildScripts.map { $0.toJSONValue() },
|
|
"buildToolPlugins": buildToolPlugins.map { $0.toJSONValue() },
|
|
"postbuildScripts": postBuildScripts.map { $0.toJSONValue() },
|
|
"buildRules": buildRules.map { $0.toJSONValue() },
|
|
"deploymentTarget": deploymentTarget?.deploymentTarget,
|
|
"info": info?.toJSONValue(),
|
|
"entitlements": entitlements?.toJSONValue(),
|
|
"transitivelyLinkDependencies": transitivelyLinkDependencies,
|
|
"directlyEmbedCarthageDependencies": directlyEmbedCarthageDependencies,
|
|
"requiresObjCLinking": requiresObjCLinking,
|
|
"scheme": scheme?.toJSONValue(),
|
|
"legacy": legacy?.toJSONValue(),
|
|
]
|
|
|
|
if productName != name {
|
|
dict["productName"] = productName
|
|
}
|
|
|
|
if onlyCopyFilesOnInstall {
|
|
dict["onlyCopyFilesOnInstall"] = true
|
|
}
|
|
|
|
if putResourcesBeforeSourcesBuildPhase {
|
|
dict["putResourcesBeforeSourcesBuildPhase"] = true
|
|
}
|
|
|
|
return dict
|
|
}
|
|
}
|