cocoapods-alexandria 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|