xccache 0.0.1a2 → 0.0.1a4
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/xccache/assets/templates/cachemap.html.template +1 -0
- data/lib/xccache/assets/templates/cachemap.js.template +35 -34
- data/lib/xccache/assets/templates/cachemap.style.css.template +3 -1
- data/lib/xccache/assets/templates/framework.modulemap.template +1 -1
- data/lib/xccache/assets/templates/resource_bundle_accessor.m.template +3 -3
- data/lib/xccache/assets/templates/umbrella.Package.swift.template +43 -7
- data/lib/xccache/cache/cachemap.rb +11 -15
- data/lib/xccache/command/base.rb +29 -0
- data/lib/xccache/command/build.rb +12 -6
- data/lib/xccache/command/pkg/build.rb +2 -6
- data/lib/xccache/command/pkg.rb +1 -0
- data/lib/xccache/command/remote/pull.rb +15 -0
- data/lib/xccache/command/remote/push.rb +15 -0
- data/lib/xccache/command/remote.rb +39 -0
- data/lib/xccache/command/rollback.rb +2 -1
- data/lib/xccache/command/use.rb +3 -2
- data/lib/xccache/command.rb +18 -2
- data/lib/xccache/core/config.rb +30 -2
- data/lib/xccache/core/git.rb +15 -3
- data/lib/xccache/core/log.rb +11 -1
- data/lib/xccache/core/parallel.rb +10 -0
- data/lib/xccache/core/sh.rb +4 -3
- data/lib/xccache/core/syntax/plist.rb +17 -0
- data/lib/xccache/core/system.rb +8 -0
- data/lib/xccache/installer/build.rb +2 -6
- data/lib/xccache/installer/rollback.rb +1 -0
- data/lib/xccache/installer/use.rb +3 -2
- data/lib/xccache/installer.rb +50 -4
- data/lib/xccache/spm/build.rb +53 -0
- data/lib/xccache/spm/desc/base.rb +10 -3
- data/lib/xccache/spm/desc/desc.rb +31 -15
- data/lib/xccache/spm/desc/target/binary.rb +8 -0
- data/lib/xccache/spm/desc/target/macro.rb +8 -0
- data/lib/xccache/spm/desc/target.rb +28 -2
- data/lib/xccache/spm/macro.rb +44 -0
- data/lib/xccache/spm/mixin.rb +4 -1
- data/lib/xccache/spm/pkg/base.rb +48 -44
- data/lib/xccache/spm/pkg/umbrella/build.rb +2 -2
- data/lib/xccache/spm/pkg/umbrella/cachemap.rb +44 -27
- data/lib/xccache/spm/pkg/umbrella/descs.rb +2 -13
- data/lib/xccache/spm/pkg/umbrella/manifest.rb +1 -1
- data/lib/xccache/spm/pkg/umbrella/viz.rb +3 -3
- data/lib/xccache/spm/pkg/umbrella/xcconfigs.rb +31 -0
- data/lib/xccache/spm/pkg/umbrella.rb +20 -10
- data/lib/xccache/spm/xcframework/metadata.rb +41 -0
- data/lib/xccache/{framework → spm/xcframework}/slice.rb +50 -53
- data/lib/xccache/spm/xcframework/xcframework.rb +56 -0
- data/lib/xccache/spm/xcframework.rb +2 -0
- data/lib/xccache/storage/base.rb +26 -0
- data/lib/xccache/storage/git.rb +48 -0
- data/lib/xccache/storage/s3.rb +53 -0
- data/lib/xccache/storage.rb +1 -0
- data/lib/xccache/swift/sdk.rb +21 -2
- data/lib/xccache/xcodeproj/build_configuration.rb +20 -0
- data/lib/xccache/xcodeproj/config.rb +9 -0
- data/lib/xccache/xcodeproj/file_system_synchronized_root_group.rb +17 -0
- data/lib/xccache/xcodeproj/group.rb +26 -0
- data/lib/xccache/xcodeproj/pkg.rb +5 -1
- data/lib/xccache/xcodeproj/project.rb +21 -1
- data/lib/xccache/xcodeproj/target.rb +5 -3
- metadata +40 -5
- data/lib/xccache/framework/xcframework.rb +0 -51
data/lib/xccache/core/git.rb
CHANGED
@@ -6,14 +6,26 @@ module XCCache
|
|
6
6
|
@root = Pathname(root)
|
7
7
|
end
|
8
8
|
|
9
|
+
def run(*args, **kwargs)
|
10
|
+
Sh.run("git -C #{root}", *args, **kwargs)
|
11
|
+
end
|
12
|
+
|
9
13
|
def sha
|
10
14
|
run("rev-parse --short HEAD", capture: true, log_cmd: false)[0].strip
|
11
15
|
end
|
12
16
|
|
13
|
-
|
17
|
+
def clean?
|
18
|
+
status("--porcelain", capture: true, log_cmd: false)[0].empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def init?
|
22
|
+
!root.glob(".git").empty?
|
23
|
+
end
|
14
24
|
|
15
|
-
|
16
|
-
|
25
|
+
%i[init checkout fetch pull push clean add commit branch remote switch status].each do |name|
|
26
|
+
define_method(name) do |*args, **kwargs|
|
27
|
+
run(name, *args, **kwargs)
|
28
|
+
end
|
17
29
|
end
|
18
30
|
end
|
19
31
|
end
|
data/lib/xccache/core/log.rb
CHANGED
@@ -9,11 +9,21 @@ module XCCache
|
|
9
9
|
include Config::Mixin
|
10
10
|
attr_accessor :indent
|
11
11
|
|
12
|
-
def section(title)
|
12
|
+
def section(title, timing: false)
|
13
|
+
start = Time.new if timing
|
13
14
|
UI.puts(title)
|
14
15
|
self.indent += 2
|
15
16
|
res = yield if block_given?
|
16
17
|
self.indent -= 2
|
18
|
+
if timing
|
19
|
+
duration = (Time.new - start).to_i
|
20
|
+
duration = if duration < 60 then "#{duration}s"
|
21
|
+
elsif duration < 60 * 60 then "#{duration / 60}m"
|
22
|
+
else
|
23
|
+
"#{duration / 3600}h"
|
24
|
+
end
|
25
|
+
UI.puts("-> Finished: #{title.dark} (#{duration})")
|
26
|
+
end
|
17
27
|
res
|
18
28
|
end
|
19
29
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "parallel"
|
2
|
+
|
3
|
+
class Array
|
4
|
+
def parallel_map(options = {})
|
5
|
+
# By default, use in_threads (IO-bound tasks)
|
6
|
+
default = {}
|
7
|
+
default[:in_threads] = Parallel.processor_count unless options.key?(:in_processes)
|
8
|
+
Parallel.map(self, { **default, **options }) { |x| yield x if block_given? }
|
9
|
+
end
|
10
|
+
end
|
data/lib/xccache/core/sh.rb
CHANGED
@@ -15,8 +15,8 @@ module XCCache
|
|
15
15
|
run(cmd, capture: true, log_cmd: false)[0].strip
|
16
16
|
end
|
17
17
|
|
18
|
-
def run(
|
19
|
-
cmd =
|
18
|
+
def run(*args, env: nil, **options)
|
19
|
+
cmd = args.join(" ")
|
20
20
|
UI.message("$ #{cmd}".cyan.dark) if config.verbose? && options[:log_cmd] != false
|
21
21
|
|
22
22
|
out, err = [], []
|
@@ -35,7 +35,8 @@ module XCCache
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
|
38
|
+
popen3_args = env ? [env, cmd] : [cmd]
|
39
|
+
Open3.popen3(*popen3_args) do |_stdin, stdout, stderr, wait_thr|
|
39
40
|
stdout_thread = Thread.new { stdout.each { |l| handle_out.call(l) } }
|
40
41
|
stderr_thread = Thread.new { stderr.each { |l| handle_err.call(l) } }
|
41
42
|
[stdout_thread, stderr_thread].each(&:join)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "cfpropertylist"
|
2
|
+
require_relative "hash"
|
3
|
+
|
4
|
+
module XCCache
|
5
|
+
class PlistRepresentable < HashRepresentable
|
6
|
+
def load
|
7
|
+
plist = CFPropertyList::List.new(file: path)
|
8
|
+
CFPropertyList.native_types(plist.value)
|
9
|
+
rescue StandardError
|
10
|
+
{}
|
11
|
+
end
|
12
|
+
|
13
|
+
def save(to: nil)
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/xccache/core/system.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "digest"
|
2
|
+
require "mkmf"
|
2
3
|
|
3
4
|
class String
|
4
5
|
def c99extidentifier
|
@@ -6,6 +7,12 @@ class String
|
|
6
7
|
end
|
7
8
|
end
|
8
9
|
|
10
|
+
class File
|
11
|
+
def self.which(bin)
|
12
|
+
find_executable0(bin)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
9
16
|
class Dir
|
10
17
|
def self.prepare(dir)
|
11
18
|
dir = Pathname(dir)
|
@@ -36,6 +43,7 @@ class Pathname
|
|
36
43
|
def copy(to: nil, to_dir: nil)
|
37
44
|
dst = to || (Pathname(to_dir) / basename)
|
38
45
|
dst.rmtree if dst.exist? || dst.symlink?
|
46
|
+
dst.parent.mkpath
|
39
47
|
FileUtils.copy_entry(self, dst)
|
40
48
|
dst
|
41
49
|
end
|
@@ -6,19 +6,15 @@ module XCCache
|
|
6
6
|
def initialize(options = {})
|
7
7
|
super
|
8
8
|
@targets = options[:targets]
|
9
|
-
@sdk = options[:sdk]
|
10
|
-
@recursive = options[:recursive]
|
11
9
|
end
|
12
10
|
|
13
11
|
def install!
|
14
12
|
perform_install do
|
15
13
|
umbrella_pkg.build(
|
16
14
|
targets: @targets,
|
17
|
-
|
18
|
-
out_dir: config.spm_binaries_frameworks_dir,
|
15
|
+
out_dir: config.spm_repo_dir,
|
19
16
|
checksum: true,
|
20
|
-
|
21
|
-
skip_resolve: @skip_resolving_dependencies,
|
17
|
+
**@build_options,
|
22
18
|
)
|
23
19
|
end
|
24
20
|
end
|
@@ -4,8 +4,8 @@ module XCCache
|
|
4
4
|
class Installer
|
5
5
|
class Use < Installer
|
6
6
|
def install!
|
7
|
-
|
8
|
-
|
7
|
+
update_projects do |project|
|
8
|
+
perform_install do
|
9
9
|
UI.section("Using cache for project #{project.display_name}".bold.green) do
|
10
10
|
replace_binaries_for_project(project)
|
11
11
|
end
|
@@ -21,6 +21,7 @@ module XCCache
|
|
21
21
|
target.add_xccache_product_dependency unless target.has_xccache_product_dependency?
|
22
22
|
target.remove_pkg_product_dependencies { |d| !d.pkg.xccache_pkg? }
|
23
23
|
end
|
24
|
+
project.remove_pkgs(&:non_xccache_pkg?) unless config.keep_pkgs_in_project?
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
data/lib/xccache/installer.rb
CHANGED
@@ -6,16 +6,28 @@ module XCCache
|
|
6
6
|
include PkgMixin
|
7
7
|
|
8
8
|
def initialize(options = {})
|
9
|
+
ctx = options[:ctx]
|
10
|
+
raise GeneralError, "Missing context (Command) for #{self.class}" if ctx.nil?
|
9
11
|
@umbrella_pkg = options[:umbrella_pkg]
|
10
|
-
@
|
12
|
+
@install_options = ctx.install_options
|
13
|
+
@build_options = ctx.build_options
|
11
14
|
end
|
12
15
|
|
13
16
|
def perform_install
|
17
|
+
config.in_installation = true
|
14
18
|
verify_projects!
|
15
|
-
|
16
|
-
|
19
|
+
if @umbrella_pkg.nil?
|
20
|
+
sync_lockfile
|
21
|
+
umbrella_pkg.prepare(**@install_options)
|
22
|
+
end
|
23
|
+
|
17
24
|
yield
|
18
25
|
umbrella_pkg.write_manifest
|
26
|
+
umbrella_pkg.gen_xcconfigs
|
27
|
+
projects.each do |project|
|
28
|
+
add_xccache_refs_to_project(project)
|
29
|
+
inject_xcconfig_to_project(project)
|
30
|
+
end
|
19
31
|
umbrella_pkg.gen_cachemap_viz
|
20
32
|
end
|
21
33
|
|
@@ -51,7 +63,7 @@ module XCCache
|
|
51
63
|
|
52
64
|
def lockfile_hash_for_project(project)
|
53
65
|
deps_by_targets = project.targets.to_h do |target|
|
54
|
-
deps = target.non_xccache_pkg_product_dependencies.map { |d| "#{d.pkg.slug}/#{d.product_name}" }
|
66
|
+
deps = target.non_xccache_pkg_product_dependencies.select(&:pkg).map { |d| "#{d.pkg.slug}/#{d.product_name}" }
|
55
67
|
[target.name, deps]
|
56
68
|
end
|
57
69
|
{
|
@@ -63,5 +75,39 @@ module XCCache
|
|
63
75
|
def verify_projects!
|
64
76
|
raise "No projects detected. Are you running on the correct project directory?" if projects.empty?
|
65
77
|
end
|
78
|
+
|
79
|
+
def add_xccache_refs_to_project(project)
|
80
|
+
group = project.xccache_config_group
|
81
|
+
add_file = proc { |p| group[p.basename.to_s] || group.new_file(p) }
|
82
|
+
add_file.call(config.spm_umbrella_sandbox / "Package.swift")
|
83
|
+
add_file.call(config.lockfile.path)
|
84
|
+
add_file.call(config.path) if config.path.exist?
|
85
|
+
group.ensure_synced_group(name: "local-packages", path: config.spm_local_pkgs_dir)
|
86
|
+
end
|
87
|
+
|
88
|
+
def inject_xcconfig_to_project(project)
|
89
|
+
group = project.xccache_config_group.ensure_synced_group(name: "xcconfigs", path: config.spm_xcconfig_dir)
|
90
|
+
project.targets.each do |target|
|
91
|
+
xcconfig_path = config.spm_xcconfig_dir / "#{target.name}.xcconfig"
|
92
|
+
target.build_configurations.each do |build_config|
|
93
|
+
if (existing = build_config.base_configuration_xcconfig)
|
94
|
+
next if existing.path == xcconfig_path
|
95
|
+
|
96
|
+
relative_path = xcconfig_path.relative_path_from(existing.path.parent)
|
97
|
+
next if existing.includes.include?(relative_path.to_s)
|
98
|
+
|
99
|
+
UI.info("Injecting base configuration for #{target} (#{build_config}) (at: #{existing.path})")
|
100
|
+
existing.path.write <<~DESC
|
101
|
+
#include "#{relative_path}" // Injected by xccache, for prebuilt macros support
|
102
|
+
#{existing.path.read.strip}
|
103
|
+
DESC
|
104
|
+
else
|
105
|
+
UI.info("Setting base configuration #{target} (#{build_config}) as #{xcconfig_path}")
|
106
|
+
build_config.base_configuration_reference_anchor = group
|
107
|
+
build_config.base_configuration_reference_relative_path = xcconfig_path.basename.to_s
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
66
112
|
end
|
67
113
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module XCCache
|
2
|
+
module SPM
|
3
|
+
class Buildable
|
4
|
+
attr_reader :name, :module_name, :pkg_dir, :pkg_desc, :sdk, :sdks, :config, :path, :tmpdir, :library_evolution
|
5
|
+
alias library_evolution? library_evolution
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@name = options[:name]
|
9
|
+
@module_name = @name.c99extidentifier
|
10
|
+
@pkg_dir = Pathname(options[:pkg_dir] || ".").expand_path
|
11
|
+
@pkg_desc = options[:pkg_desc]
|
12
|
+
@sdks = options[:sdks] || []
|
13
|
+
@sdk = options[:sdk] || @sdks&.first
|
14
|
+
@config = options[:config] || "debug"
|
15
|
+
@path = options[:path]
|
16
|
+
@tmpdir = options[:tmpdir]
|
17
|
+
@library_evolution = options[:library_evolution]
|
18
|
+
end
|
19
|
+
|
20
|
+
def build(options = {})
|
21
|
+
raise NotImplementedError
|
22
|
+
end
|
23
|
+
|
24
|
+
def swift_build(target: nil)
|
25
|
+
cmd = ["swift", "build"] + swift_build_args
|
26
|
+
cmd << "--package-path" << pkg_dir
|
27
|
+
cmd << "--target" << (target || name)
|
28
|
+
cmd << "--sdk" << sdk.sdk_path
|
29
|
+
sdk.swiftc_args.each { |arg| cmd << "-Xswiftc" << arg }
|
30
|
+
if library_evolution?
|
31
|
+
# Workaround for swiftinterface emission
|
32
|
+
# https://github.com/swiftlang/swift/issues/64669#issuecomment-1535335601
|
33
|
+
cmd << "-Xswiftc" << "-enable-library-evolution"
|
34
|
+
cmd << "-Xswiftc" << "-alias-module-names-in-module-interface"
|
35
|
+
cmd << "-Xswiftc" << "-emit-module-interface"
|
36
|
+
cmd << "-Xswiftc" << "-no-verify-emitted-module-interface"
|
37
|
+
end
|
38
|
+
Sh.run(cmd, suppress_err: /(dependency '.*' is not used by any target|unable to create symbolic link)/)
|
39
|
+
end
|
40
|
+
|
41
|
+
def swift_build_args
|
42
|
+
[
|
43
|
+
"--configuration", config,
|
44
|
+
"--triple", sdk.triple,
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
def pkg_target
|
49
|
+
@pkg_target ||= pkg_desc.get_target(name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -6,7 +6,8 @@ module XCCache
|
|
6
6
|
class BaseObject < JSONRepresentable
|
7
7
|
include Config::Mixin
|
8
8
|
|
9
|
-
|
9
|
+
ATTRS = %i[root retrieve_pkg_desc].freeze
|
10
|
+
attr_accessor(*ATTRS)
|
10
11
|
|
11
12
|
def name
|
12
13
|
raw["name"]
|
@@ -28,12 +29,18 @@ module XCCache
|
|
28
29
|
"<#{self.class} name=#{display_name}>"
|
29
30
|
end
|
30
31
|
|
32
|
+
def cast_to(cls)
|
33
|
+
o = cls.new(path, raw: raw)
|
34
|
+
ATTRS.each { |sym| o.send("#{sym}=", send(sym.to_s)) }
|
35
|
+
o
|
36
|
+
end
|
37
|
+
|
31
38
|
def pkg_name
|
32
39
|
@pkg_name ||= root.name
|
33
40
|
end
|
34
41
|
|
35
42
|
def pkg_slug
|
36
|
-
@pkg_slug ||=
|
43
|
+
@pkg_slug ||= src_dir.basename.to_s
|
37
44
|
end
|
38
45
|
|
39
46
|
def fetch(key, dtype)
|
@@ -51,7 +58,7 @@ module XCCache
|
|
51
58
|
|
52
59
|
def src_dir
|
53
60
|
@src_dir ||= begin
|
54
|
-
path = raw.fetch("packageKind", {}).fetch("root", [])[0]
|
61
|
+
path = root.raw.fetch("packageKind", {}).fetch("root", [])[0]
|
55
62
|
Pathname.new(path) unless path.nil?
|
56
63
|
end
|
57
64
|
end
|
@@ -7,18 +7,34 @@ module XCCache
|
|
7
7
|
include Cacheable
|
8
8
|
cacheable :resolve_recursive_dependencies
|
9
9
|
|
10
|
-
def self.
|
10
|
+
def self.descs_in_metadata_dir
|
11
|
+
descs = Config.instance.spm_metadata_dir.glob("*.json").map { |p| Description.new(p) }
|
12
|
+
[descs, combine_descs(descs)]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.in_dir(dir, save_to_dir: nil)
|
11
16
|
path = save_to_dir / "#{dir.basename}.json" unless save_to_dir.nil?
|
12
17
|
begin
|
13
18
|
raw = JSON.parse(Sh.capture_output("swift package dump-package --package-path #{dir}"))
|
14
|
-
|
15
|
-
this.calc_checksum if checksum
|
16
|
-
this
|
19
|
+
Description.new(path, raw: raw)
|
17
20
|
rescue StandardError => e
|
18
21
|
UI.error("Failed to dump package in #{dir}. Error: #{e}")
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
25
|
+
def self.descs_in_dir(root_dir, save_to_dir: nil)
|
26
|
+
dirs = [root_dir] + root_dir.glob(".build/checkouts/*").reject { |p| p.glob("Package*.swift").empty? }
|
27
|
+
descs = dirs.parallel_map do |dir|
|
28
|
+
desc = Description.in_dir(dir, save_to_dir: save_to_dir)
|
29
|
+
unless save_to_dir.nil?
|
30
|
+
desc.save
|
31
|
+
desc.save(to: desc.path.parent / "#{desc.name}.json") if desc.name != dir.basename.to_s
|
32
|
+
end
|
33
|
+
desc
|
34
|
+
end
|
35
|
+
[descs, combine_descs(descs)]
|
36
|
+
end
|
37
|
+
|
22
38
|
def root
|
23
39
|
self
|
24
40
|
end
|
@@ -27,10 +43,6 @@ module XCCache
|
|
27
43
|
raw["_metadata"] ||= {}
|
28
44
|
end
|
29
45
|
|
30
|
-
def checksum
|
31
|
-
metadata["checksum"]
|
32
|
-
end
|
33
|
-
|
34
46
|
def dependencies
|
35
47
|
@dependencies ||= fetch("dependencies", Dependency)
|
36
48
|
end
|
@@ -44,7 +56,7 @@ module XCCache
|
|
44
56
|
end
|
45
57
|
|
46
58
|
def targets
|
47
|
-
@targets ||= fetch("targets", Target)
|
59
|
+
@targets ||= fetch("targets", Target).map(&:downcast)
|
48
60
|
end
|
49
61
|
|
50
62
|
def binary_targets
|
@@ -74,10 +86,6 @@ module XCCache
|
|
74
86
|
!src_dir.to_s.start_with?((config.spm_build_dir / "checkouts").to_s)
|
75
87
|
end
|
76
88
|
|
77
|
-
def calc_checksum
|
78
|
-
metadata["checksum"] = git.nil? ? src_dir.checksum : git.sha
|
79
|
-
end
|
80
|
-
|
81
89
|
def traverse
|
82
90
|
nodes, edges, parents = [], [], {}
|
83
91
|
to_visit = targets.dup
|
@@ -89,6 +97,10 @@ module XCCache
|
|
89
97
|
visited << cur
|
90
98
|
nodes << cur
|
91
99
|
yield cur if block_given?
|
100
|
+
|
101
|
+
# For macro impl, we don't need their dependencies, just the tool binary
|
102
|
+
# So, no need to care about swift-syntax dependencies
|
103
|
+
next if cur.macro?
|
92
104
|
cur.direct_dependency_targets.each do |t|
|
93
105
|
to_visit << t
|
94
106
|
edges << [cur, t]
|
@@ -99,11 +111,15 @@ module XCCache
|
|
99
111
|
[nodes, edges, parents]
|
100
112
|
end
|
101
113
|
|
102
|
-
private
|
103
|
-
|
104
114
|
def git
|
105
115
|
@git ||= Git.new(src_dir) if Dir.git?(src_dir)
|
106
116
|
end
|
117
|
+
|
118
|
+
def self.combine_descs(descs)
|
119
|
+
descs_by_name = descs.flat_map { |d| [[d.name, d], [d.pkg_slug, d]] }.to_h
|
120
|
+
descs.each { |d| d.retrieve_pkg_desc = proc { |name| descs_by_name[name] } }
|
121
|
+
descs_by_name
|
122
|
+
end
|
107
123
|
end
|
108
124
|
end
|
109
125
|
end
|
@@ -7,15 +7,33 @@ module XCCache
|
|
7
7
|
include Cacheable
|
8
8
|
cacheable :recursive_targets, :direct_dependency_targets, :direct_dependencies
|
9
9
|
|
10
|
+
Dir["#{__dir__}/#{File.basename(__FILE__, '.rb')}/*.rb"].sort.each { |f| require f }
|
11
|
+
|
10
12
|
def xccache?
|
11
13
|
name.end_with?(".xccache")
|
12
14
|
end
|
13
15
|
|
16
|
+
def xccache_id
|
17
|
+
macro? ? "#{full_name}.macro" : full_name
|
18
|
+
end
|
19
|
+
|
14
20
|
def type
|
15
21
|
@type ||= raw["type"].to_sym
|
16
22
|
end
|
17
23
|
|
18
|
-
def
|
24
|
+
def downcast
|
25
|
+
cls = {
|
26
|
+
:binary => BinaryTarget,
|
27
|
+
:macro => MacroTarget,
|
28
|
+
}[type]
|
29
|
+
cls.nil? ? self : cast_to(cls)
|
30
|
+
end
|
31
|
+
|
32
|
+
def module_name
|
33
|
+
name.c99extidentifier
|
34
|
+
end
|
35
|
+
|
36
|
+
def resource_bundle_name
|
19
37
|
"#{pkg_name}_#{name}.bundle"
|
20
38
|
end
|
21
39
|
|
@@ -78,7 +96,7 @@ module XCCache
|
|
78
96
|
|
79
97
|
def recursive_targets(platform: nil)
|
80
98
|
children = direct_dependency_targets(platform: platform)
|
81
|
-
children += children.flat_map { |t| t.recursive_targets(platform: platform) }
|
99
|
+
children += children.flat_map { |t| t.macro? ? [t] : t.recursive_targets(platform: platform) }
|
82
100
|
children.uniq
|
83
101
|
end
|
84
102
|
|
@@ -102,6 +120,10 @@ module XCCache
|
|
102
120
|
true # FIXME: Handle this
|
103
121
|
end
|
104
122
|
|
123
|
+
def macro?
|
124
|
+
type == :macro
|
125
|
+
end
|
126
|
+
|
105
127
|
def binary?
|
106
128
|
type == :binary
|
107
129
|
end
|
@@ -114,6 +136,10 @@ module XCCache
|
|
114
136
|
binary_path if binary? && root.local?
|
115
137
|
end
|
116
138
|
|
139
|
+
def checksum
|
140
|
+
@checksum ||= root.git&.sha || sources_path.checksum
|
141
|
+
end
|
142
|
+
|
117
143
|
private
|
118
144
|
|
119
145
|
def find_deps(name, pkg_name, dep_type)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative "build"
|
2
|
+
|
3
|
+
module XCCache
|
4
|
+
module SPM
|
5
|
+
class Macro < Buildable
|
6
|
+
attr_reader :macosx_sdk
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
super
|
10
|
+
@library_evolution = false # swift-syntax is not compatible with library evolution
|
11
|
+
@macosx_sdk = Swift::Sdk.new(:macosx)
|
12
|
+
end
|
13
|
+
|
14
|
+
def build(_options = {})
|
15
|
+
# NOTE: Building macro binary is tricky...
|
16
|
+
# --------------------------------------------------------------------------------
|
17
|
+
# Consider this manifest config: .target(Macro) -> .macro(MacroImpl)
|
18
|
+
# where `.target(Macro)` contains the interfaces
|
19
|
+
# and `.target(MacroImpl)` contains the implementation
|
20
|
+
# --------------------------------------------------------------------------------
|
21
|
+
# Building `.macro(MacroImpl)` does not produce the tool binary (MacroImpl-tool)... Only `.o` files.
|
22
|
+
# Yet, linking those files are exhaustive due to many dependencies in swift-syntax
|
23
|
+
# Luckily, building `.target(Macro)` does produce the tool binary.
|
24
|
+
# -> WORKAROUND: Find the associated regular target and build it, then collect the tool binary
|
25
|
+
# ---------------------------------------------------------------------------------
|
26
|
+
associated_target = pkg_desc.targets.find { |t| t.direct_dependency_targets.include?(pkg_target) }
|
27
|
+
UI.message(
|
28
|
+
"#{name.yellow.dark} is a macro target. " \
|
29
|
+
"Will build the associated target #{associated_target.name.dark} to get the tool binary."
|
30
|
+
)
|
31
|
+
swift_build(target: associated_target.name)
|
32
|
+
binary_path = products_dir / "#{module_name}-tool"
|
33
|
+
raise GeneralError, "Tool binary not exist at: #{binary_path}" unless binary_path.exist?
|
34
|
+
binary_path.copy(to: path)
|
35
|
+
FileUtils.chmod("+x", path)
|
36
|
+
UI.info("-> Macro binary: #{path.to_s.dark}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def products_dir
|
40
|
+
@products_dir ||= pkg_dir / ".build" / macosx_sdk.triple / config
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/xccache/spm/mixin.rb
CHANGED
@@ -3,7 +3,10 @@ module XCCache
|
|
3
3
|
include Config::Mixin
|
4
4
|
|
5
5
|
def umbrella_pkg
|
6
|
-
@umbrella_pkg ||= SPM::Package::Umbrella.new(
|
6
|
+
@umbrella_pkg ||= SPM::Package::Umbrella.new(
|
7
|
+
root_dir: config.spm_umbrella_sandbox,
|
8
|
+
warn_if_not_direct_target: false,
|
9
|
+
)
|
7
10
|
end
|
8
11
|
end
|
9
12
|
end
|