pod-builder 1.9.2 → 2.0.0.beta.19
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
- data/.gitignore +9 -0
- data/Example/Frameworks/.gitignore +6 -0
- data/Example/Frameworks/.pod_builder/pod_builder +0 -0
- data/Example/Frameworks/PodBuilder.json +10 -4
- data/Example/Frameworks/Podfile +23 -0
- data/Example/Frameworks/Podfile.restore +40 -0
- data/Example/PodBuilderExample.xcodeproj/project.pbxproj +3 -8
- data/Example/{PodBuilderExample.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/xcschememanagement.plist → PodBuilderExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist} +2 -8
- data/Example/PodBuilderExample/AppDelegate.swift +4 -0
- data/Example/Podfile +44 -1
- data/Example/Podfile.lock +426 -7
- data/Example/Pods-acknowledgements.md +210 -0
- data/Example/Pods-acknowledgements.plist +206 -0
- data/README.md +38 -1
- data/exe/pod_builder +14 -14
- data/lib/pod_builder/analyze.rb +32 -7
- data/lib/pod_builder/analyzer.rb +16 -0
- data/lib/pod_builder/command/build.rb +110 -96
- data/lib/pod_builder/command/clean.rb +9 -11
- data/lib/pod_builder/command/clear_lldbinit.rb +1 -1
- data/lib/pod_builder/command/deintegrate.rb +2 -1
- data/lib/pod_builder/command/generate_lfs.rb +2 -2
- data/lib/pod_builder/command/install_sources.rb +1 -1
- data/lib/pod_builder/command/switch.rb +99 -99
- data/lib/pod_builder/command/sync_podfile.rb +2 -1
- data/lib/pod_builder/command/update.rb +1 -1
- data/lib/pod_builder/command/update_lldbinit.rb +2 -2
- data/lib/pod_builder/configuration.rb +62 -7
- data/lib/pod_builder/core.rb +60 -5
- data/lib/pod_builder/info.rb +24 -90
- data/lib/pod_builder/install.rb +149 -83
- data/lib/pod_builder/podfile.rb +87 -14
- data/lib/pod_builder/podfile/post_actions.rb +0 -1
- data/lib/pod_builder/podfile_item.rb +152 -74
- data/lib/pod_builder/podspec.rb +125 -133
- data/lib/pod_builder/rome/post_install.rb +248 -0
- data/lib/pod_builder/rome/pre_install.rb +6 -0
- data/lib/pod_builder/templates/build_podfile.template +1 -1
- data/lib/pod_builder/version.rb +1 -1
- data/pod-builder.gemspec +4 -4
- metadata +32 -64
- data/Example/Pods/Alamofire/LICENSE +0 -19
- data/Example/Pods/Alamofire/README.md +0 -242
- data/Example/Pods/Alamofire/Source/AFError.swift +0 -460
- data/Example/Pods/Alamofire/Source/Alamofire.swift +0 -465
- data/Example/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift +0 -37
- data/Example/Pods/Alamofire/Source/MultipartFormData.swift +0 -580
- data/Example/Pods/Alamofire/Source/NetworkReachabilityManager.swift +0 -233
- data/Example/Pods/Alamofire/Source/Notifications.swift +0 -55
- data/Example/Pods/Alamofire/Source/ParameterEncoding.swift +0 -483
- data/Example/Pods/Alamofire/Source/Request.swift +0 -654
- data/Example/Pods/Alamofire/Source/Response.swift +0 -567
- data/Example/Pods/Alamofire/Source/ResponseSerialization.swift +0 -715
- data/Example/Pods/Alamofire/Source/Result.swift +0 -300
- data/Example/Pods/Alamofire/Source/ServerTrustPolicy.swift +0 -307
- data/Example/Pods/Alamofire/Source/SessionDelegate.swift +0 -725
- data/Example/Pods/Alamofire/Source/SessionManager.swift +0 -896
- data/Example/Pods/Alamofire/Source/TaskDelegate.swift +0 -466
- data/Example/Pods/Alamofire/Source/Timeline.swift +0 -136
- data/Example/Pods/Alamofire/Source/Validation.swift +0 -315
- data/Example/Pods/Manifest.lock +0 -16
- data/Example/Pods/Pods.xcodeproj/project.pbxproj +0 -673
- data/Example/Pods/Pods.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/Alamofire.xcscheme +0 -60
- data/Example/Pods/Pods.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/Pods-PodBuilderExample.xcscheme +0 -60
- data/Example/Pods/Pods.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/xcschememanagement.plist +0 -21
- data/Example/Pods/Target Support Files/Alamofire/Alamofire-dummy.m +0 -5
- data/Example/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch +0 -12
- data/Example/Pods/Target Support Files/Alamofire/Alamofire-umbrella.h +0 -16
- data/Example/Pods/Target Support Files/Alamofire/Alamofire.modulemap +0 -6
- data/Example/Pods/Target Support Files/Alamofire/Alamofire.xcconfig +0 -9
- data/Example/Pods/Target Support Files/Alamofire/Info.plist +0 -26
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Info.plist +0 -26
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-acknowledgements.markdown +0 -26
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-acknowledgements.plist +0 -58
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-dummy.m +0 -5
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-frameworks.sh +0 -153
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-resources.sh +0 -118
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-umbrella.h +0 -16
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample.debug.xcconfig +0 -11
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample.modulemap +0 -6
- data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample.release.xcconfig +0 -11
- data/lib/pod_builder/cocoapods/specification.rb +0 -27
data/lib/pod_builder/podspec.rb
CHANGED
@@ -1,38 +1,5 @@
|
|
1
1
|
module PodBuilder
|
2
2
|
class Podspec
|
3
|
-
class PodspecItem
|
4
|
-
attr_accessor :name
|
5
|
-
attr_accessor :module_name
|
6
|
-
attr_accessor :vendored_frameworks
|
7
|
-
attr_accessor :vendored_items
|
8
|
-
attr_accessor :frameworks
|
9
|
-
attr_accessor :weak_frameworks
|
10
|
-
attr_accessor :libraries
|
11
|
-
attr_accessor :resources
|
12
|
-
attr_accessor :exclude_files
|
13
|
-
attr_accessor :xcconfig
|
14
|
-
attr_accessor :dependencies
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
@name = ""
|
18
|
-
@module_name = ""
|
19
|
-
@vendored_frameworks = []
|
20
|
-
@vendored_items = []
|
21
|
-
@frameworks = []
|
22
|
-
@weak_frameworks = []
|
23
|
-
@libraries = []
|
24
|
-
@resources = []
|
25
|
-
@exclude_files = []
|
26
|
-
@xcconfig = {}
|
27
|
-
@dependencies = []
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_s
|
31
|
-
@name
|
32
|
-
end
|
33
|
-
end
|
34
|
-
private_constant :PodspecItem
|
35
|
-
|
36
3
|
def self.generate(all_buildable_items, analyzer)
|
37
4
|
unless all_buildable_items.count > 0
|
38
5
|
return
|
@@ -40,142 +7,167 @@ module PodBuilder
|
|
40
7
|
|
41
8
|
puts "Generating PodBuilder's local podspec".yellow
|
42
9
|
|
43
|
-
podspec_items = podspec_items_from(all_buildable_items)
|
44
|
-
|
45
10
|
platform = analyzer.instance_variable_get("@result").targets.first.platform
|
46
|
-
generate_podspec_from(
|
11
|
+
generate_podspec_from(all_buildable_items, platform)
|
47
12
|
end
|
48
13
|
|
49
14
|
def self.include?(pod_name)
|
50
|
-
|
51
|
-
unless File.exist?(podspec_path)
|
52
|
-
return false
|
53
|
-
end
|
54
|
-
|
55
|
-
if Configuration.subspecs_to_split.include?(pod_name)
|
56
|
-
pod_name = pod_name.gsub("/", "_")
|
57
|
-
else
|
58
|
-
pod_name = pod_name.split("/").first
|
59
|
-
end
|
60
|
-
|
61
|
-
podspec_content = File.read(podspec_path)
|
62
|
-
|
63
|
-
# (_.*) will include prebuild podnames like s.subspec 'Podname_Subspec' do |p|
|
64
|
-
subspec_regex = "s.subspec '#{pod_name}(_.*)?' do |p|"
|
65
|
-
return (podspec_content.match(/#{subspec_regex}/) != nil)
|
15
|
+
return File.exist?(PodBuilder::prebuiltpath("#{pod_name}.podspec"))
|
66
16
|
end
|
67
17
|
|
68
18
|
private
|
69
19
|
|
70
|
-
def self.
|
71
|
-
|
72
|
-
|
73
|
-
vendored_frameworks = item.vendored_frameworks.map { |x| x.vendored_framework_path }.compact
|
74
|
-
vendored_frameworks += item.vendored_items.map { |x| File.basename(x) }.select { |x| File.exist?(PodBuilder::basepath(PodfileItem::vendored_name_framework_path(x))) }.map { |x| "Rome/#{x}" }
|
75
|
-
vendored_frameworks.uniq!
|
76
|
-
vendored_libraries = Dir.glob(PodBuilder::basepath("Rome/#{item.module_name}/**/*.a")).map { |x| x.to_s.gsub(PodBuilder::basepath, "")[1..-1] }
|
20
|
+
def self.generate_spec_keys_for(item, name, all_buildable_items)
|
21
|
+
podspec = ""
|
22
|
+
valid = false
|
77
23
|
|
78
|
-
|
79
|
-
|
80
|
-
|
24
|
+
slash_count = name.count("/") + 1
|
25
|
+
indentation = " " * slash_count
|
26
|
+
spec_var = "p#{slash_count}"
|
81
27
|
|
28
|
+
if item.name == name
|
29
|
+
vendored_frameworks = item.vendored_frameworks + ["#{item.module_name}.framework"]
|
30
|
+
existing_vendored_frameworks = vendored_frameworks.select { |t| File.exist?(PodBuilder::prebuiltpath(t) || "") }
|
31
|
+
existing_vendored_frameworks_basename = vendored_frameworks.map { |t| File.basename(t) }.select { |t| File.exist?(PodBuilder::prebuiltpath(t) || "") }
|
32
|
+
vendored_frameworks = (existing_vendored_frameworks + existing_vendored_frameworks_basename).uniq
|
33
|
+
|
34
|
+
vendored_libraries = item.vendored_libraries
|
35
|
+
existing_vendored_libraries = vendored_libraries.map { |t| "#{item.module_name}/#{t}" }.select { |t| File.exist?(PodBuilder::prebuiltpath(t) || "") }
|
36
|
+
existing_vendored_libraries_basename = vendored_libraries.map { |t| File.basename("#{item.module_name}/#{t}") }.select { |t| File.exist?(PodBuilder::prebuiltpath(t) || "") }
|
37
|
+
vendored_libraries = (existing_vendored_libraries + existing_vendored_libraries_basename).uniq
|
38
|
+
|
39
|
+
# .a are static libraries and should not be included again in the podspec to prevent duplicated symbols (in the app and in the prebuilt framework)
|
40
|
+
vendored_libraries.select! { |t| !t.end_with?(".a") }
|
41
|
+
|
42
|
+
frameworks = all_buildable_items.select { |t| vendored_frameworks.include?("#{t.module_name}.framework") }.uniq
|
43
|
+
static_frameworks = frameworks.select { |x| x.is_static }
|
44
|
+
|
45
|
+
resources = static_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/*.{nib,bundle,xcasset,strings,png,jpg,tif,tiff,otf,ttf,ttc,plist,json,caf,wav,p12,momd}" }.compact.flatten.uniq
|
46
|
+
exclude_files = static_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/Info.plist" }.compact.flatten.uniq
|
47
|
+
exclude_files += frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/#{Configuration.framework_plist_filename}" }.compact.flatten.uniq.sort
|
48
|
+
|
82
49
|
if vendored_frameworks.count > 0
|
83
|
-
podspec += "
|
84
|
-
end
|
50
|
+
podspec += "#{indentation}#{spec_var}.vendored_frameworks = '#{vendored_frameworks.uniq.sort.join("','")}'\n"
|
51
|
+
end
|
85
52
|
if vendored_libraries.count > 0
|
86
|
-
podspec += "
|
53
|
+
podspec += "#{indentation}#{spec_var}.vendored_libraries = '#{vendored_libraries.uniq.sort.join("','")}'\n"
|
87
54
|
end
|
88
55
|
if item.frameworks.count > 0
|
89
|
-
podspec += "
|
56
|
+
podspec += "#{indentation}#{spec_var}.frameworks = '#{item.frameworks.uniq.sort.join("', '")}'\n"
|
90
57
|
end
|
91
58
|
if item.libraries.count > 0
|
92
|
-
podspec += "
|
59
|
+
podspec += "#{indentation}#{spec_var}.libraries = '#{item.libraries.uniq.sort.join("', '")}'\n"
|
93
60
|
end
|
94
|
-
if
|
95
|
-
podspec += "
|
61
|
+
if resources.count > 0
|
62
|
+
podspec += "#{indentation}#{spec_var}.resources = '#{resources.uniq.sort.join("', '")}'\n"
|
96
63
|
end
|
97
|
-
if
|
98
|
-
podspec += "
|
64
|
+
if exclude_files.count > 0
|
65
|
+
podspec += "#{indentation}#{spec_var}.exclude_files = '#{exclude_files.uniq.sort.join("', '")}'\n"
|
99
66
|
end
|
100
67
|
if item.xcconfig.keys.count > 0
|
101
|
-
|
102
|
-
|
103
|
-
non_prebuilt_dependencies.each do |non_prebuilt_dependency|
|
104
|
-
podspec += " p.dependency '#{non_prebuilt_dependency.name}'\n"
|
105
|
-
end
|
106
|
-
|
107
|
-
podspec += " end"
|
108
|
-
|
109
|
-
podspecs.push(podspec)
|
110
|
-
end
|
111
|
-
|
112
|
-
cwd = File.dirname(File.expand_path(__FILE__))
|
113
|
-
podspec_file = File.read("#{cwd}/templates/build_podspec.template")
|
114
|
-
podspec_file.gsub!("%%%podspecs%%%", podspecs.join("\n\n"))
|
115
|
-
|
116
|
-
podspec_file.sub!("%%%platform_name%%%", platform.name.to_s)
|
117
|
-
podspec_file.sub!("%%%deployment_version%%%", platform.deployment_target.version)
|
118
|
-
|
119
|
-
File.write(PodBuilder::basepath("PodBuilder.podspec"), podspec_file)
|
120
|
-
end
|
121
|
-
|
122
|
-
def self.podspec_items_from(buildable_items)
|
123
|
-
podspec_items = []
|
124
|
-
|
125
|
-
buildable_items.each do |pod|
|
126
|
-
spec_exists = File.exist?(PodBuilder::basepath(pod.vendored_spec_framework_path))
|
127
|
-
subspec_exists = File.exist?(PodBuilder::basepath(pod.vendored_subspec_framework_path))
|
128
|
-
|
129
|
-
unless spec_exists || subspec_exists
|
130
|
-
puts "Skipping `#{pod.name}`, not prebuilt".blue
|
131
|
-
next
|
132
|
-
end
|
133
|
-
|
134
|
-
pod_name = Configuration.subspecs_to_split.include?(pod.name) ? pod.name : pod.root_name
|
135
|
-
unless podspec_item = podspec_items.detect { |x| x.name == pod_name }
|
136
|
-
podspec_item = PodspecItem.new
|
137
|
-
podspec_items.push(podspec_item)
|
138
|
-
podspec_item.name = pod_name
|
139
|
-
podspec_item.module_name = pod.module_name
|
140
|
-
podspec_item.vendored_items = pod.vendored_items
|
141
|
-
end
|
142
|
-
|
143
|
-
podspec_item.vendored_frameworks += [pod] + pod.dependencies(buildable_items)
|
144
|
-
|
145
|
-
podspec_item.frameworks = podspec_item.vendored_frameworks.map { |x| x.frameworks }.flatten.uniq.sort
|
146
|
-
podspec_item.weak_frameworks = podspec_item.vendored_frameworks.map { |x| x.weak_frameworks }.flatten.uniq.sort
|
147
|
-
podspec_item.libraries = podspec_item.vendored_frameworks.map { |x| x.libraries }.flatten.uniq.sort
|
148
|
-
|
149
|
-
static_vendored_frameworks = podspec_item.vendored_frameworks.select { |x| x.is_static }
|
150
|
-
|
151
|
-
podspec_item.resources = static_vendored_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/*.{nib,bundle,xcasset,strings,png,jpg,tif,tiff,otf,ttf,ttc,plist,json,caf,wav,p12,momd}" }.compact.flatten.uniq
|
152
|
-
podspec_item.exclude_files = static_vendored_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/Info.plist" }.compact.flatten.uniq
|
153
|
-
podspec_item.exclude_files += podspec_item.vendored_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/#{Configuration.framework_plist_filename}" }.compact.flatten.uniq.sort
|
154
|
-
|
155
|
-
# Merge xcconfigs
|
156
|
-
if !pod.xcconfig.empty?
|
157
|
-
pod.xcconfig.each do |k, v|
|
68
|
+
xcconfig = Hash.new
|
69
|
+
item.xcconfig.each do |k, v|
|
158
70
|
unless v != "$(inherited)"
|
71
|
+
xcconfig[k] = item.xcconfig[k]
|
159
72
|
next
|
160
73
|
end
|
161
74
|
unless k == "OTHER_LDFLAGS"
|
162
75
|
next # For the time being limit to OTHER_LDFLAGS key
|
163
76
|
end
|
164
|
-
|
165
|
-
if podspec_values =
|
77
|
+
|
78
|
+
if podspec_values = item.xcconfig[k]
|
166
79
|
podspec_values_arr = podspec_values.split(" ")
|
167
80
|
podspec_values_arr.push(v)
|
168
81
|
v = podspec_values_arr.join(" ")
|
169
82
|
end
|
170
83
|
|
171
|
-
|
84
|
+
xcconfig[k] = item.xcconfig[k]
|
85
|
+
end
|
86
|
+
|
87
|
+
if xcconfig.keys.count > 0
|
88
|
+
podspec += "#{indentation}#{spec_var}.xcconfig = #{xcconfig.to_s}\n"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
deps = item.dependency_names.sort
|
93
|
+
if name == item.root_name
|
94
|
+
deps.reject! { |t| t.split("/").first == item.root_name }
|
95
|
+
end
|
96
|
+
|
97
|
+
if deps.count > 0
|
98
|
+
if podspec.count("\n") > 1
|
99
|
+
podspec += "\n"
|
100
|
+
end
|
101
|
+
deps.each do |dependency|
|
102
|
+
podspec += "#{indentation}#{spec_var}.dependency '#{dependency}'\n"
|
172
103
|
end
|
173
104
|
end
|
174
105
|
|
175
|
-
|
106
|
+
valid = valid || vendored_frameworks.count > 0
|
176
107
|
end
|
108
|
+
|
109
|
+
subspec_names = all_buildable_items.map(&:name).select { |t| t.start_with?("#{name}/") }
|
110
|
+
subspec_names_groups = subspec_names.group_by { |t| name + "/" + t.gsub("#{name}/", '').split("/").first }
|
111
|
+
subspec_names = subspec_names_groups.keys.uniq.sort
|
112
|
+
|
113
|
+
subspec_names.each do |subspec|
|
114
|
+
subspec_item = all_buildable_items.detect { |t| t.name == subspec } || item
|
177
115
|
|
178
|
-
|
116
|
+
if podspec.length > 0
|
117
|
+
podspec += "\n"
|
118
|
+
end
|
119
|
+
|
120
|
+
subspec_keys, subspec_valid = generate_spec_keys_for(subspec_item, subspec, all_buildable_items)
|
121
|
+
valid = valid || subspec_valid
|
122
|
+
|
123
|
+
if subspec_keys.length > 0
|
124
|
+
podspec += "#{indentation}#{spec_var}.subspec '#{subspec.split("/").last}' do |p#{slash_count + 1}|\n"
|
125
|
+
podspec += subspec_keys
|
126
|
+
podspec += "#{indentation}end\n"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
return podspec, valid
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.generate_podspec_from(all_buildable_items, platform)
|
134
|
+
specs = Dir.glob(PodBuilder::prebuiltpath("*.podspec"))
|
135
|
+
specs.each do |s|
|
136
|
+
FileUtils.rm(s)
|
137
|
+
end
|
138
|
+
|
139
|
+
all_buildable_items.each do |item|
|
140
|
+
if item.name != item.root_name
|
141
|
+
if all_buildable_items.map(&:name).include?(item.root_name)
|
142
|
+
next # will process root spec, skip subspecs
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
podspec = "Pod::Spec.new do |p1|\n"
|
147
|
+
|
148
|
+
podspec += " p1.name = '#{item.root_name}'\n"
|
149
|
+
podspec += " p1.version = '#{item.version}'\n"
|
150
|
+
podspec += " p1.summary = '#{item.summary.gsub("'", "\\'")}'\n"
|
151
|
+
podspec += " p1.homepage = '#{item.homepage}'\n"
|
152
|
+
podspec += " p1.author = 'PodBuilder'\n"
|
153
|
+
podspec += " p1.source = { 'git' => '#{item.source['git']}'}\n"
|
154
|
+
podspec += " p1.license = { :type => '#{item.license}' }\n"
|
155
|
+
|
156
|
+
podspec += "\n"
|
157
|
+
podspec += " p1.#{platform.safe_string_name.downcase}.deployment_target = '#{platform.deployment_target.version}'\n"
|
158
|
+
podspec += "\n"
|
159
|
+
|
160
|
+
main_keys, valid = generate_spec_keys_for(item, item.root_name, all_buildable_items)
|
161
|
+
if !valid
|
162
|
+
next
|
163
|
+
end
|
164
|
+
|
165
|
+
podspec += main_keys
|
166
|
+
podspec += "end"
|
167
|
+
|
168
|
+
spec_path = PodBuilder::prebuiltpath("#{item.root_name}.podspec")
|
169
|
+
File.write(spec_path, podspec)
|
170
|
+
end
|
179
171
|
end
|
180
172
|
end
|
181
173
|
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require 'fourflusher'
|
2
|
+
require 'colored'
|
3
|
+
|
4
|
+
module PodBuilder
|
5
|
+
def self.build_for_iosish_platform(sandbox, build_dir, target, device, simulator, configuration, deterministic_build, build_for_apple_silicon)
|
6
|
+
raise "Apple silicon hardware still unsupported since it requires to migrate to xcframeworks" if build_for_apple_silicon
|
7
|
+
|
8
|
+
deployment_target = target.platform_deployment_target
|
9
|
+
target_label = target.cocoapods_target_label
|
10
|
+
|
11
|
+
xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [])
|
12
|
+
excluded_archs = build_for_apple_silicon ? [] : ["arm64"]
|
13
|
+
xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs)
|
14
|
+
|
15
|
+
spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
|
16
|
+
spec_names.each do |root_name, module_name|
|
17
|
+
executable_path = "#{build_dir}/#{root_name}"
|
18
|
+
device_lib = "#{build_dir}/#{configuration}-#{device}/#{root_name}/#{module_name}.framework/#{module_name}"
|
19
|
+
device_framework_lib = File.dirname(device_lib)
|
20
|
+
device_swift_header_path = "#{device_framework_lib}/Headers/#{module_name}-Swift.h"
|
21
|
+
|
22
|
+
simulator_lib = "#{build_dir}/#{configuration}-#{simulator}/#{root_name}/#{module_name}.framework/#{module_name}"
|
23
|
+
simulator_framework_lib = File.dirname(simulator_lib)
|
24
|
+
simulator_swift_header_path = "#{simulator_framework_lib}/Headers/#{module_name}-Swift.h"
|
25
|
+
|
26
|
+
next unless File.file?(device_lib) && File.file?(simulator_lib)
|
27
|
+
|
28
|
+
# Starting with Xcode 12b3 the simulator binary contains an arm64 slice as well which conflict with the one in the device_lib
|
29
|
+
# when creating the fat library. A naive workaround is to remove the arm64 from the simulator_lib however this is wrong because
|
30
|
+
# we might actually need to have 2 separated arm64 slices, one for simulator and one for device each built with different
|
31
|
+
# compile time directives (e.g #if targetEnvironment(simulator))
|
32
|
+
#
|
33
|
+
# For the time being we remove the arm64 slice bacause otherwise the `xcrun lipo -create -output ...` would fail.
|
34
|
+
if `xcrun lipo -info #{simulator_lib}`.include?("arm64")
|
35
|
+
`xcrun lipo -remove arm64 #{simulator_lib} -o #{simulator_lib}`
|
36
|
+
end
|
37
|
+
|
38
|
+
lipo_log = `xcrun lipo -create -output #{executable_path} #{device_lib} #{simulator_lib}`
|
39
|
+
puts lipo_log unless File.exist?(executable_path)
|
40
|
+
|
41
|
+
# Merge swift headers as per Xcode 10.2 release notes
|
42
|
+
if File.exist?(device_swift_header_path) && File.exist?(simulator_swift_header_path)
|
43
|
+
device_content = File.read(device_swift_header_path)
|
44
|
+
simulator_content = File.read(simulator_swift_header_path)
|
45
|
+
merged_content = %{
|
46
|
+
#if TARGET_OS_SIMULATOR
|
47
|
+
#{simulator_content}
|
48
|
+
#else
|
49
|
+
#{device_content}
|
50
|
+
#endif
|
51
|
+
}
|
52
|
+
File.write(device_swift_header_path, merged_content)
|
53
|
+
end
|
54
|
+
|
55
|
+
FileUtils.mv executable_path, device_lib, :force => true
|
56
|
+
FileUtils.mv device_framework_lib, build_dir, :force => true
|
57
|
+
FileUtils.rm simulator_lib if File.file?(simulator_lib)
|
58
|
+
FileUtils.rm device_lib if File.file?(device_lib)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil, configuration, deterministic_build, exclude_archs)
|
63
|
+
args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{configuration} -sdk #{sdk})
|
64
|
+
supported_platforms = { 'iphonesimulator' => 'iOS', 'appletvsimulator' => 'tvOS', 'watchsimulator' => 'watchOS' }
|
65
|
+
if platform = supported_platforms[sdk]
|
66
|
+
args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
xcodebuild_version = `xcodebuild -version | head -n1 | awk '{print $2}'`.strip().to_f
|
70
|
+
if exclude_archs.count > 0 && xcodebuild_version >= 12.0
|
71
|
+
args += ["EXCLUDED_ARCHS=#{exclude_archs.join(" ")}"]
|
72
|
+
end
|
73
|
+
|
74
|
+
environmental_variables = {}
|
75
|
+
if deterministic_build
|
76
|
+
environmental_variables["ZERO_AR_DATE"] = "1"
|
77
|
+
end
|
78
|
+
|
79
|
+
execute_command 'xcodebuild', args, true, environmental_variables
|
80
|
+
end
|
81
|
+
|
82
|
+
# Copy paste implementation from CocoaPods internals to be able to call poopen3 passing environmental variables
|
83
|
+
def self.execute_command(executable, command, raise_on_failure = true, environmental_variables = {})
|
84
|
+
bin = Pod::Executable.which!(executable)
|
85
|
+
|
86
|
+
command = command.map(&:to_s)
|
87
|
+
full_command = "#{bin} #{command.join(' ')}"
|
88
|
+
|
89
|
+
stdout = Pod::Executable::Indenter.new
|
90
|
+
stderr = Pod::Executable::Indenter.new
|
91
|
+
|
92
|
+
status = popen3(bin, command, stdout, stderr, environmental_variables)
|
93
|
+
stdout = stdout.join
|
94
|
+
stderr = stderr.join
|
95
|
+
output = stdout + stderr
|
96
|
+
unless status.success?
|
97
|
+
if raise_on_failure
|
98
|
+
raise "#{full_command}\n\n#{output}"
|
99
|
+
else
|
100
|
+
UI.message("[!] Failed: #{full_command}".red)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
output
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.popen3(bin, command, stdout, stderr, environmental_variables)
|
108
|
+
require 'open3'
|
109
|
+
Open3.popen3(environmental_variables, bin, *command) do |i, o, e, t|
|
110
|
+
Pod::Executable::reader(o, stdout)
|
111
|
+
Pod::Executable::reader(e, stderr)
|
112
|
+
i.close
|
113
|
+
|
114
|
+
status = t.value
|
115
|
+
|
116
|
+
o.flush
|
117
|
+
e.flush
|
118
|
+
sleep(0.01)
|
119
|
+
|
120
|
+
status
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.enable_debug_information(project_path, configuration)
|
125
|
+
project = Xcodeproj::Project.open(project_path)
|
126
|
+
project.targets.each do |target|
|
127
|
+
config = target.build_configurations.find { |config| config.name.eql? configuration }
|
128
|
+
config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf-with-dsym'
|
129
|
+
config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
|
130
|
+
end
|
131
|
+
project.save
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.copy_dsym_files(dsym_destination, configuration)
|
135
|
+
dsym_destination.rmtree if dsym_destination.directory?
|
136
|
+
|
137
|
+
platforms = Configuration.supported_platforms
|
138
|
+
platforms.each do |platform|
|
139
|
+
dsym = Pathname.glob("build/#{configuration}-#{platform}/**/*.dSYM")
|
140
|
+
dsym.each do |dsym|
|
141
|
+
destination = dsym_destination + platform
|
142
|
+
FileUtils.mkdir_p destination
|
143
|
+
FileUtils.cp_r dsym, destination, :remove_destination => true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_context, user_options|
|
150
|
+
enable_dsym = user_options.fetch('dsym', true)
|
151
|
+
configuration = user_options.fetch('configuration', 'Debug')
|
152
|
+
if user_options["pre_compile"]
|
153
|
+
user_options["pre_compile"].call(installer_context)
|
154
|
+
end
|
155
|
+
|
156
|
+
sandbox_root = Pathname(installer_context.sandbox_root)
|
157
|
+
sandbox = Pod::Sandbox.new(sandbox_root)
|
158
|
+
|
159
|
+
PodBuilder::enable_debug_information(sandbox.project_path, configuration)
|
160
|
+
|
161
|
+
build_dir = sandbox_root.parent + 'build'
|
162
|
+
destination = sandbox_root.parent + 'Rome'
|
163
|
+
|
164
|
+
build_dir.rmtree if build_dir.directory?
|
165
|
+
targets = installer_context.umbrella_targets.select { |t| t.specs.any? }
|
166
|
+
targets.each do |target|
|
167
|
+
case target.platform_name
|
168
|
+
when :ios then PodBuilder::build_for_iosish_platform(sandbox, build_dir, target, 'iphoneos', 'iphonesimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
|
169
|
+
when :osx then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
|
170
|
+
when :tvos then PodBuilder::build_for_iosish_platform(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
|
171
|
+
when :watchos then PodBuilder::build_for_iosish_platform(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
|
172
|
+
else raise "Unknown platform '#{target.platform_name}'" end
|
173
|
+
end
|
174
|
+
|
175
|
+
raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
|
176
|
+
|
177
|
+
# Make sure the device target overwrites anything in the simulator build, otherwise iTunesConnect
|
178
|
+
# can get upset about Info.plist containing references to the simulator SDK
|
179
|
+
frameworks = Pathname.glob("build/*/*/*.framework").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
|
180
|
+
frameworks += Pathname.glob("build/*.framework").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
|
181
|
+
|
182
|
+
resources = []
|
183
|
+
|
184
|
+
Pod::UI.puts "Built #{frameworks.count} #{'frameworks'.pluralize(frameworks.count)}"
|
185
|
+
|
186
|
+
destination.rmtree if destination.directory?
|
187
|
+
|
188
|
+
installer_context.umbrella_targets.each do |umbrella|
|
189
|
+
umbrella.specs.each do |spec|
|
190
|
+
consumer = spec.consumer(umbrella.platform_name)
|
191
|
+
file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
|
192
|
+
frameworks += file_accessor.vendored_libraries
|
193
|
+
frameworks += file_accessor.vendored_frameworks
|
194
|
+
resources += file_accessor.resources
|
195
|
+
end
|
196
|
+
end
|
197
|
+
frameworks.uniq!
|
198
|
+
resources.uniq!
|
199
|
+
|
200
|
+
Pod::UI.puts "Copying #{frameworks.count} #{'frameworks'.pluralize(frameworks.count)} " \
|
201
|
+
"to `#{destination.relative_path_from Pathname.pwd}`"
|
202
|
+
|
203
|
+
FileUtils.mkdir_p destination
|
204
|
+
(frameworks + resources).each do |file|
|
205
|
+
FileUtils.cp_r file, destination, :remove_destination => true
|
206
|
+
end
|
207
|
+
|
208
|
+
if enable_dsym
|
209
|
+
PodBuilder::copy_dsym_files(sandbox_root.parent + 'dSYM', configuration)
|
210
|
+
else
|
211
|
+
frameworks = Dir.glob(File.join(destination, "*.framework"))
|
212
|
+
|
213
|
+
dsym_base_path = sandbox_root.parent + 'dSYM'
|
214
|
+
|
215
|
+
# manually generate dSYMs
|
216
|
+
frameworks.each do |framework|
|
217
|
+
module_name = File.basename(framework, ".*")
|
218
|
+
is_static = `file #{File.join(framework, module_name)} | grep 'ar archive' | wc -l`.strip() != "0"
|
219
|
+
|
220
|
+
if !is_static
|
221
|
+
destination_dSYM = File.join(dsym_base_path, "#{module_name}.dSYM")
|
222
|
+
FileUtils.mkdir_p(dsym_base_path)
|
223
|
+
|
224
|
+
module_path = "#{File.join(framework, module_name)}"
|
225
|
+
system("xcrun dsymutil '#{module_path}' -no-swiftmodule-timestamp -o '#{destination_dSYM}' 2>/dev/null")
|
226
|
+
if `xcrun codesign -v #{module_path} 2>&1 | grep 'code object is not signed at all' | wc -l`.strip() == "1"
|
227
|
+
system("xcrun strip -x -S '#{module_path}'")
|
228
|
+
else
|
229
|
+
# Running strip on codesigned binaries triggers the following warning:
|
230
|
+
# 'strip: changes being made to the file will invalidate the code signature in: path to binary'
|
231
|
+
puts "#{module_name} appears to be codesigned, skipping stripping.".blue
|
232
|
+
end
|
233
|
+
|
234
|
+
# Sanity check
|
235
|
+
binary_uuid = `xcrun dwarfdump --uuid '#{module_path}' | cut -d" " -f2`
|
236
|
+
dsym_uuid = `xcrun dwarfdump --uuid '#{File.join(destination_dSYM, "Contents", "Resources", "DWARF", module_name)}' | cut -d" " -f2`
|
237
|
+
|
238
|
+
raise "dSYM sanity check failed for '#{framework}', UUID do not match!" unless binary_uuid == dsym_uuid
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
build_dir.rmtree if build_dir.directory?
|
244
|
+
|
245
|
+
if user_options["post_compile"]
|
246
|
+
user_options["post_compile"].call(installer_context)
|
247
|
+
end
|
248
|
+
end
|