mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2024-09-20 09:08:46 +03:00
159 lines
6.2 KiB
Swift
159 lines
6.2 KiB
Swift
import Foundation
|
|
import xcproj
|
|
import PathKit
|
|
import ProjectSpec
|
|
import Yams
|
|
import JSONUtilities
|
|
|
|
extension ProjectSpec {
|
|
|
|
public func getProjectBuildSettings(config: Config) -> BuildSettings {
|
|
var buildSettings: BuildSettings = [:]
|
|
|
|
if let type = config.type, options.settingPresets.applyProject {
|
|
buildSettings += SettingsPresetFile.base.getBuildSettings()
|
|
buildSettings += SettingsPresetFile.config(type).getBuildSettings()
|
|
}
|
|
|
|
// Prevent setting presets from overrwriting settings in project xcconfig files
|
|
if let configPath = configFiles[config.name] {
|
|
buildSettings = removeConfigFileSettings(from: buildSettings, configPath: configPath)
|
|
}
|
|
|
|
buildSettings += getBuildSettings(settings: settings, config: config)
|
|
|
|
return buildSettings
|
|
}
|
|
|
|
public func getTargetBuildSettings(target: Target, config: Config) -> BuildSettings {
|
|
var buildSettings = BuildSettings()
|
|
|
|
if options.settingPresets.applyTarget {
|
|
buildSettings += SettingsPresetFile.platform(target.platform).getBuildSettings()
|
|
buildSettings += SettingsPresetFile.product(target.type).getBuildSettings()
|
|
buildSettings += SettingsPresetFile.productPlatform(target.type, target.platform).getBuildSettings()
|
|
}
|
|
|
|
// Prevent setting presets from overrwriting settings in target xcconfig files
|
|
if let configPath = target.configFiles[config.name] {
|
|
buildSettings = removeConfigFileSettings(from: buildSettings, configPath: configPath)
|
|
}
|
|
// Prevent setting presets from overrwriting settings in project xcconfig files
|
|
if let configPath = configFiles[config.name] {
|
|
buildSettings = removeConfigFileSettings(from: buildSettings, configPath: configPath)
|
|
}
|
|
|
|
buildSettings += getBuildSettings(settings: target.settings, config: config)
|
|
|
|
return buildSettings
|
|
}
|
|
|
|
public func getBuildSettings(settings: Settings, config: Config) -> BuildSettings {
|
|
var buildSettings: BuildSettings = [:]
|
|
|
|
for group in settings.groups {
|
|
if let settings = settingGroups[group] {
|
|
buildSettings += getBuildSettings(settings: settings, config: config)
|
|
}
|
|
}
|
|
|
|
buildSettings += settings.buildSettings
|
|
|
|
for (configVariant, settings) in settings.configSettings {
|
|
if config.name.lowercased().contains(configVariant.lowercased()) {
|
|
buildSettings += getBuildSettings(settings: settings, config: config)
|
|
}
|
|
}
|
|
|
|
return buildSettings
|
|
}
|
|
|
|
// combines all levels of a target's settings: target, target config, project, project config
|
|
public func getCombinedBuildSettings(basePath: Path, target: Target, config: Config, includeProject: Bool = true) -> BuildSettings {
|
|
var buildSettings: BuildSettings = [:]
|
|
if includeProject {
|
|
if let configFilePath = configFiles[config.name] {
|
|
buildSettings += loadConfigFileBuildSettings(path: configFilePath)
|
|
}
|
|
buildSettings += getProjectBuildSettings(config: config)
|
|
}
|
|
if let configFilePath = target.configFiles[config.name] {
|
|
buildSettings += loadConfigFileBuildSettings(path: configFilePath)
|
|
}
|
|
buildSettings += getTargetBuildSettings(target: target, config: config)
|
|
return buildSettings
|
|
}
|
|
|
|
public func targetHasBuildSetting(_ setting: String, basePath: Path, target: Target, config: Config, includeProject: Bool = true) -> Bool {
|
|
let buildSettings = getCombinedBuildSettings(basePath: basePath, target: target, config: config, includeProject: includeProject)
|
|
return buildSettings[setting] != nil
|
|
}
|
|
|
|
/// Removes values from build settings if they are defined in an xcconfig file
|
|
private func removeConfigFileSettings(from buildSettings: BuildSettings, configPath: String) -> BuildSettings {
|
|
var buildSettings = buildSettings
|
|
|
|
if let configSettings = loadConfigFileBuildSettings(path: configPath) {
|
|
for key in configSettings.keys {
|
|
// FIXME: Catch platform specifier. e.g. LD_RUNPATH_SEARCH_PATHS[sdk=iphone*]
|
|
buildSettings.removeValue(forKey: key)
|
|
buildSettings.removeValue(forKey: key.quoted)
|
|
}
|
|
}
|
|
|
|
return buildSettings
|
|
}
|
|
|
|
/// Returns cached build settings from a config file
|
|
private func loadConfigFileBuildSettings(path: String) -> BuildSettings? {
|
|
let configFilePath = basePath + path
|
|
if let settings = configFileSettings[configFilePath.string] {
|
|
return settings
|
|
} else {
|
|
guard let configFile = try? XCConfig(path: configFilePath) else { return nil }
|
|
let settings = configFile.flattenedBuildSettings()
|
|
configFileSettings[configFilePath.string] = settings
|
|
return settings
|
|
}
|
|
}
|
|
}
|
|
|
|
// cached flattened xcconfig file settings
|
|
private var configFileSettings: [String: BuildSettings] = [:]
|
|
|
|
// cached setting preset settings
|
|
private var settingPresetSettings: [String: BuildSettings] = [:]
|
|
|
|
extension SettingsPresetFile {
|
|
|
|
public func getBuildSettings() -> BuildSettings? {
|
|
if let group = settingPresetSettings[path] {
|
|
return group
|
|
}
|
|
let relativePath = "SettingPresets/\(path).yml"
|
|
let possibleSettingsPaths: [Path] = [
|
|
Path(relativePath),
|
|
Path(Bundle.main.bundlePath) + relativePath,
|
|
Path(Bundle.main.bundlePath) + "../share/xcodegen/\(relativePath)",
|
|
Path(#file).parent().parent().parent() + relativePath,
|
|
]
|
|
|
|
guard let settingsPath = possibleSettingsPaths.first(where: { $0.exists }) else {
|
|
switch self {
|
|
case .base, .config, .platform:
|
|
print("No \"\(name)\" settings found")
|
|
case .product, .productPlatform:
|
|
break
|
|
}
|
|
return nil
|
|
}
|
|
|
|
guard let buildSettings = try? loadYamlDictionary(path: settingsPath) else {
|
|
print("Error parsing \"\(name)\" settings")
|
|
return nil
|
|
}
|
|
settingPresetSettings[path] = buildSettings
|
|
return buildSettings
|
|
}
|
|
}
|