cocoapods-binary-matchup 0.0.27 → 0.0.28
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 +4 -4
- metadata +3 -29
- data/.gitignore +0 -32
- data/.travis.yml +0 -23
- data/Gemfile +0 -13
- data/Gemfile.lock +0 -161
- data/LICENSE.txt +0 -22
- data/README.md +0 -83
- data/Rakefile +0 -13
- data/cocoapods-binary-matchup.gemspec +0 -27
- data/lib/cocoapods-binary-matchup/Integration.rb +0 -287
- data/lib/cocoapods-binary-matchup/Integration_cache.rb +0 -320
- data/lib/cocoapods-binary-matchup/Main.rb +0 -386
- data/lib/cocoapods-binary-matchup/Prebuild.rb +0 -249
- data/lib/cocoapods-binary-matchup/gem_version.rb +0 -3
- data/lib/cocoapods-binary-matchup/helper/feature_switches.rb +0 -109
- data/lib/cocoapods-binary-matchup/helper/passer.rb +0 -41
- data/lib/cocoapods-binary-matchup/helper/podfile_options.rb +0 -122
- data/lib/cocoapods-binary-matchup/helper/prebuild_sandbox.rb +0 -53
- data/lib/cocoapods-binary-matchup/helper/target_checker.rb +0 -49
- data/lib/cocoapods-binary-matchup/rome/build_framework.rb +0 -316
- data/lib/cocoapods-binary-matchup/tool/tool.rb +0 -12
- data/lib/cocoapods-binary.rb +0 -1
- data/lib/cocoapods_plugin.rb +0 -2
- data/spec/plugin_spec.rb +0 -43
- data/spec/spec_helper.rb +0 -50
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
require_relative '../tool/tool'
|
|
2
|
-
require_relative 'prebuild_sandbox'
|
|
3
|
-
|
|
4
|
-
module Pod
|
|
5
|
-
|
|
6
|
-
# a flag that indicate stages
|
|
7
|
-
class_attr_accessor :is_prebuild_stage
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# a switch for the `pod` DSL to make it only valid for ':binary => true'
|
|
11
|
-
class Podfile
|
|
12
|
-
module DSL
|
|
13
|
-
|
|
14
|
-
@@enable_prebuild_patch = false
|
|
15
|
-
|
|
16
|
-
# when enable, `pod` function will skip all pods without 'prebuild => true'
|
|
17
|
-
def self.enable_prebuild_patch(value)
|
|
18
|
-
@@enable_prebuild_patch = value
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# --- patch ---
|
|
22
|
-
# filter the pods that should be prebuild(all_binary! or binary => true),remember the pod is must remote pod
|
|
23
|
-
# this will be effective when enable_prebuild_patch is true(the binary prebuild step)
|
|
24
|
-
# when in system step, the enable_prebuild_patch is false, so the original method will be called
|
|
25
|
-
old_method = instance_method(:pod)
|
|
26
|
-
define_method(:pod) do |name, *args|
|
|
27
|
-
# if not enable, just call the original method
|
|
28
|
-
if !@@enable_prebuild_patch
|
|
29
|
-
old_method.bind(self).(name, *args)
|
|
30
|
-
return
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# patched content
|
|
34
|
-
should_prebuild = Pod::Podfile::DSL.prebuild_all
|
|
35
|
-
local = false
|
|
36
|
-
|
|
37
|
-
options = args.last
|
|
38
|
-
if options.is_a?(Hash) and options[Pod::Prebuild.keyword] != nil
|
|
39
|
-
should_prebuild = options[Pod::Prebuild.keyword]
|
|
40
|
-
local = (options[:path] != nil)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
if should_prebuild and (not local)
|
|
44
|
-
if current_target_definition.platform == :watchos
|
|
45
|
-
# watchos isn't supported currently
|
|
46
|
-
Pod::UI.warn "Binary doesn't support watchos currently: #{name}. You can manually set `binary => false` for this pod to suppress this warning."
|
|
47
|
-
return
|
|
48
|
-
end
|
|
49
|
-
old_method.bind(self).(name, *args)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# a force disable option for integral
|
|
57
|
-
class Installer
|
|
58
|
-
def self.force_disable_integration(value)
|
|
59
|
-
@@force_disable_integration = value
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# prebuild step's purpose is to build source target code or copy the prebuild framework to the target,
|
|
63
|
-
# so we need to disable the original method
|
|
64
|
-
old_method = instance_method(:integrate_user_project)
|
|
65
|
-
define_method(:integrate_user_project) do
|
|
66
|
-
if @@force_disable_integration
|
|
67
|
-
return
|
|
68
|
-
end
|
|
69
|
-
old_method.bind(self).()
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# a option to disable install complete message
|
|
74
|
-
class Installer
|
|
75
|
-
def self.disable_install_complete_message(value)
|
|
76
|
-
@@disable_install_complete_message = value
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
old_method = instance_method(:print_post_install_message)
|
|
80
|
-
define_method(:print_post_install_message) do
|
|
81
|
-
if @@disable_install_complete_message
|
|
82
|
-
return
|
|
83
|
-
end
|
|
84
|
-
old_method.bind(self).()
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# option to disable write lockfiles
|
|
89
|
-
class Config
|
|
90
|
-
|
|
91
|
-
@@force_disable_write_lockfile = false
|
|
92
|
-
def self.force_disable_write_lockfile(value)
|
|
93
|
-
@@force_disable_write_lockfile = value
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
old_method = instance_method(:lockfile_path)
|
|
97
|
-
define_method(:lockfile_path) do
|
|
98
|
-
if @@force_disable_write_lockfile
|
|
99
|
-
# As config is a singleton, sandbox_root refer to the standard sandbox.
|
|
100
|
-
manifest_lock_path = PrebuildSandbox.from_standard_sanbox_path(sandbox_root).root + 'Manifest.lock.tmp'
|
|
101
|
-
UI.puts "manifest_lock_path: #{manifest_lock_path}"
|
|
102
|
-
return manifest_lock_path
|
|
103
|
-
else
|
|
104
|
-
return old_method.bind(self).()
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
require_relative '../tool/tool'
|
|
2
|
-
|
|
3
|
-
module Pod
|
|
4
|
-
class Prebuild
|
|
5
|
-
|
|
6
|
-
# Pass the data between the 2 steps
|
|
7
|
-
#
|
|
8
|
-
# At step 2, the normal pod install, it needs some info of the
|
|
9
|
-
# prebuilt step. So we store it here.
|
|
10
|
-
#
|
|
11
|
-
class Passer
|
|
12
|
-
|
|
13
|
-
# indicate the add/remove/update of prebuit pods
|
|
14
|
-
# @return [Analyzer::SpecsState]
|
|
15
|
-
#
|
|
16
|
-
class_attr_accessor :prebuild_pods_changes
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# represent the path of resurces to copy
|
|
20
|
-
class ResourcePath
|
|
21
|
-
attr_accessor :real_file_path
|
|
22
|
-
attr_accessor :target_file_path
|
|
23
|
-
end
|
|
24
|
-
# Save the resoures for static framework, and used when installing the prebuild framework
|
|
25
|
-
# static framework needs copy the resurces mannully
|
|
26
|
-
#
|
|
27
|
-
# @return [Hash<String, [Passer::ResourcePath]>]
|
|
28
|
-
class_attr_accessor :resources_to_copy_for_static_framework
|
|
29
|
-
self.resources_to_copy_for_static_framework = {}
|
|
30
|
-
|
|
31
|
-
# Some pod won't be build in prebuild stage even if it have `binary=>true`.
|
|
32
|
-
# The targets of this pods have `oshould_build? == true`.
|
|
33
|
-
# We should skip integration (patch spec) for this pods
|
|
34
|
-
#
|
|
35
|
-
# @return [Array<String>]
|
|
36
|
-
class_attr_accessor :target_names_to_skip_integration_framework
|
|
37
|
-
self.target_names_to_skip_integration_framework = []
|
|
38
|
-
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
module Pod
|
|
2
|
-
|
|
3
|
-
class Prebuild
|
|
4
|
-
def self.keyword
|
|
5
|
-
:binary
|
|
6
|
-
end
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
class Podfile
|
|
10
|
-
class TargetDefinition
|
|
11
|
-
|
|
12
|
-
## --- option for setting using prebuild framework ---
|
|
13
|
-
def parse_prebuild_framework(name, requirements)
|
|
14
|
-
should_prebuild = Pod::Podfile::DSL.prebuild_all
|
|
15
|
-
|
|
16
|
-
options = requirements.last
|
|
17
|
-
# 如果options是hash,并且包含Pod::Prebuild.keyword,则设置should_prebuild为true
|
|
18
|
-
if options.is_a?(Hash) && options[Pod::Prebuild.keyword] != nil
|
|
19
|
-
# [DINetwork', { :binary => true, :configurations => ['Debug'] }]
|
|
20
|
-
should_prebuild = options.delete(Pod::Prebuild.keyword)
|
|
21
|
-
# [DINetwork', { :configurations => ['Debug'] }],避免干扰其他配置,不删除可能让后续cocoapods本身解析报错
|
|
22
|
-
requirements.pop if options.empty?
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
pod_name = Specification.root_name(name)
|
|
26
|
-
set_prebuild_for_pod(pod_name, should_prebuild)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def set_prebuild_for_pod(pod_name, should_prebuild)
|
|
30
|
-
|
|
31
|
-
if should_prebuild == true
|
|
32
|
-
# watchos isn't supported currently
|
|
33
|
-
return if self.platform == :watchos
|
|
34
|
-
|
|
35
|
-
@prebuild_framework_names ||= []
|
|
36
|
-
@prebuild_framework_names.push pod_name
|
|
37
|
-
else
|
|
38
|
-
@should_not_prebuild_framework_names ||= []
|
|
39
|
-
@should_not_prebuild_framework_names.push pod_name
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def prebuild_framework_names
|
|
44
|
-
names = @prebuild_framework_names || []
|
|
45
|
-
if parent != nil and parent.kind_of? TargetDefinition
|
|
46
|
-
names += parent.prebuild_framework_names
|
|
47
|
-
end
|
|
48
|
-
names
|
|
49
|
-
end
|
|
50
|
-
def should_not_prebuild_framework_names
|
|
51
|
-
names = @should_not_prebuild_framework_names || []
|
|
52
|
-
if parent != nil and parent.kind_of? TargetDefinition
|
|
53
|
-
names += parent.should_not_prebuild_framework_names
|
|
54
|
-
end
|
|
55
|
-
names
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# ---- patch method ----
|
|
59
|
-
# We want modify `store_pod` method, but it's hard to insert a line in the
|
|
60
|
-
# implementation. So we patch a method called in `store_pod`.
|
|
61
|
-
# use this method to parse prebuild framework(:binary => true)
|
|
62
|
-
old_method = instance_method(:parse_inhibit_warnings)
|
|
63
|
-
|
|
64
|
-
define_method(:parse_inhibit_warnings) do |name, requirements|
|
|
65
|
-
parse_prebuild_framework(name, requirements)
|
|
66
|
-
old_method.bind(self).(name, requirements)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
module Pod
|
|
75
|
-
class Installer
|
|
76
|
-
|
|
77
|
-
def prebuild_pod_targets
|
|
78
|
-
|
|
79
|
-
all = []
|
|
80
|
-
aggregate_targets = (self.aggregate_targets || []).select { |a| a.platform != :watchos }
|
|
81
|
-
aggregate_targets.each do |aggregate_target|
|
|
82
|
-
target_definition = aggregate_target.target_definition
|
|
83
|
-
targets = aggregate_target.pod_targets || []
|
|
84
|
-
|
|
85
|
-
UI.puts "🔍 Processing #{aggregate_target.name}:"
|
|
86
|
-
UI.puts "🔍 pod_targets count: #{targets.count}"
|
|
87
|
-
|
|
88
|
-
# filter prebuild
|
|
89
|
-
prebuild_names = target_definition.prebuild_framework_names
|
|
90
|
-
if not Podfile::DSL.prebuild_all
|
|
91
|
-
targets = targets.select { |pod_target| prebuild_names.include?(pod_target.pod_name) }
|
|
92
|
-
end
|
|
93
|
-
dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
|
|
94
|
-
targets = (targets + dependency_targets).uniq
|
|
95
|
-
|
|
96
|
-
# filter should not prebuild
|
|
97
|
-
explict_should_not_names = target_definition.should_not_prebuild_framework_names
|
|
98
|
-
targets = targets.reject { |pod_target| explict_should_not_names.include?(pod_target.pod_name) }
|
|
99
|
-
|
|
100
|
-
all += targets
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
all = all.reject {|pod_target| sandbox.local?(pod_target.pod_name) }
|
|
104
|
-
all.uniq
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# the root names who needs prebuild, including dependency pods.
|
|
108
|
-
def prebuild_pod_names
|
|
109
|
-
@prebuild_pod_names ||= self.prebuild_pod_targets.map(&:pod_name)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# 强制重新计算 prebuild_pod_names(用于主安装阶段)
|
|
113
|
-
def refresh_prebuild_pod_names!
|
|
114
|
-
@prebuild_pod_names = nil
|
|
115
|
-
prebuild_pod_names
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
module Pod
|
|
2
|
-
class PrebuildSandbox < Sandbox
|
|
3
|
-
|
|
4
|
-
# [String] standard_sandbox_path
|
|
5
|
-
def self.from_standard_sanbox_path(path)
|
|
6
|
-
# 将预构建目录设置到项目根目录,而不是Pods目录旁边
|
|
7
|
-
# 这样可以避免在删除Pods目录时丢失预构建的框架
|
|
8
|
-
project_root = Pathname.new(path).realpath.parent
|
|
9
|
-
prebuild_sandbox_path = project_root + "_Prebuild"
|
|
10
|
-
UI.puts "prebuild_sandbox_path: #{prebuild_sandbox_path}"
|
|
11
|
-
self.new(prebuild_sandbox_path)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def self.from_standard_sandbox(sandbox)
|
|
15
|
-
self.from_standard_sanbox_path(sandbox.root)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def standard_sanbox_path
|
|
19
|
-
self.root
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def generate_framework_path
|
|
23
|
-
self.root + "GeneratedFrameworks"
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def framework_folder_path_for_pod_name(name)
|
|
27
|
-
self.generate_framework_path + name
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def exsited_framework_names
|
|
31
|
-
return [] unless generate_framework_path.exist?
|
|
32
|
-
generate_framework_path.children().map do |framework_name|
|
|
33
|
-
if framework_name.directory?
|
|
34
|
-
if not framework_name.children.empty?
|
|
35
|
-
File.basename(framework_name)
|
|
36
|
-
else
|
|
37
|
-
nil
|
|
38
|
-
end
|
|
39
|
-
else
|
|
40
|
-
nil
|
|
41
|
-
end
|
|
42
|
-
end.reject(&:nil?)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def framework_existed?(root_name)
|
|
46
|
-
return false unless generate_framework_path.exist?
|
|
47
|
-
generate_framework_path.children().any? do |child|
|
|
48
|
-
child.basename.to_s == root_name
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
end
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module Pod
|
|
3
|
-
class Prebuild
|
|
4
|
-
|
|
5
|
-
# Check the targets, for the current limitation of the plugin
|
|
6
|
-
#
|
|
7
|
-
# @param [Array<PodTarget>] prebuilt_targets
|
|
8
|
-
def self.check_one_pod_should_have_only_one_target(prebuilt_targets)
|
|
9
|
-
|
|
10
|
-
targets_have_different_platforms = prebuilt_targets.select {|t| t.pod_name != t.name }
|
|
11
|
-
|
|
12
|
-
if targets_have_different_platforms.count > 0
|
|
13
|
-
names = targets_have_different_platforms.map(&:pod_name)
|
|
14
|
-
raw_names = targets_have_different_platforms.map(&:name)
|
|
15
|
-
message = "Oops, you came across a limitation of cocoapods-binary-matchup.
|
|
16
|
-
|
|
17
|
-
The plugin requires that one pod should have ONLY ONE target in the 'Pod.xcodeproj'. There are mainly 2 situations \
|
|
18
|
-
causing this problem:
|
|
19
|
-
|
|
20
|
-
1. One pod integrates in 2 or more different platforms' targets. e.g.
|
|
21
|
-
```
|
|
22
|
-
target 'iphoneApp' do
|
|
23
|
-
pod 'A', :binary => true
|
|
24
|
-
end
|
|
25
|
-
target 'watchApp' do
|
|
26
|
-
pod 'A'
|
|
27
|
-
end
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
2. Use different subspecs in multiple targets. e.g.
|
|
31
|
-
```
|
|
32
|
-
target 'iphoneApp' do
|
|
33
|
-
pod 'A/core'
|
|
34
|
-
pod 'A/network'
|
|
35
|
-
end
|
|
36
|
-
target 'iphoneAppTest' do
|
|
37
|
-
pod 'A/core'
|
|
38
|
-
end
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Related pods: #{names}, target names: #{raw_names}
|
|
42
|
-
"
|
|
43
|
-
raise Informative, message
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
end
|
|
49
|
-
end
|
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
require 'fourflusher'
|
|
2
|
-
require 'xcpretty'
|
|
3
|
-
|
|
4
|
-
CONFIGURATION = "Debug"
|
|
5
|
-
PLATFORMS = { 'iphonesimulator' => 'iOS',
|
|
6
|
-
'appletvsimulator' => 'tvOS',
|
|
7
|
-
'watchsimulator' => 'watchOS' }
|
|
8
|
-
|
|
9
|
-
# Build specific target to framework file
|
|
10
|
-
# @param [PodTarget] target
|
|
11
|
-
# a specific pod target
|
|
12
|
-
#
|
|
13
|
-
def build_for_iosish_platform(sandbox,
|
|
14
|
-
build_dir,
|
|
15
|
-
output_path,
|
|
16
|
-
target,
|
|
17
|
-
device,
|
|
18
|
-
simulator,
|
|
19
|
-
bitcode_enabled,
|
|
20
|
-
custom_build_options = [], # Array<String>
|
|
21
|
-
custom_build_options_simulator = [] # Array<String>
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
target_label = target.label # name with platform if it's used in multiple platforms
|
|
25
|
-
Pod::UI.puts "Prebuilding #{target_label}..."
|
|
26
|
-
|
|
27
|
-
other_options = []
|
|
28
|
-
# bitcode enabled
|
|
29
|
-
other_options += ['BITCODE_GENERATION_MODE=bitcode'] if bitcode_enabled
|
|
30
|
-
|
|
31
|
-
is_succeed, _ = xcodebuild(sandbox, target_label, device, target, other_options + custom_build_options)
|
|
32
|
-
exit 1 unless is_succeed
|
|
33
|
-
if Pod::Podfile::DSL.simulator_build_enabled
|
|
34
|
-
# make less arch to iphone simulator for faster build
|
|
35
|
-
custom_build_options_simulator += ['ARCHS=x86_64', 'ONLY_ACTIVE_ARCH=NO'] if simulator == 'iphonesimulator'
|
|
36
|
-
is_succeed, _ = xcodebuild(sandbox, target_label, simulator, target, other_options + custom_build_options_simulator)
|
|
37
|
-
exit 1 unless is_succeed
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# paths
|
|
41
|
-
target_name = target.name # equals target.label, like "AFNeworking-iOS" when AFNetworking is used in multiple platforms.
|
|
42
|
-
module_name = target.product_module_name
|
|
43
|
-
device_framework_path = "#{build_dir}/#{CONFIGURATION}-#{device}/#{target_name}/#{module_name}.framework"
|
|
44
|
-
device_binary = device_framework_path + "/#{module_name}"
|
|
45
|
-
|
|
46
|
-
tmp_lipoed_binary_path = "#{build_dir}/#{target_name}"
|
|
47
|
-
lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_binary}`
|
|
48
|
-
|
|
49
|
-
if Pod::Podfile::DSL.simulator_build_enabled
|
|
50
|
-
simulator_framework_path = "#{build_dir}/#{CONFIGURATION}-#{simulator}/#{target_name}/#{module_name}.framework"
|
|
51
|
-
simulator_binary = simulator_framework_path + "/#{module_name}"
|
|
52
|
-
return unless File.file?(device_binary) && File.file?(simulator_binary)
|
|
53
|
-
else
|
|
54
|
-
return unless File.file?(device_binary)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
|
|
58
|
-
FileUtils.mv tmp_lipoed_binary_path, device_binary, :force => true
|
|
59
|
-
|
|
60
|
-
# collect the swiftmodule file for various archs.
|
|
61
|
-
device_swiftmodule_path = device_framework_path + "/Modules/#{module_name}.swiftmodule"
|
|
62
|
-
if File.exist?(device_swiftmodule_path) && Pod::Podfile::DSL.simulator_build_enabled
|
|
63
|
-
simulator_framework_path = "#{build_dir}/#{CONFIGURATION}-#{simulator}/#{target_name}/#{module_name}.framework"
|
|
64
|
-
simulator_swiftmodule_path = simulator_framework_path + "/Modules/#{module_name}.swiftmodule"
|
|
65
|
-
FileUtils.cp_r simulator_swiftmodule_path + "/.", device_swiftmodule_path
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# combine the generated swift headers
|
|
69
|
-
# (In xcode 10.2, the generated swift headers vary for each archs)
|
|
70
|
-
# https://github.com/leavez/cocoapods-binary/issues/58
|
|
71
|
-
if Pod::Podfile::DSL.simulator_build_enabled
|
|
72
|
-
device_generated_swift_header_path = device_framework_path + "/Headers/#{module_name}-Swift.h"
|
|
73
|
-
device_header = File.read(device_generated_swift_header_path)
|
|
74
|
-
simulator_generated_swift_header_path = simulator_framework_path + "/Headers/#{module_name}-Swift.h"
|
|
75
|
-
if File.exist? simulator_generated_swift_header_path
|
|
76
|
-
|
|
77
|
-
simulator_header = File.read(simulator_generated_swift_header_path)
|
|
78
|
-
# https://github.com/Carthage/Carthage/issues/2718#issuecomment-473870461
|
|
79
|
-
combined_header_content = %Q{
|
|
80
|
-
#if TARGET_OS_SIMULATOR // merged by cocoapods-binary
|
|
81
|
-
|
|
82
|
-
#{simulator_header}
|
|
83
|
-
|
|
84
|
-
#else // merged by cocoapods-binary
|
|
85
|
-
|
|
86
|
-
#{device_header}
|
|
87
|
-
|
|
88
|
-
#endif // merged by cocoapods-binary
|
|
89
|
-
}
|
|
90
|
-
File.write(device_generated_swift_header_path, combined_header_content.strip)
|
|
91
|
-
end
|
|
92
|
-
else
|
|
93
|
-
device_generated_swift_header_path = device_framework_path + "/Headers/#{module_name}-Swift.h"
|
|
94
|
-
if File.exist?(device_generated_swift_header_path)
|
|
95
|
-
device_header = File.read(device_generated_swift_header_path)
|
|
96
|
-
combined_header_content = %Q{
|
|
97
|
-
#if TARGET_OS_SIMULATOR // merged by cocoapods-binary
|
|
98
|
-
|
|
99
|
-
#else // merged by cocoapods-binary
|
|
100
|
-
|
|
101
|
-
#{device_header}
|
|
102
|
-
|
|
103
|
-
#endif // merged by cocoapods-binary
|
|
104
|
-
}
|
|
105
|
-
File.write(device_generated_swift_header_path, combined_header_content.strip)
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# handle the dSYM files
|
|
110
|
-
# device_dsym = "#{device_framework_path}.dSYM"
|
|
111
|
-
# if File.exist? device_dsym
|
|
112
|
-
# # lipo the simulator dsym
|
|
113
|
-
# simulator_dsym = "#{simulator_framework_path}.dSYM"
|
|
114
|
-
# if File.exist? simulator_dsym
|
|
115
|
-
# tmp_lipoed_binary_path = "#{output_path}/#{module_name}.draft"
|
|
116
|
-
# lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_dsym}/Contents/Resources/DWARF/#{module_name} #{simulator_dsym}/Contents/Resources/DWARF/#{module_name}`
|
|
117
|
-
# puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
|
|
118
|
-
# FileUtils.mv tmp_lipoed_binary_path, "#{device_framework_path}.dSYM/Contents/Resources/DWARF/#{module_name}", :force => true
|
|
119
|
-
# end
|
|
120
|
-
# # move
|
|
121
|
-
# FileUtils.mv device_dsym, output_path, :force => true
|
|
122
|
-
# end
|
|
123
|
-
|
|
124
|
-
# output
|
|
125
|
-
output_path.mkpath unless output_path.exist?
|
|
126
|
-
|
|
127
|
-
if target.static_framework?
|
|
128
|
-
# 🔑 添加资源处理 - 修复静态库资源丢失问题
|
|
129
|
-
copy_resources_to_framework(sandbox, target, device_framework_path)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
FileUtils.mv device_framework_path, output_path, :force => true
|
|
133
|
-
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# 新增函数:拷贝资源文件到 framework
|
|
137
|
-
def copy_resources_to_framework(sandbox, target, framework_path)
|
|
138
|
-
Pod::UI.puts "📋 Processing resources for #{target.name}..."
|
|
139
|
-
|
|
140
|
-
pod_dir = Pathname.new(sandbox.pod_dir(target.pod_name))
|
|
141
|
-
framework_dir = Pathname.new(framework_path)
|
|
142
|
-
|
|
143
|
-
# 直接递归扫描 pod 目录下的所有资源文件,拷贝到 framework 根目录
|
|
144
|
-
scan_and_copy_resources_flat(pod_dir, framework_dir)
|
|
145
|
-
|
|
146
|
-
Pod::UI.puts "✅ Resource processing completed for #{target.name}"
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# 递归扫描资源文件并平铺拷贝到目标目录
|
|
150
|
-
def scan_and_copy_resources_flat(source_dir, target_dir)
|
|
151
|
-
# 确保参数是Pathname类型
|
|
152
|
-
source_dir = Pathname.new(source_dir) unless source_dir.is_a?(Pathname)
|
|
153
|
-
target_dir = Pathname.new(target_dir) unless target_dir.is_a?(Pathname)
|
|
154
|
-
|
|
155
|
-
Pod::UI.puts "📁 Recursively scanning directory: #{source_dir}"
|
|
156
|
-
|
|
157
|
-
# 资源文件扩展名
|
|
158
|
-
resource_extensions = [
|
|
159
|
-
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', # 图片
|
|
160
|
-
'.storyboard', '.xib', '.storyboardc', '.nib', # 界面文件
|
|
161
|
-
'.ttf', '.otf', '.woff', '.woff2', # 字体
|
|
162
|
-
'.mp3', '.wav', '.m4a', '.mp4', '.mov', '.avi', # 媒体
|
|
163
|
-
'.json', '.plist', '.strings', '.xcassets', # 配置文件
|
|
164
|
-
'.bin', # 二进制资源
|
|
165
|
-
'metallib' # metal or opengl文件
|
|
166
|
-
]
|
|
167
|
-
|
|
168
|
-
# 特殊处理的目录类型(这些需要完整保留)
|
|
169
|
-
special_directory_extensions = ['.bundle', '.xcassets', '.lproj']
|
|
170
|
-
|
|
171
|
-
# 递归查找并拷贝资源文件,传递原始根目录用于路径计算
|
|
172
|
-
find_and_copy_resources_recursively(source_dir, target_dir, source_dir, resource_extensions, special_directory_extensions)
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
# 递归查找资源文件并拷贝
|
|
176
|
-
def find_and_copy_resources_recursively(current_dir, target_dir, source_root_dir, resource_extensions, special_extensions)
|
|
177
|
-
# 确保所有参数都是Pathname类型
|
|
178
|
-
current_dir = Pathname.new(current_dir) unless current_dir.is_a?(Pathname)
|
|
179
|
-
target_dir = Pathname.new(target_dir) unless target_dir.is_a?(Pathname)
|
|
180
|
-
source_root_dir = Pathname.new(source_root_dir) unless source_root_dir.is_a?(Pathname)
|
|
181
|
-
|
|
182
|
-
return unless current_dir.exist? && current_dir.directory?
|
|
183
|
-
|
|
184
|
-
current_dir.children.each do |child|
|
|
185
|
-
# 跳过隐藏文件和系统目录
|
|
186
|
-
next if child.basename.to_s.start_with?('.')
|
|
187
|
-
next if ['.git', '.svn', 'node_modules', '.DS_Store'].include?(child.basename.to_s)
|
|
188
|
-
|
|
189
|
-
if child.directory?
|
|
190
|
-
# 检查是否是特殊资源目录(需要完整保留的)
|
|
191
|
-
if special_extensions.include?(child.extname)
|
|
192
|
-
Pod::UI.puts " 📦 Copying special directory: #{child.basename}"
|
|
193
|
-
target_path = target_dir + child.basename
|
|
194
|
-
FileUtils.cp_r(child.to_s, target_path.to_s, :remove_destination => true)
|
|
195
|
-
else
|
|
196
|
-
# 递归处理普通目录
|
|
197
|
-
find_and_copy_resources_recursively(child, target_dir, source_root_dir, resource_extensions, special_extensions)
|
|
198
|
-
end
|
|
199
|
-
else
|
|
200
|
-
# 检查是否是资源文件
|
|
201
|
-
if resource_extensions.include?(child.extname.downcase)
|
|
202
|
-
Pod::UI.puts " 📄 Copying resource file: #{child.basename}"
|
|
203
|
-
target_path = target_dir + child.basename
|
|
204
|
-
|
|
205
|
-
# 处理文件名冲突(如果有重名文件,添加路径前缀)
|
|
206
|
-
if target_path.exist?
|
|
207
|
-
# 计算相对于根目录的路径作为前缀
|
|
208
|
-
relative_dir = child.dirname.relative_path_from(source_root_dir)
|
|
209
|
-
safe_name = "#{relative_dir.to_s.gsub('/', '_')}_#{child.basename}"
|
|
210
|
-
target_path = target_dir + safe_name
|
|
211
|
-
Pod::UI.puts " ⚠️ File name conflict, renamed to: #{safe_name}"
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
FileUtils.cp(child.to_s, target_path.to_s)
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
def xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil, other_options=[])
|
|
221
|
-
args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{CONFIGURATION} -sdk #{sdk} )
|
|
222
|
-
platform = PLATFORMS[sdk]
|
|
223
|
-
args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
|
|
224
|
-
args += other_options
|
|
225
|
-
Pod::UI.puts "📦 start compile project #{target} (#{args}) "
|
|
226
|
-
log = `xcodebuild #{args.join(" ")} 2>&1`
|
|
227
|
-
exit_code = $?.exitstatus # Process::Status
|
|
228
|
-
is_succeed = (exit_code == 0)
|
|
229
|
-
|
|
230
|
-
if !is_succeed
|
|
231
|
-
Pod::UI.puts "❌ Build failed for target #{target} (exit code: #{exit_code})".red
|
|
232
|
-
begin
|
|
233
|
-
if log.include?('** BUILD FAILED **')
|
|
234
|
-
# use xcpretty to print build log
|
|
235
|
-
# 64 represent command invalid. http://www.manpagez.com/man/3/sysexits/
|
|
236
|
-
printer = XCPretty::Printer.new({:formatter => XCPretty::Simple, :colorize => 'auto'})
|
|
237
|
-
log.each_line do |line|
|
|
238
|
-
printer.pretty_print(line)
|
|
239
|
-
end
|
|
240
|
-
else
|
|
241
|
-
raise "shouldn't be handle by xcpretty"
|
|
242
|
-
end
|
|
243
|
-
rescue
|
|
244
|
-
puts log.red
|
|
245
|
-
end
|
|
246
|
-
Pod::UI.puts "💥 Compilation terminated due to build failure. Please check the error messages above.".red
|
|
247
|
-
exit 1
|
|
248
|
-
end
|
|
249
|
-
[is_succeed, log]
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
module Pod
|
|
253
|
-
class Prebuild
|
|
254
|
-
|
|
255
|
-
# Build the frameworks with sandbox and targets
|
|
256
|
-
#
|
|
257
|
-
# @param [String] sandbox_root_path
|
|
258
|
-
# The sandbox root path where the targets project place
|
|
259
|
-
#
|
|
260
|
-
# [PodTarget] target
|
|
261
|
-
# The pod targets to build
|
|
262
|
-
#
|
|
263
|
-
# [Pathname] output_path
|
|
264
|
-
# output path for generated frameworks
|
|
265
|
-
#
|
|
266
|
-
def self.build(sandbox_root_path, target, output_path, bitcode_enabled = false, custom_build_options=[], custom_build_options_simulator=[])
|
|
267
|
-
|
|
268
|
-
return if target.nil?
|
|
269
|
-
|
|
270
|
-
sandbox_root = Pathname(sandbox_root_path)
|
|
271
|
-
sandbox = Pod::Sandbox.new(sandbox_root)
|
|
272
|
-
build_dir = self.build_dir(sandbox_root)
|
|
273
|
-
|
|
274
|
-
# -- build the framework
|
|
275
|
-
case target.platform.name
|
|
276
|
-
when :ios then build_for_iosish_platform(sandbox, build_dir, output_path, target, 'iphoneos', 'iphonesimulator', bitcode_enabled, custom_build_options, custom_build_options_simulator)
|
|
277
|
-
when :osx then xcodebuild(sandbox, target.label, 'macosx', nil, custom_build_options)
|
|
278
|
-
# when :tvos then build_for_iosish_platform(sandbox, build_dir, target, 'appletvos', 'appletvsimulator')
|
|
279
|
-
when :watchos then build_for_iosish_platform(sandbox, build_dir, output_path, target, 'watchos', 'watchsimulator', true, custom_build_options, custom_build_options_simulator)
|
|
280
|
-
else raise "Unsupported platform for '#{target.name}': '#{target.platform.name}'" end
|
|
281
|
-
|
|
282
|
-
raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
|
|
283
|
-
|
|
284
|
-
# # --- copy the vendored libraries and framework
|
|
285
|
-
# frameworks = build_dir.children.select{ |path| File.extname(path) == ".framework" }
|
|
286
|
-
# Pod::UI.puts "Built #{frameworks.count} #{'frameworks'.pluralize(frameworks.count)}"
|
|
287
|
-
|
|
288
|
-
# pod_target = target
|
|
289
|
-
# consumer = pod_target.root_spec.consumer(pod_target.platform.name)
|
|
290
|
-
# file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(pod_target.pod_name), consumer)
|
|
291
|
-
# frameworks += file_accessor.vendored_libraries
|
|
292
|
-
# frameworks += file_accessor.vendored_frameworks
|
|
293
|
-
|
|
294
|
-
# frameworks.uniq!
|
|
295
|
-
|
|
296
|
-
# frameworks.each do |framework|
|
|
297
|
-
# FileUtils.mkdir_p destination
|
|
298
|
-
# FileUtils.cp_r framework, destination, :remove_destination => true
|
|
299
|
-
# end
|
|
300
|
-
# build_dir.rmtree if build_dir.directory?
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def self.remove_build_dir(sandbox_root)
|
|
304
|
-
path = build_dir(sandbox_root)
|
|
305
|
-
path.rmtree if path.exist?
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
private
|
|
309
|
-
|
|
310
|
-
def self.build_dir(sandbox_root)
|
|
311
|
-
# don't know why xcode chose this folder
|
|
312
|
-
sandbox_root.parent + 'build'
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
end
|
|
316
|
-
end
|