xcode-archive-cache 0.0.10.pre.1 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
data/lib/config/config.rb CHANGED
@@ -52,7 +52,7 @@ module XcodeArchiveCache
52
52
  def active_configuration
53
53
  configuration = configurations.select{|config| config.name == active_configuration_name }.first
54
54
  if configuration == nil
55
- raise Informative, "Found no configuration with name \"#{active_configuration_name}\""
55
+ raise XcodeArchiveCache::Informative, "Found no configuration with name \"#{active_configuration_name}\""
56
56
  end
57
57
 
58
58
  configuration
@@ -172,7 +172,7 @@ module XcodeArchiveCache
172
172
  begin
173
173
  eval(contents, nil, path)
174
174
  rescue Exception => e
175
- raise Informative, "Invalid #{File.basename(path)} file: #{e.message}"
175
+ raise XcodeArchiveCache::Informative, "Invalid #{File.basename(path)} file: #{e.message}"
176
176
  end
177
177
  end
178
178
 
@@ -0,0 +1,26 @@
1
+ module XCConfigExtensions
2
+ # @return [Bool]
3
+ #
4
+ def has_xcconfig?
5
+ base_configuration_reference != nil
6
+ end
7
+
8
+ # @return [String]
9
+ #
10
+ def get_xcconfig_path
11
+ base_configuration_reference.real_path
12
+ end
13
+ end
14
+
15
+ module ProjectDir
16
+ # @return [String]
17
+ #
18
+ def get_project_dir
19
+ File.dirname(project.path)
20
+ end
21
+ end
22
+
23
+ class Xcodeproj::Project::Object::XCBuildConfiguration
24
+ include XCConfigExtensions
25
+ include ProjectDir
26
+ end
@@ -0,0 +1,58 @@
1
+ module TargetEqualityCheck
2
+ # @return [String]
3
+ #
4
+ def equatable_identifier
5
+ uuid + display_name
6
+ end
7
+ end
8
+
9
+ module BuildConfigurationSearch
10
+ # @param [String] configuration_name
11
+ #
12
+ # @return [Xcodeproj::Project::Object::XCBuildConfiguration]
13
+ #
14
+ def find_build_configuration(configuration_name, raise_if_not_found: true)
15
+ build_configuration = build_configurations
16
+ .select { |configuration| configuration.name == configuration_name }
17
+ .first
18
+ if raise_if_not_found && build_configuration == nil
19
+ raise XcodeArchiveCache::Informative, "#{configuration_name} build configuration not found on target #{display_name} #{project.path}"
20
+ end
21
+
22
+ build_configuration
23
+ end
24
+ end
25
+
26
+ module SchellScriptBuildPhaseSearch
27
+ # @param [XcodeArchiveCache::BuildSettings::StringInterpolator] build_settings_interpolator
28
+ # @param [XcodeArchiveCache::BuildSettings::Container] build_settings
29
+ # @param [String] script_name
30
+ #
31
+ # @return [String]
32
+ #
33
+ def find_script(build_settings_interpolator, build_settings, script_name)
34
+ shell_script_build_phases.each do |phase|
35
+ if phase.display_name == script_name
36
+ return build_settings_interpolator.interpolate(phase.shell_script, build_settings)
37
+ .gsub(/^"|"$/, "")
38
+ .strip
39
+ end
40
+ end
41
+
42
+ nil
43
+ end
44
+ end
45
+
46
+ class Xcodeproj::Project::Object::PBXAggregateTarget
47
+ include XcodeArchiveCache::Logs
48
+ include TargetEqualityCheck
49
+ include BuildConfigurationSearch
50
+ include SchellScriptBuildPhaseSearch
51
+ end
52
+
53
+ class Xcodeproj::Project::Object::PBXNativeTarget
54
+ include XcodeArchiveCache::Logs
55
+ include TargetEqualityCheck
56
+ include BuildConfigurationSearch
57
+ include SchellScriptBuildPhaseSearch
58
+ end
@@ -7,9 +7,9 @@ module XcodeArchiveCache
7
7
  # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
8
8
  # @param [String] path
9
9
  #
10
- def add_framework_search_path(build_configuration, path)
10
+ def replace_or_add_framework_search_path(build_configuration, target_name, path)
11
11
  debug("using framework search path #{path}")
12
- add_flag_to_configuration(build_configuration, FRAMEWORK_SEARCH_PATHS_KEY, path_to_search_path(path))
12
+ replace_or_add_flag(build_configuration, [FRAMEWORK_SEARCH_PATHS_KEY], nil, [target_name], path_to_search_path(path), true)
13
13
  end
14
14
 
15
15
  # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
@@ -26,6 +26,37 @@ module XcodeArchiveCache
26
26
  # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
27
27
  # @param [XcodeArchiveCache::BuildGraph::Node] node
28
28
  #
29
+ def add_static_lib_linker_flag(build_configuration, node)
30
+ flag = get_linker_flag(node)
31
+ if flag
32
+ debug("using ld flag #{flag}")
33
+ add_linker_flag(build_configuration, flag)
34
+ end
35
+ end
36
+
37
+ # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
38
+ # @param [XcodeArchiveCache::BuildGraph::Node] node
39
+ #
40
+ def add_static_lib_libtool_flag(build_configuration, node)
41
+ flag = get_linker_flag(node)
42
+ if flag
43
+ debug("using libtool flag #{flag}")
44
+ add_libtool_flag(build_configuration, flag)
45
+ end
46
+ end
47
+
48
+ # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
49
+ # @param [String] path
50
+ #
51
+ def add_swift_include_path(build_configuration, path)
52
+ debug("adding #{path} to SWIFT_INCLUDE_PATHS")
53
+ add_flag_to_configuration(build_configuration, SWIFT_INCLUDE_PATHS_KEY, path_to_search_path(path))
54
+ end
55
+
56
+ # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
57
+ # @param [String] artifact_location
58
+ # @param [XcodeArchiveCache::BuildGraph::Node] node
59
+ #
29
60
  def add_framework_headers_iquote(build_configuration, artifact_location, node)
30
61
  headers_search_path = get_framework_headers_iquote(artifact_location, node)
31
62
  debug("using -iquote path #{headers_search_path}")
@@ -35,9 +66,9 @@ module XcodeArchiveCache
35
66
  # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
36
67
  # @param [String] path
37
68
  #
38
- def add_library_search_path(build_configuration, path)
69
+ def replace_or_add_library_search_path(build_configuration, target_name, path)
39
70
  debug("using library search path #{path}")
40
- add_flag_to_configuration(build_configuration, LIBRARY_SEARCH_PATHS_KEY, path_to_search_path(path))
71
+ replace_or_add_flag(build_configuration, [LIBRARY_SEARCH_PATHS_KEY], nil, [target_name], path_to_search_path(path), true)
41
72
  end
42
73
 
43
74
  # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
@@ -65,24 +96,14 @@ module XcodeArchiveCache
65
96
  end
66
97
 
67
98
  # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
99
+ # @param [Array<String>] old_modulemap_names
68
100
  # @param [String] path
69
101
  #
70
102
  def fix_module_map_path(build_configuration, old_modulemap_names, path)
71
- replace_module_map_flag(build_configuration.build_settings, OTHER_CFLAGS_KEY, old_modulemap_names, path)
72
- replace_module_map_flag(build_configuration.build_settings, OTHER_CPLUSPLUSFLAGS_KEY, old_modulemap_names, path)
73
- replace_module_map_flag(build_configuration.build_settings, OTHER_SWIFT_FLAGS_KEY, old_modulemap_names, path)
103
+ debug("using #{path}")
74
104
 
75
- if build_configuration.base_configuration_reference
76
- xcconfig_path = build_configuration.base_configuration_reference.real_path
77
- return unless File.exist?(xcconfig_path)
78
- xcconfig = Xcodeproj::Config.new(xcconfig_path)
79
-
80
- replace_module_map_flag(xcconfig.attributes, OTHER_CFLAGS_KEY, old_modulemap_names, path)
81
- replace_module_map_flag(xcconfig.attributes, OTHER_CPLUSPLUSFLAGS_KEY, old_modulemap_names, path)
82
- replace_module_map_flag(xcconfig.attributes, OTHER_SWIFT_FLAGS_KEY, old_modulemap_names, path)
83
-
84
- xcconfig.save_as(Pathname.new(xcconfig_path))
85
- end
105
+ settings_with_modulemaps = [OTHER_CFLAGS_KEY, OTHER_CPLUSPLUSFLAGS_KEY, OTHER_SWIFT_FLAGS_KEY]
106
+ replace_or_add_flag(build_configuration, settings_with_modulemaps, MODULE_MAP_FLAG, old_modulemap_names, path_to_search_path(path), false)
86
107
  end
87
108
 
88
109
  private
@@ -93,9 +114,13 @@ module XcodeArchiveCache
93
114
  OTHER_CFLAGS_KEY = "OTHER_CFLAGS"
94
115
  OTHER_CPLUSPLUSFLAGS_KEY = "OTHER_CPLUSPLUSFLAGS"
95
116
  OTHER_LDFLAGS_KEY = "OTHER_LDFLAGS"
117
+ OTHER_LIBTOOLFLAGS_KEY = "OTHER_LIBTOOLFLAGS"
96
118
  OTHER_SWIFT_FLAGS_KEY = "OTHER_SWIFT_FLAGS"
119
+ SWIFT_INCLUDE_PATHS_KEY = "SWIFT_INCLUDE_PATHS"
97
120
  INHERITED_SETTINGS_VALUE = "$(inherited)"
98
121
 
122
+ MODULE_MAP_FLAG = "-fmodule-map-file="
123
+
99
124
  # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
100
125
  # @param [String] flag
101
126
  #
@@ -103,6 +128,13 @@ module XcodeArchiveCache
103
128
  add_flag_to_configuration(build_configuration, OTHER_LDFLAGS_KEY, flag)
104
129
  end
105
130
 
131
+ # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
132
+ # @param [String] flag
133
+ #
134
+ def add_libtool_flag(build_configuration, flag)
135
+ add_flag_to_configuration(build_configuration, OTHER_LIBTOOLFLAGS_KEY, flag)
136
+ end
137
+
106
138
  # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
107
139
  # @param [String] flag
108
140
  #
@@ -191,50 +223,121 @@ module XcodeArchiveCache
191
223
  "-framework \"#{framework_name}\""
192
224
  end
193
225
 
194
- # @param [Hash] build_settings
195
- # @param [String] flags_key
196
- # @param [Array<String>] old_modulemap_names
197
- # @param [String] path
226
+ # @param [XcodeArchiveCache::BuildGraph::Node] node
198
227
  #
199
- def replace_module_map_flag(build_settings, flags_key, old_modulemap_names, path)
200
- flags = build_settings[flags_key]
201
- if flags
202
- build_settings[flags_key] = replace_module_map_path(flags, old_modulemap_names, path)
203
- end
204
- end
228
+ # @return [String]
229
+ #
230
+ # libSomething.a -> -lSomething
231
+ #
232
+ def get_linker_flag(node)
233
+ return unless node.product_file_name
205
234
 
206
- MODULE_MAP_FLAG = "-fmodule-map-file="
235
+ node.product_file_name.gsub(/^lib/, "-l").gsub(/\.a$/, "")
236
+ end
207
237
 
208
- # @param [String] flags
209
- # @param [Array<String>] old_modulemap_names
210
- # @param [String] path
238
+ # @param [Xcodeproj::Project::Object::XCBuildConfiguration] build_configuration
239
+ # @param [Array<String>] setting_keys
240
+ # @param [String] flag_name
241
+ # @param [Array<String>] possible_old_values
242
+ # @param [String] new_value
211
243
  #
212
- # @return [String]
244
+ def replace_or_add_flag(build_configuration, setting_keys, flag_name, possible_old_values, new_value, add_if_missing)
245
+ replaced = false
246
+
247
+ setting_keys.each do |setting|
248
+ replaced = replace_flag_value(build_configuration.build_settings, setting, flag_name, possible_old_values, new_value) || replaced
249
+ end
250
+
251
+ if build_configuration.has_xcconfig?
252
+ replaced = replace_flag_value_in_xcconfig_recursively(
253
+ build_configuration.get_xcconfig_path,
254
+ build_configuration.get_project_dir,
255
+ setting_keys,
256
+ flag_name,
257
+ possible_old_values,
258
+ new_value) || replaced
259
+ end
260
+
261
+ if !replaced && add_if_missing
262
+ full_value = get_full_flag_value(flag_name, new_value)
263
+
264
+ setting_keys.each do |setting|
265
+ add_flag_to_configuration(build_configuration, setting, full_value)
266
+ end
267
+ end
268
+ end
269
+
270
+ # @param [String] xcconfig_path
271
+ # @param [String] project_dir
272
+ # @param [Array<String>] setting_keys
273
+ # @param [String] flag_name
274
+ # @param [Array<String>] possible_old_values
275
+ # @param [String] new_value
213
276
  #
214
- def replace_module_map_path(flags, old_modulemap_names, path)
215
- return if flags == nil
277
+ def replace_flag_value_in_xcconfig_recursively(xcconfig_path, project_dir, setting_keys, flag_name, possible_old_values, new_value)
278
+ debug("changing #{possible_old_values} to #{new_value} in #{File.basename(xcconfig_path)}")
279
+ return unless File.exist?(xcconfig_path)
280
+
281
+ replaced = false
282
+ xcconfig = Xcodeproj::Config.new(xcconfig_path)
283
+
284
+ setting_keys.each do |key|
285
+ replaced = replace_flag_value(xcconfig.attributes, key, flag_name, possible_old_values, new_value) || replaced
286
+ end
287
+
288
+ xcconfig.save_as(Pathname.new(xcconfig_path))
289
+
290
+ xcconfig.includes.each do |included_xcconfig|
291
+ included_xcconfig_path = File.join(project_dir, included_xcconfig)
292
+ replaced = replace_flag_value_in_xcconfig_recursively(included_xcconfig_path, project_dir, setting_keys, flag_name, possible_old_values, new_value) || replaced
293
+ end
294
+
295
+ replaced
296
+ end
216
297
 
217
- is_flags_string = flags.is_a?(String)
218
- flags = flags.split(" ") if is_flags_string
219
- updated_flags = flags
220
- .map { |flags_line| flags_line.split(" ") }
298
+ # @param [Hash] attributes
299
+ # @param [String] setting_key
300
+ # @param [String] flag_name
301
+ # @param [Array<String>] possible_old_values
302
+ # @param [String] new_value
303
+ #
304
+ def replace_flag_value(attributes, setting_key, flag_name, possible_old_values, new_value)
305
+ build_settings = attributes[setting_key]
306
+ return unless build_settings
307
+
308
+ replaced = false
309
+ is_string = build_settings.is_a?(String)
310
+ build_settings = build_settings.split(" ") if is_string
311
+ full_value = get_full_flag_value(flag_name, new_value)
312
+ old_value_regexps = possible_old_values.map { |value| Regexp.new("/#{value}\"*$") }
313
+
314
+ updated_settings = build_settings
315
+ .map { |line| line.split(" ") }
221
316
  .flatten
222
317
  .map do |line|
318
+ if flag_name
319
+ next line unless line.include?(flag_name)
320
+ end
321
+
223
322
  updated_line = line
224
323
 
225
- if line.include?(MODULE_MAP_FLAG)
226
- old_modulemap_names.each do |name|
227
- if line.include?(name)
228
- updated_line = "#{MODULE_MAP_FLAG}\"#{path}\""
229
- break
230
- end
324
+ old_value_regexps.each do |regexp|
325
+ if regexp.match?(line)
326
+ replaced = true
327
+ updated_line = full_value
328
+ break
231
329
  end
232
330
  end
233
331
 
234
332
  updated_line
235
333
  end
236
334
 
237
- is_flags_string ? updated_flags.join(" ") : updated_flags
335
+ attributes[setting_key] = is_string ? updated_settings.join(" ") : updated_settings
336
+ replaced
337
+ end
338
+
339
+ def get_full_flag_value(flag_name, value)
340
+ "#{flag_name}#{value}"
238
341
  end
239
342
  end
240
343
  end
@@ -12,11 +12,21 @@ module XcodeArchiveCache
12
12
  debug("removing #{prebuilt_target.name} from #{dependent_target.display_name}")
13
13
 
14
14
  remove_from_dependencies(prebuilt_target, dependent_target)
15
+ remove_from_linking(prebuilt_node, dependent_target)
15
16
  remove_from_schemes(prebuilt_target, dependent_target)
16
17
 
17
18
  debug("finished removing #{prebuilt_target.name} from #{dependent_target.display_name}")
18
19
  end
19
20
 
21
+ # @param [XcodeArchiveCache::BuildGraph::Node] prebuilt_node
22
+ # @param [Xcodeproj::Project::Object::PBXNativeTarget] dependent_target
23
+ #
24
+ # @return [Boolean]
25
+ #
26
+ def is_linked(prebuilt_node, dependent_target)
27
+ !find_linked(prebuilt_node, dependent_target).empty?
28
+ end
29
+
20
30
  private
21
31
 
22
32
  # @param [Xcodeproj::Project::Object::PBXNativeTarget] prebuilt_target
@@ -46,7 +56,7 @@ module XcodeArchiveCache
46
56
  #
47
57
  def remove_from_linking(prebuilt_node, dependent_target)
48
58
  debug("product name is #{prebuilt_node.product_file_name}")
49
- frameworks = dependent_target.frameworks_build_phase.files.select {|file| file.display_name == prebuilt_node.product_file_name}
59
+ frameworks = find_linked(prebuilt_node, dependent_target)
50
60
  debug("found #{frameworks.length} linked products")
51
61
 
52
62
  frameworks.each do |framework|
@@ -67,6 +77,17 @@ module XcodeArchiveCache
67
77
  end
68
78
  end
69
79
 
80
+ # @param [Xcodeproj::Project::Object::PBXNativeTarget] dependent_target
81
+ # @param [XcodeArchiveCache::BuildGraph::Node] prebuilt_node
82
+ #
83
+ # @return [Array<PBXBuildFile>]
84
+ #
85
+ def find_linked(prebuilt_node, dependent_target)
86
+ return [] unless dependent_target.frameworks_build_phase
87
+
88
+ dependent_target.frameworks_build_phase.files.select {|file| file.display_name == prebuilt_node.product_file_name}
89
+ end
90
+
70
91
  # @param [Xcodeproj::Project::Object::PBXNativeTarget] target
71
92
  #
72
93
  # @return [Array<Xcodeproj::XCScheme>]
@@ -9,6 +9,7 @@ module XcodeArchiveCache
9
9
  def initialize(storage)
10
10
  @storage = storage
11
11
  @build_settings_interpolator = XcodeArchiveCache::BuildSettings::StringInterpolator.new
12
+ @modulemap_header_path_extractor = XcodeArchiveCache::Modulemap::HeaderPathExtractor.new
12
13
  end
13
14
 
14
15
  # @param [XcodeArchiveCache::BuildGraph::Node] node
@@ -33,16 +34,22 @@ module XcodeArchiveCache
33
34
  headers_file_paths = node.native_target
34
35
  .headers_build_phase
35
36
  .files
37
+ .select { |file| file.settings && file.settings["ATTRIBUTES"].include?("Public") }
36
38
  .map { |header| get_real_path(header) }
37
39
  .uniq
38
40
  storage.store_default_headers(node, headers_file_paths)
39
41
 
40
42
  header_count += headers_file_paths.length
43
+ end
41
44
 
42
- storage.store_modulemap(node)
45
+ modulemap_file_path = node.original_modulemap_file_path
46
+ if modulemap_file_path && File.exist?(modulemap_file_path)
47
+ header_file_paths = modulemap_header_path_extractor.extract_all_paths(modulemap_file_path)
48
+ storage.store_modulemap_headers(node, header_file_paths)
49
+ header_count += header_file_paths.length
43
50
  end
44
51
 
45
- debug("found #{header_count} headers")
52
+ debug("found #{header_count} header(s)")
46
53
  end
47
54
 
48
55
  private
@@ -55,6 +62,10 @@ module XcodeArchiveCache
55
62
  #
56
63
  attr_reader :build_settings_interpolator
57
64
 
65
+ # @return [XcodeArchiveCache::Modulemap::HeaderPathExtractor]
66
+ #
67
+ attr_reader :modulemap_header_path_extractor
68
+
58
69
  # @param [Xcodeproj::Project::Object::PBXBuildFile] build_file
59
70
  #
60
71
  # @return [String]
@@ -13,15 +13,15 @@ module XcodeArchiveCache
13
13
  @headers_mover = HeadersMover.new(storage)
14
14
  @dependency_remover = DependencyRemover.new
15
15
  @build_flags_changer = BuildFlagsChanger.new
16
- @pods_fixer = PodsScriptFixer.new
17
- @modulemap_fixer = ModulemapFixer.new(storage)
16
+ @pods_fixer = PodsScriptFixer.new(storage)
17
+ @modulemap_fixer = XcodeArchiveCache::Modulemap::HeaderPathFixer.new(storage)
18
18
  @framework_embedder = FrameworkEmbedder.new
19
19
  end
20
20
 
21
21
  # @param [XcodeArchiveCache::BuildGraph::Graph] graph
22
22
  #
23
23
  def perform_internal_injection(graph)
24
- inject_unpacked(graph.nodes)
24
+ inject_unpacked_and_rebuilt(graph.nodes)
25
25
  add_header_paths(graph.nodes)
26
26
  save_graph_projects(graph)
27
27
  end
@@ -43,7 +43,7 @@ module XcodeArchiveCache
43
43
  modulemap_fixer.fix_modulemap(node)
44
44
  end
45
45
 
46
- add_as_prebuilt_dependency(node, target, node.is_root)
46
+ add_as_prebuilt_dependency(node, target)
47
47
  remove_native_target_from_project(node)
48
48
  end
49
49
 
@@ -55,8 +55,8 @@ module XcodeArchiveCache
55
55
  # are covered by "Embed Pods Frameworks" script
56
56
  #
57
57
  if graph.node_by_name(get_pods_target_name(target))
58
- pods_fixer.fix_embed_frameworks_script(target, graph, storage.container_dir_path)
59
- pods_fixer.fix_copy_resources_script(target, graph, storage.container_dir_path)
58
+ pods_fixer.fix_embed_frameworks_script(target, graph)
59
+ pods_fixer.fix_copy_resources_script(target, graph)
60
60
  else
61
61
  framework_nodes = graph.nodes.select { |node| node.has_framework_product? }
62
62
  framework_file_paths = framework_nodes.map { |node| File.join(storage.get_storage_path(node), node.product_file_name) }
@@ -103,13 +103,18 @@ module XcodeArchiveCache
103
103
 
104
104
  # @param [Array<XcodeArchiveCache::BuildGraph::Node>] nodes
105
105
  #
106
- def inject_unpacked(nodes)
106
+ def inject_unpacked_and_rebuilt(nodes)
107
107
  cached_nodes = nodes.select { |node| node.state == :unpacked }
108
108
  cached_nodes.each do |node|
109
109
  headers_mover.prepare_headers_for_injection(node)
110
110
  modulemap_fixer.fix_modulemap(node)
111
111
  add_as_prebuilt_to_dependents(node)
112
112
  end
113
+
114
+ built_nodes = nodes.select { |node| node.state == :rebuilt_and_cached }
115
+ built_nodes.each do |node|
116
+ add_as_prebuilt_to_dependents(node)
117
+ end
113
118
  end
114
119
 
115
120
  # @param [Array<XcodeArchiveCache::BuildGraph::Node>] nodes
@@ -131,7 +136,7 @@ module XcodeArchiveCache
131
136
 
132
137
  debug("adding #{paths} to #{target.display_name}")
133
138
 
134
- build_configuration = find_build_configuration(target)
139
+ build_configuration = target.find_build_configuration(configuration_name)
135
140
  paths.each do |path|
136
141
  build_flags_changer.add_headers_search_path(build_configuration, path)
137
142
  build_flags_changer.add_iquote_path(build_configuration, path)
@@ -146,8 +151,7 @@ module XcodeArchiveCache
146
151
  .all_dependent_nodes
147
152
  .select(&:waiting_for_rebuild)
148
153
  dependent_to_rebuild.each do |dependent_node|
149
- should_link = prebuilt_node.dependent.include?(dependent_node)
150
- add_as_prebuilt_dependency(prebuilt_node, dependent_node.native_target, should_link)
154
+ add_as_prebuilt_dependency(prebuilt_node, dependent_node.native_target)
151
155
  end
152
156
 
153
157
  remove_native_target_from_project(prebuilt_node)
@@ -164,19 +168,24 @@ module XcodeArchiveCache
164
168
  # @param [XcodeArchiveCache::BuildGraph::Node] prebuilt_node
165
169
  # @param [Xcodeproj::Project::Object::PBXNativeTarget] dependent_target
166
170
  #
167
- def add_as_prebuilt_dependency(prebuilt_node, dependent_target, should_link)
171
+ def add_as_prebuilt_dependency(prebuilt_node, dependent_target)
172
+ target_identifier = get_target_identifier(dependent_target)
173
+ return if prebuilt_node.targets_injected_to.include?(target_identifier)
174
+
168
175
  debug("adding #{prebuilt_node.name} as prebuilt to #{dependent_target.display_name}")
169
176
 
170
177
  unless prebuilt_node.has_acceptable_product?
171
- raise Informative, "#{prebuilt_node.name} has unsupported product type: #{prebuilt_node.native_target.product_type}"
178
+ raise XcodeArchiveCache::Informative, "#{prebuilt_node.name} has unsupported product type: #{prebuilt_node.native_target.product_type}"
172
179
  end
173
180
 
174
181
  if prebuilt_node.has_framework_product?
175
182
  add_as_prebuilt_framework(prebuilt_node, dependent_target)
176
183
  elsif prebuilt_node.has_static_library_product?
177
- add_as_prebuilt_static_lib(prebuilt_node, dependent_target, should_link)
184
+ add_as_prebuilt_static_lib(prebuilt_node, dependent_target)
178
185
  end
179
186
 
187
+ prebuilt_node.targets_injected_to.push(target_identifier)
188
+
180
189
  debug("done with #{prebuilt_node.name} for #{dependent_target.display_name}")
181
190
  end
182
191
 
@@ -184,45 +193,47 @@ module XcodeArchiveCache
184
193
  # @param [Xcodeproj::Project::Object::PBXNativeTarget] dependent_target
185
194
  #
186
195
  def add_as_prebuilt_framework(prebuilt_node, dependent_target)
187
- build_configuration = find_build_configuration(dependent_target)
196
+ build_configuration = dependent_target.find_build_configuration(configuration_name)
188
197
 
189
198
  artifact_location = storage.get_storage_path(prebuilt_node)
190
- build_flags_changer.add_framework_search_path(build_configuration, artifact_location)
199
+ build_flags_changer.replace_or_add_framework_search_path(build_configuration, prebuilt_node.native_target.name, artifact_location)
191
200
  build_flags_changer.add_framework_headers_iquote(build_configuration, artifact_location, prebuilt_node)
192
201
 
202
+ if dependency_remover.is_linked(prebuilt_node, dependent_target)
203
+ build_flags_changer.add_framework_linker_flag(build_configuration, prebuilt_node)
204
+ end
205
+
193
206
  dependency_remover.remove_dependency(prebuilt_node, dependent_target)
194
207
  end
195
208
 
196
209
  # @param [XcodeArchiveCache::BuildGraph::Node] prebuilt_node
197
210
  # @param [Xcodeproj::Project::Object::PBXNativeTarget] dependent_target
198
- # @param [Boolean] should_link
199
211
  #
200
- def add_as_prebuilt_static_lib(prebuilt_node, dependent_target, should_link)
201
- build_configuration = find_build_configuration(dependent_target)
212
+ def add_as_prebuilt_static_lib(prebuilt_node, dependent_target)
213
+ build_configuration = dependent_target.find_build_configuration(configuration_name)
202
214
 
203
215
  injected_modulemap_file_path = storage.get_modulemap_path(prebuilt_node)
204
216
  if injected_modulemap_file_path
205
- modulemap_file_names = ["#{prebuilt_node.module_name}.modulemap", File.basename(prebuilt_node.modulemap_file_path)]
217
+ modulemap_file_names = [prebuilt_node.resulting_modulemap_file_name]
206
218
  build_flags_changer.fix_module_map_path(build_configuration, modulemap_file_names, injected_modulemap_file_path)
207
- end
208
-
209
- # if should_link
210
- artifact_location = storage.get_storage_path(prebuilt_node)
211
- build_flags_changer.add_library_search_path(build_configuration, artifact_location)
212
- # end
213
219
 
214
- dependency_remover.remove_dependency(prebuilt_node, dependent_target)
215
- end
220
+ original_modulemap_path = prebuilt_node.original_modulemap_file_path
221
+ add_header_paths_to_target(dependent_target, [File.dirname(original_modulemap_path)])
222
+ end
216
223
 
217
- # @param [Xcodeproj::Project::Object::PBXNativeTarget] target
218
- #
219
- def find_build_configuration(target)
220
- build_configuration = target.build_configurations.select { |configuration| configuration.name == configuration_name }.first
221
- unless build_configuration
222
- raise Informative, "#{configuration_name} build configuration not found on target #{node.name}"
224
+ artifact_location = storage.get_storage_path(prebuilt_node)
225
+ build_flags_changer.replace_or_add_library_search_path(build_configuration, prebuilt_node.native_target.name, artifact_location)
226
+ build_flags_changer.add_swift_include_path(build_configuration, artifact_location)
227
+
228
+ if dependency_remover.is_linked(prebuilt_node, dependent_target)
229
+ if dependent_target.product_type == Xcodeproj::Constants::PRODUCT_TYPE_UTI[:static_library]
230
+ build_flags_changer.add_static_lib_libtool_flag(build_configuration, prebuilt_node)
231
+ else
232
+ build_flags_changer.add_static_lib_linker_flag(build_configuration, prebuilt_node)
233
+ end
223
234
  end
224
235
 
225
- build_configuration
236
+ dependency_remover.remove_dependency(prebuilt_node, dependent_target)
226
237
  end
227
238
 
228
239
  # @param [Xcodeproj::Project::Object::PBXNativeTarget] target
@@ -242,6 +253,14 @@ module XcodeArchiveCache
242
253
  debug("deleting #{node.name} target")
243
254
  node.native_target.project.targets.delete(node.native_target)
244
255
  end
256
+
257
+ # @param [Xcodeproj::Project::Object::PBXNativeTarget] target
258
+ #
259
+ # @return [String]
260
+ #
261
+ def get_target_identifier(target)
262
+ target.uuid + target.project.path.realpath.to_s
263
+ end
245
264
  end
246
265
  end
247
266
  end