#!/usr/bin/swift // This script is originally from github.com/olofhellman/VerifyNoBS // The idea is that all build settings should be kept in .xcconfig files, // rather than in the xcode pbxproj file inside an Xcode project bundle // Having the script run as part of a regular build ensures that the project file // doesn't accidentally accumulate build settings import Darwin import Foundation func reportError(message: String) { print("error message was \(message)") let stderr = FileHandle.standardError if let data = message.data(using: String.Encoding.utf8, allowLossyConversion: false) { stderr.write(data) } else { print("there was an error. script \"VerifyNoBuildSettings\" could not convert error message to printable string") } } public enum ProcessXcodeprojResult { case FoundBuildSettings([String]) case Error(String) case OK(String) } public func processXcodeprojAt(url: URL) -> ProcessXcodeprojResult { let startTime = Date() guard let xcodeproj = try? String(contentsOf: url, encoding: String.Encoding.utf8) else { return .Error("script \"VerifyNoBuildSettings\" failed making xcodeproj from url") } let lines = xcodeproj.components(separatedBy: CharacterSet.newlines) print ("found \(lines.count) lines") var badLines: [String] = [] var inBuildSettingsBlock = false for nthLine in lines { if inBuildSettingsBlock { if let _ = nthLine.range(of:"\\u007d[:space:]*;", options: .regularExpression) { inBuildSettingsBlock = false } else if let _ = nthLine.range(of:"CODE_SIGN_IDENTITY") { } else if let _ = nthLine.range(of:"PRODUCT_NAME") { } else { badLines.append(nthLine) } } else { if let _ = nthLine.range(of:"buildSettings[:space:]*=", options: .regularExpression) { inBuildSettingsBlock = true } } } let timeInterval = Date().timeIntervalSince(startTime) print ("process took \(timeInterval) seconds") if (badLines.count > 0) { return .FoundBuildSettings(badLines) } return .OK(":-)") } print("Verifying no buildSettings...") let commandLineArgs = CommandLine.arguments print("processArgs were \(commandLineArgs)") let xcodeprojfilepath = commandLineArgs[1] let myUrl = URL(fileURLWithPath:xcodeprojfilepath) let result = processXcodeprojAt(url: myUrl) switch result { case .Error(let str): reportError (message: "error script \"VerifyNoBuildSettings\" encountered an error: \(str)") exit(EXIT_FAILURE) case .FoundBuildSettings(let badLines): reportError (message: "script \"VerifyNoBuildSettings\" found build settings in the project file:") for badLine in badLines { reportError (message: " \(badLine)\n") } exit(EXIT_FAILURE) case .OK: print ("script \"VerifyNoBuildSettings\" verified the project contained no buildSettings") exit(EXIT_SUCCESS) }