xccache 0.0.1 → 1.0.0.rc15341775774

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/xccache/cache/cachemap.rb +28 -11
  3. data/lib/xccache/command/base.rb +1 -4
  4. data/lib/xccache/command/build.rb +1 -14
  5. data/lib/xccache/command/off.rb +26 -0
  6. data/lib/xccache/command.rb +10 -1
  7. data/lib/xccache/core/config.rb +10 -4
  8. data/lib/xccache/core/hash.rb +9 -6
  9. data/lib/xccache/core/lockfile.rb +62 -7
  10. data/lib/xccache/core/log.rb +5 -0
  11. data/lib/xccache/core/sh.rb +3 -17
  12. data/lib/xccache/core/syntax/hash.rb +4 -0
  13. data/lib/xccache/core/system.rb +2 -1
  14. data/lib/xccache/installer/build.rb +3 -1
  15. data/lib/xccache/installer/integration/build.rb +28 -0
  16. data/lib/xccache/installer/integration/descs.rb +27 -0
  17. data/lib/xccache/installer/integration/supporting_files.rb +29 -0
  18. data/lib/xccache/installer/integration/viz.rb +38 -0
  19. data/lib/xccache/installer/integration.rb +12 -0
  20. data/lib/xccache/installer/use.rb +1 -1
  21. data/lib/xccache/installer.rb +47 -14
  22. data/lib/xccache/spm/build.rb +1 -1
  23. data/lib/xccache/spm/desc/base.rb +1 -4
  24. data/lib/xccache/spm/desc/desc.rb +2 -30
  25. data/lib/xccache/spm/mixin.rb +5 -4
  26. data/lib/xccache/spm/pkg/base.rb +40 -34
  27. data/lib/xccache/spm/pkg/proxy.rb +60 -0
  28. data/lib/xccache/spm/pkg/proxy_executable.rb +51 -0
  29. data/lib/xccache/utils/template.rb +1 -1
  30. data/lib/xccache/xcodeproj/pkg.rb +2 -4
  31. data/lib/xccache/xcodeproj/pkg_product_dependency.rb +16 -3
  32. data/lib/xccache/xcodeproj/project.rb +9 -15
  33. data/lib/xccache/xcodeproj/target.rb +4 -14
  34. data/lib/xccache.rb +5 -0
  35. metadata +12 -12
  36. data/lib/xccache/assets/templates/umbrella.Package.swift.template +0 -182
  37. data/lib/xccache/spm/pkg/umbrella/build.rb +0 -30
  38. data/lib/xccache/spm/pkg/umbrella/cachemap.rb +0 -110
  39. data/lib/xccache/spm/pkg/umbrella/descs.rb +0 -35
  40. data/lib/xccache/spm/pkg/umbrella/manifest.rb +0 -83
  41. data/lib/xccache/spm/pkg/umbrella/viz.rb +0 -40
  42. data/lib/xccache/spm/pkg/umbrella/xcconfigs.rb +0 -31
  43. data/lib/xccache/spm/pkg/umbrella.rb +0 -91
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xccache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0.rc15341775774
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thuyen Trinh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-13 00:00:00.000000000 Z
11
+ date: 2025-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: claide
@@ -69,7 +69,6 @@ files:
69
69
  - lib/xccache/assets/templates/framework.modulemap.template
70
70
  - lib/xccache/assets/templates/resource_bundle_accessor.m.template
71
71
  - lib/xccache/assets/templates/resource_bundle_accessor.swift.template
72
- - lib/xccache/assets/templates/umbrella.Package.swift.template
73
72
  - lib/xccache/cache/cachemap.rb
74
73
  - lib/xccache/command.rb
75
74
  - lib/xccache/command/base.rb
@@ -77,6 +76,7 @@ files:
77
76
  - lib/xccache/command/cache.rb
78
77
  - lib/xccache/command/cache/clean.rb
79
78
  - lib/xccache/command/cache/list.rb
79
+ - lib/xccache/command/off.rb
80
80
  - lib/xccache/command/pkg.rb
81
81
  - lib/xccache/command/pkg/build.rb
82
82
  - lib/xccache/command/remote.rb
@@ -102,6 +102,11 @@ files:
102
102
  - lib/xccache/core/system.rb
103
103
  - lib/xccache/installer.rb
104
104
  - lib/xccache/installer/build.rb
105
+ - lib/xccache/installer/integration.rb
106
+ - lib/xccache/installer/integration/build.rb
107
+ - lib/xccache/installer/integration/descs.rb
108
+ - lib/xccache/installer/integration/supporting_files.rb
109
+ - lib/xccache/installer/integration/viz.rb
105
110
  - lib/xccache/installer/rollback.rb
106
111
  - lib/xccache/installer/use.rb
107
112
  - lib/xccache/main.rb
@@ -119,13 +124,8 @@ files:
119
124
  - lib/xccache/spm/mixin.rb
120
125
  - lib/xccache/spm/pkg.rb
121
126
  - lib/xccache/spm/pkg/base.rb
122
- - lib/xccache/spm/pkg/umbrella.rb
123
- - lib/xccache/spm/pkg/umbrella/build.rb
124
- - lib/xccache/spm/pkg/umbrella/cachemap.rb
125
- - lib/xccache/spm/pkg/umbrella/descs.rb
126
- - lib/xccache/spm/pkg/umbrella/manifest.rb
127
- - lib/xccache/spm/pkg/umbrella/viz.rb
128
- - lib/xccache/spm/pkg/umbrella/xcconfigs.rb
127
+ - lib/xccache/spm/pkg/proxy.rb
128
+ - lib/xccache/spm/pkg/proxy_executable.rb
129
129
  - lib/xccache/spm/xcframework.rb
130
130
  - lib/xccache/spm/xcframework/metadata.rb
131
131
  - lib/xccache/spm/xcframework/slice.rb
@@ -161,9 +161,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
161
161
  version: '0'
162
162
  required_rubygems_version: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - ">="
164
+ - - ">"
165
165
  - !ruby/object:Gem::Version
166
- version: '0'
166
+ version: 1.3.1
167
167
  requirements: []
168
168
  rubygems_version: 3.2.33
169
169
  signing_key:
@@ -1,182 +0,0 @@
1
- // swift-tools-version: 6.0
2
- import Foundation
3
- import PackageDescription
4
-
5
- /*
6
- MARK: INSTRUCTIONS
7
- ----------------------------------------------------------------------------------------------------------------------
8
- This Package manifest is auto-generated from xccache (last updated: <%= timestamp %>).
9
- ----------------------------------------------------------------------------------------------------------------------
10
- During local development, you can switch between *BINARY mode* and *SOURCE mode* by adding or removing the `.binary`
11
- suffix in the JSON below.
12
- As a user, you just need to care about the JSON. The rest is just the tool's internal logic.
13
-
14
- NOTE that a product (ex. `pkg/foo.binary`) can only be used as binary if:
15
- - Binary exists for `pkg/foo` (in `xccache/packages/binaries/foo/foo.xcframework`)
16
- - Binary exists for all of its dependencies
17
- The tool auto-fallbacks to the *SOURCE mode* if the conditions are not met.
18
- ----------------------------------------------------------------------------------------------------------------------
19
- */
20
- let JSON = """
21
- <%= json %>
22
- """
23
- let DEPENDENCIES: [Package.Dependency] = [
24
- <%= dependencies %>
25
- ]
26
- let PLATFORMS: [SupportedPlatform] = [
27
- <%= platforms %>
28
- ]
29
- let PRODUCTS_TO_TARGETS: [String: [String]] = try parseJSON("""
30
- <%= products_to_targets %>
31
- """)
32
- // ------------------------------------------------------------------------------------
33
-
34
- // MARK: Main
35
- _ = try XCCache.Package(parseJSON(JSON)).spm
36
-
37
- // MARK: XCCache
38
- enum XCCache {
39
- // MARK: Config
40
- @MainActor
41
- struct Config {
42
- static let pkgDir = URL(filePath: #filePath).deletingLastPathComponent()
43
- // NOTE: Do NOT change `binariesDir` to `static let`
44
- // Somehow, incremental resolution doesnt work causing the `binaryExist` wrongly cached
45
- static var binariesDir: URL { pkgDir.appending(path: "binaries") }
46
- }
47
-
48
- // MARK: Package
49
- @MainActor
50
- final class Package {
51
- let targets: [XCCache.Target]
52
- init(_ dict: [String: [String]]) {
53
- targets = dict.map { XCCache.Target($0, $1) }
54
- }
55
-
56
- var spm: PackageDescription.Package {
57
- let regularTargets = targets.map(\.spm)
58
- let binaryTargets = targets.flatMap(\.flattenRegularDeps).unique(by: \.name).compactMap(\.spmBinaryTarget)
59
- return .init(
60
- name: "xccache",
61
- platforms: PLATFORMS,
62
- products: targets.map(\.spmProduct),
63
- dependencies: DEPENDENCIES,
64
- targets: regularTargets + binaryTargets
65
- )
66
- }
67
- }
68
-
69
- // MARK: Target
70
- @MainActor
71
- final class Target {
72
- let name: String
73
- let deps: [UmbrellaDependency]
74
- init(_ name: String, _ deps: [String]) {
75
- self.name = name
76
- self.deps = deps.map { UmbrellaDependency($0) }
77
- }
78
-
79
- var spmProduct: PackageDescription.Product {
80
- .library(name: name, targets: [name])
81
- }
82
- var spm: PackageDescription.Target {
83
- .target(
84
- name: name,
85
- dependencies: flattenRegularDeps.map(\.spm),
86
- path: ".Sources/\(name)",
87
- swiftSettings: [
88
- .unsafeFlags(macroFlags),
89
- ]
90
- )
91
- }
92
- var flattenDeps: [Dependency] { deps.flatMap(\.toBinariesIfOk).unique(by: \.name) }
93
- var flattenRegularDeps: [Dependency] { flattenDeps.filter(\.regular) }
94
- var macroFlags: [String] { flattenDeps.filter(\.macroBinary).flatMap(\.macroFlags) }
95
- }
96
-
97
- // MARK: Dependency
98
- @MainActor
99
- class Dependency {
100
- let name: String
101
- let bareName: String
102
- let binaryURL: URL
103
- let binary: Bool
104
- let macro: Bool
105
- var regular: Bool { !macro }
106
- var regularBinary: Bool { binary && regular }
107
- var macroBinary: Bool { binary && macro }
108
-
109
- init(_ name: String) {
110
- self.name = name
111
- self.bareName = String(name.basename.split(separator: ".")[0])
112
- self.macro = name.contains(".macro")
113
- self.binaryURL = if macro {
114
- Config.binariesDir.appending(path: "\(bareName)/\(bareName).macro").readlink()
115
- } else {
116
- Config.binariesDir.appending(path: "\(bareName)/\(bareName).xcframework").readlink()
117
- }
118
- self.binary = name.hasSuffix(".binary") && binaryURL.exist
119
- }
120
-
121
- var macroFlags: [String] {
122
- ["-load-plugin-executable", "\(binaryURL.path())#\(bareName)"]
123
- }
124
-
125
- var spm: PackageDescription.Target.Dependency {
126
- if binary { return .byName(name: name) }
127
- return .product(name: bareName, package: name.slug)
128
- }
129
- var spmBinaryTarget: PackageDescription.Target? {
130
- regularBinary ? .binaryTarget(name: name, path: "binaries/\(bareName)/\(bareName).xcframework") : nil
131
- }
132
- }
133
-
134
- @MainActor
135
- class UmbrellaDependency: Dependency {
136
- let binaries: [Dependency]
137
- override init(_ name: String) {
138
- binaries = (PRODUCTS_TO_TARGETS[name.withoutBinary] ?? []).map { Dependency("\($0).binary") }
139
- super.init(name)
140
- }
141
- var toBinariesIfOk: [Dependency] {
142
- if name.hasSuffix(".binary"), !binaries.isEmpty && binaries.allSatisfy(\.binary) { return binaries }
143
- return [Dependency(name.withoutBinary)]
144
- }
145
- }
146
- }
147
-
148
- // MARK: Helpers
149
- func parseJSON<T>(_ content: String) throws -> T {
150
- if let data = content.data(using: .utf8), let result = try JSONSerialization.jsonObject(with: data) as? T {
151
- return result
152
- }
153
- throw NSError(domain: "Invalid JSON:\n\(content)", code: 111)
154
- }
155
-
156
- extension URL {
157
- var basename: String { lastPathComponent }
158
- var exist: Bool { FileManager.default.fileExists(atPath: readlink().path()) }
159
- /// Resolve symlinks recursively, equivalent to `readlink -f` in bash
160
- func readlink() -> URL {
161
- var prev = self, cur = resolvingSymlinksInPath()
162
- while prev != cur {
163
- prev = cur
164
- cur = cur.resolvingSymlinksInPath()
165
- }
166
- return cur
167
- }
168
- }
169
-
170
- extension String {
171
- var slug: String { (self as NSString).deletingLastPathComponent.basename }
172
- var basename: String { (self as NSString).lastPathComponent }
173
- var withoutExtenstion: String { (self as NSString).deletingPathExtension }
174
- var withoutBinary: String { replacing(#/\.binary$/#, with: "") }
175
- }
176
-
177
- extension Sequence {
178
- func unique<T: Hashable>(by: (Element) -> T) -> [Element] {
179
- var seen: Set<T> = []
180
- return filter { seen.insert(by($0)).inserted }
181
- }
182
- }
@@ -1,30 +0,0 @@
1
- module XCCache
2
- module SPM
3
- class Package
4
- module UmbrellaBuildMixin
5
- def build(options = {})
6
- to_build = targets_to_build(options)
7
- return UI.warn("Detected no targets to build among cache-missed targets") if to_build.empty?
8
-
9
- UI.info("-> Targets to build: #{to_build.to_s.bold}")
10
- super(options.merge(:targets => to_build))
11
- sync_cachemap(sdks: options[:sdks])
12
- end
13
-
14
- def targets_to_build(options)
15
- items = options[:targets] || []
16
- items = config.cachemap.missed.map { |x| File.basename(x) } if items.empty?
17
- targets = @descs.flat_map(&:targets).select { |t| items.include?(t.name) }
18
- if options[:recursive]
19
- UI.message("Will include cache-missed recursive targets")
20
- targets += targets.flat_map do |t|
21
- t.recursive_targets.select { |x| config.cachemap.missed?(x.full_name) }
22
- end
23
- end
24
- # TODO: Sort by number of dependents
25
- targets.map(&:full_name).uniq
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,110 +0,0 @@
1
- module XCCache
2
- module SPM
3
- class Package
4
- module UmbrellaCachemapMixin
5
- def sync_cachemap(sdks: [])
6
- UI.section("Syncing cachemap (sdks: #{sdks.map(&:name)})")
7
- nodes, edges, parents = xccache_desc.traverse
8
- cache_data = gen_cache_data(nodes, parents, sdks)
9
- targets_data, macros_data, deps_data = {}, {}, {}
10
- xccache_desc.targets.each do |agg_target|
11
- targets, macros = [], []
12
- agg_target.direct_dependencies.each do |d|
13
- all_hit = d.recursive_targets.all? { |t| cache_data[t] == :hit }
14
- # If any associated targets is missed -> use original product form
15
- # Otherwise, replace with recursive targets' binaries
16
- deps_data[d.full_name] = d.recursive_targets.map(&:xccache_id)
17
- targets << (all_hit ? "#{d.full_name}.binary" : d.full_name)
18
- macros += d.recursive_targets.select(&:macro?).map(&:full_name) if all_hit
19
- end
20
- targets_data[agg_target.name] = targets.uniq.sort_by(&:downcase)
21
- macros_data[agg_target.name] = macros.uniq
22
- end
23
-
24
- config.cachemap.raw = {
25
- "manifest" => {
26
- "targets" => targets_data,
27
- "macros" => macros_data,
28
- "deps" => deps_data,
29
- },
30
- "cache" => cache_data.transform_keys(&:full_name),
31
- "depgraph" => {
32
- "nodes" => nodes.map { |x| target_to_cytoscape_node(x, cache_data) },
33
- "edges" => edges.map { |x, y| { :source => x.full_name, :target => y.full_name } },
34
- },
35
- }
36
- config.cachemap.save
37
- config.cachemap.print_stats
38
- end
39
-
40
- private
41
-
42
- def gen_cache_data(nodes, parents, sdks)
43
- result = nodes.to_h do |node|
44
- res = if config.ignore?(node.full_name) then :ignored
45
- else
46
- verify_binary?(node, sdks) ? :hit : :missed
47
- end
48
- [node, res]
49
- end
50
-
51
- # Propagate cache miss
52
- to_visit = result.select { |_, v| %i[missed ignore].include?(v) }.keys
53
- visited = Set.new
54
- until to_visit.empty?
55
- node = to_visit.pop
56
- next if visited.include?(node)
57
- visited << node
58
- result[node] = :missed if result[node] == :hit
59
- to_visit += parents[node] if parents.key?(node)
60
- end
61
- result.reject { |k, _| k.name.end_with?(".xccache") }
62
- end
63
-
64
- def verify_binary?(target, sdks)
65
- return true if target.binary?
66
-
67
- bpath = binary_path(target.xccache_id)
68
- bpath_with_checksum = binary_path(target.xccache_id, checksum: target.checksum, in_repo: true)
69
-
70
- check = proc do
71
- # For macro, we just need the tool binary to exist
72
- # For regular targets, the xcframework must satisfy the sdk constraints (ie. containing all the slices)
73
- next bpath_with_checksum.exist? if target.macro?
74
-
75
- metadata = XCFramework::Metadata.new(bpath_with_checksum / "Info.plist")
76
- expected_triples = sdks.map { |sdk| sdk.triple(without_vendor: true) }
77
- missing_triples = expected_triples - metadata.triples
78
- missing_triples.empty?
79
- end
80
-
81
- # If requirements are meet, create symlink `A-abc123.xcframework` -> `A.framework`
82
- # Otherwise, remove symlink `A.xcframework`
83
- if check.call
84
- bpath_with_checksum.symlink_to(bpath)
85
- elsif bpath.exist?
86
- bpath.rmtree
87
- end
88
- bpath.exist?
89
- end
90
-
91
- def binary_path(name, checksum: nil, in_repo: false)
92
- suffix = checksum.nil? ? "" : "-#{checksum}"
93
- ext = File.extname(name) == ".macro" ? ".macro" : ".xcframework"
94
- binaries_dir = in_repo ? config.spm_cache_dir : config.spm_binaries_dir
95
- p = binaries_dir / File.basename(name, ".*")
96
- p / "#{p.basename}#{suffix}#{ext}"
97
- end
98
-
99
- def target_to_cytoscape_node(x, cache_data)
100
- h = { :id => x.full_name, :cache => cache_data[x] }
101
- h[:type] = if x.name.end_with?(".xccache") then "agg"
102
- elsif x.macro? then "macro" end
103
- h[:checksum] = x.checksum
104
- h[:binary] = binary_path(x.xccache_id) if cache_data[x] == :hit
105
- h
106
- end
107
- end
108
- end
109
- end
110
- end
@@ -1,35 +0,0 @@
1
- module XCCache
2
- module SPM
3
- class Package
4
- module UmbrellaDescsMixin
5
- def gen_metadata
6
- UI.section("Generating metadata of packages", timing: true) do
7
- @descs, @descs_by_name = Description.descs_in_dir(root_dir, save_to_dir: config.spm_metadata_dir)
8
- end
9
- end
10
-
11
- def xccache_desc
12
- @xccache_desc ||= desc_of("xccache")
13
- end
14
-
15
- def targets_of_products(products)
16
- products = [products] if products.is_a?(String)
17
- products.flat_map { |x| desc_of(x).targets_of_products(File.basename(x)) }
18
- end
19
-
20
- def dependency_targets_of_products(products)
21
- products = [products] if products.is_a?(String)
22
- products.flat_map { |p| @dependency_targets_by_products[p] || [p] }.uniq
23
- end
24
-
25
- def desc_of(d)
26
- @descs_by_name[d.split("/").first]
27
- end
28
-
29
- def binary_targets
30
- @descs_by_name.values.flatten.uniq.flat_map(&:binary_targets)
31
- end
32
- end
33
- end
34
- end
35
- end
@@ -1,83 +0,0 @@
1
- module XCCache
2
- module SPM
3
- class Package
4
- module UmbrellaManifestMixin
5
- def write_manifest(no_cache: false)
6
- UI.info("Writing Package.swift (package: #{root_dir.basename})")
7
- Template.new("umbrella.Package.swift").render(
8
- {
9
- :timestamp => Time.new.strftime("%F %T"),
10
- :json => manifest_targets_json(no_cache: no_cache),
11
- :products_to_targets => manifest_products_to_targets_json(no_cache: no_cache),
12
- :platforms => manifest_platforms,
13
- :dependencies => manifest_pkg_dependencies,
14
- :swift_version => Swift::Swiftc.version_without_patch,
15
- },
16
- save_to: root_dir / "Package.swift",
17
- )
18
- end
19
-
20
- def manifest_targets_json(no_cache: false)
21
- data = no_cache ? config.lockfile.targets_data : config.cachemap.manifest_data["targets"]
22
- JSON.pretty_generate(data)
23
- end
24
-
25
- def manifest_products_to_targets_json(no_cache: false)
26
- data = no_cache ? {} : config.cachemap.manifest_data["deps"]
27
- JSON.pretty_generate(data)
28
- end
29
-
30
- def manifest_pkg_dependencies
31
- decl = proc do |hash|
32
- if (path_from_root = hash["path_from_root"])
33
- absolute_path = (Pathname(".") / path_from_root).expand_path
34
- next ".package(path: \"#{absolute_path}\")"
35
- end
36
-
37
- requirement = hash["requirement"]
38
- case requirement["kind"]
39
- when "upToNextMajorVersion"
40
- opt = ".upToNextMajor(from: \"#{requirement['minimumVersion']}\")"
41
- when "upToNextMinorVersion"
42
- opt = ".upToNextMinor(from: \"#{requirement['minimumVersion']}\")"
43
- when "exactVersion"
44
- opt = "exact: \"#{requirement['version']}\""
45
- when "branch"
46
- opt = "branch: \"#{requirement['branch']}\""
47
- when "revision"
48
- opt = "revision: \"#{requirement['revision']}\""
49
- when "versionRange"
50
- opt = "\"#{requirement['minimumVersion']}\"..<\"#{requirement['maximumVersion']}\""
51
- end
52
- ".package(url: \"#{hash['repositoryURL']}\", #{opt})"
53
- end
54
-
55
- config.lockfile.pkgs.map { |h| " #{decl.call(h)}," }.join("\n")
56
- end
57
-
58
- def manifest_platforms
59
- @manifest_platforms ||= begin
60
- to_spm_platform = {
61
- :ios => "iOS",
62
- :macos => "macOS",
63
- :osx => "macOS",
64
- :tvos => "tvOS",
65
- :watchos => "watchOS",
66
- :visionos => "visionOS",
67
- }
68
- hash = {}
69
- config.project_targets.each do |t|
70
- platform = to_spm_platform[t.platform_name]
71
- hash[platform] ||= []
72
- hash[platform] << t.deployment_target.split(".")[0]
73
- end
74
- hash
75
- .transform_values(&:min)
76
- .map { |platform, version| " .#{platform}(.v#{version})," }
77
- .join("\n")
78
- end
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,40 +0,0 @@
1
- module XCCache
2
- module SPM
3
- class Package
4
- module UmbrellaVizMixin
5
- def gen_cachemap_viz
6
- stats = config.cachemap.stats
7
- html_path = config.sandbox / "cachemap.html"
8
- js_path = Dir.prepare(config.sandbox / "assets") / "cachemap.js"
9
- css_path = config.sandbox / "assets" / "style.css"
10
-
11
- root_dir = Pathname(".").expand_path
12
- to_relative = proc do |p|
13
- p.to_s.start_with?(root_dir.to_s) ? p.relative_path_from(root_dir).to_s : p.to_s
14
- end
15
-
16
- UI.info("Cachemap visualization: #{html_path}")
17
- Template.new("cachemap.html").render(
18
- {
19
- :root_dir => root_dir.to_s,
20
- :root_dir_short => root_dir.basename.to_s,
21
- :lockfile_path => config.lockfile.path.to_s,
22
- :lockfile_path_short => to_relative.call(config.lockfile.path),
23
- :binaries_dir => config.spm_binaries_dir.to_s,
24
- :binaries_dir_short => to_relative.call(config.spm_binaries_dir),
25
- :desc_hit => stats[:hit],
26
- :desc_missed => stats[:missed],
27
- :desc_ignored => stats[:ignored],
28
- },
29
- save_to: html_path
30
- )
31
- Template.new("cachemap.js").render(
32
- { :json => JSON.pretty_generate(config.cachemap.depgraph_data) },
33
- save_to: js_path
34
- )
35
- Template.new("cachemap.style.css").render(save_to: css_path)
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,31 +0,0 @@
1
- module XCCache
2
- module SPM
3
- class Package
4
- module UmbrellaXCConfigsMixin
5
- def gen_xcconfigs
6
- UI.section("Generating xcconfigs") do
7
- macros_config_by_targets.each do |target, hash|
8
- xcconfig_path = config.spm_xcconfig_dir / "#{target}.xcconfig"
9
- UI.message("XCConfig of target #{target} at: #{xcconfig_path}")
10
- Xcodeproj::Config.new(hash).save_as(xcconfig_path)
11
- end
12
- end
13
- end
14
-
15
- private
16
-
17
- def macros_config_by_targets
18
- config.cachemap.manifest_data["macros"].to_h do |target, macros|
19
- swift_flags = macros.map do |m|
20
- basename = File.basename(m, ".*")
21
- binary_path = config.spm_binaries_dir / basename / "#{basename}.macro"
22
- "-load-plugin-executable #{binary_path}##{basename}"
23
- end
24
- hash = { "OTHER_SWIFT_FLAGS" => "$(inherited) #{swift_flags.join(' ')}" }
25
- [File.basename(target, ".*"), hash]
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,91 +0,0 @@
1
- require "xccache/swift/swiftc"
2
- require "xccache/utils/template"
3
- require "xccache/cache/cachemap"
4
- require "xccache/spm/pkg/base"
5
-
6
- Dir["#{__dir__}/#{File.basename(__FILE__, '.rb')}/*.rb"].sort.each { |f| require f }
7
-
8
- module XCCache
9
- module SPM
10
- class Package
11
- class Umbrella < Package
12
- include Config::Mixin
13
- include UmbrellaCachemapMixin
14
- include UmbrellaDescsMixin
15
- include UmbrellaBuildMixin
16
- include UmbrellaManifestMixin
17
- include UmbrellaVizMixin
18
- include UmbrellaXCConfigsMixin
19
-
20
- def initialize(options = {})
21
- super
22
- @descs = []
23
- @descs_by_name = {}
24
- @dependency_targets_by_products = {}
25
- end
26
-
27
- def prepare(options = {})
28
- create
29
- resolve unless options[:skip_resolving_dependencies]
30
- create_symlinks_for_convenience
31
- create_symlinks_to_local_pkgs
32
- gen_metadata
33
- resolve_recursive_dependencies
34
- create_symlinks_to_artifacts
35
- sync_cachemap(sdks: options[:sdks])
36
- end
37
-
38
- def resolve_recursive_dependencies
39
- UI.section("Resolving recursive dependencies")
40
- @descs.each do |desc|
41
- @dependency_targets_by_products.merge!(desc.resolve_recursive_dependencies.transform_keys(&:full_name))
42
- end
43
- end
44
-
45
- def create
46
- UI.info("Creating umbrella package")
47
- # Initially, write json with the original data in lockfile (without cache)
48
- write_manifest(no_cache: true)
49
- # Create dummy sources dirs prefixed with `.` so that they do not show up in Xcode
50
- config.project_targets.each do |target|
51
- dir = Dir.prepare(root_dir / ".Sources" / "#{target.name}.xccache")
52
- (dir / "dummy.swift").write("")
53
- end
54
- end
55
-
56
- def create_symlinks_for_convenience
57
- # Symlinks for convenience
58
- (root_dir / "binaries").symlink_to(root_dir.parent / "binaries")
59
- (root_dir / ".build").symlink_to(root_dir.parent / ".build")
60
- (root_dir / ".build/checkouts").symlink_to(root_dir.parent / "checkouts")
61
- end
62
-
63
- def create_symlinks_to_local_pkgs
64
- pkg_desc.dependencies.select(&:local?).each do |dep|
65
- # For metadata generation
66
- dep.path.symlink_to(root_dir / ".build/checkouts/#{dep.slug}")
67
- # For convenience, synced group under `xccache.config` group in xcodeproj
68
- dep.path.symlink_to(Config.instance.spm_local_pkgs_dir / dep.slug)
69
- end
70
- end
71
-
72
- def create_symlinks_to_artifacts
73
- # Clean up symlinks beforehand
74
- config.spm_binaries_dir.glob("*/*.{xcframework,macro}").each do |p|
75
- p.rmtree if p.symlink?
76
- end
77
-
78
- binary_targets.each do |target|
79
- dst_path = config.spm_binaries_dir / target.name / "#{target.name}.xcframework"
80
- # For local xcframework, just symlink to the path
81
- # Zip frameworks (either of local or remote pkgs) are unzipped in the build artifacts
82
- target.local_binary_path.symlink_to(dst_path) if target.local_binary_path&.extname == ".xcframework"
83
- config.spm_artifacts_dir.glob("#{target.full_name}/*.xcframework").each do |p|
84
- p.symlink_to(dst_path)
85
- end
86
- end
87
- end
88
- end
89
- end
90
- end
91
- end