Last active
December 28, 2016 22:39
-
-
Save pmairoldi/1b3ec373bd9f0f7d4b2be687463b7988 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'xcodeproj' | |
## PUBLIC INTERFACE ### | |
def project_name | |
'Moya' | |
end | |
def platforms | |
{ | |
macos: '10.11', | |
ios: '8.0', | |
tvos: '9.0', | |
watchos: '2.0' | |
} | |
end | |
def framework_search_paths | |
{ | |
macos: '$(SRCROOT)/Carthage/Build/Mac/ $(inherited)', | |
ios: '$(SRCROOT)/Carthage/Build/iOS/ $(inherited)', | |
tvos: '$(SRCROOT)/Carthage/Build/tvOS/ $(inherited)', | |
watchos: '$(SRCROOT)/Carthage/Build/watchOS/ $(inherited)' | |
} | |
end | |
def targets_to_generate | |
[ | |
{ | |
name: 'Moya', | |
info_plist: 'Supporting Files/Info.plist', | |
bundle_id: 'org.cocoapods.Moya', | |
framework_header: 'Supporting Files/Moya.h', | |
include_files: ['Source/**/*.*'], | |
exclude_files: ['Source/ReactiveSwift/**/*.*', 'Source/RxSwift/**/*.*'] | |
}, | |
{ | |
name: 'ReactiveMoya', | |
info_plist: 'Supporting Files/Info.plist', | |
bundle_id: 'org.cocoapods.ReactiveMoya', | |
framework_header: 'Supporting Files/ReactiveMoya.h', | |
include_files: ['Source/ReactiveSwift/**/*.*'], | |
exclude_files: [], | |
dependencies: ['Moya.framework'] | |
}, | |
{ | |
name: 'RxMoya', | |
info_plist: 'Supporting Files/Info.plist', | |
bundle_id: 'org.cocoapods.RxMoya', | |
framework_header: 'Supporting Files/RxMoya.h', | |
include_files: ['Source/RxSwift/**/*.*'], | |
exclude_files: [], | |
dependencies: ['Moya.framework'] | |
} | |
] | |
end | |
def language | |
:swift | |
end | |
def swift_version | |
3.0 | |
end | |
## PRIVATE INTERFACE ## | |
def supported_platforms(platforms, is_test_target = false) | |
platforms.keys | |
.reject { |platform| is_test_target && platform == :watchos } | |
.map { |platform| values_for_supported_platform(platform) } | |
.join(' ') | |
end | |
def values_for_supported_platform(platform) | |
case platform | |
when :macos | |
'macosx' | |
when :ios | |
'iphoneos iphonesimulator' | |
when :tvos | |
'appletvos appletvsimulator' | |
when :watchos | |
'watchos watchsimulator' | |
else | |
abort 'platform not supported!' | |
end | |
end | |
def project_path | |
project_name << '.xcodeproj' | |
end | |
def apply_general_build_settings(settings) | |
settings['SDKROOT'] = 'macosx' | |
settings['SUPPORTED_PLATFORMS'] = supported_platforms(platforms) | |
settings['TARGETED_DEVICE_FAMILY'] = '1,2,3,4' | |
settings['MACOSX_DEPLOYMENT_TARGET'] = platforms[:macos] | |
settings['IPHONEOS_DEPLOYMENT_TARGET'] = platforms[:ios] | |
settings['TVOS_DEPLOYMENT_TARGET'] = platforms[:tvos] | |
settings['WATCHOS_DEPLOYMENT_TARGET'] = platforms[:watchos] | |
settings['CODE_SIGN_IDENTITY'] = '' | |
settings['COMBINE_HIDPI_IMAGES'] = 'YES' | |
settings['FRAMEWORK_SEARCH_PATHS[sdk=macosx*]'] = framework_search_paths[:macos] | |
settings['FRAMEWORK_SEARCH_PATHS[sdk=iphone*]'] = framework_search_paths[:ios] | |
settings['FRAMEWORK_SEARCH_PATHS[sdk=appletv*]'] = framework_search_paths[:tvos] | |
settings['FRAMEWORK_SEARCH_PATHS[sdk=watch*]'] = framework_search_paths[:watchos] | |
settings['SWIFT_VERSION'] = swift_version | |
settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Owholemodule' | |
settings['CLANG_WARN_INFINITE_RECURSION'] = 'YES' | |
settings['CLANG_WARN_SUSPICIOUS_MOVE'] = 'YES' | |
settings['ENABLE_STRICT_OBJC_MSGSEND'] = 'YES' | |
settings['GCC_NO_COMMON_BLOCKS'] = 'YES' | |
end | |
def apply_test_build_settings(settings) | |
settings['SUPPORTED_PLATFORMS'] = supported_platforms(platforms, true) | |
settings['LD_RUNPATH_SEARCH_PATHS'] = '$(inherited) @executable_path/Frameworks @loader_path/Frameworks' | |
settings['LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]'] = '$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks' | |
end | |
def apply_target_build_settings(settings, target_settings) | |
settings.delete('CODE_SIGN_IDENTITY') | |
settings['INFOPLIST_FILE'] = target_settings[:info_plist] | |
settings['PRODUCT_BUNDLE_IDENTIFIER'] = target_settings[:bundle_id] | |
end | |
def paths_for_file(project, file) | |
[project.new_file(file)] | |
end | |
def find_group(project, path) | |
folder_path = File.dirname(path) | |
group = project.main_group.find_subpath(folder_path, true) | |
group | |
end | |
def add_framework_header(project, target, settings) | |
return unless settings.key?(:framework_header) | |
header_path = settings[:framework_header] | |
header_file_group = find_group(project, header_path) | |
header_file = header_file_group.new_reference(header_path) | |
header_build_file = target.headers_build_phase.add_file_reference(header_file, true) | |
header_build_file.settings ||= {} | |
header_build_file.settings['ATTRIBUTES'] = ['Public'] | |
end | |
def add_info_plist(project, settings) | |
info_plist_path = settings[:info_plist] | |
info_plist_group = find_group(project, info_plist_path) | |
has_info_plist = info_plist_group.find_file_by_path(info_plist_path) | |
info_plist_group.new_reference(settings[:info_plist]) unless has_info_plist | |
end | |
def add_supporting_files(project, target, settings) | |
add_info_plist(project, settings) | |
add_framework_header(project, target, settings) | |
end | |
def reject_excluded_files(exclude_files, path) | |
exclude_files.each do |files_to_exclude| | |
files_to_exclude.each do |file_to_exclude| | |
return true if File.fnmatch(file_to_exclude, path) | |
end | |
end | |
false | |
end | |
def add_source_files(project, target, settings) | |
exclude_files = settings[:exclude_files].map do |path| | |
Dir[path] | |
end | |
source_files = settings[:include_files].map do |path| | |
Dir[path].reject do |path| | |
reject_excluded_files(exclude_files, path) | |
end | |
end | |
source_files.each do |file_directory| | |
file_directory.each do |path| | |
source_file_group = find_group(project, path) | |
has_source_file = source_file_group.find_file_by_path(path) | |
unless has_source_file | |
source_file = source_file_group.new_reference(path) | |
target.source_build_phase.add_file_reference(source_file, true) | |
end | |
end | |
end | |
end | |
def add_dependencies(project, target, settings) | |
return unless settings.key?(:dependencies) | |
frameworks = settings[:dependencies].map do |name| | |
project.products.find { |x| x.path == name } | |
end | |
frameworks.each do |path| | |
target.frameworks_build_phase.add_file_reference(path, true) | |
end | |
end | |
def create_target(project, settings, type) | |
name = settings[:name] | |
# Target | |
target = project.new(Xcodeproj::Project::Object::PBXNativeTarget) | |
project.targets << target | |
target.name = name | |
target.product_name = name | |
target.product_type = Xcodeproj::Constants::PRODUCT_TYPE_UTI[type] | |
target.build_configuration_list = Xcodeproj::Project::ProjectHelper.configuration_list(project, :osx, nil, type, language) | |
add_supporting_files(project, target, settings) | |
add_source_files(project, target, settings) | |
target.build_configurations.each do |configuration| | |
apply_target_build_settings(configuration.build_settings, settings) | |
end | |
# Product | |
product = project.products_group.new_product_ref_for_target(name, type) | |
target.product_reference = product | |
# Build phases | |
target.build_phases << project.new(Xcodeproj::Project::Object::PBXSourcesBuildPhase) | |
target.build_phases << project.new(Xcodeproj::Project::Object::PBXFrameworksBuildPhase) | |
# Dependencies | |
add_dependencies(project, target, settings) | |
end | |
def update_schemes(project, targets) | |
project.recreate_user_schemes | |
targets.each do |target_settings| | |
Xcodeproj::XCScheme.share_scheme(project_path, target_settings[:name]) | |
end | |
end | |
## Script ## | |
project = Xcodeproj::Project.new(project_path) | |
targets_to_generate.each do |target_settings| | |
target = create_target(project, target_settings, :framework) | |
next unless target_settings.key?(:test_target) | |
unit_test_settings = target_settings[:test_target] | |
test_target = create_target(project, unit_test_settings, :unit_test_bundle) | |
test_target.add_dependency(target) | |
end | |
project.build_configurations.each do |configuration| | |
apply_general_build_settings(configuration.build_settings) | |
end | |
project.native_targets.each do |target| | |
next unless target.test_target_type? | |
target.build_configurations.each do |configuration| | |
apply_test_build_settings(configuration.build_settings) | |
end | |
end | |
update_schemes(project, targets_to_generate) | |
project.save |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment