Skip to content

Instantly share code, notes, and snippets.

@pmairoldi
Last active December 28, 2016 22:39
Show Gist options
  • Save pmairoldi/1b3ec373bd9f0f7d4b2be687463b7988 to your computer and use it in GitHub Desktop.
Save pmairoldi/1b3ec373bd9f0f7d4b2be687463b7988 to your computer and use it in GitHub Desktop.
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