├── .clang-format ├── .gitignore ├── Configurations ├── Common.xcconfig ├── Platform │ ├── iOS.xcconfig │ ├── macOS.xcconfig │ ├── tvOS.xcconfig │ └── watchOS.xcconfig ├── Product │ ├── Application.xcconfig │ ├── DynamicFramework.xcconfig │ ├── LogicTests.xcconfig │ └── StaticFramework.xcconfig ├── Project │ ├── Debug.xcconfig │ └── Release.xcconfig └── Warnings.xcconfig ├── README.md └── Scripts └── xctask ├── build_framework_task.rb └── build_task.rb /.clang-format: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-present, Parse, LLC. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | --- 9 | Language: Cpp 10 | BasedOnStyle: LLVM 11 | AccessModifierOffset: -2 12 | AlignAfterOpenBracket: true 13 | AlignEscapedNewlinesLeft: true 14 | AlignOperands: true 15 | AlignTrailingComments: false 16 | AllowAllParametersOfDeclarationOnNextLine: false 17 | AllowShortBlocksOnASingleLine: false 18 | AllowShortCaseLabelsOnASingleLine: false 19 | AllowShortIfStatementsOnASingleLine: true 20 | AllowShortLoopsOnASingleLine: false 21 | AllowShortFunctionsOnASingleLine: false 22 | AlwaysBreakAfterDefinitionReturnType: false 23 | AlwaysBreakTemplateDeclarations: false 24 | AlwaysBreakBeforeMultilineStrings: false 25 | BreakBeforeBinaryOperators: None 26 | BreakBeforeTernaryOperators: true 27 | BreakConstructorInitializersBeforeComma: true 28 | BinPackParameters: true 29 | BinPackArguments: true 30 | ColumnLimit: 0 31 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 32 | ConstructorInitializerIndentWidth: 4 33 | DerivePointerAlignment: true 34 | ExperimentalAutoDetectBinPacking: true 35 | IndentCaseLabels: true 36 | IndentWrappedFunctionNames: true 37 | IndentFunctionDeclarationAfterType: true 38 | MaxEmptyLinesToKeep: 1 39 | KeepEmptyLinesAtTheStartOfBlocks: true 40 | NamespaceIndentation: None 41 | ObjCBlockIndentWidth: 4 42 | ObjCSpaceAfterProperty: true 43 | ObjCSpaceBeforeProtocolList: true 44 | PenaltyBreakBeforeFirstCallParameter: 19 45 | PenaltyBreakComment: 300 46 | PenaltyBreakString: 1000 47 | PenaltyBreakFirstLessLess: 140 48 | PenaltyExcessCharacter: 1000000 49 | PenaltyReturnTypeOnItsOwnLine: 120 50 | PointerAlignment: Right 51 | SpacesBeforeTrailingComments: 1 52 | Cpp11BracedListStyle: true 53 | Standard: Cpp11 54 | IndentWidth: 4 55 | TabWidth: 4 56 | UseTab: Never 57 | BreakBeforeBraces: Attach 58 | SpacesInParentheses: false 59 | SpacesInSquareBrackets: false 60 | SpacesInAngles: false 61 | SpaceInEmptyParentheses: false 62 | SpacesInCStyleCastParentheses: false 63 | SpaceAfterCStyleCast: false 64 | SpacesInContainerLiterals: true 65 | SpaceBeforeAssignmentOperators: true 66 | ContinuationIndentWidth: 4 67 | CommentPragmas: '^ IWYU pragma:' 68 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 69 | SpaceBeforeParens: ControlStatements 70 | DisableFormat: false 71 | ... 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Carthage/Build 3 | -------------------------------------------------------------------------------- /Configurations/Common.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | #include "Warnings.xcconfig" 11 | 12 | // Disable legacy-compatible header searching 13 | ALWAYS_SEARCH_USER_PATHS = NO 14 | 15 | // Architectures to build 16 | ARCHS = $(ARCHS_STANDARD) 17 | 18 | // Whether to enable module imports 19 | CLANG_ENABLE_MODULES = YES 20 | CLANG_ENABLE_MODULE_DEBUGGING = NO 21 | 22 | // Build Options 23 | CLANG_ENABLE_OBJC_ARC = YES 24 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0 25 | 26 | // Whether to strip out code that isn't called from anywhere 27 | DEAD_CODE_STRIPPING = NO 28 | 29 | // The format of debugging symbols 30 | DEBUG_INFORMATION_FORMAT = dwarf-with-dsym 31 | 32 | // C Language 33 | GCC_C_LANGUAGE_STANDARD = gnu11 34 | 35 | // C++ Language 36 | CLANG_CXX_LANGUAGE_STANDARD = gnu++14 37 | CLANG_CXX_LIBRARY = libc++ 38 | 39 | // Code Generation 40 | GCC_DYNAMIC_NO_PIC = NO 41 | GCC_INLINES_ARE_PRIVATE_EXTERN = YES 42 | GCC_NO_COMMON_BLOCKS = YES 43 | GCC_SYMBOLS_PRIVATE_EXTERN = NO 44 | 45 | // Static Analyzer - Analysis Policy 46 | RUN_CLANG_STATIC_ANALYZER = YES 47 | CLANG_STATIC_ANALYZER_MODE_ON_ANALYZE_ACTION = deep 48 | CLANG_STATIC_ANALYZER_MODE = shallow 49 | -------------------------------------------------------------------------------- /Configurations/Platform/iOS.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | SDKROOT = iphoneos 11 | IPHONEOS_DEPLOYMENT_TARGET = 7.0 12 | 13 | // Supported device families (1 is iPhone, 2 is iPad, 3 is Apple TV) 14 | TARGETED_DEVICE_FAMILY = 1,2 15 | 16 | // Where to find embedded frameworks 17 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks 18 | -------------------------------------------------------------------------------- /Configurations/Platform/macOS.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | SDKROOT = macosx 11 | MACOSX_DEPLOYMENT_TARGET = 10.9 12 | 13 | // Where to find embedded frameworks 14 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_path/../Frameworks 15 | -------------------------------------------------------------------------------- /Configurations/Platform/tvOS.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | SDKROOT = appletvos 11 | TVOS_DEPLOYMENT_TARGET = 9.0 12 | 13 | // Supported device families (1 is iPhone, 2 is iPad, 3 is Apple TV) 14 | TARGETED_DEVICE_FAMILY = 3 15 | 16 | // Where to find embedded frameworks 17 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks 18 | -------------------------------------------------------------------------------- /Configurations/Platform/watchOS.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | SDKROOT = watchos 11 | WATCHOS_DEPLOYMENT_TARGET = 2.0 12 | 13 | // Supported device families (1 is iPhone, 2 is iPad, 3 is Apple TV, 4 is watch) 14 | TARGETED_DEVICE_FAMILY = 4 15 | 16 | // Where to find embedded frameworks 17 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks 18 | -------------------------------------------------------------------------------- /Configurations/Product/Application.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | // Whether to strip out code that isn't called from anywhere 11 | DEAD_CODE_STRIPPING = NO 12 | 13 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon 14 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage 15 | 16 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @loader_path/Frameworks @executable_path/Frameworks 17 | -------------------------------------------------------------------------------- /Configurations/Product/DynamicFramework.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | // Dynamic frameworks are backed by dynamic library. 11 | MACH_O_TYPE = mh_dylib 12 | 13 | // Whether this framework should define an LLVM module 14 | DEFINES_MODULE = YES 15 | 16 | // Disable clang modules autolink 17 | CLANG_MODULES_AUTOLINK = NO 18 | 19 | // Whether to strip out code that isn't called from anywhere 20 | DEAD_CODE_STRIPPING = NO 21 | 22 | // Whether function calls should be position-dependent (should always be disabled for shared code) 23 | GCC_DYNAMIC_NO_PIC = NO 24 | 25 | // Don't include in an xcarchive 26 | SKIP_INSTALL = YES 27 | 28 | // Don't install in any specific location 29 | INSTALL_PATH = 30 | 31 | // Do not require code signing 32 | CODE_SIGNING_REQUIRED = NO 33 | 34 | // Disable code signing 35 | CODE_SIGN_IDENTITY = 36 | 37 | // Enables the framework to be included from any location as long as the loader’s runpath search paths includes it. 38 | // For example from an application bundle (inside the "Frameworks" folder) or shared folder. 39 | LD_DYLIB_INSTALL_NAME = @rpath/$(PRODUCT_NAME).$(WRAPPER_EXTENSION)/$(PRODUCT_NAME) 40 | DYLIB_INSTALL_NAME_BASE = @rpath 41 | -------------------------------------------------------------------------------- /Configurations/Product/LogicTests.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | BUNDLE_LOADER = $(TEST_HOST) 11 | 12 | OTHER_LDFLAGS = $(inherited) -ObjC -framework XCTest 13 | -------------------------------------------------------------------------------- /Configurations/Product/StaticFramework.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | // Static frameworks are backed by static libraries 11 | MACH_O_TYPE = staticlib 12 | 13 | // Whether this framework should define an LLVM module 14 | DEFINES_MODULE = YES 15 | 16 | // Disable clang modules autolink 17 | CLANG_MODULES_AUTOLINK = NO 18 | 19 | // Whether to strip out code that isn't called from anywhere 20 | DEAD_CODE_STRIPPING = NO 21 | 22 | // Whether function calls should be position-dependent (should always be disabled for shared code) 23 | GCC_DYNAMIC_NO_PIC = NO 24 | 25 | // Enables the framework to be included from any location as long as the loader’s runpath search paths includes it. 26 | // For example from an application bundle (inside the "Frameworks" folder) or shared folder 27 | INSTALL_PATH = @rpath 28 | 29 | // Don't include in an xcarchive 30 | SKIP_INSTALL = YES 31 | 32 | // Do not require code signing 33 | CODE_SIGNING_REQUIRED = NO 34 | 35 | // Disable code signing 36 | CODE_SIGN_IDENTITY = 37 | -------------------------------------------------------------------------------- /Configurations/Project/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | #include "../Common.xcconfig" 11 | 12 | // Architectures 13 | ONLY_ACTIVE_ARCH = YES 14 | 15 | // Optimization 16 | GCC_OPTIMIZATION_LEVEL = 0 17 | SWIFT_OPTIMIZATION_LEVEL = -Onone 18 | 19 | // Preprocessor 20 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited) 21 | ENABLE_NS_ASSERTIONS = YES 22 | 23 | // Testability 24 | ENABLE_TESTABILITY = YES 25 | 26 | // Deployment 27 | COPY_PHASE_STRIP = NO 28 | 29 | SANITIZE_FLAGS = -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap 30 | OTHER_CFLAGS = $(value) $(SANITIZE_FLAGS) 31 | OTHER_LDFLAGS = $(value) $(SANITIZE_FLAGS) 32 | -------------------------------------------------------------------------------- /Configurations/Project/Release.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | #include "../Common.xcconfig" 11 | 12 | // Architectures 13 | ONLY_ACTIVE_ARCH = NO 14 | 15 | // Build 16 | VALIDATE_PRODUCT = YES 17 | 18 | // Optimization 19 | GCC_OPTIMIZATION_LEVEL = s 20 | SWIFT_OPTIMIZATION_LEVEL = -Owholemodule 21 | 22 | // Preprocessor 23 | ENABLE_NS_ASSERTIONS = NO 24 | 25 | // Deployment 26 | DEPLOYMENT_POSTPROCESSING = YES 27 | COPY_PHASE_STRIP = YES 28 | STRIP_STYLE = debugging 29 | STRIP_INSTALLED_PRODUCT = YES 30 | -------------------------------------------------------------------------------- /Configurations/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015-present, Parse, LLC. 3 | // All rights reserved. 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. An additional grant 7 | // of patent rights can be found in the PATENTS file in the same directory. 8 | // 9 | 10 | ENABLE_STRICT_OBJC_MSGSEND = YES 11 | 12 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES 13 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES 14 | GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES 15 | GCC_WARN_CHECK_SWITCH_STATEMENTS = YES 16 | GCC_WARN_MISSING_PARENTHESES = YES 17 | GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES 18 | GCC_WARN_UNKNOWN_PRAGMAS = YES 19 | GCC_WARN_UNUSED_FUNCTION = YES 20 | GCC_WARN_UNUSED_LABEL = YES 21 | GCC_WARN_UNUSED_VALUE = YES 22 | GCC_WARN_UNUSED_VARIABLE = YES 23 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES 24 | GCC_WARN_UNDECLARED_SELECTOR = YES 25 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES 26 | GCC_WARN_UNINITIALIZED_AUTOS = YES 27 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES 28 | GCC_WARN_SHADOW = YES 29 | 30 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES 31 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 32 | CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES 33 | CLANG_WARN_BOOL_CONVERSION = YES 34 | CLANG_WARN_CONSTANT_CONVERSION = YES 35 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES 36 | CLANG_WARN_EMPTY_BODY = YES 37 | CLANG_WARN_ENUM_CONVERSION = YES 38 | CLANG_WARN_UNREACHABLE_CODE = YES 39 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 40 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES 41 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES 42 | CLANG_WARN_BOOL_CONVERSION = YES 43 | CLANG_WARN_INFINITE_RECURSION = YES 44 | CLANG_WARN_SUSPICIOUS_MOVE = YES 45 | 46 | // Errors 47 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR 48 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR 49 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR 50 | 51 | // Static Analyzer Warnings 52 | CLANG_ANALYZER_NONNULL = YES 53 | CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES 54 | 55 | // 56 | // Extra warnings, not available directly in build settings. 57 | // 'auto-import' - warns when an old-style hashed import could be replaced with modular import aka @import. 58 | // 'switch-enum' - enforces explicit handling of cases in switch statements. 59 | // 'method-signatures' - enforces method signatures to always match. 60 | // 'idiomatic-parentheses' - do not allow usage of an assignment as a condition without extra paranthesis. 61 | // 'covered-switch-default' - warns when implementing 'default' case in switch statement that covers all options. 62 | // 'custom-atomic-properties' - safeguards atomic properties with custom implementations. 63 | // 'cstring-format-directive' - do not allow NSString * to be used as c-string formatting argument aka '%s'. 64 | // 'conditional-uninitialized' - warn about potential use of of uninitialized variables. 65 | // 'unused-exception-parameter' - @try @catch without usage of exception parameter. 66 | // 'missing-variable-declarations' - will mark all variables that are missing declarations, including non-static extern constants. 67 | // 68 | WARNING_CFLAGS = $(inherited) -Wswitch-enum -Wmethod-signatures -Widiomatic-parentheses -Wcustom-atomic-properties -Wconditional-uninitialized -Wunused-exception-parameter -Wmissing-variable-declarations 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xctoolchain 2 | Common configuration files and scripts that are used to build our SDKs with Xcode. 3 | -------------------------------------------------------------------------------- /Scripts/xctask/build_framework_task.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Copyright (c) 2015-present, Parse, LLC. 4 | # All rights reserved. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. An additional grant 8 | # of patent rights can be found in the PATENTS file in the same directory. 9 | # 10 | 11 | require 'naturally' 12 | require_relative 'build_task' 13 | 14 | module XCTask 15 | # This class defines all possible framework types for BuildFrameworkTask. 16 | class FrameworkType 17 | IOS = 'ios' 18 | OSX = 'osx' 19 | WATCHOS = 'watchos' 20 | TVOS = 'tvos' 21 | 22 | def self.verify(type) 23 | if type.nil? || (type != IOS && type != OSX && type != WATCHOS && type != TVOS) 24 | fail "Unknown framework type. Available types: 'ios', 'osx', 'watchos', 'tvos'." 25 | end 26 | end 27 | end 28 | 29 | # This class adds ability to easily configure a building of iOS/OSX framework and execute the build process. 30 | class BuildFrameworkTask 31 | attr_accessor :directory 32 | attr_accessor :build_directory 33 | attr_accessor :framework_type 34 | attr_accessor :framework_name 35 | 36 | attr_accessor :workspace 37 | attr_accessor :project 38 | attr_accessor :scheme 39 | attr_accessor :configuration 40 | 41 | def initialize 42 | @directory = '.' 43 | @build_directory = './build' 44 | yield self if block_given? 45 | end 46 | 47 | def execute 48 | verify 49 | prepare_build 50 | build 51 | end 52 | 53 | private 54 | 55 | def verify 56 | FrameworkType.verify(@framework_type) 57 | end 58 | 59 | def prepare_build 60 | Dir.chdir(@directory) unless @directory.nil? 61 | end 62 | 63 | def build 64 | case @framework_type 65 | when FrameworkType::IOS 66 | build_ios_framework 67 | when FrameworkType::OSX 68 | build_osx_framework 69 | when FrameworkType::WATCHOS 70 | build_watchos_framework 71 | when FrameworkType::TVOS 72 | build_tvos_framework 73 | end 74 | end 75 | 76 | def build_ios_framework 77 | framework_paths = [] 78 | framework_paths << build_framework('iphoneos') 79 | framework_paths << build_framework('iphonesimulator', '"platform=iOS Simulator,name=iPhone 6s"') 80 | final_path = final_framework_path 81 | 82 | system("rm -rf #{final_path} && cp -R #{framework_paths[0]} #{final_path}") 83 | 84 | binary_name = File.basename(@framework_name, '.framework') 85 | system("rm -rf #{final_path}/#{binary_name}") 86 | 87 | lipo_command = 'lipo -create' 88 | framework_paths.each do |path| 89 | lipo_command += " #{path}/#{binary_name}" 90 | end 91 | lipo_command += " -o #{final_path}/#{binary_name}" 92 | 93 | result = system(lipo_command) 94 | unless result 95 | puts 'Failed to lipo iOS framework.' 96 | exit(1) 97 | end 98 | result 99 | end 100 | 101 | def build_watchos_framework 102 | framework_paths = [] 103 | framework_paths << build_framework('watchos') 104 | framework_paths << build_framework('watchsimulator', '"platform=watchOS Simulator,name=Apple Watch - 42mm"') 105 | final_path = final_framework_path 106 | 107 | system("rm -rf #{final_path} && cp -R #{framework_paths[0]} #{final_path}") 108 | 109 | binary_name = File.basename(@framework_name, '.framework') 110 | system("rm -rf #{final_path}/#{binary_name}") 111 | 112 | lipo_command = 'lipo -create' 113 | framework_paths.each do |path| 114 | lipo_command += " #{path}/#{binary_name}" 115 | end 116 | lipo_command += " -o #{final_path}/#{binary_name}" 117 | 118 | result = system(lipo_command) 119 | unless result 120 | puts 'Failed to lipo watchOS framework.' 121 | exit(1) 122 | end 123 | result 124 | end 125 | 126 | def build_tvos_framework 127 | framework_paths = [] 128 | framework_paths << build_framework('appletvos') 129 | framework_paths << build_framework('appletvsimulator', '"platform=tvOS Simulator,name=Apple TV 1080p"') 130 | final_path = final_framework_path 131 | 132 | system("rm -rf #{final_path} && cp -R #{framework_paths[0]} #{final_path}") 133 | 134 | binary_name = File.basename(@framework_name, '.framework') 135 | system("rm -rf #{final_path}/#{binary_name}") 136 | 137 | lipo_command = 'lipo -create' 138 | framework_paths.each do |path| 139 | lipo_command += " #{path}/#{binary_name}" 140 | end 141 | lipo_command += " -o #{final_path}/#{binary_name}" 142 | 143 | result = system(lipo_command) 144 | unless result 145 | puts 'Failed to lipo tvOS framework.' 146 | exit(1) 147 | end 148 | result 149 | end 150 | 151 | def build_osx_framework 152 | build_path = build_framework('macosx') 153 | final_path = final_framework_path 154 | system("rm -rf #{final_path} && cp -R #{build_path} #{final_path}") 155 | end 156 | 157 | def build_framework(sdk, destination = nil) 158 | configuration_directory = configuration_build_directory(sdk) 159 | build_task = BuildTask.new do |t| 160 | t.directory = @directory 161 | t.project = @project 162 | t.workspace = @workspace 163 | 164 | t.scheme = @scheme 165 | t.sdk = latest_sdk(sdk) 166 | t.configuration = @configuration 167 | t.destinations = [destination] unless destination.nil? 168 | 169 | t.actions = [BuildAction::CLEAN, BuildAction::BUILD] 170 | t.formatter = BuildFormatter::XCPRETTY 171 | 172 | t.additional_options = { 'CONFIGURATION_BUILD_DIR' => "'#{configuration_directory}'" } 173 | end 174 | 175 | result = build_task.execute 176 | unless result 177 | puts "Failed to build framework for #{sdk}." 178 | exit(1) 179 | end 180 | 181 | "#{configuration_directory}/#{@framework_name}" 182 | end 183 | 184 | def latest_sdk(platform) 185 | sdks = Naturally.sort(`xcodebuild -showsdks`.scan(/-sdk (.*)$/)).reverse.flatten 186 | sdks.select { |s| s =~ /#{platform}/ }[0] 187 | end 188 | 189 | def configuration_build_directory(sdk) 190 | "#{@build_directory}/#{@configuration}-#{@framework_type}-#{sdk}" 191 | end 192 | 193 | def final_framework_path 194 | "#{@build_directory}/#{@framework_name}" 195 | end 196 | end 197 | end 198 | -------------------------------------------------------------------------------- /Scripts/xctask/build_task.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Copyright (c) 2015-present, Parse, LLC. 4 | # All rights reserved. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. An additional grant 8 | # of patent rights can be found in the PATENTS file in the same directory. 9 | # 10 | 11 | module XCTask 12 | # This class defines all possible build formatters for BuildTask. 13 | class BuildFormatter 14 | XCODEBUILD = 'xcodebuild' 15 | XCPRETTY = 'xcpretty' 16 | XCTOOL = 'xctool' 17 | 18 | def self.verify(formatter) 19 | if formatter && 20 | formatter != XCPRETTY && 21 | formatter != XCODEBUILD && 22 | formatter != XCTOOL 23 | fail "Unknown formatter used. Available formatters: 'xcodebuild', 'xcpretty', 'xctool'." 24 | end 25 | end 26 | end 27 | 28 | # This class defines all possible build actions for BuildTask. 29 | class BuildAction 30 | BUILD = 'build' 31 | CLEAN = 'clean' 32 | TEST = 'test' 33 | ANALYZE = 'analyze' 34 | 35 | def self.verify(action) 36 | if action.nil? || 37 | (action != BUILD && 38 | action != CLEAN && 39 | action != TEST && 40 | action != ANALYZE) 41 | fail "Unknown build action used. Available actions: 'build', 'clean', 'test', 'analyze'." 42 | end 43 | end 44 | end 45 | 46 | # This class adds ability to easily configure a xcodebuild task and execute it. 47 | class BuildTask 48 | attr_accessor :directory 49 | attr_accessor :workspace 50 | attr_accessor :project 51 | 52 | attr_accessor :scheme 53 | attr_accessor :sdk 54 | attr_accessor :configuration 55 | attr_accessor :destinations 56 | 57 | attr_accessor :additional_options 58 | attr_accessor :actions 59 | attr_accessor :formatter 60 | 61 | attr_accessor :reports_enabled 62 | 63 | def initialize 64 | @directory = '.' 65 | @destinations = [] 66 | @additional_options = {} 67 | 68 | yield self if block_given? 69 | end 70 | 71 | def execute 72 | verify 73 | prepare_build 74 | build 75 | end 76 | 77 | private 78 | 79 | def verify 80 | BuildFormatter.verify(@formatter) 81 | @actions.each do |action| 82 | BuildAction.verify(action) 83 | end 84 | end 85 | 86 | def prepare_build 87 | Dir.chdir(@directory) unless @directory.nil? 88 | end 89 | 90 | def build 91 | system(build_command_string(@formatter)) 92 | end 93 | 94 | def build_command_string(formatter) 95 | command_string = nil 96 | 97 | case formatter 98 | when BuildFormatter::XCODEBUILD 99 | command_string = 'xcodebuild ' + build_options_string 100 | when BuildFormatter::XCPRETTY 101 | command_string = build_command_string('xcodebuild') + ' | xcpretty -c' 102 | if @actions.include? BuildAction::TEST 103 | command_string += " --report junit --output build/reports/#{@sdk}.xml" 104 | end 105 | command_string += ' ; exit ${PIPESTATUS[0]}' 106 | when BuildFormatter::XCTOOL 107 | command_string = 'xctool ' + build_options_string 108 | else 109 | command_string = build_command_string(BuildFormatter::XCODEBUILD) 110 | end 111 | 112 | command_string 113 | end 114 | 115 | def build_options_string 116 | opts = [] 117 | opts << "-workspace #{@workspace}" if @workspace 118 | opts << "-project #{@project}" if @project 119 | opts << "-scheme #{@scheme}" if @scheme 120 | opts << "-sdk #{@sdk}" if @sdk 121 | opts << "-configuration #{@configuration}" if @configuration 122 | @destinations.each do |d| 123 | opts << "-destination #{d}" 124 | end 125 | opts << @actions.compact.join(' ') if @actions 126 | 127 | @additional_options.each do |key, value| 128 | opts << "#{key}=#{value}" 129 | end 130 | 131 | opts.compact.join(' ') 132 | end 133 | end 134 | end 135 | --------------------------------------------------------------------------------