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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea58d5804a6b809038af9c443a49426935c3f1b82673ce4029cadcd5dcdb21a2
4
- data.tar.gz: edae37d1c99f73465be2486e910e32bb4b445811d4ef8dd4db91e45853f34a6e
3
+ metadata.gz: b2121ee4ca94b2acfa38e1071a6f30209381464a7da5239e919d4b70cafd1d84
4
+ data.tar.gz: 9874700c995c65ee3ecaa4772a1aa6deba6868591b96da6d271b9ee1f32588df
5
5
  SHA512:
6
- metadata.gz: a753ce67b8129209b5da8e0afbdbd542da9660651ae47559fcfacbcf25ed9d35bedc45dbc05d23f13b33b1e4d05885f54bb43aaea2d3e2b4085f3fc1e960be63
7
- data.tar.gz: c90dee530d492db4c3986c0e0ca6d651e0099a8f0348cdb4f5fa0110a32d143932809bdfce295ab4dc36e8180456320a208ff9f927cc2478f9b8d086cc016c32
6
+ metadata.gz: 528092da4900b8232d71a9583ec0752c92ff2ee851bc13db3609c91c1a9aec3db4278abb777a3c574728d35b409b59ede6fc1481c0dafed49b93a396b994b114
7
+ data.tar.gz: c16c9ff1c2623437b5e29c0fea3cd1bc10cfe631c4df1772197595392b5a05286a8223294c20f9dc306b5ed47089f7c7c85c7eeb4138a940d2a37861c6266bdc
@@ -2,6 +2,8 @@ module XcodeArchiveCache
2
2
  module Build
3
3
  class ProductExtractor
4
4
 
5
+ include XcodeArchiveCache::Logs
6
+
5
7
  # @param [String] configuration
6
8
  # @param [String] derived_data_path
7
9
  #
@@ -17,7 +19,9 @@ module XcodeArchiveCache
17
19
  #
18
20
  def list_product_contents(built_node)
19
21
  file_paths = list_products(built_node)
20
- file_paths.select { |path| File.exist?(path) }.map { |path| File.realpath(path) }
22
+ file_paths
23
+ .select { |path| File.exist?(path) }
24
+ .map { |path| File.realpath(path) }
21
25
  end
22
26
 
23
27
  private
@@ -44,7 +48,7 @@ module XcodeArchiveCache
44
48
  elsif built_node.has_acceptable_product?
45
49
  list_single_product(built_node)
46
50
  else
47
- raise Informative, "#{built_node.name} has unsupported product type: #{built_node.native_target.product_type}"
51
+ raise XcodeArchiveCache::Informative, "#{built_node.name} has unsupported product type: #{built_node.native_target.product_type}"
48
52
  end
49
53
  end
50
54
 
@@ -56,7 +60,7 @@ module XcodeArchiveCache
56
60
  framework_glob = get_main_product_glob(built_node)
57
61
  framework_path = Dir.glob(framework_glob).first
58
62
  unless framework_path
59
- raise Informative, "Framework product not found for #{built_node.name}"
63
+ raise XcodeArchiveCache::Informative, "Framework product not found for #{built_node.name}"
60
64
  end
61
65
 
62
66
  framework_dsym_glob = File.join(File.dirname(framework_glob), built_node.dsym_file_name)
@@ -75,7 +79,7 @@ module XcodeArchiveCache
75
79
  product_glob = get_main_product_glob(built_node)
76
80
  product_path = Dir.glob(product_glob).first
77
81
  unless product_path
78
- raise Informative, "Product of type #{built_node.native_target.product_type} not found for #{built_node.name}"
82
+ raise XcodeArchiveCache::Informative, "Product of type #{built_node.native_target.product_type} not found for #{built_node.name}"
79
83
  end
80
84
 
81
85
  paths = [product_path]
@@ -83,8 +87,32 @@ module XcodeArchiveCache
83
87
  # this one is generated during Swift compilation
84
88
  # so we need to cache it as well
85
89
  #
86
- swift_objc_interface_header_path = built_node.swift_objc_interface_header_path
87
- paths << swift_objc_interface_header_path if swift_objc_interface_header_path
90
+ swift_objc_interface_header_glob = get_swift_objc_interface_header_glob(built_node)
91
+ swift_objc_interface_header_path = Dir.glob(swift_objc_interface_header_glob).first
92
+ if swift_objc_interface_header_path
93
+ debug("using Swift-ObjC interface header #{swift_objc_interface_header_path}")
94
+ paths << swift_objc_interface_header_path
95
+ end
96
+
97
+ swiftmodule_glob = get_swiftmodule_glob(built_node)
98
+ if swiftmodule_glob
99
+ swiftmodule_path = Dir.glob(swiftmodule_glob).first
100
+
101
+ if swiftmodule_path
102
+ debug("using swiftmodule #{swiftmodule_path}")
103
+ paths << swiftmodule_path
104
+ end
105
+ end
106
+
107
+ modulemap_glob = get_modulemap_glob(built_node)
108
+ if modulemap_glob
109
+ modulemap_path = Dir.glob(modulemap_glob).first
110
+
111
+ if modulemap_path
112
+ debug("using modulemap #{modulemap_path}")
113
+ paths << modulemap_path
114
+ end
115
+ end
88
116
 
89
117
  paths
90
118
  end
@@ -94,12 +122,57 @@ module XcodeArchiveCache
94
122
  # @return [String]
95
123
  #
96
124
  def get_main_product_glob(built_node)
97
- product_name = built_node.native_target.product_reference.name ?
98
- built_node.native_target.product_reference.name :
99
- built_node.native_target.product_reference.path
125
+ product_names = [File.basename(built_node.native_target.product_reference.path)]
126
+ if built_node.native_target.product_reference.name
127
+ product_names.push(File.basename(built_node.native_target.product_reference.name))
128
+ end
129
+
130
+ get_product_glob(product_names.select { |name| File.extname(name).length > 0 })
131
+ end
132
+
133
+ # @param [XcodeArchiveCache::BuildGraph::Node] built_node
134
+ #
135
+ # @return [String]
136
+ #
137
+ def get_swift_objc_interface_header_glob(built_node)
138
+ get_product_glob([File.basename(built_node.swift_objc_interface_header_file)])
139
+ end
140
+
141
+ # @param [XcodeArchiveCache::BuildGraph::Node] built_node
142
+ #
143
+ # @return [String]
144
+ #
145
+ def get_swiftmodule_glob(built_node)
146
+ if built_node.module_name
147
+ get_product_glob([built_node.module_name + ".swiftmodule"])
148
+ end
149
+ end
150
+
151
+ # @param [XcodeArchiveCache::BuildGraph::Node] built_node
152
+ #
153
+ # @return [String]
154
+ #
155
+ def get_modulemap_glob(built_node)
156
+ resulting_modulemap_file_name = built_node.resulting_modulemap_file_name
157
+ if resulting_modulemap_file_name
158
+ get_product_glob([resulting_modulemap_file_name])
159
+ else
160
+ modulemap_file_path = built_node.original_modulemap_file_path
161
+ if modulemap_file_path && File.exist?(modulemap_file_path)
162
+ modulemap_file_name = File.basename(modulemap_file_path)
163
+ get_product_glob([modulemap_file_name])
164
+ end
165
+ end
166
+ end
167
+
168
+ # @param [Array<String>] file_names
169
+ #
170
+ # @return [String]
171
+ #
172
+ def get_product_glob(file_names)
100
173
  File.join(derived_data_path,
101
174
  "**",
102
- File.basename(product_name))
175
+ "{#{file_names.join(",")}}")
103
176
  end
104
177
 
105
178
  # @param [String] framework_path
@@ -110,7 +183,7 @@ module XcodeArchiveCache
110
183
  executable_name = File.basename(framework_path, File.extname(framework_path))
111
184
  executable_path = File.join(framework_path, executable_name)
112
185
  unless File.exist?(executable_path)
113
- raise Informative, "Failed to find executable inside framework: #{framework_path}"
186
+ raise XcodeArchiveCache::Informative, "Failed to find executable inside framework: #{framework_path}"
114
187
  end
115
188
 
116
189
  uuids = list_bc_symbolmap_uuids(executable_path)
@@ -6,8 +6,8 @@ module XcodeArchiveCache
6
6
 
7
7
  # @param [XcodeArchiveCache::Xcodebuild::Executor] xcodebuild_executor
8
8
  #
9
- def initialize(native_target_finder, xcodebuild_executor)
10
- @build_settings_loader = XcodeArchiveCache::BuildSettings::Loader.new(xcodebuild_executor)
9
+ def initialize(native_target_finder, build_settings_loader)
10
+ @build_settings_loader = build_settings_loader
11
11
  @native_target_finder = native_target_finder
12
12
  @sha_calculator = NodeShaCalculator.new
13
13
  end
@@ -61,13 +61,17 @@ module XcodeArchiveCache
61
61
  display_name = target.display_name
62
62
  if target_stack.include?(display_name)
63
63
  target_stack.push(display_name)
64
- raise Informative, "Circular dependency detected: #{target_stack.join(" -> ")}"
64
+ raise XcodeArchiveCache::Informative, "Circular dependency detected: #{target_stack.join(" -> ")}"
65
65
  end
66
66
 
67
67
  node = ALL_NODES.select {|node| node.native_target.uuid == target.uuid && node.native_target.project == target.project}.first
68
68
  if node
69
69
  debug("already traversed this one")
70
- graph.add_multiple_nodes(node.subgraph) unless graph.nodes.include?(node)
70
+ unless graph.nodes.include?(node)
71
+ nodes_to_add = node.subgraph.select {|subgraph_node| !graph.nodes.include?(subgraph_node)}
72
+ graph.add_multiple_nodes(nodes_to_add)
73
+ end
74
+
71
75
  return node
72
76
  else
73
77
  debug("adding new node")
@@ -79,11 +83,7 @@ module XcodeArchiveCache
79
83
  dependencies = []
80
84
  target_stack.push(display_name)
81
85
 
82
- dependency_targets = target.dependencies.map {|dependency| native_target_finder.find_for_dependency(dependency)} +
83
- target.frameworks_build_phase.files.map {|file| native_target_finder.find_for_file(file)}
84
-
85
- # PBXNativeTarget has no custom equality check
86
- deduplicated_targets = dependency_targets.compact.uniq {|dependency_target| dependency_target.uuid + dependency_target.display_name}
86
+ deduplicated_targets = native_target_finder.find_native_dependencies(target)
87
87
  debug("dependency targets: #{deduplicated_targets.map(&:display_name)}")
88
88
 
89
89
  deduplicated_targets.each do |dependency_target|
@@ -141,7 +141,7 @@ module XcodeArchiveCache
141
141
  info("getting settings for #{target.display_name}")
142
142
  build_settings = build_settings_loader.get_settings(target.project.path, target.display_name)
143
143
  unless build_settings
144
- raise Informative, "No build settings loaded for #{target.display_name}"
144
+ raise XcodeArchiveCache::Informative, "No build settings loaded for #{target.display_name}"
145
145
  end
146
146
 
147
147
  build_settings
@@ -3,9 +3,14 @@ module XcodeArchiveCache
3
3
  class NativeTargetFinder
4
4
 
5
5
  # @param [Array<Xcodeproj::Project>] projects
6
+ # @param [String] build_configuration_name
6
7
  #
7
- def initialize(projects)
8
+ def initialize(projects, build_configuration_name)
8
9
  @all_targets = extract_targets(projects)
10
+ @build_configuration_name = build_configuration_name
11
+ @interpolator = XcodeArchiveCache::BuildSettings::StringInterpolator.new
12
+
13
+ setup_product_name_to_target_mapping
9
14
  end
10
15
 
11
16
  # @param [Array<Xcodeproj::Project>] projects
@@ -14,30 +19,67 @@ module XcodeArchiveCache
14
19
  #
15
20
  def extract_targets(projects)
16
21
  projects
17
- .map {|project| unnest(project)}
18
- .flatten
19
- .uniq
20
- .map(&:native_targets)
21
- .flatten
22
- .select {|target| !target.test_target_type?}
22
+ .map {|project| unnest(project)}
23
+ .flatten
24
+ .sort_by(&:path)
25
+ .inject([]) {|unique, current| unique.last && unique.last.path == current.path ? unique : unique + [current]}
26
+ .map(&:native_targets)
27
+ .flatten
28
+ .select {|target| !target.test_target_type?}
23
29
  end
24
30
 
25
31
  # @param [String] platform_name
26
32
  #
33
+ # @return [Array<Xcodeproj::Project::Object::PBXNativeTarget>]
34
+ #
27
35
  def set_platform_name_filter(platform_name)
28
36
  @platform_name = platform_name
29
37
  end
30
38
 
39
+ # @param [Xcodeproj::Project::Object::PBXNativeTarget] target
40
+ #
41
+ # @return [Array<Xcodeproj::Project::Object::PBXNativeTarget>]
42
+ #
43
+ def find_native_dependencies(target)
44
+ direct_dependencies = target
45
+ .dependencies
46
+ .map {|dependency| find_for_dependency(dependency)}
47
+ linked_dependencies = find_linked_dependencies(target)
48
+ join(direct_dependencies, linked_dependencies)
49
+ end
50
+
51
+ # @param [Xcodeproj::Project::Object::PBXAbstractTarget] target
52
+ #
53
+ # @return [Array<Xcodeproj::Project::Object::PBXAbstractTarget>]
54
+ #
55
+ def find_all_dependencies(target)
56
+ direct_dependencies = target
57
+ .dependencies
58
+ .map {|dependency| find_any_for_dependency(dependency)}
59
+ linked_dependencies = []
60
+
61
+ if target.is_a?(Xcodeproj::Project::Object::PBXNativeTarget)
62
+ linked_dependencies = find_linked_dependencies(target)
63
+ end
64
+
65
+ join(direct_dependencies, linked_dependencies)
66
+ end
67
+
31
68
  # @param [Xcodeproj::Project::Object::PBXTargetDependency] dependency
32
69
  #
33
70
  # @return [Xcodeproj::Project::Object::PBXNativeTarget]
34
71
  #
35
72
  def find_for_dependency(dependency)
36
73
  # targets from embedded projects are proxied
37
- target = dependency.target ? dependency.target : dependency.target_proxy.proxied_object
74
+ target = find_any_for_dependency(dependency)
38
75
  target.is_a?(Xcodeproj::Project::Object::PBXNativeTarget) ? target : nil
39
76
  end
40
77
 
78
+ def find_any_for_dependency(dependency)
79
+ target = dependency.target ? dependency.target : dependency.target_proxy.proxied_object
80
+ target && target.platform_name == platform_name ? target : nil
81
+ end
82
+
41
83
  # @param [Xcodeproj::Project::Object::PBXBuildFile] file
42
84
  #
43
85
  # @return [Xcodeproj::Project::Object::PBXNativeTarget]
@@ -60,7 +102,7 @@ module XcodeArchiveCache
60
102
  end
61
103
 
62
104
  if target == nil
63
- raise Informative, "Target for #{file.file_ref.path} not found"
105
+ raise XcodeArchiveCache::Informative, "Target for #{file.file_ref.path} not found"
64
106
  end
65
107
 
66
108
  target
@@ -68,7 +110,7 @@ module XcodeArchiveCache
68
110
  # products of sibling project targets are added as PBXFileReferences
69
111
  targets = find_with_product_path(file.file_ref.path)
70
112
  if targets.length > 1
71
- raise Informative, "Found more than one target with product #{File.basename(file.file_ref.path)} in:\n#{targets.map(&:project)}"
113
+ raise XcodeArchiveCache::Informative, "Found more than one target with product #{File.basename(file.file_ref.path)} in:\n#{targets.map(&:project)}"
72
114
  end
73
115
 
74
116
  targets.first
@@ -77,9 +119,16 @@ module XcodeArchiveCache
77
119
 
78
120
  # @param [String] product_name
79
121
  #
122
+ # @return [Xcodeproj::Project::Object::PBXNativeTarget]
123
+ #
80
124
  def find_for_product_name(product_name)
81
- all_targets.select {|native_target| native_target.name == product_name || native_target.product_reference.display_name == product_name}
82
- .first
125
+ canonical = all_targets
126
+ .select {|native_target| native_target.name == product_name || native_target.product_reference.display_name == product_name || native_target.product_reference.path == product_name }
127
+ .first
128
+
129
+ parsed = @product_name_to_target[product_name]
130
+
131
+ canonical ? canonical : parsed
83
132
  end
84
133
 
85
134
  private
@@ -92,6 +141,36 @@ module XcodeArchiveCache
92
141
  #
93
142
  attr_accessor :platform_name
94
143
 
144
+ # @return [String]
145
+ #
146
+ attr_reader :build_configuration_name
147
+
148
+ def setup_product_name_to_target_mapping
149
+ @product_name_to_target = Hash.new
150
+
151
+ @all_targets.each do |target|
152
+ build_settings = target.find_build_configuration(build_configuration_name, raise_if_not_found: false)&.build_settings
153
+ next unless build_settings
154
+
155
+ full_settings = build_settings
156
+ full_settings[XcodeArchiveCache::BuildSettings::TARGET_NAME_KEY] = target.name
157
+ product_name = @interpolator.interpolate(build_settings[XcodeArchiveCache::BuildSettings::PRODUCT_NAME_KEY], full_settings)
158
+
159
+ next if product_name == nil
160
+
161
+ product_name_extension = ""
162
+ case target.product_type
163
+ when Xcodeproj::Constants::PRODUCT_TYPE_UTI[:framework]
164
+ product_name_extension = ".framework"
165
+ when Xcodeproj::Constants::PRODUCT_TYPE_UTI[:static_library]
166
+ product_name_extension = ".a"
167
+ end
168
+
169
+ full_product_name = "#{product_name}#{product_name_extension}"
170
+ @product_name_to_target[full_product_name] = target
171
+ end
172
+ end
173
+
95
174
  # @param [Xcodeproj::Project] project
96
175
  #
97
176
  # @return [Array<Xcodeproj::Project>]
@@ -106,6 +185,28 @@ module XcodeArchiveCache
106
185
  [project] + nested_projects + subnested_projects
107
186
  end
108
187
 
188
+ # @param [Xcodeproj::Project::Object::PBXNativeTarget] target
189
+ #
190
+ # @return [Array<Xcodeproj::Project::Object::PBXNativeTarget>]
191
+ #
192
+ def find_linked_dependencies(target)
193
+ target
194
+ .frameworks_build_phase
195
+ .files
196
+ .map {|file| find_for_file(file)}
197
+ end
198
+
199
+ # @param [Array<Xcodeproj::Project::Object::PBXAbstractTarget>] direct_dependencies
200
+ # @params [Array<Xcodeproj::Project::Object::PBXNativeTarget>] linked_dependencies
201
+ #
202
+ # @return [Array<Xcodeproj::Project::Object::PBXAbstractTarget>]
203
+ #
204
+ def join(direct_dependencies, linked_dependencies)
205
+ (direct_dependencies + linked_dependencies)
206
+ .compact
207
+ .uniq(&:equatable_identifier)
208
+ end
209
+
109
210
  # @param [String] uuid
110
211
  #
111
212
  # @return [Xcodeproj::Project::Object::PBXNativeTarget]
@@ -128,7 +229,16 @@ module XcodeArchiveCache
128
229
  # @return [Array<Xcodeproj::Project::Object::PBXNativeTarget>]
129
230
  #
130
231
  def find_with_product_path(path)
131
- all_targets.select {|target| target.platform_name == platform_name && target.product_reference.path == path}
232
+ canonical = all_targets.select {|target| target.platform_name == platform_name && target.product_reference.path == path }
233
+ parsed = @product_name_to_target[File.basename(path)]
234
+
235
+ if canonical.length > 0
236
+ canonical
237
+ elsif parsed
238
+ [parsed]
239
+ else
240
+ []
241
+ end
132
242
  end
133
243
  end
134
244
  end
@@ -34,6 +34,10 @@ module XcodeArchiveCache
34
34
  #
35
35
  attr_accessor :build_settings
36
36
 
37
+ # @return [Array<Xcodeproj::Project::Object::PBXNativeTarget>]
38
+ #
39
+ attr_reader :targets_injected_to
40
+
37
41
  # @param [String] name
38
42
  # @param [Xcodeproj::Project::Object::PBXNativeTarget] native_target
39
43
  # @param [Boolean] is_root
@@ -44,6 +48,7 @@ module XcodeArchiveCache
44
48
  @is_root = is_root
45
49
  @dependent = []
46
50
  @dependencies = []
51
+ @targets_injected_to = []
47
52
  @state = :unknown
48
53
  end
49
54
 
@@ -91,8 +96,8 @@ module XcodeArchiveCache
91
96
 
92
97
  # @return [String]
93
98
  #
94
- def modulemap_file_path
95
- modulemap_file = build_settings[XcodeArchiveCache::BuildSettings::MODULEMAP_FILE_KEY]
99
+ def original_modulemap_file_path
100
+ modulemap_file = modulemap_file_name
96
101
  return unless modulemap_file
97
102
 
98
103
  Pathname.new(modulemap_file).absolute? ? modulemap_file : File.join(File.dirname(native_target.project.path), modulemap_file)
@@ -100,11 +105,12 @@ module XcodeArchiveCache
100
105
 
101
106
  # @return [String]
102
107
  #
103
- def swift_objc_interface_header_path
104
- header_file = swift_objc_interface_header_file
105
- return if header_file == nil
106
-
107
- File.join(build_settings[XcodeArchiveCache::BuildSettings::DERIVED_SOURCES_DIR_KEY], header_file)
108
+ def resulting_modulemap_file_name
109
+ if module_name
110
+ module_name + ".modulemap"
111
+ else
112
+ File.basename(modulemap_file_name)
113
+ end
108
114
  end
109
115
 
110
116
  # @return [String]
@@ -127,6 +133,12 @@ module XcodeArchiveCache
127
133
  build_settings[XcodeArchiveCache::BuildSettings::PRODUCT_MODULE_NAME_KEY]
128
134
  end
129
135
 
136
+ # @return [String]
137
+ #
138
+ def modulemap_file_name
139
+ build_settings[XcodeArchiveCache::BuildSettings::MODULEMAP_FILE_KEY]
140
+ end
141
+
130
142
  # @return [Array<Node>]
131
143
  # Direct + transitive dependents
132
144
  #
@@ -2,6 +2,10 @@ module XcodeArchiveCache
2
2
  module BuildGraph
3
3
  class NodeShaCalculator
4
4
 
5
+ def initialize
6
+ @own_sha = calculate_own_sources_sha
7
+ end
8
+
5
9
  # @param [XcodeArchiveCache::BuildGraph::Node] node
6
10
  #
7
11
  def calculate(node)
@@ -24,6 +28,20 @@ module XcodeArchiveCache
24
28
 
25
29
  private
26
30
 
31
+ # @return [String]
32
+ #
33
+ attr_reader :own_sha
34
+
35
+ # @return [String]
36
+ #
37
+ def calculate_own_sources_sha
38
+ root = Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
39
+ source_file_glob = File.join(root.realpath.to_s, "**", "*.rb")
40
+ source_file_paths = Dir.glob(source_file_glob)
41
+
42
+ calculate_sha(source_file_paths)
43
+ end
44
+
27
45
  # @param [XcodeArchiveCache::BuildGraph::Node] node
28
46
  #
29
47
  # @return [Array<String>]
@@ -36,7 +54,7 @@ module XcodeArchiveCache
36
54
  inputs << list_build_phase_inputs(build_phase)
37
55
  end
38
56
 
39
- modulemap_file_path = node.modulemap_file_path
57
+ modulemap_file_path = node.original_modulemap_file_path
40
58
  inputs << modulemap_file_path if modulemap_file_path
41
59
 
42
60
  # file path order should not affect evaluation result
@@ -74,7 +92,7 @@ module XcodeArchiveCache
74
92
  # @param [Array<String>] dependency_shas
75
93
  #
76
94
  def save_auxiliary_data(build_settings, dependency_shas, tempfile)
77
- file_contents = build_settings + dependency_shas.join("\n")
95
+ file_contents = build_settings + dependency_shas.join("\n") + "\nXCODE-ARCHIVE-CACHE: #{own_sha}\n"
78
96
  tempfile << file_contents
79
97
  tempfile.flush
80
98
  end
@@ -73,6 +73,7 @@ module XcodeArchiveCache
73
73
  original_platform = settings[EFFECTIVE_PLATFORM_NAME_KEY]
74
74
  simulator_platform = settings[CORRESPONDING_SIMULATOR_PLATFORM_NAME_KEY]
75
75
  settings[EFFECTIVE_PLATFORM_NAME_KEY] = "-#{simulator_platform}"
76
+ settings[PLATFORM_NAME_KEY] = simulator_platform
76
77
 
77
78
  configuration = settings[CONFIGURATION_KEY]
78
79
  path_regexp = Regexp.new("#{configuration}#{original_platform}")
@@ -82,6 +83,7 @@ module XcodeArchiveCache
82
83
  end
83
84
  end
84
85
 
86
+ PLATFORM_NAME_KEY = "PLATFORM_NAME".freeze
85
87
  EFFECTIVE_PLATFORM_NAME_KEY = "EFFECTIVE_PLATFORM_NAME".freeze
86
88
  CORRESPONDING_SIMULATOR_PLATFORM_NAME_KEY = "CORRESPONDING_SIMULATOR_PLATFORM_NAME".freeze
87
89
  CONFIGURATION_KEY = "CONFIGURATION".freeze
@@ -1,6 +1,8 @@
1
1
  module XcodeArchiveCache
2
2
  module BuildSettings
3
3
 
4
+ PRODUCT_NAME_KEY = "PRODUCT_NAME".freeze
5
+ TARGET_NAME_KEY = "TARGET_NAME".freeze
4
6
  FULL_PRODUCT_NAME_KEY = "FULL_PRODUCT_NAME".freeze
5
7
  DWARF_DSYM_FILE_NAME_KEY = "DWARF_DSYM_FILE_NAME".freeze
6
8
  MODULEMAP_FILE_KEY = "MODULEMAP_FILE".freeze
@@ -1,11 +1,24 @@
1
1
  module XcodeArchiveCache
2
2
  module BuildSettings
3
+ class SettingEntry
4
+ attr_reader :name
5
+ attr_reader :modifiers
6
+ attr_reader :full_string
7
+
8
+ def initialize(name, modifiers, full_string)
9
+ @name = name
10
+ @modifiers = modifiers
11
+ @full_string = full_string
12
+ end
13
+ end
14
+
3
15
  class Parser
4
16
 
5
17
  def initialize
6
18
  @setting_name_regex = Regexp.new("^(?<#{SETTING_NAME_GROUP}>#{SETTING_NAME_CHARACTERS})\s=")
7
19
  @setting_value_regex = Regexp.new("^#{SETTING_NAME_CHARACTERS}\s=\s(?<#{SETTING_VALUE_GROUP}>.+)$")
8
20
  @setting_entry_regex = create_entry_regex
21
+ @setting_entry_part_regex = Regexp.new("#{SETTING_ENTRY_PART_CHARACTERS}")
9
22
  @setting_entry_name_regex = Regexp.new(SETTING_NAME_CHARACTERS)
10
23
  end
11
24
 
@@ -13,12 +26,18 @@ module XcodeArchiveCache
13
26
  #
14
27
  # @return [Array<String>]
15
28
  #
16
- def find_all_names(string)
29
+ def find_all_entries(string)
30
+ return nil if string == nil
31
+
17
32
  string.scan(setting_entry_regex)
18
- .map {|entry| entry.scan(setting_entry_name_regex).first}
19
- .flatten
33
+ .map {|entry|
34
+ parts = entry.scan(setting_entry_part_regex)
35
+ name = parts.first
36
+ modifiers = parts.drop(1)
37
+
38
+ name != nil ? SettingEntry.new(name, modifiers, entry) : nil
39
+ }
20
40
  .compact
21
- .uniq
22
41
  end
23
42
 
24
43
  # @param [String] string
@@ -47,7 +66,7 @@ module XcodeArchiveCache
47
66
  #
48
67
  # @return [Regexp]
49
68
  #
50
- def create_entry_regex(characters = SETTING_NAME_CHARACTERS)
69
+ def create_entry_regex(characters = SETTING_ALL_CHARACTERS)
51
70
  Regexp.new("\\$[({]#{characters}[)}]")
52
71
  end
53
72
 
@@ -65,10 +84,14 @@ module XcodeArchiveCache
65
84
  #
66
85
  attr_reader :setting_entry_regex
67
86
 
87
+ attr_reader :setting_entry_part_regex
88
+
68
89
  # @return [Regexp]
69
90
  #
70
91
  attr_reader :setting_entry_name_regex
71
92
 
93
+ SETTING_ALL_CHARACTERS = "[A-Za-z0-9_:]+".freeze
94
+ SETTING_ENTRY_PART_CHARACTERS = "[A-Za-z0-9_]+".freeze
72
95
  SETTING_NAME_CHARACTERS = "[A-Z0-9_]+".freeze
73
96
  SETTING_NAME_GROUP = "name".freeze
74
97
  SETTING_VALUE_GROUP = "value".freeze
@@ -12,15 +12,17 @@ module XcodeArchiveCache
12
12
  # @return [String]
13
13
  #
14
14
  def interpolate(string, build_settings)
15
- names = parser.find_all_names(string)
15
+ return nil if string == nil
16
+
17
+ entries = parser.find_all_entries(string)
16
18
  result = string
17
19
 
18
- names.each do |name|
19
- value = build_settings[name]
20
+ entries.each do |entry|
21
+ value = build_settings[entry.name]
20
22
  next unless value
21
23
 
22
- replacement_regex = parser.create_entry_regex(name)
23
- result = result.gsub(replacement_regex, value)
24
+ modified_value = modify_setting_value(value, entry.modifiers)
25
+ result = result.gsub(entry.full_string, modified_value)
24
26
  end
25
27
 
26
28
  result
@@ -31,6 +33,20 @@ module XcodeArchiveCache
31
33
  # @return [Parser]
32
34
  #
33
35
  attr_accessor :parser
36
+
37
+ def modify_setting_value(value, modifiers)
38
+ modified_value = value
39
+
40
+ modifiers.each do |modifier|
41
+ case modifier
42
+ when "c99extidentifier"
43
+ modified_value = modified_value.gsub(/[-\s]/, "_")
44
+ else
45
+ end
46
+ end
47
+
48
+ modified_value
49
+ end
34
50
  end
35
51
  end
36
52
  end