xcode-archive-cache 0.0.8.pre.2 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/artifact_cache/archiver.rb +2 -1
- data/lib/artifact_cache/local_storage.rb +2 -1
- data/lib/build/performer.rb +1 -1
- data/lib/build/product_extractor.rb +88 -5
- data/lib/build_graph/builder.rb +5 -1
- data/lib/build_graph/native_target_finder.rb +46 -11
- data/lib/build_graph/node.rb +50 -2
- data/lib/build_graph/rebuild_evaluator.rb +30 -4
- data/lib/build_graph/sha_calculator.rb +22 -1
- data/lib/build_settings/extractor.rb +21 -1
- data/lib/build_settings/filter.rb +7 -3
- data/lib/build_settings/loader.rb +8 -1
- data/lib/build_settings/parser.rb +1 -1
- data/lib/injection/build_flags_changer.rb +173 -4
- data/lib/injection/dependency_remover.rb +22 -1
- data/lib/injection/headers_mover.rb +27 -3
- data/lib/injection/injector.rb +69 -20
- data/lib/injection/storage.rb +47 -6
- data/lib/modulemap/file_handler.rb +20 -0
- data/lib/modulemap/header_path_extractor.rb +67 -0
- data/lib/modulemap/header_path_fixer.rb +65 -0
- data/lib/runner/runner.rb +31 -24
- data/lib/shell/executor.rb +2 -2
- data/lib/xcode-archive-cache.rb +4 -0
- data/lib/xcodebuild/executor.rb +4 -0
- metadata +32 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff86c853bc7b50f265964695cd55edd14821c821f5d27a1f916dcc23ccc1c4b4
|
4
|
+
data.tar.gz: a11e6dd9c98f59526f6f5329aab00acdcc58b5d7e2b65d83b6a1348d647a2323
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a71f194f4af63d93ee4f256977eb98525065599a36f270215c5c0f3a18cb8742957bb8f2e407497a7629f05ba18b9532d093d02b1dec305fcf4f82f815473431
|
7
|
+
data.tar.gz: ba25058d81d37e12594422d9a765d07fb8af192b53fe980ca3b4da3e1eac61f5a0bc69454f406be92094742e7809dbe8f4887d33e48b305c869733e5c581a4d8
|
@@ -9,7 +9,8 @@ module XcodeArchiveCache
|
|
9
9
|
#
|
10
10
|
def archive(path, destination)
|
11
11
|
if File.exists?(destination)
|
12
|
-
|
12
|
+
warn "Replacing artifact archive at path #{destination}"
|
13
|
+
FileUtils.rm_rf(destination)
|
13
14
|
end
|
14
15
|
|
15
16
|
if File.file?(path)
|
@@ -60,7 +60,8 @@ module XcodeArchiveCache
|
|
60
60
|
state_file_path = archive_path + ".state"
|
61
61
|
|
62
62
|
if File.exist?(state_file_path)
|
63
|
-
|
63
|
+
warn "Replacing state file #{state_file_path}"
|
64
|
+
FileUtils.rm_f(state_file_path)
|
64
65
|
end
|
65
66
|
|
66
67
|
dependency_shas = node.dependencies
|
data/lib/build/performer.rb
CHANGED
@@ -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
|
22
|
+
file_paths
|
23
|
+
.select { |path| File.exist?(path) }
|
24
|
+
.map { |path| File.realpath(path) }
|
21
25
|
end
|
22
26
|
|
23
27
|
private
|
@@ -78,7 +82,39 @@ module XcodeArchiveCache
|
|
78
82
|
raise Informative, "Product of type #{built_node.native_target.product_type} not found for #{built_node.name}"
|
79
83
|
end
|
80
84
|
|
81
|
-
[product_path]
|
85
|
+
paths = [product_path]
|
86
|
+
|
87
|
+
# this one is generated during Swift compilation
|
88
|
+
# so we need to cache it as well
|
89
|
+
#
|
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
|
116
|
+
|
117
|
+
paths
|
82
118
|
end
|
83
119
|
|
84
120
|
# @param [XcodeArchiveCache::BuildGraph::Node] built_node
|
@@ -89,9 +125,52 @@ module XcodeArchiveCache
|
|
89
125
|
product_name = built_node.native_target.product_reference.name ?
|
90
126
|
built_node.native_target.product_reference.name :
|
91
127
|
built_node.native_target.product_reference.path
|
128
|
+
get_product_glob(File.basename(product_name))
|
129
|
+
end
|
130
|
+
|
131
|
+
# @param [XcodeArchiveCache::BuildGraph::Node] built_node
|
132
|
+
#
|
133
|
+
# @return [String]
|
134
|
+
#
|
135
|
+
def get_swift_objc_interface_header_glob(built_node)
|
136
|
+
get_product_glob(File.basename(built_node.swift_objc_interface_header_file))
|
137
|
+
end
|
138
|
+
|
139
|
+
# @param [XcodeArchiveCache::BuildGraph::Node] built_node
|
140
|
+
#
|
141
|
+
# @return [String]
|
142
|
+
#
|
143
|
+
def get_swiftmodule_glob(built_node)
|
144
|
+
if built_node.module_name
|
145
|
+
get_product_glob(built_node.module_name + ".swiftmodule")
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# @param [XcodeArchiveCache::BuildGraph::Node] built_node
|
150
|
+
#
|
151
|
+
# @return [String]
|
152
|
+
#
|
153
|
+
def get_modulemap_glob(built_node)
|
154
|
+
resulting_modulemap_file_name = built_node.resulting_modulemap_file_name
|
155
|
+
if resulting_modulemap_file_name
|
156
|
+
get_product_glob(resulting_modulemap_file_name)
|
157
|
+
else
|
158
|
+
modulemap_file_path = built_node.original_modulemap_file_path
|
159
|
+
if modulemap_file_path && File.exist?(modulemap_file_path)
|
160
|
+
modulemap_file_name = File.basename(modulemap_file_path)
|
161
|
+
get_product_glob(modulemap_file_name)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# @param [String] file_name
|
167
|
+
#
|
168
|
+
# @return [String]
|
169
|
+
#
|
170
|
+
def get_product_glob(file_name)
|
92
171
|
File.join(derived_data_path,
|
93
172
|
"**",
|
94
|
-
|
173
|
+
file_name)
|
95
174
|
end
|
96
175
|
|
97
176
|
# @param [String] framework_path
|
@@ -106,7 +185,7 @@ module XcodeArchiveCache
|
|
106
185
|
end
|
107
186
|
|
108
187
|
uuids = list_bc_symbolmap_uuids(executable_path)
|
109
|
-
uuids.map {|uuid| find_bc_symbolmap(uuid)}.flatten
|
188
|
+
uuids.map { |uuid| find_bc_symbolmap(uuid) }.flatten
|
110
189
|
end
|
111
190
|
|
112
191
|
# @param [String] executable_path
|
@@ -114,7 +193,11 @@ module XcodeArchiveCache
|
|
114
193
|
# @return [Array<String>]
|
115
194
|
#
|
116
195
|
def list_bc_symbolmap_uuids(executable_path)
|
117
|
-
|
196
|
+
begin
|
197
|
+
shell_executor.execute_for_output("otool -l #{executable_path} | grep uuid | awk {'print $2'}").split("\n")
|
198
|
+
rescue
|
199
|
+
[]
|
200
|
+
end
|
118
201
|
end
|
119
202
|
|
120
203
|
# @param [String] uuid
|
data/lib/build_graph/builder.rb
CHANGED
@@ -67,7 +67,11 @@ module XcodeArchiveCache
|
|
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
|
-
|
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")
|
@@ -5,13 +5,22 @@ module XcodeArchiveCache
|
|
5
5
|
# @param [Array<Xcodeproj::Project>] projects
|
6
6
|
#
|
7
7
|
def initialize(projects)
|
8
|
-
@all_targets = projects
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
@all_targets = extract_targets(projects)
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param [Array<Xcodeproj::Project>] projects
|
12
|
+
#
|
13
|
+
# @return [Array<Xcodeproj::Project::Object::PBXNativeTarget>]
|
14
|
+
#
|
15
|
+
def extract_targets(projects)
|
16
|
+
projects
|
17
|
+
.map {|project| unnest(project)}
|
18
|
+
.flatten
|
19
|
+
.sort_by(&:path)
|
20
|
+
.inject([]) {|unique, current| unique.last && unique.last.path == current.path ? unique : unique + [current]}
|
21
|
+
.map(&:native_targets)
|
22
|
+
.flatten
|
23
|
+
.select {|target| !target.test_target_type?}
|
15
24
|
end
|
16
25
|
|
17
26
|
# @param [String] platform_name
|
@@ -36,9 +45,26 @@ module XcodeArchiveCache
|
|
36
45
|
#
|
37
46
|
def find_for_file(file)
|
38
47
|
if file.file_ref.is_a?(Xcodeproj::Project::Object::PBXReferenceProxy)
|
39
|
-
project = file.file_ref.remote_ref.container_portal_object
|
40
48
|
product_reference_uuid = file.file_ref.remote_ref.remote_global_id_string
|
41
|
-
find_with_product_ref_uuid(
|
49
|
+
target = find_with_product_ref_uuid(product_reference_uuid)
|
50
|
+
if target == nil
|
51
|
+
project = file.file_ref.remote_ref.container_portal_object
|
52
|
+
target = find_in_project(project, product_reference_uuid)
|
53
|
+
|
54
|
+
# allow all targets from this project
|
55
|
+
# to be linked to that exact project
|
56
|
+
#
|
57
|
+
# otherwise, injection will operate on different Xcodeproj::Project objects
|
58
|
+
# resulting to only the last target being actually removed
|
59
|
+
#
|
60
|
+
@all_targets += extract_targets([project])
|
61
|
+
end
|
62
|
+
|
63
|
+
if target == nil
|
64
|
+
raise Informative, "Target for #{file.file_ref.path} not found"
|
65
|
+
end
|
66
|
+
|
67
|
+
target
|
42
68
|
elsif file.file_ref.is_a?(Xcodeproj::Project::Object::PBXFileReference)
|
43
69
|
# products of sibling project targets are added as PBXFileReferences
|
44
70
|
targets = find_with_product_path(file.file_ref.path)
|
@@ -54,7 +80,7 @@ module XcodeArchiveCache
|
|
54
80
|
#
|
55
81
|
def find_for_product_name(product_name)
|
56
82
|
all_targets.select {|native_target| native_target.name == product_name || native_target.product_reference.display_name == product_name}
|
57
|
-
|
83
|
+
.first
|
58
84
|
end
|
59
85
|
|
60
86
|
private
|
@@ -85,7 +111,16 @@ module XcodeArchiveCache
|
|
85
111
|
#
|
86
112
|
# @return [Xcodeproj::Project::Object::PBXNativeTarget]
|
87
113
|
#
|
88
|
-
def find_with_product_ref_uuid(
|
114
|
+
def find_with_product_ref_uuid(uuid)
|
115
|
+
all_targets.select {|target| target.product_reference.uuid == uuid}.first
|
116
|
+
end
|
117
|
+
|
118
|
+
# @param [Xcodeproj::Project] project
|
119
|
+
# @param [String] uuid
|
120
|
+
#
|
121
|
+
# @return [Xcodeproj::Project::Object::PBXNativeTarget]
|
122
|
+
#
|
123
|
+
def find_in_project(project, uuid)
|
89
124
|
project.native_targets.select {|target| target.product_reference.uuid == uuid}.first
|
90
125
|
end
|
91
126
|
|
data/lib/build_graph/node.rb
CHANGED
@@ -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
|
|
@@ -86,9 +91,52 @@ module XcodeArchiveCache
|
|
86
91
|
# @return [String]
|
87
92
|
#
|
88
93
|
def dsym_file_name
|
89
|
-
|
94
|
+
build_settings ? build_settings[XcodeArchiveCache::BuildSettings::DWARF_DSYM_FILE_NAME_KEY] : nil
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [String]
|
98
|
+
#
|
99
|
+
def original_modulemap_file_path
|
100
|
+
modulemap_file = modulemap_file_name
|
101
|
+
return unless modulemap_file
|
102
|
+
|
103
|
+
Pathname.new(modulemap_file).absolute? ? modulemap_file : File.join(File.dirname(native_target.project.path), modulemap_file)
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [String]
|
107
|
+
#
|
108
|
+
def resulting_modulemap_file_name
|
109
|
+
if module_name
|
110
|
+
module_name + ".modulemap"
|
111
|
+
else
|
112
|
+
File.basename(modulemap_file_name)
|
113
|
+
end
|
114
|
+
end
|
90
115
|
|
91
|
-
|
116
|
+
# @return [String]
|
117
|
+
#
|
118
|
+
def swift_objc_interface_header_file
|
119
|
+
header_file = build_settings[XcodeArchiveCache::BuildSettings::SWIFT_OBJC_INTERFACE_HEADER_NAME_KEY]
|
120
|
+
if header_file == nil
|
121
|
+
our_module_name = module_name
|
122
|
+
return if our_module_name == nil
|
123
|
+
|
124
|
+
header_file = our_module_name + "-Swift.h"
|
125
|
+
end
|
126
|
+
|
127
|
+
header_file
|
128
|
+
end
|
129
|
+
|
130
|
+
# @return [String]
|
131
|
+
#
|
132
|
+
def module_name
|
133
|
+
build_settings[XcodeArchiveCache::BuildSettings::PRODUCT_MODULE_NAME_KEY]
|
134
|
+
end
|
135
|
+
|
136
|
+
# @return [String]
|
137
|
+
#
|
138
|
+
def modulemap_file_name
|
139
|
+
build_settings[XcodeArchiveCache::BuildSettings::MODULEMAP_FILE_KEY]
|
92
140
|
end
|
93
141
|
|
94
142
|
# @return [Array<Node>]
|
@@ -8,24 +8,50 @@ module XcodeArchiveCache
|
|
8
8
|
@cache_storage = cache_storage
|
9
9
|
end
|
10
10
|
|
11
|
+
# @param [XcodeArchiveCache::BuildGraph::Graph] graph
|
12
|
+
#
|
13
|
+
def evaluate_build_graph(graph)
|
14
|
+
return if graph.root_node.state != :unknown
|
15
|
+
|
16
|
+
# DFS over graph, evaluating dependencies first
|
17
|
+
#
|
18
|
+
stack = [graph.root_node]
|
19
|
+
|
20
|
+
while stack.length > 0
|
21
|
+
last_node = stack.last
|
22
|
+
|
23
|
+
if last_node.state == :evaluating_dependencies
|
24
|
+
# dependencies were evaluated, we're good to go
|
25
|
+
evaluate(last_node)
|
26
|
+
stack.delete_at(stack.length - 1)
|
27
|
+
elsif last_node.state == :unknown
|
28
|
+
last_node.state = :evaluating_dependencies
|
29
|
+
stack += last_node.dependencies.select { |dependency| dependency.state == :unknown }
|
30
|
+
else
|
31
|
+
stack.delete_at(stack.length - 1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
11
38
|
# @param [XcodeArchiveCache::BuildGraph::Node] node
|
12
39
|
#
|
13
40
|
def evaluate(node)
|
14
|
-
|
41
|
+
has_dependencies_waiting_for_rebuild = node.dependencies
|
42
|
+
.reduce(false) { |rebuild, dependency| rebuild || dependency.waiting_for_rebuild }
|
15
43
|
|
16
44
|
# we include dependency shas in every node sha calculation,
|
17
45
|
# so if some dependency changes, that change propagates
|
18
46
|
# all the way to the top level
|
19
47
|
#
|
20
|
-
if cache_storage.cached_artifact_path(node) == nil
|
48
|
+
if has_dependencies_waiting_for_rebuild || cache_storage.cached_artifact_path(node) == nil
|
21
49
|
node.state = :waiting_for_rebuild
|
22
50
|
else
|
23
51
|
node.state = :exists_in_cache
|
24
52
|
end
|
25
53
|
end
|
26
54
|
|
27
|
-
private
|
28
|
-
|
29
55
|
# @return [XcodeArchiveCache::ArtifactCache::AbstractStorage]
|
30
56
|
#
|
31
57
|
attr_reader :cache_storage
|
@@ -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,6 +54,9 @@ module XcodeArchiveCache
|
|
36
54
|
inputs << list_build_phase_inputs(build_phase)
|
37
55
|
end
|
38
56
|
|
57
|
+
modulemap_file_path = node.original_modulemap_file_path
|
58
|
+
inputs << modulemap_file_path if modulemap_file_path
|
59
|
+
|
39
60
|
# file path order should not affect evaluation result
|
40
61
|
inputs.flatten.compact.sort
|
41
62
|
end
|
@@ -71,7 +92,7 @@ module XcodeArchiveCache
|
|
71
92
|
# @param [Array<String>] dependency_shas
|
72
93
|
#
|
73
94
|
def save_auxiliary_data(build_settings, dependency_shas, tempfile)
|
74
|
-
file_contents = build_settings + dependency_shas.join("\n")
|
95
|
+
file_contents = build_settings + dependency_shas.join("\n") + "\nXCODE-ARCHIVE-CACHE: #{own_sha}\n"
|
75
96
|
tempfile << file_contents
|
76
97
|
tempfile.flush
|
77
98
|
end
|