cocoapods-alexandria 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/cocoapods-alexandria.rb +1 -0
- data/lib/cocoapods-alexandria/env_ci/post_install.rb +28 -0
- data/lib/cocoapods-alexandria/env_ci/pre_install.rb +29 -0
- data/lib/cocoapods-alexandria/env_local/post_install.rb +38 -0
- data/lib/cocoapods-alexandria/env_local/pre_install.rb +24 -0
- data/lib/cocoapods-alexandria/gem_version.rb +3 -0
- data/lib/cocoapods-alexandria/helper/environment.rb +3 -0
- data/lib/cocoapods-alexandria/helper/podfile.rb +14 -0
- data/lib/cocoapods-alexandria/helper/user_options.rb +37 -0
- data/lib/cocoapods-alexandria/helper/xcodeproj.rb +27 -0
- data/lib/cocoapods-alexandria/main.rb +18 -0
- data/lib/cocoapods-alexandria/register_hooks.rb +15 -0
- data/lib/cocoapods-alexandria/rome/compiler.rb +70 -0
- data/lib/cocoapods-alexandria/rome/framework_cache.rb +117 -0
- data/lib/cocoapods-alexandria/rome/lockfile.rb +68 -0
- data/lib/cocoapods-alexandria/xcodegen/dependencies_generator.rb +51 -0
- data/lib/cocoapods-alexandria/xcodegen/dependency.rb +54 -0
- data/lib/cocoapods-alexandria/xcodegen/xcodegen.rb +21 -0
- data/lib/cocoapods_plugin.rb +1 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e638279de826395aa7ac4b217a85b16fb8fe255161a418d1c185157594715339
|
4
|
+
data.tar.gz: b42e571938bd4f2ae2f701c393d0f7518ef53169c89db75419e5b40627b7367b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 86d6d34039cafc3dab302c23d86d96c36fdb1c4b63b8f337432fc1bc0f7bb39b41cad86ed9ecab0bf2ee4d684d65c81379193b8793d318a912833aefa19402de
|
7
|
+
data.tar.gz: b0aedadd56ae7a45bfef37197c92ccf2c0292d2e180c711c709abc9b54bd0cbed310257f7a7cc251e99d4893e9950ab2f3e722754d4ebe42d9bacd2e2ce7efdf
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-alexandria/gem_version'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class CIPostInstallHook
|
3
|
+
attr_reader :installer_context, :pods_project, :cache, :options
|
4
|
+
|
5
|
+
def initialize(installer_context, user_options)
|
6
|
+
@installer_context = installer_context
|
7
|
+
@pods_project = installer_context.pods_project
|
8
|
+
@cache = FrameworkCache.new(installer_context)
|
9
|
+
@options = UserOptions.new(installer_context, user_options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
Pod::UI.title "Compile dependencies"
|
14
|
+
|
15
|
+
if options.force_bitcode
|
16
|
+
Pod::UI.puts "Forcing bitcode generation"
|
17
|
+
pods_project.force_bitcode_generation
|
18
|
+
end
|
19
|
+
cache.delete_changed_frameworks
|
20
|
+
cache.build_frameworks
|
21
|
+
cache.cache_lockfile
|
22
|
+
|
23
|
+
Pod::UI.title "Generating project using XcodeGen"
|
24
|
+
XcodeGen::generate_dependencies(installer_context, options)
|
25
|
+
XcodeGen::generate
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class CIPreInstallHook
|
3
|
+
attr_reader :podfile, :options
|
4
|
+
|
5
|
+
def initialize(installer_context, user_options)
|
6
|
+
@podfile = installer_context.podfile
|
7
|
+
@options = UserOptions.new(installer_context, user_options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
Pod::UI.puts "Cocoapods Alexandria running in CI mode."
|
12
|
+
|
13
|
+
Pod::UI.title "Preparing environment..."
|
14
|
+
podfile.prepare_for_xcodegen
|
15
|
+
podfile.disable_integration
|
16
|
+
delete_workspace
|
17
|
+
|
18
|
+
Pod::UI.title "Continuing with normal CocoaPods"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def delete_workspace
|
24
|
+
Dir['*.xcworkspace'].each do |workspace|
|
25
|
+
FileUtils.remove_dir(workspace, force: true)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class LocalPostInstallHook
|
3
|
+
attr_reader :pods_project, :sandbox_root, :umbrella_targets, :options
|
4
|
+
|
5
|
+
def initialize(installer_context, user_options)
|
6
|
+
@pods_project = installer_context.pods_project
|
7
|
+
@sandbox_root = installer_context.sandbox_root
|
8
|
+
@umbrella_targets = installer_context.umbrella_targets
|
9
|
+
@options = UserOptions.new(installer_context, user_options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
Pod::UI.title "Tweaking CocoaPods for XcodeGen..."
|
14
|
+
pods_project.fix_deployment_target_warnings
|
15
|
+
include_user_configs_in_pods_xcconfigs
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def include_user_configs_in_pods_xcconfigs
|
21
|
+
umbrella_targets.each do |target|
|
22
|
+
pods_project.configurations.each do |config|
|
23
|
+
config_path = options.environment_configs_for(target.cocoapods_target_label)[config]
|
24
|
+
append_include_to_config(target, config, config_path)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def append_include_to_config(target, config, include)
|
30
|
+
xcconfig = "#{sandbox_root}/Target Support Files/#{target.cocoapods_target_label}/#{target.cocoapods_target_label}.#{config.downcase}.xcconfig"
|
31
|
+
|
32
|
+
File.open(xcconfig, 'a') do |f|
|
33
|
+
f.puts ''
|
34
|
+
f.puts "#include \"../../../#{include}\""
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class LocalPreInstallHook
|
3
|
+
attr_reader :podfile, :options
|
4
|
+
|
5
|
+
def initialize(installer_context, user_options)
|
6
|
+
@podfile = installer_context.podfile
|
7
|
+
@options = UserOptions.new(installer_context, user_options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
Pod::UI.puts "Cocoapods Alexandria running in local mode."
|
12
|
+
|
13
|
+
Pod::UI.title "Generating project using XcodeGen"
|
14
|
+
XcodeGen::cleanupRome
|
15
|
+
XcodeGen::clearDependencies(options.xcodegen_dependencies_file)
|
16
|
+
XcodeGen::generate
|
17
|
+
|
18
|
+
Pod::UI.title "Preparing environment..."
|
19
|
+
podfile.prepare_for_xcodegen
|
20
|
+
|
21
|
+
Pod::UI.title "Continuing with normal CocoaPods"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class UserOptions
|
3
|
+
attr_reader :environment_configs
|
4
|
+
attr_reader :force_bitcode
|
5
|
+
attr_reader :xcodegen_dependencies_file
|
6
|
+
|
7
|
+
def initialize(installer_context, user_options)
|
8
|
+
@environment_configs = user_options.fetch('environment_configs', default_configurations(installer_context))
|
9
|
+
@force_bitcode = user_options.fetch('force_bitcode', true)
|
10
|
+
@xcodegen_dependencies_file = user_options.fetch('xcodegen_dependencies_file', 'projectDependencies.yml')
|
11
|
+
end
|
12
|
+
|
13
|
+
def environment_configs_for(target)
|
14
|
+
environment_configs[normalize_target(target)]
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def default_configurations(installer_context)
|
20
|
+
if installer_context.respond_to? :umbrella_targets
|
21
|
+
installer_context.umbrella_targets.map { |target|
|
22
|
+
target_name = normalize_target(target.cocoapods_target_label)
|
23
|
+
configs = installer_context.pods_project.configurations
|
24
|
+
.map { |config| [config, "Supporting Files/Settings-#{config.gsub('-', ' ').split[0]}.xcconfig"] }
|
25
|
+
.to_h
|
26
|
+
[target_name, configs]
|
27
|
+
}.to_h
|
28
|
+
else
|
29
|
+
{}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def normalize_target(target)
|
34
|
+
target.sub(/^Pods-/, '')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Xcodeproj
|
2
|
+
class Project
|
3
|
+
def configurations
|
4
|
+
build_configurations
|
5
|
+
.map(&:name)
|
6
|
+
.reject { |c| ['Debug', 'Release'].include? c }
|
7
|
+
end
|
8
|
+
|
9
|
+
def fix_deployment_target_warnings
|
10
|
+
targets.each do |target|
|
11
|
+
target.build_configurations.each do |config|
|
12
|
+
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] == '8.0'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
save
|
16
|
+
end
|
17
|
+
|
18
|
+
def force_bitcode_generation
|
19
|
+
targets.each do |target|
|
20
|
+
target.build_configurations.each do |config|
|
21
|
+
config.build_settings['BITCODE_GENERATION_MODE'] = 'bitcode'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
save
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'helper/environment'
|
2
|
+
require_relative 'helper/podfile'
|
3
|
+
require_relative 'helper/user_options'
|
4
|
+
require_relative 'helper/xcodeproj'
|
5
|
+
require_relative 'rome/compiler'
|
6
|
+
require_relative 'rome/framework_cache'
|
7
|
+
require_relative 'rome/lockfile'
|
8
|
+
require_relative 'xcodegen/dependencies_generator'
|
9
|
+
require_relative 'xcodegen/dependency'
|
10
|
+
require_relative 'xcodegen/xcodegen'
|
11
|
+
|
12
|
+
require_relative 'env_ci/post_install'
|
13
|
+
require_relative 'env_ci/pre_install'
|
14
|
+
require_relative 'env_local/post_install'
|
15
|
+
require_relative 'env_local/pre_install'
|
16
|
+
|
17
|
+
|
18
|
+
require_relative 'register_hooks'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Pod::HooksManager.register("cocoapods-alexandria", :pre_install) do |installer_context, user_options|
|
2
|
+
if is_ci?
|
3
|
+
PodAlexandria::CIPreInstallHook.new(installer_context, user_options).run
|
4
|
+
else
|
5
|
+
PodAlexandria::LocalPreInstallHook.new(installer_context, user_options).run
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
Pod::HooksManager.register("cocoapods-alexandria", :post_install) do |installer_context, user_options|
|
10
|
+
if is_ci?
|
11
|
+
PodAlexandria::CIPostInstallHook.new(installer_context, user_options).run
|
12
|
+
else
|
13
|
+
PodAlexandria::LocalPostInstallHook.new(installer_context, user_options).run
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class Compiler
|
3
|
+
attr_reader :sandbox, :build_dir, :destination, :configuration, :flags
|
4
|
+
|
5
|
+
def initialize(sandbox, build_dir, destination, configuration, flags)
|
6
|
+
@sandbox = sandbox
|
7
|
+
@build_dir = build_dir
|
8
|
+
@destination = destination
|
9
|
+
@configuration = configuration
|
10
|
+
@flags = flags
|
11
|
+
end
|
12
|
+
|
13
|
+
def build(target)
|
14
|
+
sdk = platform_sdk[target.platform_name]
|
15
|
+
deployment_target = target.platform_deployment_target
|
16
|
+
target_label = target.cocoapods_target_label
|
17
|
+
|
18
|
+
# build each dependency of target
|
19
|
+
spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
|
20
|
+
|
21
|
+
spec_names.map { |root_name, module_name|
|
22
|
+
next if skip_build?(root_name, module_name, sdk)
|
23
|
+
if File.directory?(build_path(target, module_name, sdk))
|
24
|
+
build_path(target, module_name, sdk)
|
25
|
+
else
|
26
|
+
xcodebuild(root_name, module_name, sdk, deployment_target)
|
27
|
+
end
|
28
|
+
}.compact
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def platform_sdk
|
34
|
+
{ :ios => 'iphoneos', :osx => 'macosx', :tvos => 'appletvos', :watchos => 'watchos' }
|
35
|
+
end
|
36
|
+
|
37
|
+
def skip_build?(target, module_name, sdk)
|
38
|
+
File.directory?(destination_path(module_name)) ||
|
39
|
+
!is_native_target?(target)
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_native_target?(target_name)
|
43
|
+
project.targets
|
44
|
+
.find { |t| t.name == target_name }
|
45
|
+
.is_a?(Xcodeproj::Project::Object::PBXNativeTarget)
|
46
|
+
end
|
47
|
+
|
48
|
+
def xcodebuild(target, module_name, sdk, deployment_target)
|
49
|
+
args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{configuration} -sdk #{sdk})
|
50
|
+
args += flags unless flags.nil?
|
51
|
+
|
52
|
+
Pod::UI.puts "Building '#{target}' for #{sdk}..."
|
53
|
+
Pod::Executable.execute_command 'xcodebuild', args, true
|
54
|
+
|
55
|
+
build_path(target, module_name, sdk)
|
56
|
+
end
|
57
|
+
|
58
|
+
def project
|
59
|
+
@project ||= Xcodeproj::Project.open(sandbox.project_path)
|
60
|
+
end
|
61
|
+
|
62
|
+
def build_path(target, module_name, sdk)
|
63
|
+
"#{build_dir}/#{configuration}-#{sdk}/#{target}/#{module_name}.framework"
|
64
|
+
end
|
65
|
+
|
66
|
+
def destination_path(module_name)
|
67
|
+
"#{destination}/#{module_name}.framework"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class FrameworkCache
|
3
|
+
attr_reader :configuration, :flags, :sandbox, :sandbox_root, :project_dir, :build_dir, :destination, :umbrella_targets
|
4
|
+
|
5
|
+
def initialize(installer_context)
|
6
|
+
@configuration = 'Release'
|
7
|
+
@flags = []
|
8
|
+
@sandbox_root = Pathname(installer_context.sandbox_root)
|
9
|
+
@sandbox = Pod::Sandbox.new(sandbox_root)
|
10
|
+
@project_dir = sandbox_root.parent
|
11
|
+
@build_dir = project_dir + 'build'
|
12
|
+
@destination = project_dir + 'Rome'
|
13
|
+
@umbrella_targets = installer_context.umbrella_targets
|
14
|
+
end
|
15
|
+
|
16
|
+
def podfile_lock
|
17
|
+
@podfile_lock ||= Lockfile.new(project_dir + 'Podfile.lock')
|
18
|
+
end
|
19
|
+
|
20
|
+
def cached_podfile_lock
|
21
|
+
@cached_podfile_lock ||= Lockfile.new(sandbox_root + 'Rome-Podfile.lock')
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_changed_frameworks
|
25
|
+
# if first run (no cache), make sure we nuke partials
|
26
|
+
if !cached_podfile_lock.exists?
|
27
|
+
Pod::UI.info 'No cached lockfile, deleting all cached frameworks'
|
28
|
+
delete_all
|
29
|
+
return
|
30
|
+
end
|
31
|
+
|
32
|
+
# return early if identical
|
33
|
+
return unless podfile_lock.exists? and cached_podfile_lock.exists?
|
34
|
+
if podfile_lock.matches? cached_podfile_lock
|
35
|
+
Pod::UI.info 'Podfile.lock did not change, leaving frameworks as is'
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
Pod::UI.info '⚠️ Podfile.lock did change, deleting updated frameworks'
|
40
|
+
changed = podfile_lock.changed_specs(cached_podfile_lock)
|
41
|
+
affected = podfile_lock.specs_affected_by(changed)
|
42
|
+
|
43
|
+
# delete affected frameworks
|
44
|
+
Pod::UI.info "Affected frameworks: #{affected.sort.join(', ')}" unless affected.empty?
|
45
|
+
affected.each { |pod| delete(pod) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_frameworks
|
49
|
+
compiler = Compiler.new(sandbox, build_dir, destination, configuration, flags)
|
50
|
+
frameworks = umbrella_targets.select { |t| t.specs.any? }.flat_map { |target|
|
51
|
+
compiler.build(target)
|
52
|
+
}
|
53
|
+
|
54
|
+
Pod::UI.info "🔥 Built #{frameworks.count} #{'frameworks'.pluralize(frameworks.count)}" unless frameworks.empty?
|
55
|
+
|
56
|
+
FileUtils.mkdir_p destination
|
57
|
+
collect_files(frameworks).each do |file|
|
58
|
+
FileUtils.cp_r file, destination, :remove_destination => true
|
59
|
+
end
|
60
|
+
|
61
|
+
build_dir.rmtree if build_dir.directory?
|
62
|
+
end
|
63
|
+
|
64
|
+
def cache_lockfile
|
65
|
+
if podfile_lock.exists?
|
66
|
+
Pod::UI.info "Caching new Podfile.lock"
|
67
|
+
podfile_lock.copy_to(cached_podfile_lock)
|
68
|
+
else
|
69
|
+
Pod::UI.info "Deleting cached Podfile.lock"
|
70
|
+
cached_podfile_lock.delete
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def spec_modules
|
77
|
+
@spec_modules ||= umbrella_targets.map { |t|
|
78
|
+
t.specs.map { |spec| [spec.root.name, spec.root.module_name] }
|
79
|
+
}.flatten(1).uniq.to_h
|
80
|
+
end
|
81
|
+
|
82
|
+
def module_name(spec)
|
83
|
+
spec.gsub(/^([0-9])/, '_\1').gsub(/[^a-zA-Z0-9_]/, '_')
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete_all
|
87
|
+
FileUtils.remove_dir(build_dir, true)
|
88
|
+
FileUtils.remove_dir(destination, true)
|
89
|
+
end
|
90
|
+
|
91
|
+
def delete(spec)
|
92
|
+
name = spec_modules[spec] || module_name(spec)
|
93
|
+
path = "#{destination}/#{name}.framework"
|
94
|
+
|
95
|
+
if File.directory?(path)
|
96
|
+
FileUtils.remove_dir(path, true)
|
97
|
+
else
|
98
|
+
Pod::UI.warning "🤔 Could not delete #{path}, it does not exist! (this is normal for newly added pods)"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def collect_files(frameworks)
|
103
|
+
resources = []
|
104
|
+
|
105
|
+
umbrella_targets.each do |target|
|
106
|
+
target.specs.each do |spec|
|
107
|
+
consumer = spec.consumer(target.platform_name)
|
108
|
+
file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
|
109
|
+
frameworks += file_accessor.vendored_libraries + file_accessor.vendored_frameworks
|
110
|
+
resources += file_accessor.resources
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
frameworks.uniq + resources.uniq
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class Lockfile
|
3
|
+
attr_reader :path
|
4
|
+
|
5
|
+
def initialize(path)
|
6
|
+
@path = path
|
7
|
+
end
|
8
|
+
|
9
|
+
def exists?
|
10
|
+
File.file?(path)
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(lockfile)
|
14
|
+
FileUtils.identical?(path, lockfile.path)
|
15
|
+
end
|
16
|
+
|
17
|
+
# collect changed specs (changed checksum, checkout or deleted pod)
|
18
|
+
def changed_specs(lockfile)
|
19
|
+
changed_checksums = spec_checksums.select { |k,v| v != lockfile.spec_checksums[k] }.keys
|
20
|
+
changed_checkout = checkout_options.select { |k,v| v != lockfile.checkout_options[k] }.keys
|
21
|
+
deleted_specs = lockfile.spec_checksums.keys - spec_checksums.keys
|
22
|
+
|
23
|
+
changed_checksums.to_set.merge(changed_checksums).merge(deleted_specs)
|
24
|
+
end
|
25
|
+
|
26
|
+
# collect affected frameworks (and filter out subspecs)
|
27
|
+
def specs_affected_by(specs)
|
28
|
+
affected = specs
|
29
|
+
|
30
|
+
loop do
|
31
|
+
items = pods.select { |s|
|
32
|
+
s.is_a?(Hash) && s.values.flatten.any? { |ss| affected.include? ss.split.first }
|
33
|
+
}.map { |s| s.keys.first.split.first }
|
34
|
+
|
35
|
+
break if affected.superset? (affected + items)
|
36
|
+
affected.merge(items)
|
37
|
+
end
|
38
|
+
|
39
|
+
affected = affected & spec_checksums.keys
|
40
|
+
end
|
41
|
+
|
42
|
+
def copy_to(lockfile)
|
43
|
+
FileUtils.copy_file(path, lockfile.path)
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete
|
47
|
+
FileUtils.remove_file(path, true)
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def contents
|
53
|
+
@contents ||= YAML.load_file(path)
|
54
|
+
end
|
55
|
+
|
56
|
+
def spec_checksums
|
57
|
+
contents.fetch('SPEC CHECKSUMS', {})
|
58
|
+
end
|
59
|
+
|
60
|
+
def checkout_options
|
61
|
+
contents.fetch('CHECKOUT OPTIONS', {})
|
62
|
+
end
|
63
|
+
|
64
|
+
def pods
|
65
|
+
contents.fetch('PODS', [])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module PodAlexandria
|
4
|
+
class XcodeGen
|
5
|
+
# Generate the project dependencies file, adding frameworks to the right targets
|
6
|
+
# and also checking if they are linked dynamically or not.
|
7
|
+
def self.generate_dependencies(installer_context, options)
|
8
|
+
targets = installer_context.umbrella_targets.map { |target|
|
9
|
+
generate_for_target(installer_context, target, options.environment_configs_for(target.cocoapods_target_label))
|
10
|
+
}.to_h
|
11
|
+
|
12
|
+
File.open(options.xcodegen_dependencies_file, 'w') { |file|
|
13
|
+
YAML::dump({ 'targets' => targets }, file)
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def self.generate_for_target(installer_context, target, configurations)
|
20
|
+
target_name = target.cocoapods_target_label.sub(/^Pods-/, '')
|
21
|
+
xcconfig = config_file_for_target(installer_context, target)
|
22
|
+
|
23
|
+
[
|
24
|
+
target_name,
|
25
|
+
{
|
26
|
+
'configFiles' => configurations,
|
27
|
+
'dependencies' => get_dependencies_from_xcconfig(xcconfig).map { |dependency|
|
28
|
+
if dependency.exists?
|
29
|
+
{ 'framework' => dependency.path, 'embed' => dependency.is_dynamic? }
|
30
|
+
else
|
31
|
+
{ 'sdk' => dependency.sdk }
|
32
|
+
end
|
33
|
+
}
|
34
|
+
}
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.config_file_for_target(installer_context, target)
|
39
|
+
Dir["#{installer_context.sandbox_root}/Target Support Files/#{target.cocoapods_target_label}/#{target.cocoapods_target_label}.*.xcconfig"]
|
40
|
+
.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.get_dependencies_from_xcconfig(file)
|
44
|
+
File.readlines(file).select { |line| line.start_with?('OTHER_LDFLAGS') }.first
|
45
|
+
.split('=')[1].tr('"', '') # get value (and remove quotes)
|
46
|
+
.gsub('-framework', '').gsub('-ObjC', '') # remove unneeded flags
|
47
|
+
.split.drop(1) # remove inherited
|
48
|
+
.map { |d| Dependency.new(d) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class Dependency
|
3
|
+
attr_reader :value
|
4
|
+
|
5
|
+
def initialize(value)
|
6
|
+
@value = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def path
|
10
|
+
binary = Dir["Rome/*.{framework,xcframework}/**/#{binary_name}"].first
|
11
|
+
binary&.split(File::SEPARATOR)&.first(2)&.join(File::SEPARATOR)
|
12
|
+
end
|
13
|
+
|
14
|
+
def sdk
|
15
|
+
if is_library?
|
16
|
+
"lib#{module_name}.tbd"
|
17
|
+
else
|
18
|
+
"#{value}.framework"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def exists?
|
23
|
+
path != nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def is_dynamic?
|
27
|
+
if path.end_with? 'xcframework'
|
28
|
+
any_arch = Dir["#{path}/*/*.framework"].first
|
29
|
+
binary = "#{any_arch}/#{value}"
|
30
|
+
else
|
31
|
+
binary = "#{path}/#{value}"
|
32
|
+
end
|
33
|
+
!%x(file #{binary} | grep dynamic).to_s.strip.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def is_library?
|
39
|
+
value.start_with? '-l'
|
40
|
+
end
|
41
|
+
|
42
|
+
def binary_name
|
43
|
+
if is_library?
|
44
|
+
"lib#{module_name}.a"
|
45
|
+
else
|
46
|
+
module_name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def module_name
|
51
|
+
value.delete_prefix('-l')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PodAlexandria
|
2
|
+
class XcodeGen
|
3
|
+
def self.cleanupRome
|
4
|
+
FileUtils.remove_dir('build', force: true)
|
5
|
+
FileUtils.remove_dir('dSYM', force: true)
|
6
|
+
FileUtils.remove_dir('Rome', force: true)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.clearDependencies(xcodegen_dependencies_file)
|
10
|
+
File.truncate(xcodegen_dependencies_file, 0)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.generate
|
14
|
+
unless system('which xcodegen > /dev/null')
|
15
|
+
abort 'XcodeGen is not installed. Visit https://github.com/yonaskolb/XcodeGen to learn more.'
|
16
|
+
end
|
17
|
+
|
18
|
+
system('xcodegen')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-alexandria/main'
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cocoapods-alexandria
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Jennes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-01-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cocoapods
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- david.jennes@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- lib/cocoapods-alexandria.rb
|
63
|
+
- lib/cocoapods-alexandria/env_ci/post_install.rb
|
64
|
+
- lib/cocoapods-alexandria/env_ci/pre_install.rb
|
65
|
+
- lib/cocoapods-alexandria/env_local/post_install.rb
|
66
|
+
- lib/cocoapods-alexandria/env_local/pre_install.rb
|
67
|
+
- lib/cocoapods-alexandria/gem_version.rb
|
68
|
+
- lib/cocoapods-alexandria/helper/environment.rb
|
69
|
+
- lib/cocoapods-alexandria/helper/podfile.rb
|
70
|
+
- lib/cocoapods-alexandria/helper/user_options.rb
|
71
|
+
- lib/cocoapods-alexandria/helper/xcodeproj.rb
|
72
|
+
- lib/cocoapods-alexandria/main.rb
|
73
|
+
- lib/cocoapods-alexandria/register_hooks.rb
|
74
|
+
- lib/cocoapods-alexandria/rome/compiler.rb
|
75
|
+
- lib/cocoapods-alexandria/rome/framework_cache.rb
|
76
|
+
- lib/cocoapods-alexandria/rome/lockfile.rb
|
77
|
+
- lib/cocoapods-alexandria/xcodegen/dependencies_generator.rb
|
78
|
+
- lib/cocoapods-alexandria/xcodegen/dependency.rb
|
79
|
+
- lib/cocoapods-alexandria/xcodegen/xcodegen.rb
|
80
|
+
- lib/cocoapods_plugin.rb
|
81
|
+
homepage: https://github.com/appwise-labs/Alexandria
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubygems_version: 3.0.3
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Alexandria allows for easier integration with XcodeGen, and automatically
|
104
|
+
switches to a 'Rome' mode on CI (pre-compile frameworks)
|
105
|
+
test_files: []
|