pod-builder 1.9.2 → 2.0.0.beta.21

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -0
  3. data/Example/PodBuilder/.gitignore +6 -0
  4. data/Example/PodBuilder/.pod_builder/pod_builder +0 -0
  5. data/Example/{Frameworks → PodBuilder}/PodBuilder.json +10 -4
  6. data/Example/PodBuilder/Podfile +23 -0
  7. data/Example/PodBuilder/Podfile.restore +40 -0
  8. data/Example/PodBuilderExample.xcodeproj/project.pbxproj +3 -8
  9. data/Example/{PodBuilderExample.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/xcschememanagement.plist → PodBuilderExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist} +2 -8
  10. data/Example/PodBuilderExample/AppDelegate.swift +4 -0
  11. data/Example/Podfile +42 -1
  12. data/Example/Podfile.lock +426 -7
  13. data/Example/Pods-acknowledgements.md +210 -0
  14. data/Example/Pods-acknowledgements.plist +206 -0
  15. data/README.md +50 -13
  16. data/exe/pod_builder +39 -28
  17. data/lib/pod_builder/analyze.rb +32 -7
  18. data/lib/pod_builder/analyzer.rb +16 -0
  19. data/lib/pod_builder/command/build.rb +44 -161
  20. data/lib/pod_builder/command/build_all.rb +2 -2
  21. data/lib/pod_builder/command/clean.rb +34 -55
  22. data/lib/pod_builder/command/clear_lldbinit.rb +7 -3
  23. data/lib/pod_builder/command/deintegrate.rb +29 -7
  24. data/lib/pod_builder/command/generate_lfs.rb +3 -3
  25. data/lib/pod_builder/command/generate_podspec.rb +3 -2
  26. data/lib/pod_builder/command/info.rb +1 -1
  27. data/lib/pod_builder/command/init.rb +37 -14
  28. data/lib/pod_builder/command/install_sources.rb +21 -14
  29. data/lib/pod_builder/command/none.rb +2 -2
  30. data/lib/pod_builder/command/restore_all.rb +4 -4
  31. data/lib/pod_builder/command/switch.rb +137 -95
  32. data/lib/pod_builder/command/sync_podfile.rb +5 -3
  33. data/lib/pod_builder/command/update.rb +5 -6
  34. data/lib/pod_builder/command/update_lldbinit.rb +11 -9
  35. data/lib/pod_builder/configuration.rb +88 -13
  36. data/lib/pod_builder/core.rb +93 -12
  37. data/lib/pod_builder/info.rb +32 -98
  38. data/lib/pod_builder/install.rb +255 -195
  39. data/lib/pod_builder/licenses.rb +4 -4
  40. data/lib/pod_builder/podfile.rb +287 -73
  41. data/lib/pod_builder/podfile/post_actions.rb +9 -15
  42. data/lib/pod_builder/podfile_cp.rb +93 -0
  43. data/lib/pod_builder/podfile_item.rb +181 -82
  44. data/lib/pod_builder/podspec.rb +144 -135
  45. data/lib/pod_builder/rome/post_install.rb +240 -0
  46. data/lib/pod_builder/rome/pre_install.rb +6 -0
  47. data/lib/pod_builder/templates/build_podfile.template +3 -3
  48. data/lib/pod_builder/version.rb +1 -1
  49. data/pod-builder.gemspec +4 -4
  50. metadata +34 -65
  51. data/Example/Pods/Alamofire/LICENSE +0 -19
  52. data/Example/Pods/Alamofire/README.md +0 -242
  53. data/Example/Pods/Alamofire/Source/AFError.swift +0 -460
  54. data/Example/Pods/Alamofire/Source/Alamofire.swift +0 -465
  55. data/Example/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift +0 -37
  56. data/Example/Pods/Alamofire/Source/MultipartFormData.swift +0 -580
  57. data/Example/Pods/Alamofire/Source/NetworkReachabilityManager.swift +0 -233
  58. data/Example/Pods/Alamofire/Source/Notifications.swift +0 -55
  59. data/Example/Pods/Alamofire/Source/ParameterEncoding.swift +0 -483
  60. data/Example/Pods/Alamofire/Source/Request.swift +0 -654
  61. data/Example/Pods/Alamofire/Source/Response.swift +0 -567
  62. data/Example/Pods/Alamofire/Source/ResponseSerialization.swift +0 -715
  63. data/Example/Pods/Alamofire/Source/Result.swift +0 -300
  64. data/Example/Pods/Alamofire/Source/ServerTrustPolicy.swift +0 -307
  65. data/Example/Pods/Alamofire/Source/SessionDelegate.swift +0 -725
  66. data/Example/Pods/Alamofire/Source/SessionManager.swift +0 -896
  67. data/Example/Pods/Alamofire/Source/TaskDelegate.swift +0 -466
  68. data/Example/Pods/Alamofire/Source/Timeline.swift +0 -136
  69. data/Example/Pods/Alamofire/Source/Validation.swift +0 -315
  70. data/Example/Pods/Manifest.lock +0 -16
  71. data/Example/Pods/Pods.xcodeproj/project.pbxproj +0 -673
  72. data/Example/Pods/Pods.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/Alamofire.xcscheme +0 -60
  73. data/Example/Pods/Pods.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/Pods-PodBuilderExample.xcscheme +0 -60
  74. data/Example/Pods/Pods.xcodeproj/xcuserdata/tomas.xcuserdatad/xcschemes/xcschememanagement.plist +0 -21
  75. data/Example/Pods/Target Support Files/Alamofire/Alamofire-dummy.m +0 -5
  76. data/Example/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch +0 -12
  77. data/Example/Pods/Target Support Files/Alamofire/Alamofire-umbrella.h +0 -16
  78. data/Example/Pods/Target Support Files/Alamofire/Alamofire.modulemap +0 -6
  79. data/Example/Pods/Target Support Files/Alamofire/Alamofire.xcconfig +0 -9
  80. data/Example/Pods/Target Support Files/Alamofire/Info.plist +0 -26
  81. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Info.plist +0 -26
  82. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-acknowledgements.markdown +0 -26
  83. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-acknowledgements.plist +0 -58
  84. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-dummy.m +0 -5
  85. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-frameworks.sh +0 -153
  86. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-resources.sh +0 -118
  87. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample-umbrella.h +0 -16
  88. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample.debug.xcconfig +0 -11
  89. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample.modulemap +0 -6
  90. data/Example/Pods/Target Support Files/Pods-PodBuilderExample/Pods-PodBuilderExample.release.xcconfig +0 -11
  91. data/lib/pod_builder/cocoapods/specification.rb +0 -27
@@ -3,8 +3,10 @@ require 'fileutils'
3
3
  require 'colored'
4
4
 
5
5
  require 'pod_builder/podfile'
6
+ require 'pod_builder/podfile_cp'
6
7
  require 'pod_builder/podfile_item'
7
8
  require 'pod_builder/analyze'
9
+ require 'pod_builder/analyzer'
8
10
  require 'pod_builder/install'
9
11
  require 'pod_builder/info'
10
12
  require 'pod_builder/configuration'
@@ -14,17 +16,26 @@ require 'pod_builder/licenses'
14
16
  require 'core_ext/string'
15
17
 
16
18
  module PodBuilder
19
+ @@xcodeproj_path = nil
20
+ @@xcodeworkspace_path = nil
21
+
17
22
  def self.safe_rm_rf(path)
18
23
  unless File.exist?(path)
19
24
  return
20
25
  end
21
26
 
27
+ unless File.directory?(path)
28
+ FileUtils.rm(path)
29
+
30
+ return
31
+ end
32
+
22
33
  current_dir = Dir.pwd
23
34
 
24
35
  Dir.chdir(path)
25
36
 
26
37
  h = `git rev-parse --show-toplevel`.strip()
27
- raise "\n\nNo git repository found, can't delete files!\n".red if h.empty?
38
+ raise "\n\nNo git repository found in '#{path}', can't delete files!\n".red if h.empty? && !path.start_with?(Configuration.build_base_path)
28
39
 
29
40
  FileUtils.rm_rf(path)
30
41
 
@@ -36,8 +47,64 @@ module PodBuilder
36
47
  end
37
48
 
38
49
  def self.basepath(child = "")
50
+ if child.nil?
51
+ return nil
52
+ end
53
+
39
54
  return "#{Configuration.base_path}/#{child}".gsub("//", "/").gsub(/\/$/, '')
40
55
  end
56
+
57
+ def self.prebuiltpath(child = "")
58
+ if child.nil?
59
+ return nil
60
+ end
61
+
62
+ path = basepath("Prebuilt")
63
+ if child.length > 0
64
+ path += "/#{child}"
65
+ end
66
+
67
+ return path
68
+ end
69
+
70
+ def self.buildpath_prebuiltpath(child = "")
71
+ if child.nil?
72
+ return nil
73
+ end
74
+
75
+ path = "#{Configuration.build_path}/Prebuilt"
76
+ if child.length > 0
77
+ path += "/#{child}"
78
+ end
79
+
80
+ return path
81
+ end
82
+
83
+ def self.buildpath_dsympath(child = "")
84
+ if child.nil?
85
+ return nil
86
+ end
87
+
88
+ path = "#{Configuration.build_path}/dSYM"
89
+ if child.length > 0
90
+ path += "/#{child}"
91
+ end
92
+
93
+ return path
94
+ end
95
+
96
+ def self.dsympath(child = "")
97
+ if child.nil?
98
+ return nil
99
+ end
100
+
101
+ path = basepath("dSYM")
102
+ if child.length > 0
103
+ path += "/#{child}"
104
+ end
105
+
106
+ return path
107
+ end
41
108
 
42
109
  def self.project_path(child = "")
43
110
  project = PodBuilder::find_xcodeworkspace
@@ -46,27 +113,36 @@ module PodBuilder
46
113
  end
47
114
 
48
115
  def self.find_xcodeproj
116
+ unless @@xcodeproj_path.nil?
117
+ return @@xcodeproj_path
118
+ end
49
119
  project_name = File.basename(find_xcodeworkspace, ".*")
50
120
 
51
121
  xcodeprojects = Dir.glob("#{home}/**/#{project_name}.xcodeproj").select { |x|
52
122
  folder_in_home = x.gsub(home, "")
53
123
  !folder_in_home.include?("/Pods/") && !x.include?(PodBuilder::basepath("Sources")) && !x.include?(basepath)
54
124
  }
55
- raise "xcodeproj not found!".red if xcodeprojects.count == 0
56
- raise "Found multiple xcodeproj:\n#{xcodeprojects.join("\n")}".red if xcodeprojects.count > 1
125
+ raise "\n\nxcodeproj not found!".red if xcodeprojects.count == 0
126
+ raise "\n\nFound multiple xcodeproj:\n#{xcodeprojects.join("\n")}".red if xcodeprojects.count > 1
57
127
 
58
- return xcodeprojects.first
128
+ @@xcodeproj_path = xcodeprojects.first
129
+ return @@xcodeproj_path
59
130
  end
60
131
 
61
132
  def self.find_xcodeworkspace
133
+ unless @@xcodeworkspace_path.nil?
134
+ return @@xcodeworkspace_path
135
+ end
136
+
62
137
  xcworkspaces = Dir.glob("#{home}/**/#{Configuration.project_name}*.xcworkspace").select { |x|
63
138
  folder_in_home = x.gsub(home, "")
64
139
  !folder_in_home.include?("/Pods/") && !x.include?(PodBuilder::basepath("Sources")) && !x.include?(basepath) && !x.include?(".xcodeproj/")
65
140
  }
66
- raise "xcworkspace not found!".red if xcworkspaces.count == 0
67
- raise "Found multiple xcworkspaces:\n#{xcworkspaces.join("\n")}".red if xcworkspaces.count > 1
141
+ raise "\n\nxcworkspace not found!".red if xcworkspaces.count == 0
142
+ raise "\n\nFound multiple xcworkspaces:\n#{xcworkspaces.join("\n")}".red if xcworkspaces.count > 1
68
143
 
69
- return xcworkspaces.first
144
+ @@xcodeworkspace_path = xcworkspaces.first
145
+ return @@xcodeworkspace_path
70
146
  end
71
147
 
72
148
  def self.prepare_basepath
@@ -93,18 +169,22 @@ module PodBuilder
93
169
 
94
170
  def self.system_swift_version
95
171
  swift_version = `swiftc --version | grep -o 'swiftlang-.*\s'`.strip()
96
- raise "Unsupported swift compiler version, expecting `swiftlang` keyword in `swiftc --version`" if swift_version.length == 0
172
+ raise "\n\nUnsupported swift compiler version, expecting `swiftlang` keyword in `swiftc --version`".red if swift_version.length == 0
97
173
  return swift_version
98
174
  end
99
175
 
100
- def self.add_lock_file
101
- lockfile_path = File.join(home, Configuration.lock_filename)
176
+ def self.add_lockfile
177
+ lockfile_path = Configuration.lockfile_path
102
178
 
103
179
  if File.exist?(lockfile_path)
104
180
  if pid = File.read(lockfile_path)
105
181
  begin
106
182
  if Process.getpgid(pid)
183
+ if Configuration.deterministic_build
184
+ raise "\n\nAnother PodBuilder pending task is running\n".red
185
+ else
107
186
  raise "\n\nAnother PodBuilder pending task is running on this project\n".red
187
+ end
108
188
  end
109
189
  rescue
110
190
  end
@@ -114,8 +194,9 @@ module PodBuilder
114
194
  File.write(lockfile_path, Process.pid, mode: "w")
115
195
  end
116
196
 
117
- def self.remove_lock_file
118
- lockfile_path = File.join(home, Configuration.lock_filename)
197
+ def self.remove_lockfile
198
+ lockfile_path = Configuration.lockfile_path
199
+
119
200
  if File.exist?(lockfile_path)
120
201
  FileUtils.rm(lockfile_path)
121
202
  end
@@ -1,69 +1,33 @@
1
- require 'cfpropertylist'
1
+ require 'json'
2
2
 
3
3
  module PodBuilder
4
4
  class Info
5
5
  def self.generate_info
6
- restore_path = PodBuilder::basepath("Podfile.restore")
7
- unless File.exist?(restore_path)
8
- raise "No Podfile.restore file found"
9
- return false
10
- end
11
-
12
- podspec_path = PodBuilder::basepath("PodBuilder.podspec")
13
- unless File.exist?(podspec_path)
14
- raise "No PodBuilder.podspec file found"
15
- return false
16
- end
17
-
18
- restore_content = File.read(restore_path)
19
-
20
6
  swift_version = PodBuilder::system_swift_version
21
7
  result = {}
22
8
  name = nil
23
- File.read(podspec_path).each_line do |line|
24
- if (matches = line.match(/s.subspec '(.*)' do \|p\|/)) && matches.size == 2
25
- name = matches[1]
26
- elsif (matches = line.match(/p.vendored_frameworks = '(.*)'/)) && matches.size == 2
27
- path = matches[1].split("'").first
28
- plist_path = File.join(PodBuilder::basepath(path), Configuration.framework_plist_filename)
29
-
30
- # fix name if it's a subspec
31
- if (subspec_items = name.split("_")) && (subspec = subspec_items.last) && subspec_items.count > 1
32
- if path.include?("/#{subspec}")
33
- name = name.sub(/_#{subspec}$/, "/#{subspec}")
34
- end
35
- end
36
-
37
- base = PodBuilder::basepath.gsub(PodBuilder::home + "/", "")
38
- framework_path = File.join(base, matches[1].split("'").first)
39
- result[name] = { framework_path: framework_path }
40
9
 
41
- specs = restore_podspecs(name.split("/").first, restore_content)
42
- unless specs.count > 0
43
- raise "pod `#{name}` not found in restore file"
44
- end
45
-
46
- restore_line = restore_line(name, restore_content)
47
- version = version_info(restore_line)
48
- is_static = is_static(restore_line)
49
- result[name].merge!({ "restore_info": { "version": version, "specs": specs, "is_static": is_static }})
50
- if swift_version = swift_version(restore_line)
51
- result[name][:restore_info].merge!({ "swift_version": swift_version })
52
- end
53
-
54
- prebuilt_info = prebuilt_info(plist_path)
55
- if prebuilt_info.count > 0
56
- result[name].merge!({ "prebuilt_info": prebuilt_info })
57
- end
58
- end
10
+ Dir.glob(PodBuilder::prebuiltpath("**/#{Configuration.prebuilt_info_filename}")).each do |json_path|
11
+ name, prebuilt_info = prebuilt_info(json_path)
12
+ result[name] = prebuilt_info
59
13
  end
60
14
 
61
15
  return result
62
16
  end
63
17
 
64
18
  private
19
+
20
+ def self.pod_name_from_entry(line)
21
+ if (matches = line&.match(/pod '(.*?)'/)) && matches.size == 2
22
+ pod_name = matches[1]
23
+
24
+ return pod_name
25
+ end
26
+
27
+ return "unknown_podname"
28
+ end
65
29
 
66
- def self.version_info(line)
30
+ def self.version_info_from_entry(line)
67
31
  if (matches = line&.match(/pod '(.*)', '=(.*)'/)) && matches.size == 3
68
32
  pod_name = matches[1]
69
33
  tag = matches[2]
@@ -87,70 +51,40 @@ module PodBuilder
87
51
  tag = matches[3]
88
52
 
89
53
  return { "repo": repo, "tag": tag }
54
+ elsif (matches = line&.match(/pod '(.*)', :path => '(.*)'/)) && matches.size == 3
55
+ pod_name = matches[1]
56
+
57
+ return { "repo": "local" }
58
+ elsif (matches = line&.match(/pod '(.*)', :podspec => '(.*)'/)) && matches.size == 3
59
+ pod_name = matches[1]
60
+
61
+ return { "repo": "local" }
90
62
  else
91
- raise "Failed extracting version from line:\n#{line}\n\n"
63
+ raise "\n\nFailed extracting version from line:\n#{line}\n\n".red
92
64
  end
93
65
  end
94
66
 
95
- def self.swift_version(line)
96
- return podbuilder_tag("sv", line)
97
- end
98
-
99
- def self.is_static(line)
100
- if str_tag = podbuilder_tag("is", line)
101
- return str_tag == "true"
102
- end
103
-
104
- return nil
105
- end
106
-
107
- def self.podbuilder_tag(name, line)
108
- if (matches = line&.match(/#{name}<(.*?)?>/)) && matches.size == 2
109
- return matches[1]
110
- end
111
-
112
- return nil
113
- end
114
-
115
67
  def self.prebuilt_info(path)
116
68
  unless File.exist?(path)
117
69
  return {}
118
70
  end
119
-
120
- plist = CFPropertyList::List.new(:file => path)
121
- data = CFPropertyList.native_types(plist.value)
122
-
71
+
72
+ data = JSON.load(File.read(path))
73
+
123
74
  result = {}
124
75
  if swift_version = data["swift_version"]
125
76
  result.merge!({ "swift_version": swift_version})
126
77
  end
127
78
 
128
- pod_version = version_info(data["entry"])
129
-
79
+ pod_version = version_info_from_entry(data["entry"])
80
+ pod_name = pod_name_from_entry(data["entry"])
81
+
130
82
  result.merge!({ "version": pod_version })
131
83
  result.merge!({ "specs": (data["specs"] || []) })
132
84
  result.merge!({ "is_static": (data["is_static"] || false) })
133
85
  result.merge!({ "original_compile_path": (data["original_compile_path"] || "") })
134
86
 
135
- return result
136
- end
137
-
138
- def self.restore_podspecs(root_name, restore_content)
139
- specs = []
140
- restore_content.each_line do |line|
141
- if (matches = line.match(/pod '(#{root_name})(\/.*?)?'/)) && matches.size == 3
142
- specs.push(matches[1] + (matches[2] || ""))
143
- end
144
- end
145
-
146
- return specs.uniq
147
- end
148
-
149
- def self.restore_line(name, restore_content)
150
- unless (matches = restore_content.match(/pod '#{name}(\/.*)?'.*/)) && matches.size == 2
151
- raise "pod `#{name}` not found in restore file"
152
- end
153
- return matches[0]
154
- end
87
+ return pod_name, result
88
+ end
155
89
  end
156
90
  end
@@ -1,41 +1,8 @@
1
- require 'cfpropertylist'
2
-
3
- # We swizzle the analyzer to inject spec overrides. This might no longer be needed
4
- # given that we're swizzling the Pod::Downloader as well
5
- class Pod::Specification::Linter::Analyzer
6
- alias_method :swz_analyze, :analyze
7
-
8
- def analyze(*args)
9
- spec = consumer.spec
10
- if overrides = PodBuilder::Configuration.spec_overrides[spec.name]
11
- overrides.each do |k, v|
12
- spec.attributes_hash[k] = v
13
- end
14
- end
15
-
16
- return swz_analyze
17
- end
18
- end
1
+ require 'digest'
2
+ require 'colored'
3
+ require 'highline/import'
19
4
 
20
- Pod::Downloader.singleton_class.send(:alias_method, :swz_download, :download)
21
- module Pod::Downloader
22
- def self.download(
23
- request,
24
- target,
25
- can_cache: true,
26
- cache_path: Pod::Config.instance.cache_root + 'Pods'
27
- )
28
- result = swz_download(request, target)
29
-
30
- if overrides = PodBuilder::Configuration.spec_overrides[result.spec.name]
31
- overrides.each do |k, v|
32
- result.spec.attributes_hash[k] = v
33
- end
34
- end
35
-
36
- result
37
- end
38
- end
5
+ # The following begin/end clause contains a set of monkey patches of the original CP implementation
39
6
 
40
7
  # The Pod::Target and Pod::Installer::Xcode::PodTargetDependencyInstaller swizzles patch
41
8
  # the following issues:
@@ -44,6 +11,23 @@ end
44
11
  begin
45
12
  require 'cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb'
46
13
 
14
+ class Pod::Specification
15
+ Pod::Specification.singleton_class.send(:alias_method, :swz_from_hash, :from_hash)
16
+ Pod::Specification.singleton_class.send(:alias_method, :swz_from_string, :from_string)
17
+
18
+ def self.from_string(*args)
19
+ spec = swz_from_string(*args)
20
+
21
+ if overrides = PodBuilder::Configuration.spec_overrides[spec.name]
22
+ overrides.each do |k, v|
23
+ spec.attributes_hash[k] = v
24
+ end
25
+ end
26
+
27
+ spec
28
+ end
29
+ end
30
+
47
31
  class Pod::Target
48
32
  attr_accessor :mock_dynamic_framework
49
33
 
@@ -56,7 +40,7 @@ begin
56
40
  elsif defined?(Pod::Target::BuildType) # CocoaPods 1.7, 1.8
57
41
  Pod::Target::BuildType.new(linkage: :dynamic, packaging: :framework)
58
42
  else
59
- raise "BuildType not found. Open an issue reporting your CocoaPods version"
43
+ raise "\n\nBuildType not found. Open an issue reporting your CocoaPods version".red
60
44
  end
61
45
  else
62
46
  swz_build_type()
@@ -64,6 +48,19 @@ begin
64
48
  end
65
49
  end
66
50
 
51
+ # Starting from CocoaPods 1.10.0 and later resources are no longer copied inside the .framework
52
+ # when building static frameworks. While this is correct when using CP normally, for redistributable
53
+ # frameworks we require resources to be shipped along the binary
54
+ class Pod::Installer::Xcode::PodsProjectGenerator::PodTargetInstaller
55
+ alias_method :swz_add_files_to_build_phases, :add_files_to_build_phases
56
+
57
+ def add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
58
+ target.mock_dynamic_framework = target.build_as_static_framework?
59
+ swz_add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
60
+ target.mock_dynamic_framework = false
61
+ end
62
+ end
63
+
67
64
  class Pod::Installer::Xcode::PodTargetDependencyInstaller
68
65
  alias_method :swz_wire_resource_bundle_targets, :wire_resource_bundle_targets
69
66
 
@@ -80,211 +77,229 @@ end
80
77
 
81
78
  module PodBuilder
82
79
  class Install
80
+ # This method will generate prebuilt data by building from "/tmp/pod_builder/Podfile"
83
81
  def self.podfile(podfile_content, podfile_items, build_configuration)
82
+ puts "Preparing build Podfile".yellow
83
+
84
84
  PodBuilder::safe_rm_rf(Configuration.build_path)
85
85
  FileUtils.mkdir_p(Configuration.build_path)
86
-
87
- # Copy the repo to extract license (and potentially other files in the future)
88
- podfile_items.select { |x| x.is_development_pod }.each do |podfile_item|
89
- destination_path = "#{Configuration.build_path}/Pods/#{podfile_item.name}"
90
- FileUtils.mkdir_p(destination_path)
91
-
92
- if Pathname.new(podfile_item.path).absolute?
93
- FileUtils.cp_r("#{podfile_item.path}/.", destination_path)
94
- else
95
- FileUtils.cp_r("#{PodBuilder::basepath(podfile_item.path)}/.", destination_path)
96
- end
97
-
98
- # It is important that CocoaPods compiles the files under Configuration.build_path in order that DWARF
99
- # debug info reference to this path. Doing otherwise breaks the assumptions that make the `update_lldbinit`
100
- # command work
101
- podfile_content.gsub!(podfile_item.path, destination_path)
102
-
103
- license_files = Dir.glob("#{destination_path}/**/*acknowledgements.plist").each { |f| File.delete(f) }
104
- end
105
86
 
106
87
  init_git(Configuration.build_path) # this is needed to be able to call safe_rm_rf
107
88
 
108
- podfile_path = "#{Configuration.build_path}/Podfile"
89
+ podfile_content = copy_development_pods_source_code(podfile_content, podfile_items)
90
+
91
+ podfile_content = Podfile.update_path_entries(podfile_content, Install.method(:podfile_path_transform))
92
+ podfile_content = Podfile.update_project_entries(podfile_content, Install.method(:podfile_path_transform))
93
+ podfile_content = Podfile.update_require_entries(podfile_content, Install.method(:podfile_path_transform))
94
+
95
+ podfile_path = File.join(Configuration.build_path, "Podfile")
109
96
  File.write(podfile_path, podfile_content)
110
- Podfile.update_path_entires(podfile_path, true)
111
- Podfile.update_project_entries(podfile_path, true)
112
97
 
113
98
  begin
114
99
  lock_file = "#{Configuration.build_path}/pod_builder.lock"
115
100
  FileUtils.touch(lock_file)
101
+
102
+ use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
116
103
 
117
104
  install
118
105
 
119
- add_framework_plist_info(podfile_items)
120
- cleanup_frameworks(podfile_items)
121
- copy_frameworks(podfile_items)
122
- copy_libraries(podfile_items)
123
- if build_configuration != "debug"
124
- copy_dsyms(podfile_items)
125
- end
106
+ copy_prebuilt_items(podfile_items)
107
+ add_prebuilt_info_file(podfile_items)
108
+
109
+ licenses = license_specifiers()
110
+
111
+ if !OPTIONS.has_key?(:debug)
112
+ PodBuilder::safe_rm_rf(Configuration.build_path)
113
+ end
114
+
115
+ return licenses
126
116
  rescue Exception => e
117
+ if File.directory?("#{Configuration.build_path}/Pods/Pods.xcodeproj")
118
+ if ENV['DEBUGGING']
119
+ system("xed #{Configuration.build_path}/Pods")
120
+ else
121
+ confirm = ask("\n\nOh no! Something went wrong during prebuild phase! Do you want to open the prebuild project to debug the error, you will need to add and run the Pods-Dummy scheme? [Y/N] ".red) { |yn| yn.limit = 1, yn.validate = /[yn]/i }
122
+ if confirm.downcase == 'y'
123
+ system("xed #{Configuration.build_path}/Pods")
124
+ end
125
+ end
126
+ end
127
+
127
128
  raise e
128
- ensure
129
- FileUtils.rm(lock_file)
129
+ ensure
130
+ FileUtils.rm(lock_file) if File.exist?(lock_file)
130
131
  end
131
132
  end
132
133
 
133
134
  private
134
135
 
135
- def self.install
136
- CLAide::Command::PluginManager.load_plugins("cocoapods")
136
+ def self.license_specifiers
137
+ acknowledge_file = "#{Configuration.build_path}/Pods/Target Support Files/Pods-DummyTarget/Pods-DummyTarget-acknowledgements.plist"
138
+ unless File.exist?(acknowledge_file)
139
+ raise "\n\nLicense file not found".red
140
+ end
137
141
 
138
- current_dir = Dir.pwd
139
-
140
- Dir.chdir(Configuration.build_path)
142
+ plist = CFPropertyList::List.new(:file => acknowledge_file)
143
+ data = CFPropertyList.native_types(plist.value)
144
+
145
+ return data["PreferenceSpecifiers"] || []
146
+ end
141
147
 
142
- config = Pod::Config.new()
143
- installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
144
- installer.repo_update = false
145
- installer.update = false
146
- installer.install!
148
+ def self.copy_development_pods_source_code(podfile_content, podfile_items)
149
+ if Configuration.build_using_repo_paths
150
+ return podfile_content
151
+ end
147
152
 
148
- Dir.chdir(current_dir)
149
- end
153
+ # Development pods are normally built/integrated without moving files from their original paths.
154
+ # It is important that CocoaPods compiles the files under Configuration.build_path in order that
155
+ # DWARF debug info reference to this constant path. Doing otherwise breaks the assumptions that
156
+ # makes the `update_lldbinit` command work.
157
+ development_pods = podfile_items.select { |x| x.is_development_pod }
158
+ development_pods.each do |podfile_item|
159
+ destination_path = "#{Configuration.build_path}/Pods/#{podfile_item.name}"
160
+ FileUtils.mkdir_p(destination_path)
150
161
 
151
- def self.rel_path(path, podfile_items)
152
- name = File.basename(path)
153
- name_no_ext = File.basename(name, File.extname(name))
154
- if podfile_item = podfile_items.detect { |x| x.module_name == name_no_ext && Configuration.subspecs_to_split.include?(x.name) }
155
- return "#{podfile_item.prebuilt_rel_path}"
156
- else
157
- return name
162
+ if Pathname.new(podfile_item.path).absolute?
163
+ FileUtils.cp_r("#{podfile_item.path}/.", destination_path)
164
+ else
165
+ FileUtils.cp_r("#{PodBuilder::basepath(podfile_item.path)}/.", destination_path)
166
+ end
167
+
168
+ podfile_content.gsub!("'#{podfile_item.path}'", "'#{destination_path}'")
158
169
  end
170
+
171
+ return podfile_content
159
172
  end
160
173
 
161
- def self.add_framework_plist_info(podfile_items)
162
- swift_version = PodBuilder::system_swift_version
163
- Dir.glob("#{Configuration.build_path}/Rome/*.framework") do |framework_path|
164
- filename_ext = File.basename(framework_path)
165
- filename = File.basename(framework_path, ".*")
166
-
167
- specs = podfile_items.select { |x| x.module_name == filename }
168
- specs += podfile_items.select { |x| x.vendored_items.map { |x| File.basename(x) }.include?(filename_ext) }
169
- if podfile_item = specs.first
170
- podbuilder_file = File.join(framework_path, Configuration.framework_plist_filename)
171
- entry = podfile_item.entry(true, false)
172
-
173
- plist = CFPropertyList::List.new
174
- plist_data = {}
175
- plist_data['entry'] = entry
176
- plist_data['is_prebuilt'] = podfile_item.is_prebuilt
177
- if Dir.glob(File.join(framework_path, "Headers/*-Swift.h")).count > 0
178
- plist_data['swift_version'] = swift_version
174
+ def self.use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
175
+ if OPTIONS.has_key?(:force_rebuild)
176
+ return
177
+ end
178
+
179
+ download # Copy files under #{Configuration.build_path}/Pods so that we can determine build folder hashes
180
+
181
+ podfile_content = File.read(podfile_path)
182
+
183
+ # Replace prebuilt entries in Podfile for Pods that have no changes in source code which will avoid rebuilding them
184
+ items = podfile_items.group_by { |t| t.root_name }.map { |k, v| v.first } # Return one podfile_item per root_name
185
+ items.each do |item|
186
+ podspec_path = item.prebuilt_podspec_path
187
+ if last_build_folder_hash = build_folder_hash_in_prebuilt_info_file(item)
188
+ if last_build_folder_hash == build_folder_hash(item)
189
+ puts "No changes detected to '#{item.root_name}', will skip rebuild".blue
190
+ podfile_items.select { |t| t.root_name == item.root_name }.each do |replace_item|
191
+ replace_regex = "pod '#{Regexp.quote(replace_item.name)}', .*"
192
+ replace_line_found = podfile_content =~ /#{replace_regex}/i
193
+ raise "\n\nFailed finding pod entry for '#{replace_item.name}'".red unless replace_line_found
194
+ podfile_content.gsub!(/#{replace_regex}/, replace_item.prebuilt_entry(true, true))
195
+ end
179
196
  end
180
- subspecs_deps = specs.map(&:dependency_names).flatten
181
- subspec_self_deps = subspecs_deps.select { |x| x.start_with?("#{podfile_item.root_name}/") }
182
- plist_data['specs'] = (specs.map(&:name) + subspec_self_deps).uniq
183
- plist_data['is_static'] = podfile_item.is_static
184
- plist_data['original_compile_path'] = Pathname.new(Configuration.build_path).realpath.to_s
185
-
186
- plist.value = CFPropertyList.guess(plist_data)
187
- plist.save(podbuilder_file, CFPropertyList::List::FORMAT_BINARY)
188
- else
189
- raise "Unable to detect item for framework #{filename}.framework. Please open a bug report!"
190
197
  end
191
198
  end
199
+
200
+ File.write(podfile_path, podfile_content)
192
201
  end
193
202
 
194
- def self.cleanup_frameworks(podfile_items)
195
- Dir.glob("#{Configuration.build_path}/Rome/*.framework") do |framework_path|
196
- framework_rel_path = rel_path(framework_path, podfile_items)
197
- dsym_path = framework_rel_path + ".dSYM"
203
+ def self.install
204
+ puts "Prebuilding items".yellow
205
+
206
+ CLAide::Command::PluginManager.load_plugins("cocoapods")
207
+
208
+ Dir.chdir(Configuration.build_path) do
209
+ config = Pod::Config.new()
210
+ installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
211
+ installer.repo_update = false
212
+ installer.update = false
213
+
214
+ install_start_time = Time.now
215
+ installer.install!
216
+ install_time = Time.now - install_start_time
198
217
 
199
- PodBuilder::safe_rm_rf(PodBuilder::basepath("Rome/#{framework_rel_path}"))
200
- PodBuilder::safe_rm_rf(PodBuilder::basepath("dSYM/iphoneos/#{dsym_path}"))
201
- PodBuilder::safe_rm_rf(PodBuilder::basepath("dSYM/iphonesimulator/#{dsym_path}"))
218
+ puts "Build completed in #{install_time.to_i} seconds".blue
202
219
  end
203
220
  end
204
221
 
205
- def self.copy_frameworks(podfile_items)
206
- Dir.glob("#{Configuration.build_path}/Rome/*.framework") do |framework_path|
207
- framework_rel_path = rel_path(framework_path, podfile_items)
222
+ def self.download
223
+ puts "Downloading Pods source code".yellow
208
224
 
209
- destination_path = PodBuilder::basepath("Rome/#{framework_rel_path}")
210
- FileUtils.mkdir_p(File.dirname(destination_path))
211
- FileUtils.cp_r(framework_path, destination_path)
225
+ CLAide::Command::PluginManager.load_plugins("cocoapods")
226
+
227
+ Dir.chdir(Configuration.build_path) do
228
+ Pod::UserInterface::config.silent = true
229
+
230
+ config = Pod::Config.new()
231
+ installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
232
+ installer.repo_update = false
233
+ installer.update = false
234
+ installer.prepare
235
+ installer.resolve_dependencies
236
+ installer.download_dependencies
237
+
238
+ Pod::UserInterface::config.silent = false
212
239
  end
213
240
  end
214
241
 
215
- def self.copy_libraries(podfile_items)
216
- Dir.glob("#{Configuration.build_path}/Rome/*.a") do |library_path|
217
- library_name = File.basename(library_path)
218
-
219
- # Find vendored libraries in the build folder:
220
- # This allows to determine which Pod is associated to the vendored_library
221
- # because there are cases where vendored_libraries are specified with wildcards (*.a)
222
- # making it impossible to determine the associated Pods when building multiple pods at once
223
- search_base = "#{Configuration.build_path}/Pods/"
224
- podfile_items.each do |podfile_item|
225
- if podfile_item.vendored_framework_path.nil?
226
- next
227
- end
228
-
229
- podfile_item.vendored_items.each do |vendored_item|
230
- unless vendored_item.end_with?(".a")
231
- next
232
- end
233
-
234
- if result = Dir.glob("#{search_base}**/#{vendored_item}").first
235
- result_path = result.gsub(search_base, "")
236
- module_name = result_path.split("/").first
237
- if module_name == podfile_item.module_name
238
- library_rel_path = rel_path(module_name, podfile_items)
239
-
240
- result_path = result_path.split("/").drop(1).join("/")
241
-
242
- destination_path = PodBuilder::basepath("Rome/#{library_rel_path}/#{result_path}")
243
- FileUtils.mkdir_p(File.dirname(destination_path))
244
- FileUtils.cp_r(library_path, destination_path, :remove_destination => true)
245
- end
246
- end
247
- end
242
+ def self.copy_prebuilt_items(podfile_items)
243
+ FileUtils.mkdir_p(PodBuilder::prebuiltpath)
248
244
 
249
- # A pod might depend upon a static library that is shipped with a prebuilt framework
250
- # which is not added to the Rome folder and the PodBuilder.podspec
251
- #
252
- # An example is Google-Mobile-Ads-SDK which adds
253
- # - vendored framework: GooleMobileAds.framework
254
- # - vendored library: libGooleMobileAds.a
255
- # These might be used by another pod (e.g AppNexusSDK/GoogleAdapterThatDependsOnGooglePod)
256
- podfile_item.libraries.each do |library|
257
- if result = Dir.glob("#{search_base}**/lib#{library}.a").first
258
- result_path = result.gsub(search_base, "")
259
-
260
- library_rel_path = rel_path(podfile_item.module_name, podfile_items)
261
-
262
- result_path = result_path.split("/").drop(1).join("/")
263
-
264
- destination_path = PodBuilder::basepath("Rome/#{library_rel_path}/#{result_path}")
265
- FileUtils.mkdir_p(File.dirname(destination_path))
266
- FileUtils.cp_r(library_path, destination_path)
267
- end
268
- end
245
+ root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
246
+ root_names.each do |prebuilt_name|
247
+ source_path = PodBuilder::buildpath_prebuiltpath(prebuilt_name)
248
+ unless File.directory?(source_path)
249
+ puts "Prebuilt items for #{prebuilt_name} not found".blue
250
+ next
251
+ end
252
+ if Dir.empty?(source_path)
253
+ next # When using prebuilt items we end up with empty folders
269
254
  end
255
+
256
+ PodBuilder::safe_rm_rf(PodBuilder::prebuiltpath(prebuilt_name))
257
+ FileUtils.cp_r(source_path, PodBuilder::prebuiltpath)
270
258
  end
271
- end
272
259
 
273
- def self.copy_dsyms(podfile_items)
274
- Dir.glob("#{Configuration.build_path}/dSYM/*iphoneos/**/*.dSYM") do |dsym_path|
275
- framework_rel_path = rel_path(dsym_path.gsub(File.extname(dsym_path), ""), podfile_items)
276
-
277
- destination_path = PodBuilder::basepath("dSYM/iphoneos/#{File.dirname(framework_rel_path)}")
278
- FileUtils.mkdir_p(destination_path)
279
- FileUtils.cp_r(dsym_path, destination_path)
260
+ # Folder won't exist if no dSYM were generated (all static libs)
261
+ if File.directory?(PodBuilder::buildpath_dsympath)
262
+ FileUtils.mkdir_p(PodBuilder::dsympath)
263
+ FileUtils.cp_r(PodBuilder::buildpath_dsympath, PodBuilder::basepath)
280
264
  end
265
+ end
281
266
 
282
- Dir.glob("#{Configuration.build_path}/dSYM/*iphonesimulator/**/*.dSYM") do |dsym_path|
283
- framework_rel_path = rel_path(dsym_path.gsub(File.extname(dsym_path), ""), podfile_items)
267
+ def self.add_prebuilt_info_file(podfile_items)
268
+ swift_version = PodBuilder::system_swift_version
284
269
 
285
- destination_path = PodBuilder::basepath("dSYM/iphonesimulator/#{File.dirname(framework_rel_path)}")
286
- FileUtils.mkdir_p(destination_path)
287
- FileUtils.cp_r(dsym_path, destination_path)
270
+ root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
271
+ root_names.each do |prebuilt_name|
272
+ path = PodBuilder::prebuiltpath(prebuilt_name)
273
+
274
+ unless File.directory?(path)
275
+ puts "Prebuilt items for #{prebuilt_name} not found".blue
276
+ next
277
+ end
278
+
279
+ unless podfile_item = podfile_items.detect { |t| t.name == prebuilt_name } || podfile_items.detect { |t| t.root_name == prebuilt_name }
280
+ puts "Prebuilt items for #{prebuilt_name} not found #2".blue
281
+ next
282
+ end
283
+
284
+ podbuilder_file = File.join(path, Configuration.prebuilt_info_filename)
285
+ entry = podfile_item.entry(true, false)
286
+
287
+ data = {}
288
+ data['entry'] = entry
289
+ data['is_prebuilt'] = podfile_item.is_prebuilt
290
+ if Dir.glob(File.join(path, "#{podfile_item.module_name}/Headers/*-Swift.h")).count > 0
291
+ data['swift_version'] = swift_version
292
+ end
293
+
294
+ specs = podfile_items.select { |x| x.module_name == podfile_item.module_name }
295
+ subspecs_deps = specs.map(&:dependency_names).flatten
296
+ subspec_self_deps = subspecs_deps.select { |x| x.start_with?("#{prebuilt_name}/") }
297
+ data['specs'] = (specs.map(&:name) + subspec_self_deps).uniq
298
+ data['is_static'] = podfile_item.is_static
299
+ data['original_compile_path'] = Pathname.new(Configuration.build_path).realpath.to_s
300
+ data['build_folder_hash'] = build_folder_hash(podfile_item)
301
+
302
+ File.write(podbuilder_file, JSON.pretty_generate(data))
288
303
  end
289
304
  end
290
305
 
@@ -295,5 +310,50 @@ module PodBuilder
295
310
  system("git init")
296
311
  Dir.chdir(current_dir)
297
312
  end
313
+
314
+ def self.build_folder_hash_in_prebuilt_info_file(podfile_item)
315
+ prebuilt_info_path = PodBuilder::prebuiltpath(File.join(podfile_item.root_name, Configuration.prebuilt_info_filename))
316
+
317
+ if File.exist?(prebuilt_info_path)
318
+ data = JSON.parse(File.read(prebuilt_info_path))
319
+ return data['build_folder_hash']
320
+ else
321
+ return nil
322
+ end
323
+ end
324
+
325
+ def self.build_folder_hash(podfile_item)
326
+ if podfile_item.is_development_pod
327
+ if Pathname.new(podfile_item.path).absolute?
328
+ item_path = podfile_item.path
329
+ else
330
+ item_path = PodBuilder::basepath(podfile_item.path)
331
+ end
332
+ else
333
+ item_path = "#{Configuration.build_path}/Pods/#{podfile_item.root_name}"
334
+ end
335
+
336
+ return `find '#{item_path}' -type f -print0 | sort -z | xargs -0 shasum | shasum | cut -d' ' -f1`.strip()
337
+ end
338
+
339
+ def self.podfile_path_transform(path)
340
+ if Configuration.build_using_repo_paths
341
+ return File.expand_path(PodBuilder::basepath(path))
342
+ else
343
+ use_absolute_paths = true
344
+ podfile_path = File.join(Configuration.build_path, "Podfile")
345
+ original_basepath = PodBuilder::basepath
346
+
347
+ podfile_base_path = Pathname.new(File.dirname(podfile_path))
348
+
349
+ original_path = Pathname.new(File.join(original_basepath, path))
350
+ replace_path = original_path.relative_path_from(podfile_base_path)
351
+ if use_absolute_paths
352
+ replace_path = replace_path.expand_path(podfile_base_path)
353
+ end
354
+
355
+ return replace_path
356
+ end
357
+ end
298
358
  end
299
359
  end