pod-builder 2.0.0.beta.25 → 2.0.0.beta.26

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75b20eb1955937c42e11f9e8e261f40a907a50a7225a6a892915963d82b99317
4
- data.tar.gz: 3a2b45e51f95e4573bfc29838181f823fa9c12b754c751cb0506c28c3a09a60c
3
+ metadata.gz: 026afc87b8f1c1b60367e611927d1e958f9eab4fa8b362fe5530b8f364b73469
4
+ data.tar.gz: d20a47f60ffea78ad81acb3b7e015bbd62c081ac0b5e493d652a56c24ff07704
5
5
  SHA512:
6
- metadata.gz: 7ca77c2cce6fdc77c95a6748cbaf1cf08dc6163cf0906ae09a90a05373832d5dc35c4a4b04a57a00776bed873eb5cbee590127749d5d93cd621b85fd88ec5eed
7
- data.tar.gz: 22d3bc57f93f27118788ecd95097eaa9d522032e6a19fd5f9ab673834fb2d3655c5f9387b57cbdd01cf77b3d41ad39e59563151e2680cd5bccea938cacb14b42
6
+ metadata.gz: 9ecececb6dca35557797fade2be225d7212d2090a5b2a94883842f7f1bf0d0cb9272eaf3abb721e92f50db8e6e7384453b0c9e5e6929a26a96310ba761dc0d45
7
+ data.tar.gz: b0f464538c82dc152c388a3cc20ab7b8b14a0a4e28469fea60ee7f7ecc314ea4475895b7fdecd387da8e12be437b4ccea005bd7bb148a9f16458d0a2c53ecd96
data/README.md CHANGED
@@ -118,16 +118,20 @@ Will recompile all pods to the versions defined in the Restore-Podfile. You woul
118
118
 
119
119
  When using PodBuilder you loose ability to directly access to the source code of a pod. To overcome this limitation you can use this command which downloads the pod's source code to _PodBuilder/Sources_ and with some [tricks](https://medium.com/@t.camin/debugging-prebuilt-frameworks-c9f52d42600b) restores the ability to use the debugger and step into the code of your prebuilt dependencies. This can be very helpful to catch the exact location of a crash when it occurs (showing something more useful than assembly code). It is however advisable to switch to the original pod when doing any advanced debugging during development of code that involves a pod.
120
120
 
121
- #### `update_lldbinit` command
121
+ #### `generate_lldbinit` command
122
122
 
123
- In some situations you may already have source code for your prebuilt frameworks (e.g. committed in your repo). In this case there is no need to use the `install_sources`, you can run this command passing the folder that contains the source code that you used to generate the prebuilt frameworks. This will update a custom specified `lldbinit` file which will restore the ability to use the debugger and step into the code of your prebuilt dependencies.
123
+ In some situations you may already have source code for your prebuilt frameworks, for example if your project is organized as a monorepo. In this case there is no need to use the `install_sources`, you can run this command passing the folder that contains the source code that you used to generate the prebuilt frameworks.
124
124
 
125
- The `lldbinit` should not be autoloaded from Xcode (e.g. should not be placed under ~/.lldbinit-Xcode) because it can cause weird issues with debugging. Instead load the file using a shared breakpoint placed at the beginning loading by invoking a
125
+ This command will generate a custom lldinit file which will be stored in the _PodBuilder_ folder. Note that this file is added to the .gitignore since it contains absolute path information. Since Xcode 11.5 customly defined lldbinit can be selected in the Run tab in your scheme project ("LLDB Init File"). You should select the generated llbb file path or, if you're using project generation tools such as XcodeGen, you can set it to `${SRCROOT}/../PodBuilder/lldbinit`.
126
126
 
127
+ The most convenient place to update the lldbinit file is in your Podfile pre_install or post_install actions. It is suggested to add the following lines
127
128
 
128
- #### `clear_lldbinit` command
129
+ ````
130
+ pid = spawn("pod_builder generate_lldbinit")
131
+ Process.detach(pid)
132
+ ```
129
133
 
130
- Run this command to remove PodBuilder's customizations from the specified `lldbinit`.
134
+ To generate lldbinit file. We're generating it asynchronously to avoid unnecessarily slow down `pod install` since this file will be needed only when build and running your application.
131
135
 
132
136
  #### `switch` command
133
137
 
@@ -308,16 +312,6 @@ Normally when multiple subspecs are specified in a target a single framework is
308
312
  }
309
313
  ```
310
314
 
311
- #### `lfs_update_gitattributes` 
312
-
313
- Adds a _.gitattributes_ to _PodBuilder/Prebuilt_ and _PodBuilder/dSYM_ to exclude large files. If `lfs_include_pods_folder` is true it will add a the same _.gitattributes_ to the application's _Pods_ folder as well.
314
-
315
-
316
- #### `lfs_include_pods_folder`
317
-
318
- See [`lfs_update_gitattributes`](#lfs_update_gitattributes).
319
-
320
-
321
315
  #### `use_bundler`
322
316
 
323
317
  If you use bundler to pin the version of CocoaPods in your project set this to true. Default false.
@@ -358,11 +352,6 @@ How to proceed in these cases?
358
352
  3. One-by-one switch your pods back to prebuilt, verifying everytime that your Project still compiles.
359
353
 
360
354
 
361
- ### **Build failed with longish output to the stdout, what should I do next?**
362
-
363
- Relaunch the build command passing `-d`, this won't delete the temporary _/tmp/pod_builder_ folder on failure. Open _/tmp/pod_builder/Pods/Pods.xcproject_, make the Pods-DummyTarget target visible by clicking on _Show_ under _Product->Scheme->Manage shemes..._ and build from within Xcode. This will help you understand what went wrong. Remeber to verify that you're building the _Release_ build configuration.
364
-
365
-
366
355
  ### **Do I need to commit compiled frameworks?**
367
356
 
368
357
  No. If the size of compiled frameworks in your repo is a concern (and for whatever reason you can't use [Git-LFS](#git-lfs)) you can choose add the _Prebuilt_ and _dSYM_ folder to .gitignore and run `pod_builder update` to rebuild all frameworks that need to be recompiled.
@@ -374,9 +363,8 @@ Please open an issue here. You may also add the name of the pod to the [`skip_po
374
363
 
375
364
  # Git LFS
376
365
 
377
- PodBuilder integrates with [Git Large File Storage](https://git-lfs.github.com) to move large files, like the prebuilt frameworks, out of your git repo. This allows to benefit from the compilation speed ups of the precompiled frameworks without impacting on your repo overall size.
366
+ We high encourage to use PodBuilder in combination with Git LFS. Tacking PodBuilder/Prebuilt/**/*.framework/* and PodBuilder/Prebuilt/**/*.a and PodBuilder/dSYM/**/* will ensure that your repo size stays under control with all the benefits of having prebuilt dependencies ready to use.
378
367
 
379
- When [`lfs_update_gitattributes = true`](#lfs_update_gitattributes) PodBuilder will automatically update the _.gitattributes_ with the files generated by PodBuilder when building pods.
380
368
 
381
369
  # Try it out!
382
370
 
@@ -39,8 +39,7 @@ Command:
39
39
  + update Rebuild items that are outdated
40
40
  + restore_all Rebuild all pods declared in the Restore-Podfile
41
41
  + install_sources Install sources of pods to debug into prebuilt items
42
- + update_lldbinit Generate an lldbinit file with setting target.source-map to debug prebuilt items
43
- + clear_lldbinit Clear an lldbinit file from PodBuilder's customizations
42
+ + generate_lldbinit Generate an lldbinit file with setting target.source-map to debug prebuilt items
44
43
  + switch Switch between prebuilt/development/standard pod in the Application-Podfile
45
44
  + clean Remove prebuild items, dSYMs and source files added by `install_sources` command that are no longer in the PodBuilder-Podfile
46
45
  + sync_podfile Update your Application-Podfile with all pods declared in the PodBuilder-Podfile
@@ -198,14 +197,6 @@ Options:
198
197
  ]
199
198
  },
200
199
 
201
- "update_lfs" => {
202
- :opts => OptionParser.new do |opts|
203
- end,
204
- :call => [
205
- PodBuilder::Command::GenerateLFS
206
- ]
207
- },
208
-
209
200
  "deintegrate" => {
210
201
  :opts => OptionParser.new do |opts|
211
202
  opts.banner = "
@@ -259,40 +250,27 @@ Usage:
259
250
  ]
260
251
  },
261
252
 
262
- "update_lldbinit" => {
253
+ "generate_lldbinit" => {
263
254
  :opts => OptionParser.new do |opts|
264
255
  opts.banner = "
265
256
  Usage:
266
257
 
267
- $ pod_builder update_lldbinit <LLDBINIT_PATH> <PATH>
268
-
269
- Update LLDBINIT_PATH setting target.source-map in order to be able to step into
270
- and debug prebuilt prebuilt's code.
258
+ $ pod_builder generate_lldbinit [PATH]
271
259
 
272
- Specify the PATH of the folder containing the source code of prebuilt items. PATH can be relative to PodBuilder's Prebuilt folder.
260
+ Update PodBuilder's custom lldbinit by setting the target.source-map which allows to
261
+ step into and debug prebuilt prebuilt's code. To allow this to work it is required
262
+ to specify a path containing the source code that generated the prebuilt item.
273
263
 
274
- "
264
+ You can pass a [PATH] which PodBuilder will use to look for dependencies's source code.
265
+ If omitted it will be implied that the project is organized as a monorepo expecting
266
+ source code dependencies to live in the project repo.
267
+ "
275
268
  end,
276
269
  :call => [
277
270
  PodBuilder::Command::UpdateLldbInit
278
271
  ]
279
272
  },
280
273
 
281
- "clear_lldbinit" => {
282
- :opts => OptionParser.new do |opts|
283
- opts.banner = "
284
- Usage:
285
-
286
- $ pod_builder clear_lldbinit <LLDBINIT_PATH>
287
-
288
- Clear LLDBINIT_PATH setting target.source-map PodBuilder's customizations
289
- "
290
- end,
291
- :call => [
292
- PodBuilder::Command::ClearLldbInit
293
- ]
294
- },
295
-
296
274
  "switch" => {
297
275
  :opts => OptionParser.new do |opts|
298
276
  opts.banner = "
@@ -9,8 +9,6 @@ require 'pod_builder/command/deintegrate'
9
9
  require 'pod_builder/command/generate_podspec'
10
10
  require 'pod_builder/command/install_sources'
11
11
  require 'pod_builder/command/switch'
12
- require 'pod_builder/command/generate_lfs'
13
12
  require 'pod_builder/command/sync_podfile'
14
13
  require 'pod_builder/command/info'
15
- require 'pod_builder/command/update_lldbinit'
16
- require 'pod_builder/command/clear_lldbinit'
14
+ require 'pod_builder/command/generate_lldbinit'
@@ -96,7 +96,6 @@ module PodBuilder
96
96
 
97
97
  Licenses::write(licenses, all_buildable_items)
98
98
 
99
- GenerateLFS::call()
100
99
  Podspec::generate(all_buildable_items, analyzer)
101
100
 
102
101
  builded_pods = podfiles_items.flatten
@@ -0,0 +1,151 @@
1
+ require 'pod_builder/core'
2
+ require 'digest'
3
+
4
+ module PodBuilder
5
+ module Command
6
+ class UpdateLldbInit
7
+ def self.call
8
+ Configuration.check_inited
9
+ if Configuration.build_using_repo_paths
10
+ raise "\n\nlldb shenanigans not supported when 'build_using_repo_paths' is enabled".red
11
+ end
12
+
13
+ arguments = ARGV.dup
14
+
15
+ if arguments.count > 0
16
+ source_path = arguments[0]
17
+ if !is_absolute_path(source_path)
18
+ source_path = PodBuilder::basepath(source_path)
19
+ end
20
+ source_path = File.expand_path(source_path)
21
+
22
+ raise "\n\nSpecified path does not exists" unless File.directory?(source_path)
23
+ end
24
+
25
+ base_path = PodBuilder::basepath
26
+
27
+ app_podfile_content = File.read(PodBuilder::project_path("Podfile"))
28
+ podfile_hash = Digest::MD5.hexdigest(app_podfile_content)
29
+
30
+ lldbinit_path = File.expand_path(PodBuilder::basepath(Configuration.lldbinit_name))
31
+ lldbinit_content = File.exist?(lldbinit_path) ? File.read(lldbinit_path) : ""
32
+
33
+ if lldbinit_content.include?("# <pb_md5:#{base_path}:#{podfile_hash}")
34
+ puts "\n\n🎉 already in sync!\n".green
35
+ return 0
36
+ end
37
+
38
+ puts "Extracting debug information".yellow
39
+
40
+ unless source_path.nil?
41
+ podspec_paths = Dir.glob("#{source_path}/**/*.podspec") + Dir.glob("#{source_path}/**/*.podspec.json")
42
+ podspec_contents = podspec_paths.map { |t| File.read(t).gsub(/\s+/, "").gsub("\"", "'") }
43
+ end
44
+
45
+ source_map_lines = []
46
+ Dir.glob("#{PodBuilder::prebuiltpath}/**/Podbuilder.json").each do |path|
47
+ data = JSON.parse(File.read(path))
48
+ next if data.fetch("is_prebuilt", true)
49
+
50
+ # It would be much nicer if PodBuilder.json already contained this info in a custom key
51
+ pod_name_matches = data["entry"].match(/pod '(.*?)'/)
52
+ next unless pod_name_matches&.size == 2
53
+
54
+ podspec_name = pod_name_matches[1]
55
+ podspec_path = "#{File.dirname(path)}/#{podspec_name}.podspec"
56
+
57
+ next unless File.exist?(podspec_path)
58
+
59
+ build_source_path_matches = data["entry"].match(/:path => '(.*?)'/)
60
+ if build_source_path_matches&.size == 2
61
+ build_source_path = build_source_path_matches[1]
62
+
63
+ if !is_absolute_path(build_source_path[0])
64
+ build_source_path = PodBuilder::basepath(build_source_path)
65
+ end
66
+ build_source_path = File.expand_path(build_source_path)
67
+ elsif source_path.nil?
68
+ next
69
+ else
70
+ # Find source code for podspec_name
71
+ podspec_path = find_podspec_path_for(podspec_name, podspec_paths, podspec_contents)
72
+ next if podspec_path.nil?
73
+ end
74
+
75
+ original_compile_path = data["original_compile_path"] + "/Pods/#{podspec_name}"
76
+ if is_prebuilt_pod(podspec_path, app_podfile_content)
77
+ unless source_map_lines.include?("settings append target.source-map '#{original_compile_path}'")
78
+ source_map_lines.push("# <pb:#{base_path}>\n", "settings append target.source-map '#{original_compile_path}' '#{build_source_path}'\n")
79
+ end
80
+ end
81
+ end
82
+
83
+ rewrite_lldinit(lldbinit_path, source_map_lines, base_path, podfile_hash)
84
+
85
+ puts "\n\n🎉 done!\n".green
86
+ return 0
87
+ end
88
+
89
+ private
90
+
91
+ def self.is_absolute_path(path)
92
+ return ["~", "/"].any? { |t| t.start_with?(t) }
93
+ end
94
+
95
+ def self.is_prebuilt_pod(podspec_path, app_podfile_content)
96
+ development_path = Pathname.new(podspec_path).relative_path_from(Pathname.new(PodBuilder::project_path)).parent.to_s
97
+
98
+ return app_podfile_content.include?(":path => '#{development_path}'")
99
+ end
100
+
101
+ def self.rewrite_lldinit(lldbinit_path, source_map_lines, base_path, podfile_hash)
102
+ puts "Writing #{lldbinit_path}".yellow
103
+
104
+ FileUtils.touch(lldbinit_path)
105
+ raise "\n\nDestination file should be a file".red unless File.exist?(lldbinit_path)
106
+
107
+ lldbinit_lines = []
108
+ skipNext = false
109
+ File.read(lldbinit_path).each_line do |line|
110
+ if line.include?("# <pb:#{base_path}>") || line.include?("# <pb>")
111
+ skipNext = true
112
+ next
113
+ elsif skipNext
114
+ skipNext = false
115
+ next
116
+ elsif line != "\n"
117
+ if line.include?("settings set target.source-map")
118
+ raise "\n\n#{lldbinit_destination_path} already includes a manual `settings set target.source-map`. This is unsupported and you'll have to manually remove that entry\n".red
119
+ end
120
+ lldbinit_lines.push(line)
121
+ end
122
+ end
123
+
124
+ source_map_lines.insert(0, "# <pb>\n")
125
+ source_map_lines.insert(1, "settings clear target.source-map\n")
126
+ source_map_lines.insert(2, "# <pb:#{base_path}>\n")
127
+ source_map_lines.insert(3, "# <pb_md5:#{base_path}:#{podfile_hash}>\n")
128
+
129
+ lldbinit_lines += source_map_lines
130
+
131
+ File.write(lldbinit_path, lldbinit_lines.join())
132
+ end
133
+
134
+ def self.find_podspec_path_for(name, podspec_paths, podspec_contents)
135
+ if (path = podspec_paths.detect { |t| File.basename(t, ".podspec") == name.gsub("_", "-") })
136
+ return path
137
+ elsif (path_index = podspec_contents.find_index { |t| t.include?(".module_name='#{name}'") })
138
+ return podspec_paths[path_index]
139
+ elsif (path_index = podspec_contents.find_index { |t| t.include?(".name='#{name}") }) # kind of optimistic,, but a last resort
140
+ return podspec_paths[path_index]
141
+ elsif (path_index = podspec_contents.find_index { |t| t.include?("'module_name':'#{name}'") }) # [json podspec]
142
+ return podspec_paths[path_index]
143
+ elsif (path_index = podspec_contents.find_index { |t| t.include?("'name':'#{name}") }) # [json podspec] kind of optimistic,, but a last resort
144
+ return podspec_paths[path_index]
145
+ else
146
+ return nil
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -22,17 +22,8 @@ module PodBuilder
22
22
  FileUtils.mkdir_p("#{OPTIONS[:prebuild_path]}/.pod_builder")
23
23
  FileUtils.touch("#{OPTIONS[:prebuild_path]}/.pod_builder/pod_builder")
24
24
 
25
- source_path_rel_path = "Sources"
26
- development_pods_config_rel_path = Configuration.dev_pods_configuration_filename
27
-
28
- git_ignores = ["Pods/",
29
- "*.xcworkspace",
30
- "*.xcodeproj",
31
- "Podfile.lock",
32
- source_path_rel_path,
33
- development_pods_config_rel_path]
34
-
35
- File.write("#{OPTIONS[:prebuild_path]}/.gitignore", git_ignores.join("\n"))
25
+ write_gitignore
26
+ write_gitattributes
36
27
 
37
28
  project_podfile_path = PodBuilder::project_path("Podfile")
38
29
  prebuilt_podfile_path = File.join(OPTIONS[:prebuild_path], "Podfile")
@@ -61,6 +52,27 @@ module PodBuilder
61
52
 
62
53
  private
63
54
 
55
+ def self.write_gitignore
56
+ source_path_rel_path = "Sources"
57
+ development_pods_config_rel_path = Configuration.dev_pods_configuration_filename
58
+
59
+ git_ignores = ["Pods/",
60
+ "*.xcworkspace",
61
+ "*.xcodeproj",
62
+ "Podfile.lock",
63
+ Configuration.lldbinit_name,
64
+ source_path_rel_path,
65
+ development_pods_config_rel_path]
66
+
67
+ File.write("#{OPTIONS[:prebuild_path]}/.gitignore", git_ignores.join("\n"))
68
+ end
69
+
70
+ def self.write_gitattributes
71
+ git_attributes = ["#{Configuration.prebuilt_info_filename} binary"]
72
+
73
+ File.write("#{OPTIONS[:prebuild_path]}/.gitattributes", git_attributes.join("\n"))
74
+ end
75
+
64
76
  def self.podfile_path_transform(path)
65
77
  use_absolute_paths = false
66
78
  podfile_path = File.join(OPTIONS[:prebuild_path], "Podfile")
@@ -23,7 +23,6 @@ module PodBuilder
23
23
  DEFAULT_FORCE_PREBUILD_PODS = ["Firebase", "GoogleTagManager"]
24
24
  DEFAULT_BUILD_SYSTEM = "Legacy".freeze # either Latest (New build system) or Legacy (Standard build system)
25
25
  DEFAULT_LIBRARY_EVOLUTION_SUPPORT = false
26
- MIN_LFS_SIZE_KB = 256.freeze
27
26
  DEFAULT_PLATFORMS = ["iphoneos", "iphonesimulator", "appletvos", "appletvsimulator"].freeze
28
27
  DEFAULT_BUILD_FOR_APPLE_SILICON = false
29
28
  DEFAULT_BUILD_USING_REPO_PATHS = false
@@ -31,7 +30,6 @@ module PodBuilder
31
30
  private_constant :DEFAULT_BUILD_SETTINGS
32
31
  private_constant :DEFAULT_BUILD_SYSTEM
33
32
  private_constant :DEFAULT_LIBRARY_EVOLUTION_SUPPORT
34
- private_constant :MIN_LFS_SIZE_KB
35
33
 
36
34
  class <<self
37
35
  attr_accessor :allow_building_development_pods
@@ -51,9 +49,6 @@ module PodBuilder
51
49
  attr_accessor :build_path
52
50
  attr_accessor :configuration_filename
53
51
  attr_accessor :dev_pods_configuration_filename
54
- attr_accessor :lfs_min_file_size
55
- attr_accessor :lfs_update_gitattributes
56
- attr_accessor :lfs_include_pods_folder
57
52
  attr_accessor :project_name
58
53
  attr_accessor :restore_enabled
59
54
  attr_accessor :prebuilt_info_filename
@@ -65,6 +60,7 @@ module PodBuilder
65
60
  attr_accessor :build_for_apple_silicon
66
61
  attr_accessor :build_using_repo_paths
67
62
  attr_accessor :react_native_project
63
+ attr_accessor :lldbinit_name
68
64
  end
69
65
 
70
66
  @allow_building_development_pods = false
@@ -84,14 +80,12 @@ module PodBuilder
84
80
  @build_path = build_base_path
85
81
  @configuration_filename = "PodBuilder.json".freeze
86
82
  @dev_pods_configuration_filename = "PodBuilderDevPodsPaths.json".freeze
87
- @lfs_min_file_size = MIN_LFS_SIZE_KB
88
- @lfs_update_gitattributes = false
89
- @lfs_include_pods_folder = false
90
83
  @project_name = ""
91
84
  @restore_enabled = true
92
85
  @prebuilt_info_filename = "PodBuilder.json"
93
86
  @lockfile_name = "PodBuilder.lock"
94
87
  @lockfile_path = "/tmp/#{lockfile_name}"
88
+ @lldbinit_name = "lldbinit".freeze
95
89
 
96
90
  @use_bundler = false
97
91
  @deterministic_build = false
@@ -173,16 +167,6 @@ module PodBuilder
173
167
  Configuration.subspecs_to_split = value
174
168
  end
175
169
  end
176
- if value = json["lfs_update_gitattributes"]
177
- if [TrueClass, FalseClass].include?(value.class)
178
- Configuration.lfs_update_gitattributes = value
179
- end
180
- end
181
- if value = json["lfs_include_pods_folder"]
182
- if [TrueClass, FalseClass].include?(value.class)
183
- Configuration.lfs_include_pods_folder = value
184
- end
185
- end
186
170
  if value = json["project_name"]
187
171
  if value.is_a?(String) && value.length > 0
188
172
  Configuration.project_name = value
@@ -262,8 +246,6 @@ module PodBuilder
262
246
  config["library_evolution_support"] = Configuration.library_evolution_support
263
247
  config["license_filename"] = Configuration.license_filename
264
248
  config["subspecs_to_split"] = Configuration.subspecs_to_split
265
- config["lfs_update_gitattributes"] = Configuration.lfs_update_gitattributes
266
- config["lfs_include_pods_folder"] = Configuration.lfs_include_pods_folder
267
249
  config["restore_enabled"] = Configuration.restore_enabled
268
250
  config["allow_building_development_pods"] = Configuration.allow_building_development_pods
269
251
  config["use_bundler"] = Configuration.use_bundler
@@ -10,29 +10,29 @@ require 'highline/import'
10
10
  # - https://github.com/leavez/cocoapods-binary/issues/50
11
11
  begin
12
12
  require 'cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb'
13
-
13
+
14
14
  class Pod::Specification
15
15
  Pod::Specification.singleton_class.send(:alias_method, :swz_from_hash, :from_hash)
16
16
  Pod::Specification.singleton_class.send(:alias_method, :swz_from_string, :from_string)
17
-
17
+
18
18
  def self.from_string(*args)
19
19
  spec = swz_from_string(*args)
20
-
20
+
21
21
  if overrides = PodBuilder::Configuration.spec_overrides[spec.name]
22
22
  overrides.each do |k, v|
23
23
  spec.attributes_hash[k] = v
24
24
  end
25
25
  end
26
-
26
+
27
27
  spec
28
28
  end
29
29
  end
30
-
30
+
31
31
  class Pod::Target
32
32
  attr_accessor :mock_dynamic_framework
33
-
33
+
34
34
  alias_method :swz_build_type, :build_type
35
-
35
+
36
36
  def build_type
37
37
  if mock_dynamic_framework == true
38
38
  if defined?(Pod::BuildType) # CocoaPods 1.9 and later
@@ -47,23 +47,23 @@ begin
47
47
  end
48
48
  end
49
49
  end
50
-
50
+
51
51
  # Starting from CocoaPods 1.10.0 and later resources are no longer copied inside the .framework
52
52
  # when building static frameworks. While this is correct when using CP normally, for redistributable
53
53
  # frameworks we require resources to be shipped along the binary
54
54
  class Pod::Installer::Xcode::PodsProjectGenerator::PodTargetInstaller
55
55
  alias_method :swz_add_files_to_build_phases, :add_files_to_build_phases
56
-
56
+
57
57
  def add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
58
58
  target.mock_dynamic_framework = target.build_as_static_framework?
59
59
  swz_add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
60
60
  target.mock_dynamic_framework = false
61
61
  end
62
62
  end
63
-
63
+
64
64
  class Pod::Installer::Xcode::PodTargetDependencyInstaller
65
65
  alias_method :swz_wire_resource_bundle_targets, :wire_resource_bundle_targets
66
-
66
+
67
67
  def wire_resource_bundle_targets(resource_bundle_targets, native_target, pod_target)
68
68
  pod_target.mock_dynamic_framework = pod_target.build_as_static_framework?
69
69
  res = swz_wire_resource_bundle_targets(resource_bundle_targets, native_target, pod_target)
@@ -71,6 +71,31 @@ begin
71
71
  return res
72
72
  end
73
73
  end
74
+
75
+ class Pod::Target::BuildSettings
76
+ class <<self
77
+ attr_accessor :patch_static_library_generation
78
+ end
79
+
80
+ alias_method :swz_add_inherited_to_plural, :add_inherited_to_plural
81
+
82
+ def add_inherited_to_plural(hash)
83
+ # There's probably a better place to monkey patch this
84
+ h = swz_add_inherited_to_plural(hash)
85
+ if Pod::Target::BuildSettings.patch_static_library_generation
86
+ # Static frameworks should NOT import underlying modules to simplify integration of the produced
87
+ # artifacts. Without these build options you can integrate the static library the same way you
88
+ # would do with a vanilla static library target in Xcode: you just copy the .a and set the Swift
89
+ # import path to point to the module map file (which doesn't seem to be needed).
90
+ flags = h["OTHER_SWIFT_FLAGS"].dup
91
+ flags.gsub!("-import-underlying-module", "")
92
+ flags.gsub!("-Xcc -fmodule-map-file=\"${SRCROOT}/${MODULEMAP_FILE}\"", "")
93
+ h["OTHER_SWIFT_FLAGS"] = flags
94
+ end
95
+
96
+ return h
97
+ end
98
+ end
74
99
  rescue LoadError
75
100
  # CocoaPods 1.6.2 or earlier
76
101
  end
@@ -80,38 +105,38 @@ module PodBuilder
80
105
  # This method will generate prebuilt data by building from "/tmp/pod_builder/Podfile"
81
106
  def self.podfile(podfile_content, podfile_items, build_configuration)
82
107
  puts "Preparing build Podfile".yellow
83
-
108
+
84
109
  PodBuilder::safe_rm_rf(Configuration.build_path)
85
110
  FileUtils.mkdir_p(Configuration.build_path)
86
111
 
87
112
  init_git(Configuration.build_path) # this is needed to be able to call safe_rm_rf
88
-
113
+
89
114
  podfile_content = copy_development_pods_source_code(podfile_content, podfile_items)
90
-
115
+
91
116
  podfile_content = Podfile.update_path_entries(podfile_content, Install.method(:podfile_path_transform))
92
117
  podfile_content = Podfile.update_project_entries(podfile_content, Install.method(:podfile_path_transform))
93
118
  podfile_content = Podfile.update_require_entries(podfile_content, Install.method(:podfile_path_transform))
94
-
119
+
95
120
  podfile_path = File.join(Configuration.build_path, "Podfile")
96
121
  File.write(podfile_path, podfile_content)
97
-
122
+
98
123
  begin
99
124
  lock_file = "#{Configuration.build_path}/pod_builder.lock"
100
125
  FileUtils.touch(lock_file)
101
-
126
+
102
127
  use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
103
-
128
+
104
129
  install
105
-
130
+
106
131
  copy_prebuilt_items(podfile_items)
107
132
  add_prebuilt_info_file(podfile_items)
108
-
133
+
109
134
  licenses = license_specifiers()
110
-
135
+
111
136
  if !OPTIONS.has_key?(:debug)
112
137
  PodBuilder::safe_rm_rf(Configuration.build_path)
113
138
  end
114
-
139
+
115
140
  return licenses
116
141
  rescue Exception => e
117
142
  if File.directory?("#{Configuration.build_path}/Pods/Pods.xcodeproj")
@@ -124,64 +149,64 @@ module PodBuilder
124
149
  end
125
150
  end
126
151
  end
127
-
152
+
128
153
  raise e
129
154
  ensure
130
155
  FileUtils.rm(lock_file) if File.exist?(lock_file)
131
156
  end
132
157
  end
133
-
158
+
134
159
  private
135
-
160
+
136
161
  def self.license_specifiers
137
162
  acknowledge_file = "#{Configuration.build_path}/Pods/Target Support Files/Pods-DummyTarget/Pods-DummyTarget-acknowledgements.plist"
138
163
  unless File.exist?(acknowledge_file)
139
164
  raise "\n\nLicense file not found".red
140
165
  end
141
-
166
+
142
167
  plist = CFPropertyList::List.new(:file => acknowledge_file)
143
168
  data = CFPropertyList.native_types(plist.value)
144
-
169
+
145
170
  return data["PreferenceSpecifiers"] || []
146
171
  end
147
-
172
+
148
173
  def self.copy_development_pods_source_code(podfile_content, podfile_items)
149
174
  if Configuration.build_using_repo_paths
150
175
  return podfile_content
151
176
  end
152
-
177
+
153
178
  # Development pods are normally built/integrated without moving files from their original paths.
154
179
  # It is important that CocoaPods compiles the files under Configuration.build_path in order that
155
180
  # DWARF debug info reference to this constant path. Doing otherwise breaks the assumptions that
156
- # makes the `update_lldbinit` command work.
181
+ # makes the `generate_lldbinit` command work.
157
182
  development_pods = podfile_items.select { |x| x.is_development_pod }
158
183
  development_pods.each do |podfile_item|
159
184
  destination_path = "#{Configuration.build_path}/Pods/#{podfile_item.name}"
160
185
  FileUtils.mkdir_p(destination_path)
161
-
186
+
162
187
  if Pathname.new(podfile_item.path).absolute?
163
188
  FileUtils.cp_r("#{podfile_item.path}/.", destination_path)
164
189
  else
165
190
  FileUtils.cp_r("#{PodBuilder::basepath(podfile_item.path)}/.", destination_path)
166
191
  end
167
-
192
+
168
193
  podfile_content.gsub!("'#{podfile_item.path}'", "'#{destination_path}'")
169
194
  end
170
-
195
+
171
196
  return podfile_content
172
197
  end
173
-
198
+
174
199
  def self.use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
175
200
  if OPTIONS.has_key?(:force_rebuild)
176
201
  return
177
202
  end
178
-
203
+
179
204
  download # Copy files under #{Configuration.build_path}/Pods so that we can determine build folder hashes
180
-
205
+
181
206
  podfile_content = File.read(podfile_path)
182
-
207
+
183
208
  gitignored_files = PodBuilder::gitignoredfiles
184
-
209
+
185
210
  # Replace prebuilt entries in Podfile for Pods that have no changes in source code which will avoid rebuilding them
186
211
  items = podfile_items.group_by { |t| t.root_name }.map { |k, v| v.first } # Return one podfile_item per root_name
187
212
  items.each do |item|
@@ -198,15 +223,15 @@ module PodBuilder
198
223
  end
199
224
  end
200
225
  end
201
-
226
+
202
227
  File.write(podfile_path, podfile_content)
203
228
  end
204
-
229
+
205
230
  def self.install
206
231
  puts "Prebuilding items".yellow
207
-
232
+
208
233
  CLAide::Command::PluginManager.load_plugins("cocoapods")
209
-
234
+
210
235
  Dir.chdir(Configuration.build_path) do
211
236
  config = Pod::Config.new()
212
237
  installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
@@ -214,21 +239,24 @@ module PodBuilder
214
239
  installer.update = false
215
240
 
216
241
  install_start_time = Time.now
242
+
243
+ monkey_patch_static_library_generation()
244
+
217
245
  installer.install!
218
246
  install_time = Time.now - install_start_time
219
-
247
+
220
248
  puts "Build completed in #{install_time.to_i} seconds".blue
221
249
  end
222
250
  end
223
-
251
+
224
252
  def self.download
225
253
  puts "Downloading Pods source code".yellow
226
-
254
+
227
255
  CLAide::Command::PluginManager.load_plugins("cocoapods")
228
-
256
+
229
257
  Dir.chdir(Configuration.build_path) do
230
258
  Pod::UserInterface::config.silent = true
231
-
259
+
232
260
  config = Pod::Config.new()
233
261
  installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
234
262
  installer.repo_update = false
@@ -236,14 +264,14 @@ module PodBuilder
236
264
  installer.prepare
237
265
  installer.resolve_dependencies
238
266
  installer.download_dependencies
239
-
267
+
240
268
  Pod::UserInterface::config.silent = false
241
269
  end
242
270
  end
243
-
271
+
244
272
  def self.copy_prebuilt_items(podfile_items)
245
273
  FileUtils.mkdir_p(PodBuilder::prebuiltpath)
246
-
274
+
247
275
  root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
248
276
  root_names.each do |prebuilt_name|
249
277
  source_path = PodBuilder::buildpath_prebuiltpath(prebuilt_name)
@@ -254,40 +282,42 @@ module PodBuilder
254
282
  if Dir.empty?(source_path)
255
283
  next # When using prebuilt items we end up with empty folders
256
284
  end
257
-
285
+
258
286
  PodBuilder::safe_rm_rf(PodBuilder::prebuiltpath(prebuilt_name))
259
287
  FileUtils.cp_r(source_path, PodBuilder::prebuiltpath)
260
288
  end
261
-
289
+
262
290
  # Folder won't exist if no dSYM were generated (all static libs)
263
291
  if File.directory?(PodBuilder::buildpath_dsympath)
264
292
  FileUtils.mkdir_p(PodBuilder::dsympath)
265
293
  FileUtils.cp_r(PodBuilder::buildpath_dsympath, PodBuilder::basepath)
266
294
  end
267
295
  end
268
-
296
+
269
297
  def self.add_prebuilt_info_file(podfile_items)
270
298
  gitignored_files = PodBuilder::gitignoredfiles
271
-
299
+
272
300
  swift_version = PodBuilder::system_swift_version
273
301
 
302
+ write_prebuilt_info_filename_gitattributes
303
+
274
304
  root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
275
305
  root_names.each do |prebuilt_name|
276
306
  path = PodBuilder::prebuiltpath(prebuilt_name)
277
-
307
+
278
308
  unless File.directory?(path)
279
309
  puts "Prebuilt items for #{prebuilt_name} not found".blue
280
310
  next
281
311
  end
282
-
312
+
283
313
  unless podfile_item = podfile_items.detect { |t| t.name == prebuilt_name } || podfile_items.detect { |t| t.root_name == prebuilt_name }
284
314
  puts "Prebuilt items for #{prebuilt_name} not found #2".blue
285
315
  next
286
316
  end
287
-
317
+
288
318
  podbuilder_file = File.join(path, Configuration.prebuilt_info_filename)
289
319
  entry = podfile_item.entry(true, false)
290
-
320
+
291
321
  data = {}
292
322
  data['entry'] = entry
293
323
  data['is_prebuilt'] = podfile_item.is_prebuilt
@@ -302,22 +332,30 @@ module PodBuilder
302
332
  data['is_static'] = podfile_item.is_static
303
333
  data['original_compile_path'] = Pathname.new(Configuration.build_path).realpath.to_s
304
334
  data['build_folder_hash'] = build_folder_hash(podfile_item, gitignored_files)
305
-
335
+
306
336
  File.write(podbuilder_file, JSON.pretty_generate(data))
307
337
  end
308
338
  end
309
339
 
340
+ def self.write_prebuilt_info_filename_gitattributes
341
+ gitattributes_path = PodBuilder::basepath(".gitattributes")
342
+ expected_attributes = ["#{Configuration.configuration_filename} binary"].join
343
+ unless File.exists?(gitattributes_path) && File.read(gitattributes_path).include?(expected_attributes)
344
+ File.write(gitattributes_path, expected_attributes, mode: 'a')
345
+ end
346
+ end
347
+
310
348
  def self.init_git(path)
311
349
  current_dir = Dir.pwd
312
-
350
+
313
351
  Dir.chdir(path)
314
352
  system("git init")
315
353
  Dir.chdir(current_dir)
316
354
  end
317
-
355
+
318
356
  def self.build_folder_hash_in_prebuilt_info_file(podfile_item)
319
357
  prebuilt_info_path = PodBuilder::prebuiltpath(File.join(podfile_item.root_name, Configuration.prebuilt_info_filename))
320
-
358
+
321
359
  if File.exist?(prebuilt_info_path)
322
360
  data = JSON.parse(File.read(prebuilt_info_path))
323
361
  return data['build_folder_hash']
@@ -325,7 +363,7 @@ module PodBuilder
325
363
  return nil
326
364
  end
327
365
  end
328
-
366
+
329
367
  def self.build_folder_hash(podfile_item, exclude_files)
330
368
  if podfile_item.is_development_pod
331
369
  if Pathname.new(podfile_item.path).absolute?
@@ -333,7 +371,7 @@ module PodBuilder
333
371
  else
334
372
  item_path = PodBuilder::basepath(podfile_item.path)
335
373
  end
336
-
374
+
337
375
  rootpath = PodBuilder::git_rootpath
338
376
  file_hashes = []
339
377
  Dir.glob("#{item_path}/**/*", File::FNM_DOTMATCH) do |path|
@@ -347,7 +385,7 @@ module PodBuilder
347
385
  file_hashes.push(Digest::MD5.hexdigest(File.read(path)))
348
386
  end
349
387
  end
350
-
388
+
351
389
  return Digest::MD5.hexdigest(file_hashes.join)
352
390
  else
353
391
  # Pod folder might be under .gitignore
@@ -363,17 +401,23 @@ module PodBuilder
363
401
  use_absolute_paths = true
364
402
  podfile_path = File.join(Configuration.build_path, "Podfile")
365
403
  original_basepath = PodBuilder::basepath
366
-
404
+
367
405
  podfile_base_path = Pathname.new(File.dirname(podfile_path))
368
-
406
+
369
407
  original_path = Pathname.new(File.join(original_basepath, path))
370
408
  replace_path = original_path.relative_path_from(podfile_base_path)
371
409
  if use_absolute_paths
372
410
  replace_path = replace_path.expand_path(podfile_base_path)
373
411
  end
374
-
412
+
375
413
  return replace_path
376
414
  end
377
- end
415
+ end
416
+
417
+ def self.monkey_patch_static_library_generation()
418
+ podfile_path = File.join(Configuration.build_path, "Podfile")
419
+
420
+ Pod::Target::BuildSettings.patch_static_library_generation = !File.read(podfile_path).include?("use_frameworks!")
421
+ end
378
422
  end
379
423
  end