pod-builder 1.9.3 → 2.0.0.beta.22
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/README.md +50 -13
- data/exe/pod_builder +39 -28
- data/lib/pod_builder/analyze.rb +32 -7
- data/lib/pod_builder/analyzer.rb +16 -0
- data/lib/pod_builder/command/build.rb +44 -161
- data/lib/pod_builder/command/build_all.rb +2 -2
- data/lib/pod_builder/command/clean.rb +34 -55
- data/lib/pod_builder/command/clear_lldbinit.rb +7 -3
- data/lib/pod_builder/command/deintegrate.rb +29 -7
- data/lib/pod_builder/command/generate_lfs.rb +3 -3
- data/lib/pod_builder/command/generate_podspec.rb +3 -2
- data/lib/pod_builder/command/info.rb +1 -1
- data/lib/pod_builder/command/init.rb +37 -14
- data/lib/pod_builder/command/install_sources.rb +21 -14
- data/lib/pod_builder/command/none.rb +2 -2
- data/lib/pod_builder/command/restore_all.rb +4 -4
- data/lib/pod_builder/command/switch.rb +137 -95
- data/lib/pod_builder/command/sync_podfile.rb +5 -3
- data/lib/pod_builder/command/update.rb +5 -6
- data/lib/pod_builder/command/update_lldbinit.rb +11 -9
- data/lib/pod_builder/configuration.rb +88 -13
- data/lib/pod_builder/core.rb +93 -12
- data/lib/pod_builder/info.rb +32 -98
- data/lib/pod_builder/install.rb +255 -195
- data/lib/pod_builder/licenses.rb +4 -4
- data/lib/pod_builder/podfile.rb +283 -73
- data/lib/pod_builder/podfile/post_actions.rb +9 -15
- data/lib/pod_builder/podfile_cp.rb +93 -0
- data/lib/pod_builder/podfile_item.rb +181 -82
- data/lib/pod_builder/podspec.rb +144 -135
- data/lib/pod_builder/rome/post_install.rb +240 -0
- data/lib/pod_builder/rome/pre_install.rb +6 -0
- data/lib/pod_builder/templates/build_podfile.template +3 -3
- data/lib/pod_builder/version.rb +1 -1
- data/pod-builder.gemspec +6 -6
- metadata +27 -80
- data/Example/Frameworks/PodBuilder.json +0 -32
- data/Example/PodBuilderExample.xcodeproj/project.pbxproj +0 -416
- data/Example/PodBuilderExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- data/Example/PodBuilderExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- data/Example/PodBuilderExample.xcodeproj/project.xcworkspace/xcuserdata/tomas.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/Example/PodBuilderExample.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- data/Example/PodBuilderExample.xcworkspace/contents.xcworkspacedata +0 -10
- data/Example/PodBuilderExample/AppDelegate.swift +0 -47
- data/Example/PodBuilderExample/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -98
- data/Example/PodBuilderExample/Assets.xcassets/Contents.json +0 -6
- data/Example/PodBuilderExample/Base.lproj/LaunchScreen.storyboard +0 -25
- data/Example/PodBuilderExample/Base.lproj/Main.storyboard +0 -24
- data/Example/PodBuilderExample/Info.plist +0 -45
- data/Example/PodBuilderExample/ViewController.swift +0 -25
- data/Example/Podfile +0 -8
- data/Example/Podfile.lock +0 -16
- 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,8 @@
|
|
1
|
+
# This file contains the logic that generates the .podspec files that are placed
|
2
|
+
# along to the prebuild frameworks under PodBuilder/Prebuilt
|
3
|
+
|
1
4
|
module PodBuilder
|
2
5
|
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
6
|
def self.generate(all_buildable_items, analyzer)
|
37
7
|
unless all_buildable_items.count > 0
|
38
8
|
return
|
@@ -40,142 +10,181 @@ module PodBuilder
|
|
40
10
|
|
41
11
|
puts "Generating PodBuilder's local podspec".yellow
|
42
12
|
|
43
|
-
podspec_items = podspec_items_from(all_buildable_items)
|
44
|
-
|
45
13
|
platform = analyzer.instance_variable_get("@result").targets.first.platform
|
46
|
-
generate_podspec_from(
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.include?(pod_name)
|
50
|
-
podspec_path = PodBuilder::basepath("PodBuilder.podspec")
|
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)
|
14
|
+
generate_podspec_from(all_buildable_items, platform)
|
66
15
|
end
|
67
16
|
|
68
17
|
private
|
69
18
|
|
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] }
|
19
|
+
def self.generate_spec_keys_for(item, name, all_buildable_items)
|
20
|
+
podspec = ""
|
21
|
+
valid = false
|
77
22
|
|
78
|
-
|
79
|
-
|
80
|
-
|
23
|
+
slash_count = name.count("/") + 1
|
24
|
+
indentation = " " * slash_count
|
25
|
+
spec_var = "p#{slash_count}"
|
81
26
|
|
27
|
+
if item.name == name
|
28
|
+
if_exists = lambda { |t| File.exist?(PodBuilder::prebuiltpath("#{item.root_name}/#{t}") || "") }
|
29
|
+
|
30
|
+
vendored_frameworks = item.vendored_frameworks + ["#{item.module_name}.framework"]
|
31
|
+
existing_vendored_frameworks = vendored_frameworks.select(&if_exists)
|
32
|
+
existing_vendored_frameworks_basename = vendored_frameworks.map { |t| File.basename(t) }.select(&if_exists)
|
33
|
+
vendored_frameworks = (existing_vendored_frameworks + existing_vendored_frameworks_basename).uniq
|
34
|
+
|
35
|
+
vendored_libraries = item.vendored_libraries
|
36
|
+
existing_vendored_libraries = vendored_libraries.map { |t| "#{item.module_name}/#{t}" }.select(&if_exists)
|
37
|
+
existing_vendored_libraries_basename = vendored_libraries.map { |t| File.basename(t) }.select(&if_exists)
|
38
|
+
vendored_libraries = (existing_vendored_libraries + existing_vendored_libraries_basename).uniq
|
39
|
+
|
40
|
+
# .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)
|
41
|
+
vendored_libraries.reject! { |t| t.end_with?(".a") }
|
42
|
+
|
43
|
+
frameworks = all_buildable_items.select { |t| vendored_frameworks.include?("#{t.module_name}.framework") }.uniq
|
44
|
+
static_frameworks = frameworks.select { |x| x.is_static }
|
45
|
+
|
46
|
+
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
|
47
|
+
exclude_files = static_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/Info.plist" }.compact.flatten.uniq
|
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
|
-
|
68
|
+
xcconfig = Hash.new
|
69
|
+
item.xcconfig.each do |k, v|
|
70
|
+
unless v != "$(inherited)"
|
71
|
+
xcconfig[k] = item.xcconfig[k]
|
72
|
+
next
|
73
|
+
end
|
74
|
+
unless k == "OTHER_LDFLAGS"
|
75
|
+
next # For the time being limit to OTHER_LDFLAGS key
|
76
|
+
end
|
77
|
+
|
78
|
+
if podspec_values = item.xcconfig[k]
|
79
|
+
podspec_values_arr = podspec_values.split(" ")
|
80
|
+
podspec_values_arr.push(v)
|
81
|
+
v = podspec_values_arr.join(" ")
|
82
|
+
end
|
83
|
+
|
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 }
|
102
95
|
end
|
103
|
-
|
104
|
-
|
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"
|
103
|
+
end
|
105
104
|
end
|
106
105
|
|
107
|
-
|
108
|
-
|
109
|
-
podspecs.push(podspec)
|
106
|
+
valid = valid || vendored_frameworks.count > 0
|
110
107
|
end
|
111
108
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
115
|
+
|
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
|
120
131
|
end
|
121
132
|
|
122
|
-
def self.
|
123
|
-
|
133
|
+
def self.generate_podspec_from(all_buildable_items, platform)
|
134
|
+
prebuilt_podspec_path = all_buildable_items.map(&:prebuilt_podspec_path)
|
135
|
+
prebuilt_podspec_path.each do |path|
|
136
|
+
if File.exist?(path)
|
137
|
+
FileUtils.rm(path)
|
138
|
+
end
|
139
|
+
end
|
124
140
|
|
125
|
-
|
126
|
-
|
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
|
141
|
+
all_buildable_items.each do |item|
|
142
|
+
if item.is_prebuilt
|
131
143
|
next
|
132
144
|
end
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
podspec_item.vendored_items = pod.vendored_items
|
145
|
+
if item.name != item.root_name
|
146
|
+
if all_buildable_items.map(&:name).include?(item.root_name)
|
147
|
+
next # will process root spec, skip subspecs
|
148
|
+
end
|
149
|
+
end
|
150
|
+
if File.exist?(item.prebuilt_podspec_path)
|
151
|
+
next # skip if podspec was already generated
|
141
152
|
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
153
|
|
151
|
-
|
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
|
+
podspec = "Pod::Spec.new do |p1|\n"
|
154
155
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
next # For the time being limit to OTHER_LDFLAGS key
|
163
|
-
end
|
156
|
+
podspec += " p1.name = '#{item.root_name}'\n"
|
157
|
+
podspec += " p1.version = '#{item.version}'\n"
|
158
|
+
podspec += " p1.summary = '#{item.summary.gsub("'", "\\'")}'\n"
|
159
|
+
podspec += " p1.homepage = '#{item.homepage}'\n"
|
160
|
+
podspec += " p1.author = 'PodBuilder'\n"
|
161
|
+
podspec += " p1.source = { 'git' => '#{item.source['git']}'}\n"
|
162
|
+
podspec += " p1.license = { :type => '#{item.license}' }\n"
|
164
163
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
164
|
+
podspec += "\n"
|
165
|
+
podspec += " p1.#{platform.safe_string_name.downcase}.deployment_target = '#{platform.deployment_target.version}'\n"
|
166
|
+
podspec += "\n"
|
167
|
+
|
168
|
+
main_keys, valid = generate_spec_keys_for(item, item.root_name, all_buildable_items)
|
169
|
+
if !valid
|
170
|
+
next
|
173
171
|
end
|
174
172
|
|
175
|
-
|
173
|
+
podspec += main_keys
|
174
|
+
podspec += "end"
|
175
|
+
|
176
|
+
spec_path = item.prebuilt_podspec_path
|
177
|
+
if File.directory?(File.dirname(spec_path))
|
178
|
+
File.write(spec_path, podspec)
|
179
|
+
else
|
180
|
+
message = "Prebuilt podspec destination not found for #{File.basename(spec_path)}".red
|
181
|
+
if ENV['DEBUGGING']
|
182
|
+
puts message
|
183
|
+
else
|
184
|
+
raise message
|
185
|
+
end
|
186
|
+
end
|
176
187
|
end
|
177
|
-
|
178
|
-
return podspec_items
|
179
188
|
end
|
180
189
|
end
|
181
190
|
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# TODO: Add support when building without use_frameworks!
|
2
|
+
|
3
|
+
require 'fourflusher'
|
4
|
+
require 'colored'
|
5
|
+
|
6
|
+
module PodBuilder
|
7
|
+
def self.build_for_iosish_platform(sandbox, build_dir, target, device, simulator, configuration, deterministic_build, build_for_apple_silicon)
|
8
|
+
raise "\n\nApple silicon hardware still unsupported since it requires to migrate to xcframeworks".red if build_for_apple_silicon
|
9
|
+
|
10
|
+
dsym_device_folder = File.join(build_dir, "dSYM", device)
|
11
|
+
dsym_simulator_folder = File.join(build_dir, "dSYM", simulator)
|
12
|
+
FileUtils.mkdir_p(dsym_device_folder)
|
13
|
+
FileUtils.mkdir_p(dsym_simulator_folder)
|
14
|
+
|
15
|
+
deployment_target = target.platform_deployment_target
|
16
|
+
target_label = target.cocoapods_target_label
|
17
|
+
|
18
|
+
xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [])
|
19
|
+
excluded_archs = build_for_apple_silicon ? [] : ["arm64"]
|
20
|
+
xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs)
|
21
|
+
|
22
|
+
spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
|
23
|
+
spec_names.each do |root_name, module_name|
|
24
|
+
device_base = "#{build_dir}/#{configuration}-#{device}/#{root_name}"
|
25
|
+
device_lib = "#{device_base}/#{module_name}.framework/#{module_name}"
|
26
|
+
device_dsym = "#{device_base}/#{module_name}.framework.dSYM"
|
27
|
+
device_framework_lib = File.dirname(device_lib)
|
28
|
+
device_swift_header_path = "#{device_framework_lib}/Headers/#{module_name}-Swift.h"
|
29
|
+
|
30
|
+
simulator_base = "#{build_dir}/#{configuration}-#{simulator}/#{root_name}"
|
31
|
+
simulator_lib = "#{simulator_base}/#{module_name}.framework/#{module_name}"
|
32
|
+
simulator_dsym = "#{simulator_base}/#{module_name}.framework.dSYM"
|
33
|
+
simulator_framework_lib = File.dirname(simulator_lib)
|
34
|
+
simulator_swift_header_path = "#{simulator_framework_lib}/Headers/#{module_name}-Swift.h"
|
35
|
+
|
36
|
+
next unless File.file?(device_lib) && File.file?(simulator_lib)
|
37
|
+
|
38
|
+
# Starting with Xcode 12b3 the simulator binary contains an arm64 slice as well which conflict with the one in the device_lib
|
39
|
+
# when creating the fat library. A naive workaround is to remove the arm64 from the simulator_lib however this is wrong because
|
40
|
+
# we might actually need to have 2 separated arm64 slices, one for simulator and one for device each built with different
|
41
|
+
# compile time directives (e.g #if targetEnvironment(simulator))
|
42
|
+
#
|
43
|
+
# For the time being we remove the arm64 slice bacause otherwise the `xcrun lipo -create -output ...` would fail.
|
44
|
+
if `xcrun lipo -info #{simulator_lib}`.include?("arm64")
|
45
|
+
`xcrun lipo -remove arm64 #{simulator_lib} -o #{simulator_lib}`
|
46
|
+
end
|
47
|
+
|
48
|
+
raise "Lipo failed on #{device_lib}" unless system("xcrun lipo -create -output #{device_lib} #{device_lib} #{simulator_lib}")
|
49
|
+
|
50
|
+
# Merge swift headers as per Xcode 10.2 release notes
|
51
|
+
if File.exist?(device_swift_header_path) && File.exist?(simulator_swift_header_path)
|
52
|
+
device_content = File.read(device_swift_header_path)
|
53
|
+
simulator_content = File.read(simulator_swift_header_path)
|
54
|
+
merged_content = %{
|
55
|
+
#if TARGET_OS_SIMULATOR
|
56
|
+
#{simulator_content}
|
57
|
+
#else
|
58
|
+
#{device_content}
|
59
|
+
#endif
|
60
|
+
}
|
61
|
+
File.write(device_swift_header_path, merged_content)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Merge device framework into simulator framework (so that e.g swift Module folder is merged)
|
65
|
+
# letting device framework files overwrite simulator ones
|
66
|
+
FileUtils.cp_r(File.join(device_framework_lib, "."), simulator_framework_lib)
|
67
|
+
source_lib = File.dirname(simulator_framework_lib)
|
68
|
+
|
69
|
+
FileUtils.cp_r(source_lib, build_dir)
|
70
|
+
|
71
|
+
FileUtils.cp_r(device_dsym, dsym_device_folder) if File.exist?(device_dsym)
|
72
|
+
FileUtils.cp_r(simulator_dsym, dsym_simulator_folder) if File.exist?(simulator_dsym)
|
73
|
+
|
74
|
+
# Remove frameworks leaving dSYMs
|
75
|
+
FileUtils.rm_rf(device_framework_lib)
|
76
|
+
FileUtils.rm_rf(simulator_framework_lib)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil, configuration, deterministic_build, exclude_archs)
|
81
|
+
args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{configuration} -sdk #{sdk})
|
82
|
+
supported_platforms = { 'iphonesimulator' => 'iOS', 'appletvsimulator' => 'tvOS', 'watchsimulator' => 'watchOS' }
|
83
|
+
if platform = supported_platforms[sdk]
|
84
|
+
args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
|
85
|
+
end
|
86
|
+
|
87
|
+
xcodebuild_version = `xcodebuild -version | head -n1 | awk '{print $2}'`.strip().to_f
|
88
|
+
if exclude_archs.count > 0 && xcodebuild_version >= 12.0
|
89
|
+
args += ["EXCLUDED_ARCHS=#{exclude_archs.join(" ")}"]
|
90
|
+
end
|
91
|
+
|
92
|
+
environmental_variables = {}
|
93
|
+
if deterministic_build
|
94
|
+
environmental_variables["ZERO_AR_DATE"] = "1"
|
95
|
+
end
|
96
|
+
|
97
|
+
execute_command 'xcodebuild', args, true, environmental_variables
|
98
|
+
end
|
99
|
+
|
100
|
+
# Copy paste implementation from CocoaPods internals to be able to call poopen3 passing environmental variables
|
101
|
+
def self.execute_command(executable, command, raise_on_failure = true, environmental_variables = {})
|
102
|
+
bin = Pod::Executable.which!(executable)
|
103
|
+
|
104
|
+
command = command.map(&:to_s)
|
105
|
+
full_command = "#{bin} #{command.join(' ')}"
|
106
|
+
|
107
|
+
stdout = Pod::Executable::Indenter.new
|
108
|
+
stderr = Pod::Executable::Indenter.new
|
109
|
+
|
110
|
+
status = popen3(bin, command, stdout, stderr, environmental_variables)
|
111
|
+
stdout = stdout.join
|
112
|
+
stderr = stderr.join
|
113
|
+
output = stdout + stderr
|
114
|
+
unless status.success?
|
115
|
+
if raise_on_failure
|
116
|
+
raise "#{full_command}\n\n#{output}"
|
117
|
+
else
|
118
|
+
UI.message("[!] Failed: #{full_command}".red)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
output
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.popen3(bin, command, stdout, stderr, environmental_variables)
|
126
|
+
require 'open3'
|
127
|
+
Open3.popen3(environmental_variables, bin, *command) do |i, o, e, t|
|
128
|
+
Pod::Executable::reader(o, stdout)
|
129
|
+
Pod::Executable::reader(e, stderr)
|
130
|
+
i.close
|
131
|
+
|
132
|
+
status = t.value
|
133
|
+
|
134
|
+
o.flush
|
135
|
+
e.flush
|
136
|
+
sleep(0.01)
|
137
|
+
|
138
|
+
status
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.enable_debug_information(project_path, configuration)
|
143
|
+
project = Xcodeproj::Project.open(project_path)
|
144
|
+
project.targets.each do |target|
|
145
|
+
config = target.build_configurations.find { |config| config.name.eql? configuration }
|
146
|
+
config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf-with-dsym'
|
147
|
+
config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
|
148
|
+
end
|
149
|
+
project.save
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_context, user_options|
|
156
|
+
enable_dsym = user_options.fetch('dsym', true)
|
157
|
+
configuration = user_options.fetch('configuration', 'Debug')
|
158
|
+
if user_options["pre_compile"]
|
159
|
+
user_options["pre_compile"].call(installer_context)
|
160
|
+
end
|
161
|
+
|
162
|
+
sandbox_root = Pathname(installer_context.sandbox_root)
|
163
|
+
sandbox = Pod::Sandbox.new(sandbox_root)
|
164
|
+
|
165
|
+
PodBuilder::enable_debug_information(sandbox.project_path, configuration)
|
166
|
+
|
167
|
+
build_dir = sandbox_root.parent + 'build'
|
168
|
+
base_destination = sandbox_root.parent + 'Prebuilt'
|
169
|
+
|
170
|
+
build_dir.rmtree if build_dir.directory?
|
171
|
+
targets = installer_context.umbrella_targets.select { |t| t.specs.any? }
|
172
|
+
targets.each do |target|
|
173
|
+
case target.platform_name
|
174
|
+
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)
|
175
|
+
when :osx then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
|
176
|
+
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)
|
177
|
+
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)
|
178
|
+
else raise "\n\nUnknown platform '#{target.platform_name}'".red end
|
179
|
+
end
|
180
|
+
|
181
|
+
raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
|
182
|
+
|
183
|
+
built_count = installer_context.umbrella_targets.map { |t| t.specs.map(&:name) }.flatten.map { |t| t.split("/").first }.uniq.count
|
184
|
+
Pod::UI.puts "Built #{built_count} #{'items'.pluralize(built_count)}, copying..."
|
185
|
+
|
186
|
+
base_destination.rmtree if base_destination.directory?
|
187
|
+
|
188
|
+
installer_context.umbrella_targets.each do |umbrella|
|
189
|
+
umbrella.specs.each do |spec|
|
190
|
+
root_name = spec.name.split("/").first
|
191
|
+
# Make sure the device target overwrites anything in the simulator build, otherwise iTunesConnect
|
192
|
+
# can get upset about Info.plist containing references to the simulator SDK
|
193
|
+
frameworks = Pathname.glob("build/#{root_name}/*.framework").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
|
194
|
+
|
195
|
+
consumer = spec.consumer(umbrella.platform_name)
|
196
|
+
file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
|
197
|
+
frameworks += file_accessor.vendored_libraries
|
198
|
+
frameworks += file_accessor.vendored_frameworks
|
199
|
+
resources = file_accessor.resources
|
200
|
+
|
201
|
+
destination = File.join(base_destination, root_name)
|
202
|
+
FileUtils.mkdir_p(destination)
|
203
|
+
|
204
|
+
files = frameworks + resources
|
205
|
+
files.each do |file|
|
206
|
+
FileUtils.cp_r(file, destination)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Depending on the resource it may happen that it is present twice, both in the .framework and in the parent folder
|
212
|
+
Dir.glob("#{base_destination}/*") do |path|
|
213
|
+
unless File.directory?(path)
|
214
|
+
return
|
215
|
+
end
|
216
|
+
|
217
|
+
files = Dir.glob("#{path}/*")
|
218
|
+
framework_files = Dir.glob("#{path}/*.framework/**/*").map { |t| File.basename(t) }
|
219
|
+
|
220
|
+
files.each do |file|
|
221
|
+
filename = File.basename(file.gsub(/\.xib$/, ".nib"))
|
222
|
+
if framework_files.include?(filename)
|
223
|
+
FileUtils.rm_rf(file)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
if enable_dsym
|
229
|
+
FileUtils.mv("#{build_dir}/dSYM", sandbox_root.parent)
|
230
|
+
else
|
231
|
+
raise "Not implemented"
|
232
|
+
end
|
233
|
+
|
234
|
+
build_dir.rmtree if build_dir.directory?
|
235
|
+
|
236
|
+
if user_options["post_compile"]
|
237
|
+
user_options["post_compile"].call(installer_context)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|