cocoapods-mapfile 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -1
- data/lib/cocoapods-hmap/executable.rb +230 -0
- data/lib/cocoapods-hmap/framework/framework_vfs.rb +95 -0
- data/lib/cocoapods-hmap/helper/build_setting_helper.rb +40 -0
- data/lib/cocoapods-hmap/helper/pods_helper.rb +104 -0
- data/lib/cocoapods-hmap/helper/xcconfig_helper.rb +82 -0
- data/lib/cocoapods-hmap/hmap_reader.rb +16 -0
- data/lib/cocoapods-hmap/hmap_save.rb +46 -0
- data/lib/cocoapods-hmap/hmap_struct.rb +2 -55
- data/lib/cocoapods-hmap/hmap_writer.rb +62 -100
- data/lib/cocoapods-hmap/pods_specification.rb +60 -0
- data/lib/cocoapods-hmap/utils.rb +24 -66
- data/lib/cocoapods-hmap/version.rb +1 -1
- data/lib/cocoapods-hmap/view.rb +1 -0
- data/lib/cocoapods_hmap.rb +7 -1
- data/lib/cocoapods_plugin.rb +1 -1
- metadata +24 -4
- data/lib/cocoapods-hmap/pods_helper.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e843368c99922210970ea7de9ab8d2bcc895a158901d054a1cd076d29d73310
|
4
|
+
data.tar.gz: 8f7430064b4472cb4fd6c9fa42dfdd7a144d314c702ab7500a42b0ff302d9ab5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1b0fbf54c2976dd6f7fcba6eca0d1d421a1df6360216e2049643d6ec1133592f19ce49786f58d0c100d71ce923492cf0135be75cbffbaae6e5a40f8b2a1c749
|
7
|
+
data.tar.gz: 9429682a00e5c633baf19f845f691b7fd64b6fa687af9afcb776b5beb86245338e5d1b2d910482809f66d91f660fb02e69c6ce1d3026922f1c6cf447e4345d0d
|
data/README.md
CHANGED
@@ -7,6 +7,11 @@ A CocoaPods plugin which can gen/read header map file.
|
|
7
7
|
**hmap-gen** is able to scan the header files of the target referenced components in the specified Cocoapods project, and generates a header map file that public to all the components
|
8
8
|
as well as generates a public and private header map file for each referenced component.
|
9
9
|
|
10
|
+
- `<header.h>` : -I<hmap file path>
|
11
|
+
- `header.h` : iquote <hmap file path>
|
12
|
+
|
13
|
+
For framework, use [yaml-vfs](https://github.com/Cat1237/yaml-vfs) create VFS file to map framework Headers and Modules dir and pass VFS file to `-ivfsoverlay` parameter.
|
14
|
+
|
10
15
|
A hmap file includes four types of headers:
|
11
16
|
|
12
17
|
- header.h
|
@@ -70,7 +75,7 @@ plugin 'cocoapods-mapfile'
|
|
70
75
|
```
|
71
76
|
This was equl:
|
72
77
|
```rb
|
73
|
-
pod hmap-gen --project-directory=/project/dir/
|
78
|
+
pod hmap-gen --project-directory=/project/dir/
|
74
79
|
```
|
75
80
|
|
76
81
|
Every time you execute pod install or pod update, `cocoapods-mapfile` will automatically generate a `header map file` for you and modify `HEAD_SEARCH_PATHS`.
|
@@ -0,0 +1,230 @@
|
|
1
|
+
module HMap
|
2
|
+
module Executable
|
3
|
+
# Creates the methods for the executable with the given name.
|
4
|
+
#
|
5
|
+
# @param [Symbol] name
|
6
|
+
# the name of the executable.
|
7
|
+
#
|
8
|
+
# @return [void]
|
9
|
+
#
|
10
|
+
def executable(name)
|
11
|
+
define_method(name) do |*command|
|
12
|
+
Executable.execute_command(name, Array(command).flatten, false)
|
13
|
+
end
|
14
|
+
|
15
|
+
define_method(name.to_s + '!') do |*command|
|
16
|
+
Executable.execute_command(name, Array(command).flatten, true)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Executes the given command displaying it if in verbose mode.
|
21
|
+
#
|
22
|
+
# @param [String] executable
|
23
|
+
# The binary to use.
|
24
|
+
#
|
25
|
+
# @param [Array<#to_s>] command
|
26
|
+
# The command to send to the binary.
|
27
|
+
#
|
28
|
+
# @param [Bool] raise_on_failure
|
29
|
+
# Whether it should raise if the command fails.
|
30
|
+
#
|
31
|
+
# @raise If the executable could not be located.
|
32
|
+
#
|
33
|
+
# @raise If the command fails and the `raise_on_failure` is set to true.
|
34
|
+
#
|
35
|
+
# @return [String] the output of the command (STDOUT and STDERR).
|
36
|
+
#
|
37
|
+
def self.execute_command(executable, command, raise_on_failure = true)
|
38
|
+
bin = which!(executable)
|
39
|
+
|
40
|
+
command = command.map(&:to_s)
|
41
|
+
if File.basename(bin) == 'tar.exe'
|
42
|
+
# Tar on Windows needs --force-local
|
43
|
+
command.push('--force-local')
|
44
|
+
end
|
45
|
+
full_command = "#{bin} #{command.join(' ')}"
|
46
|
+
|
47
|
+
if Pod::Config.instance.verbose?
|
48
|
+
p("$ #{full_command}")
|
49
|
+
stdout = Indenter.new(STDOUT)
|
50
|
+
stderr = Indenter.new(STDERR)
|
51
|
+
else
|
52
|
+
stdout = Indenter.new
|
53
|
+
stderr = Indenter.new
|
54
|
+
end
|
55
|
+
|
56
|
+
status = popen3(bin, command, stdout, stderr)
|
57
|
+
stdout = stdout.join
|
58
|
+
stderr = stderr.join
|
59
|
+
output = stdout + stderr
|
60
|
+
unless status.success?
|
61
|
+
if raise_on_failure
|
62
|
+
raise Informative, "#{full_command}\n\n#{output}"
|
63
|
+
else
|
64
|
+
p("[!] Failed: #{full_command}".red)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
stdout
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the absolute path to the binary with the given name on the current
|
72
|
+
# `PATH`, or `nil` if none is found.
|
73
|
+
#
|
74
|
+
# @param [String] program
|
75
|
+
# The name of the program being searched for.
|
76
|
+
#
|
77
|
+
# @return [String,Nil] The absolute path to the given program, or `nil` if
|
78
|
+
# it wasn't found in the current `PATH`.
|
79
|
+
#
|
80
|
+
def self.which(program)
|
81
|
+
program = program.to_s
|
82
|
+
paths = ENV.fetch('PATH') { '' }.split(File::PATH_SEPARATOR)
|
83
|
+
paths.unshift('./')
|
84
|
+
paths.uniq!
|
85
|
+
paths.each do |path|
|
86
|
+
bin = File.expand_path(program, path)
|
87
|
+
bin += '.exe' if Gem.win_platform?
|
88
|
+
return bin if File.file?(bin) && File.executable?(bin)
|
89
|
+
end
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the absolute path to the binary with the given name on the current
|
94
|
+
# `PATH`, or raises if none is found.
|
95
|
+
#
|
96
|
+
# @param [String] program
|
97
|
+
# The name of the program being searched for.
|
98
|
+
#
|
99
|
+
# @return [String] The absolute path to the given program.
|
100
|
+
#
|
101
|
+
def self.which!(program)
|
102
|
+
which(program).tap do |bin|
|
103
|
+
raise Informative, "Unable to locate the executable `#{program}`" unless bin
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Runs the given command, capturing the desired output.
|
108
|
+
#
|
109
|
+
# @param [String] executable
|
110
|
+
# The binary to use.
|
111
|
+
#
|
112
|
+
# @param [Array<#to_s>] command
|
113
|
+
# The command to send to the binary.
|
114
|
+
#
|
115
|
+
# @param [Symbol] capture
|
116
|
+
# Whether it should raise if the command fails.
|
117
|
+
#
|
118
|
+
# @param [Hash] env
|
119
|
+
# Environment variables to be set for the command.
|
120
|
+
#
|
121
|
+
# @raise If the executable could not be located.
|
122
|
+
#
|
123
|
+
# @return [(String, Process::Status)]
|
124
|
+
# The desired captured output from the command, and the status from
|
125
|
+
# running the command.
|
126
|
+
#
|
127
|
+
def self.capture_command(executable, command, capture: :merge, env: {}, **kwargs)
|
128
|
+
bin = which!(executable)
|
129
|
+
|
130
|
+
require 'open3'
|
131
|
+
command = command.map(&:to_s)
|
132
|
+
case capture
|
133
|
+
when :merge then Open3.capture2e(env, [bin, bin], *command, **kwargs)
|
134
|
+
when :both then Open3.capture3(env, [bin, bin], *command, **kwargs)
|
135
|
+
when :out then Open3.capture3(env, [bin, bin], *command, **kwargs).values_at(0, -1)
|
136
|
+
when :err then Open3.capture3(env, [bin, bin], *command, **kwargs).drop(1)
|
137
|
+
when :none then Open3.capture3(env, [bin, bin], *command, **kwargs).last
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# (see Executable.capture_command)
|
142
|
+
#
|
143
|
+
# @raise If running the command fails
|
144
|
+
#
|
145
|
+
def self.capture_command!(executable, command, **kwargs)
|
146
|
+
capture_command(executable, command, **kwargs).tap do |result|
|
147
|
+
result = Array(result)
|
148
|
+
status = result.last
|
149
|
+
unless status.success?
|
150
|
+
output = result[0..-2].join
|
151
|
+
raise Informative, "#{executable} #{command.join(' ')}\n\n#{output}".strip
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.popen3(bin, command, stdout, stderr)
|
157
|
+
require 'open3'
|
158
|
+
Open3.popen3(bin, *command) do |i, o, e, t|
|
159
|
+
reader(o, stdout)
|
160
|
+
reader(e, stderr)
|
161
|
+
i.close
|
162
|
+
|
163
|
+
status = t.value
|
164
|
+
|
165
|
+
o.flush
|
166
|
+
e.flush
|
167
|
+
sleep(0.01)
|
168
|
+
|
169
|
+
status
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.reader(input, output)
|
174
|
+
Thread.new do
|
175
|
+
buf = ''
|
176
|
+
begin
|
177
|
+
loop do
|
178
|
+
buf << input.readpartial(4096)
|
179
|
+
loop do
|
180
|
+
string, separator, buf = buf.partition(/[\r\n]/)
|
181
|
+
if separator.empty?
|
182
|
+
buf = string
|
183
|
+
break
|
184
|
+
end
|
185
|
+
output << (string << separator)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
rescue EOFError, IOError
|
189
|
+
output << (buf << $/) unless buf.empty?
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
#-------------------------------------------------------------------------#
|
195
|
+
|
196
|
+
# Helper class that allows to write to an {IO} instance taking into account
|
197
|
+
# the UI indentation level.
|
198
|
+
#
|
199
|
+
class Indenter < ::Array
|
200
|
+
# @return [Fixnum] The indentation level of the UI.
|
201
|
+
#
|
202
|
+
attr_reader :indent
|
203
|
+
|
204
|
+
# @return [IO] the {IO} to which the output should be printed.
|
205
|
+
#
|
206
|
+
attr_reader :io
|
207
|
+
|
208
|
+
# Init a new Indenter
|
209
|
+
#
|
210
|
+
# @param [IO] io @see io
|
211
|
+
#
|
212
|
+
def initialize(io = nil)
|
213
|
+
@io = io
|
214
|
+
@indent = ' ' * 1
|
215
|
+
end
|
216
|
+
|
217
|
+
# Stores a portion of the output and prints it to the {IO} instance.
|
218
|
+
#
|
219
|
+
# @param [String] value
|
220
|
+
# the output to print.
|
221
|
+
#
|
222
|
+
# @return [void]
|
223
|
+
#
|
224
|
+
def <<(value)
|
225
|
+
super
|
226
|
+
io << "#{indent}#{value}" if io
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module HMap
|
2
|
+
module Target
|
3
|
+
class FrameworkEntry
|
4
|
+
attr_reader :configuration, :platform, :app_build_dir, :project_temp_dir
|
5
|
+
attr_accessor :headers_real_paths, :modules_real_paths
|
6
|
+
|
7
|
+
def initialize(configuration, platform, app_build_dir, project_temp_dir)
|
8
|
+
@configuration = configuration
|
9
|
+
@platform = platform
|
10
|
+
@app_build_dir = app_build_dir
|
11
|
+
@project_temp_dir = project_temp_dir
|
12
|
+
@headers_real_paths = []
|
13
|
+
@modules_real_paths = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def framework_moduler_path
|
17
|
+
File.join(app_build_dir, 'Modules')
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.new_from_configuration_platform(configuration, platform, name, framework_name)
|
21
|
+
dir = "#{configuration}-#{platform}"
|
22
|
+
app_build_dir = File.join(PodsSpecification.instance.app_build_dir, dir, name,
|
23
|
+
"#{framework_name}.framework")
|
24
|
+
project_temp_dir = File.join(PodsSpecification.instance.project_temp_dir, dir, "#{name}.build")
|
25
|
+
new(configuration, platform, app_build_dir, project_temp_dir)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.new_entrys_from_configurations_platforms(configurations, platforms, name, framework_name, module_path, headers)
|
29
|
+
effective_platforms = Utils.effective_platforms_names(platforms)
|
30
|
+
configurations.flat_map do |configuration|
|
31
|
+
effective_platforms.map do |platform|
|
32
|
+
entry = new_from_configuration_platform(configuration, platform, name, framework_name)
|
33
|
+
entry.add_headers_modules(module_path, framework_name, headers)
|
34
|
+
entry
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_headers_modules(module_path, framework_name, headers)
|
40
|
+
has_private_module = module_path.glob('module*.modulemap').length > 1
|
41
|
+
e_headers = ->(path, *names) { names.inject(Pathname(path)) { |e, n| e.join(n) } }
|
42
|
+
@headers_real_paths += headers
|
43
|
+
@headers_real_paths << e_headers.call(app_build_dir, 'Headers',
|
44
|
+
"#{framework_name}-Swift.h")
|
45
|
+
@modules_real_paths << e_headers.call(project_temp_dir, 'module.modulemap')
|
46
|
+
if has_private_module
|
47
|
+
@modules_real_paths << e_headers.call(entry.project_temp_dir,
|
48
|
+
'module.private.modulemap')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class FrameworkVFS
|
54
|
+
attr_reader :entrys
|
55
|
+
|
56
|
+
def initialize(entrys = [])
|
57
|
+
@entrys = entrys
|
58
|
+
end
|
59
|
+
|
60
|
+
def vfs_path
|
61
|
+
return {} if entrys.empty?
|
62
|
+
|
63
|
+
entrys.each_with_object({}) do |entry, paths|
|
64
|
+
c = "#{entry.configuration}-#{entry.platform}"
|
65
|
+
paths[c] ||= []
|
66
|
+
paths[c] << entry
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def vfs_path_by_platform_and_configuration(platform, config)
|
71
|
+
return vfs_path if platform.nil? && config.nil?
|
72
|
+
|
73
|
+
key = platform if config.nil?
|
74
|
+
key = config if platform.nil?
|
75
|
+
vfs_path.select { |k, _| k.include?(key) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def write(path = nil)
|
79
|
+
vfs_path.each do |key, values|
|
80
|
+
es = values.map do |value|
|
81
|
+
headers_real_paths = value.headers_real_paths
|
82
|
+
modules_real_paths = value.modules_real_paths
|
83
|
+
VFS::FileCollectorEntry.new(Pathname(value.app_build_dir), modules_real_paths, headers_real_paths)
|
84
|
+
end
|
85
|
+
fc = VFS::FileCollector.new(es)
|
86
|
+
pa = Helper::Pods.vfs_files_dir.join(key)
|
87
|
+
pa = File.join(path, key) unless path.nil?
|
88
|
+
pa = Pathname(pa)
|
89
|
+
pa.mkpath unless pa.exist?
|
90
|
+
fc.write_mapping(pa)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module HMap
|
2
|
+
# A collection of build setting functions used throughout cocoapods-hmap.
|
3
|
+
module BuildSettingHelper
|
4
|
+
def self.clean_hmap(clean_hmap, *targets)
|
5
|
+
return clean_hmap unless clean_hmap
|
6
|
+
|
7
|
+
FileUtils.rm_rf(Helper::Pods.hmap_files_dir)
|
8
|
+
targets.each { |target| clean_other_c_flags_build_setting(target) }
|
9
|
+
clean_hmap
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.target_xcconfig_path(targets)
|
13
|
+
targets.each do |target|
|
14
|
+
raise ClassIncludedError.new(target.class, Pod::Target) unless target.is_a?(Pod::Target)
|
15
|
+
|
16
|
+
config_h = Pod::Target.instance_method(:build_settings).bind(target).call
|
17
|
+
config_h.each_key do |configuration_name|
|
18
|
+
xcconfig = target.xcconfig_path(configuration_name)
|
19
|
+
yield(xcconfig, target) if block_given?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.clean_other_c_flags_build_setting(targets)
|
25
|
+
target_xcconfig_path(targets) do |xc, _|
|
26
|
+
c = HMap::XcodeprojHelper.new(xc)
|
27
|
+
c.clean_hmap_xcconfig_other_c_flags_and_save
|
28
|
+
puts "\t -xcconfig path: #{xc} clean finish."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.change_other_c_flags_xcconfig_build_settings(hmap_h, targets, use_headermap: false, save_origin: true)
|
33
|
+
target_xcconfig_path(targets) do |xc, target|
|
34
|
+
c = HMap::XcodeprojHelper.new(xc)
|
35
|
+
c.change_xcconfig_other_c_flags_and_save(hmap_h, target.build_as_framework?, use_headermap: use_headermap,
|
36
|
+
save_origin: save_origin)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml_vfs'
|
4
|
+
require 'cocoapods'
|
5
|
+
|
6
|
+
module HMap
|
7
|
+
# A collection of Helper functions used throughout cocoapods-hmap.
|
8
|
+
module Helper
|
9
|
+
# A collection of Pods Helper functions used throughout cocoapods-hmap.
|
10
|
+
module Pods
|
11
|
+
|
12
|
+
def self.hmap_files_dir
|
13
|
+
Pathname(File.join(Pod::Config.instance.sandbox.headers_root, HMAP_DIR))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.vfs_files_dir
|
17
|
+
hmap_files_dir.join('vfs')
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.hmap_files_paths(name)
|
21
|
+
[hmap_files_dir.join("#{name}.hmap"), hmap_files_dir.join("#{name}-iquote.hmap")]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.pods_hmap_files_dir
|
25
|
+
"${PODS_ROOT}/Headers/#{HMAP_DIR}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.write_vfs_yaml(targets)
|
29
|
+
es = targets.flat_map do |target|
|
30
|
+
if target.build_as_framework?
|
31
|
+
spec_path = target.specs.map(&:defined_in_file).uniq.first
|
32
|
+
platforms = target_support_platforms(spec_path)
|
33
|
+
headers = headers_mappings_by_file_accessor(target)
|
34
|
+
headers << target.umbrella_header_path
|
35
|
+
Target::FrameworkEntry.new_entrys_from_configurations_platforms(target.user_build_configurations.keys, platforms, target.name, target.product_module_name, target.support_files_dir, headers)
|
36
|
+
end
|
37
|
+
end.compact
|
38
|
+
Target::FrameworkVFS.new(es).write
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.target_support_platforms(spec_path)
|
42
|
+
validator = Pod::Validator.new(spec_path, Pod::Config.instance.sources_manager.master.map(&:url))
|
43
|
+
validator.platforms_to_lint(validator.spec).map(&:name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.headers_mappings_by_file_accessor(target, type = :source_files)
|
47
|
+
valid_accessors = target.file_accessors.reject { |fa| fa.spec.non_library_specification? }
|
48
|
+
valid_accessors.each_with_object([]) do |file_accessor, sum|
|
49
|
+
sum << case type
|
50
|
+
when :private_header_files then file_accessor.headers - file_accessor.public_headers
|
51
|
+
when :source_files then file_accessor.headers
|
52
|
+
when :public_header_files then file_accessor.public_headers
|
53
|
+
end
|
54
|
+
end.flatten
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.header_mappings(target, type = :source_files)
|
58
|
+
mappings = {}
|
59
|
+
h_headers = lambda { |headers, h_type|
|
60
|
+
root = Pod::Config.instance.sandbox.root.join(target.headers_sandbox)
|
61
|
+
case h_type
|
62
|
+
when :private_header_files
|
63
|
+
headers << target.prefix_header_path if target.build_as_framework?
|
64
|
+
headers.each do |header|
|
65
|
+
mappings[HEAD_SEARCH_IQUOTE] ||= []
|
66
|
+
mappings[HEAD_SEARCH_IQUOTE] << [header.basename.to_s, "#{header.dirname}/", header.basename.to_s]
|
67
|
+
r_header_path = header.relative_path_from(root)
|
68
|
+
mappings[HEAD_SEARCH_IQUOTE] << [r_header_path.to_s, "#{header.dirname}/", header.basename.to_s]
|
69
|
+
end
|
70
|
+
when :public_header_files
|
71
|
+
headers << target.umbrella_header_path if target.build_as_framework?
|
72
|
+
headers.each do |header|
|
73
|
+
mappings[HEAD_SEARCH_IQUOTE] ||= []
|
74
|
+
mappings[HEAD_SEARCH_IQUOTE] << [header.basename.to_s, "#{target.product_module_name}/",
|
75
|
+
header.basename.to_s]
|
76
|
+
r_header_path = header.relative_path_from(root)
|
77
|
+
mappings[HEAD_SEARCH_IQUOTE] << [r_header_path.to_s, "#{header.dirname}/", header.basename.to_s]
|
78
|
+
mappings[HEAD_SEARCH_I] ||= []
|
79
|
+
mappings[HEAD_SEARCH_I] << [r_header_path.to_s, "#{header.dirname}/", header.basename.to_s]
|
80
|
+
mappings[HEAD_SEARCH_I] << [header.basename.to_s, "#{target.product_module_name}/",
|
81
|
+
header.basename.to_s]
|
82
|
+
|
83
|
+
mappings[HEAD_SEARCH_I] << ["#{target.product_module_name}/#{header.basename}", "#{header.dirname}/",
|
84
|
+
header.basename.to_s]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
}
|
88
|
+
|
89
|
+
valid_accessors = target.file_accessors.reject { |fa| fa.spec.non_library_specification? }
|
90
|
+
valid_accessors.each do |file_accessor|
|
91
|
+
case type
|
92
|
+
when :private_header_files then h_headers.call(file_accessor.headers - file_accessor.public_headers,
|
93
|
+
:private_header_files)
|
94
|
+
when :source_files
|
95
|
+
h_headers.call(file_accessor.headers - file_accessor.public_headers, :private_header_files)
|
96
|
+
h_headers.call(file_accessor.public_headers, :public_header_files)
|
97
|
+
when :public_header_files then h_headers.call(file_accessor.public_headers, :public_header_files)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
mappings
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HMap
|
4
|
+
# A collection of Helper functions used throughout cocoapods-hmap.
|
5
|
+
class XcodeprojHelper
|
6
|
+
require 'xcodeproj'
|
7
|
+
OTHER_CFLAGS = 'OTHER_CFLAGS'
|
8
|
+
HEAD_SEARCH_PATHS = 'HEADER_SEARCH_PATHS'
|
9
|
+
# A collection of Pods Helper functions used throughout cocoapods-hmap.
|
10
|
+
attr_reader :xcconfig_path, :build_setting_key
|
11
|
+
|
12
|
+
def initialize(xcconfig)
|
13
|
+
@xcconfig_path = xcconfig
|
14
|
+
@xcconfig = Xcodeproj::Config.new(xcconfig_path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def change_xcconfig_other_c_flags_and_save(values, build_as_framework, use_headermap: false, save_origin: true)
|
18
|
+
setting = values.flat_map do |config|
|
19
|
+
['$(inherited)', "-I\"#{Helper::Pods.pods_hmap_files_dir}/#{config}.hmap\"",
|
20
|
+
"-iquote \"#{Helper::Pods.pods_hmap_files_dir}/#{config}-iquote.hmap\""]
|
21
|
+
end
|
22
|
+
if build_as_framework
|
23
|
+
setting << "-ivfsoverlay \"#{Helper::Pods.pods_hmap_files_dir}/vfs/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/all-product-headers.yaml\""
|
24
|
+
end
|
25
|
+
change_xcconfig_build_setting(OTHER_CFLAGS, setting.join(' '), save_origin) do |xcconfig|
|
26
|
+
xcconfig.attributes['USE_HEADERMAP'] = 'NO' unless use_headermap
|
27
|
+
save_build_setting_to_xcconfig(HMap::XcodeprojHelper::HEAD_SEARCH_PATHS)
|
28
|
+
end
|
29
|
+
save_to_path
|
30
|
+
end
|
31
|
+
|
32
|
+
def change_xcconfig_build_setting(build_setting_key, setting, save_origin)
|
33
|
+
origin_build_setting = @xcconfig.attributes[build_setting_key]
|
34
|
+
save_origin_build_setting = save_build_setting_to_xcconfig(build_setting_key)
|
35
|
+
hmap_build_setting = @xcconfig.attributes[hmap_key(build_setting_key)]
|
36
|
+
value = setting
|
37
|
+
value = "#{value} ${#{save_key(build_setting_key)}}" if save_origin && !save_origin_build_setting.nil?
|
38
|
+
@xcconfig.attributes[hmap_key(build_setting_key)] = value
|
39
|
+
@xcconfig.attributes[build_setting_key] = "${#{hmap_key(build_setting_key)}}"
|
40
|
+
yield(@xcconfig) if block_given?
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_build_setting_to_xcconfig(key)
|
44
|
+
origin_build_setting = @xcconfig.attributes[key]
|
45
|
+
if origin_build_setting.nil? || !origin_build_setting.include?(hmap_key(key))
|
46
|
+
@xcconfig.attributes[save_key(key)] = origin_build_setting unless origin_build_setting.nil?
|
47
|
+
@xcconfig.attributes.delete(key)
|
48
|
+
end
|
49
|
+
@xcconfig.attributes[save_key(key)]
|
50
|
+
end
|
51
|
+
|
52
|
+
def clean_hmap_xcconfig_other_c_flags_and_save
|
53
|
+
clean_hmap_build_setting_to_xcconfig(OTHER_CFLAGS)
|
54
|
+
clean_hmap_build_setting_to_xcconfig(HEAD_SEARCH_PATHS)
|
55
|
+
@xcconfig.attributes['USE_HEADERMAP'] = 'YES'
|
56
|
+
save_to_path
|
57
|
+
end
|
58
|
+
|
59
|
+
def clean_hmap_build_setting_to_xcconfig(build_setting)
|
60
|
+
save_origin_build_setting = @xcconfig.attributes[save_key(build_setting)]
|
61
|
+
origin_build_setting = @xcconfig.attributes[build_setting]
|
62
|
+
@xcconfig.attributes[build_setting] = save_origin_build_setting unless save_origin_build_setting.nil?
|
63
|
+
@xcconfig.attributes.delete(hmap_key(build_setting))
|
64
|
+
@xcconfig.attributes.delete(save_key(build_setting))
|
65
|
+
end
|
66
|
+
|
67
|
+
def save_to_path(path = nil)
|
68
|
+
path = xcconfig_path if path.nil?
|
69
|
+
@xcconfig.save_as(path)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def hmap_key(key)
|
75
|
+
"HMAP_PODS_#{key}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def save_key(key)
|
79
|
+
"SAVE_#{key}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -1,6 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module HMap
|
4
|
+
# hmap bucket
|
5
|
+
class HMapBucketStr
|
6
|
+
attr_reader :key, :perfix, :suffix
|
7
|
+
|
8
|
+
def initialize(key, perfix, suffix)
|
9
|
+
@key = key
|
10
|
+
@perfix = perfix
|
11
|
+
@suffix = suffix
|
12
|
+
end
|
13
|
+
|
14
|
+
def description
|
15
|
+
<<-DESC
|
16
|
+
Key #{@key} -> Prefix #{@perfix}, Suffix #{@suffix}
|
17
|
+
DESC
|
18
|
+
end
|
19
|
+
end
|
4
20
|
# hmap file reader
|
5
21
|
class MapFileReader
|
6
22
|
# @return [String, nil] the filename loaded from, or nil if loaded from a binary
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HMap
|
4
|
+
class HMapSaver
|
5
|
+
attr_reader :string_table, :buckets, :headers
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@string_table = "\0"
|
9
|
+
@buckets = []
|
10
|
+
@headers = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def header_to_hash(keys, headers, index, buckets)
|
14
|
+
index = index.length
|
15
|
+
keys.inject('') do |sum, bucket|
|
16
|
+
buckte = HMapBucketStr.new(*bucket)
|
17
|
+
string_t = buckte.bucket_to_string(headers, index + sum.length)
|
18
|
+
buckets.push(buckte)
|
19
|
+
sum + string_t
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_to_string_table(str)
|
24
|
+
@string_table += "#{Utils.safe_encode(str, 'ASCII-8BIT')}\0"
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_to_headers(key)
|
28
|
+
if headers[key].nil?
|
29
|
+
headers[key] = string_table.length
|
30
|
+
add_to_string_table(key)
|
31
|
+
end
|
32
|
+
headers[key]
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_to_buckets(*buckets)
|
36
|
+
values = buckets.map { |key| add_to_headers(key) }
|
37
|
+
bucket = HMapBucket.new(*values)
|
38
|
+
bucket.uuid = Utils.string_downcase_hash(buckets.first)
|
39
|
+
@buckets << bucket
|
40
|
+
end
|
41
|
+
|
42
|
+
def write_to(path)
|
43
|
+
MapFile.new(@string_table, @buckets).write(path)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# require 'cocoapods-hmap/view'
|
4
|
-
|
5
3
|
module HMap
|
6
4
|
HEADER_CONST = {
|
7
5
|
HMAP_HEADER_MAGIC_NUMBER: 0x686d6170,
|
@@ -114,62 +112,11 @@ module HMap
|
|
114
112
|
}.merge super
|
115
113
|
end
|
116
114
|
end
|
117
|
-
|
118
|
-
# HMapBucketStr => HMapBucket.
|
119
|
-
# @see https://clang.llvm.org/doxygen/structclang_1_1HMapHeader.html
|
120
|
-
# @abstract
|
121
|
-
class HMapBucketStr
|
122
|
-
attr_reader :uuid, :key, :perfix, :suffix
|
123
|
-
|
124
|
-
def initialize(key, perfix, suffix)
|
125
|
-
@uuid = Utils.string_downcase_hash(key)
|
126
|
-
@key = key
|
127
|
-
@perfix = perfix
|
128
|
-
@suffix = suffix
|
129
|
-
@str_ins = {}
|
130
|
-
end
|
131
|
-
|
132
|
-
def bucket_to_string(headers, index)
|
133
|
-
bucket = [key, perfix, suffix]
|
134
|
-
bucket.inject('') do |sum, arg|
|
135
|
-
if headers[arg].nil?
|
136
|
-
headers[arg] = sum.length + index
|
137
|
-
sum += "#{Utils.safe_encode(arg, 'ASCII-8BIT')}\0"
|
138
|
-
end
|
139
|
-
@str_ins[arg] = headers[arg]
|
140
|
-
sum
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def bucket
|
145
|
-
HMapBucket.new(@str_ins[@key], @str_ins[@perfix], @str_ins[@suffix])
|
146
|
-
end
|
147
|
-
|
148
|
-
# @return [String] the serialized fields of the mafile
|
149
|
-
def serialize
|
150
|
-
bucket.serialize
|
151
|
-
end
|
152
|
-
|
153
|
-
def description
|
154
|
-
<<-DESC
|
155
|
-
Key #{@key} -> Prefix #{@perfix}, Suffix #{@suffix}
|
156
|
-
DESC
|
157
|
-
end
|
158
|
-
|
159
|
-
def to_h
|
160
|
-
{
|
161
|
-
'key' => { 'index' => str_ins[@key], 'key' => @key },
|
162
|
-
'perfix' => { 'index' => str_ins[@perfix], 'perfix' => @perfix },
|
163
|
-
'suffix' => { 'index' => str_ins[@suffix], 'suffix' => @suffix }
|
164
|
-
}
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
115
|
# HMapBucket structure.
|
169
116
|
# @see https://clang.llvm.org/doxygen/structclang_1_1HMapHeader.html
|
170
117
|
# @abstract
|
171
118
|
class HMapBucket < HMapStructure
|
172
|
-
attr_accessor :key, :perfix, :suffix
|
119
|
+
attr_accessor :key, :perfix, :suffix, :uuid
|
173
120
|
|
174
121
|
SIZEOF = 12
|
175
122
|
FORMAT = 'L=3'
|
@@ -210,7 +157,7 @@ module HMap
|
|
210
157
|
@header = populate_hmap_header(nums, entries)
|
211
158
|
@buckets = add_bucket(buckets, nums)
|
212
159
|
end
|
213
|
-
|
160
|
+
|
214
161
|
def num_buckets(count, pow2)
|
215
162
|
if count < 8
|
216
163
|
pow2 <<= 1 if count * 4 >= pow2 * 3
|
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
require 'cocoapods'
|
4
4
|
|
5
|
+
module Pod
|
6
|
+
Validator.class_eval do
|
7
|
+
def results=(v)
|
8
|
+
@results = v
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
5
13
|
module HMap
|
6
14
|
# mapfile dir name
|
7
15
|
# @api private
|
@@ -16,130 +24,84 @@ module HMap
|
|
16
24
|
private_header_files: 'private',
|
17
25
|
source_files: 'all'
|
18
26
|
}.freeze
|
19
|
-
|
27
|
+
HEAD_SEARCH_I = '-I'
|
28
|
+
HEAD_SEARCH_IQUOTE = '-iquote'
|
20
29
|
# build setting HEAD_SEARCH_PATHs
|
21
30
|
HEAD_SEARCH_PATHS = 'HEADER_SEARCH_PATHS'
|
31
|
+
|
22
32
|
# Helper module which returns handle method from MapFileWriter.
|
23
33
|
class MapFileWriter
|
24
34
|
# @param save_origin_header_search_paths save_origin_header_search_paths
|
25
35
|
# @param clean_hmap clean up all hmap setup
|
26
36
|
def initialize(save_origin_header_search_paths, clean_hmap)
|
27
|
-
config = Pod::Config.instance
|
28
|
-
analyze = Helper::Pods.pod_analyze(config)
|
29
|
-
hmap_dir = hmap_dir(config)
|
30
|
-
targets = analyze.targets
|
31
|
-
pod_targets = analyze.pod_targets
|
32
|
-
clean_hmap(clean_hmap, hmap_dir, targets, pod_targets)
|
33
|
-
return if clean_hmap
|
34
|
-
|
35
37
|
@save_origin_header_search_paths = save_origin_header_search_paths
|
36
|
-
|
38
|
+
@hmap_saver = HMapSaver.new
|
39
|
+
@hmap_saver_iquote = HMapSaver.new
|
40
|
+
create_mapfile(clean_hmap)
|
37
41
|
end
|
38
42
|
|
39
43
|
private
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def gen_mapfile(targets, pod_targets, hmap_d)
|
58
|
-
puts('Inspecting targets to integrate ')
|
59
|
-
merge_all_pods_target_headers_mapfile(pod_targets, hmap_d)
|
60
|
-
merge_all_target_public_mapfile(targets, hmap_d)
|
61
|
-
create_each_target_mapfile(pod_targets, hmap_d)
|
62
|
-
end
|
63
|
-
|
64
|
-
def from_header_mappings_by_file_accessor(header_h, buckets, target, hmap_type)
|
65
|
-
hmap_s = 'headers'
|
66
|
-
hmap_s = "#{HMMAP_TYPE[hmap_type]}_#{hmap_s}" unless hmap_type == :source_files
|
67
|
-
headers = target.header_mappings_by_file_accessor.keys.flat_map(&hmap_s.to_sym)
|
68
|
-
s_headers = Helper::Pods.pod_target_source_header_map(target, hmap_type)
|
69
|
-
headers.each_with_object(buckets) do |header_f, sum|
|
70
|
-
keys = header_perfix(target, header_f, s_headers)
|
71
|
-
sum[0] += header_to_hash(keys, header_h, sum[0].length, sum[1])
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def header_perfix(target, file, s_headers)
|
76
|
-
key = file.basename.to_s
|
77
|
-
project_name = "#{target.project_name}/#{file.basename}"
|
78
|
-
product_module_name = "#{target.product_module_name}/#{file.basename}"
|
79
|
-
perfix = "#{file.dirname}/"
|
80
|
-
keys = [key, project_name, product_module_name] + (s_headers[key].nil? ? [] : s_headers[key])
|
81
|
-
keys.compact.uniq.inject([]) do |sum, name|
|
82
|
-
sum << [name, perfix, key]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def header_to_hash(keys, headers, index, buckets)
|
87
|
-
keys.inject('') do |sum, bucket|
|
88
|
-
buckte = HMapBucketStr.new(*bucket)
|
89
|
-
string_t = buckte.bucket_to_string(headers, index + sum.length)
|
90
|
-
buckets.push(buckte)
|
91
|
-
sum + string_t
|
92
|
-
end
|
93
|
-
end
|
45
|
+
# Integrates the projects mapfile associated
|
46
|
+
# with the App project and Pods project.
|
47
|
+
#
|
48
|
+
# @param [clean] clean hmap dir @see #podfile
|
49
|
+
# @return [void]
|
50
|
+
#
|
51
|
+
def create_mapfile(clean)
|
52
|
+
puts "Current hmap files dir: #{Helper::Pods.hmap_files_dir}"
|
53
|
+
puts "Current vfs files dir: #{Helper::Pods.vfs_files_dir}"
|
54
|
+
analyze = PodsSpecification.instance.analyze
|
55
|
+
targets = analyze.targets
|
56
|
+
pod_targets = analyze.pod_targets
|
57
|
+
return if BuildSettingHelper.clean_hmap(clean, targets, pod_targets)
|
94
58
|
|
95
|
-
|
96
|
-
|
97
|
-
targets.each do |target|
|
98
|
-
hmap_name = "All-Pods-Public-#{target.name}-hmap.hmap"
|
99
|
-
single_target_mapfile(target.pod_targets, hmap_dir, hmap_name, method)
|
100
|
-
change_target_xcconfig_header_search_path([hmap_name], true, *targets)
|
101
|
-
end
|
59
|
+
merge_all_pods_target_headers_mapfile(pod_targets)
|
60
|
+
merge_all_target_public_headers_mapfile(targets)
|
102
61
|
end
|
103
62
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
change_target_xcconfig_header_search_path([hmap_name], true, *pod_targets)
|
63
|
+
def from_header_mappings(target, type = :source_files)
|
64
|
+
headers = Helper::Pods.header_mappings(target, type)
|
65
|
+
headers[HEAD_SEARCH_IQUOTE].each { |value| @hmap_saver_iquote.add_to_buckets(*value) }
|
66
|
+
headers[HEAD_SEARCH_I].each { |value| @hmap_saver.add_to_buckets(*value) }
|
109
67
|
end
|
110
68
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
single_target_mapfile([target], File.join(hmap_dir, target.name), hmap_name, method, key)
|
117
|
-
"#{target.name}/#{hmap_name}" if key == :source_files
|
118
|
-
end.compact
|
119
|
-
# change_target_xcconfig_header_search_path(hmap_h, false, target)
|
69
|
+
def merge_all_target_public_headers_mapfile(targets)
|
70
|
+
names = targets.map do |target|
|
71
|
+
hmap_name = "all-public-#{target.name}"
|
72
|
+
create_hmap_vfs_files(target.pod_targets, hmap_name, :public_header_files)
|
73
|
+
hmap_name
|
120
74
|
end
|
75
|
+
BuildSettingHelper.change_other_c_flags_xcconfig_build_settings(names, targets,
|
76
|
+
save_origin: @save_origin_header_search_paths)
|
121
77
|
end
|
122
78
|
|
123
|
-
def
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
129
|
-
wirte_mapfile_to_path(hmap_path, buckets)
|
79
|
+
def merge_all_pods_target_headers_mapfile(pod_targets)
|
80
|
+
hmap_name = 'all-pods-all-header'
|
81
|
+
create_hmap_vfs_files(pod_targets, hmap_name, :source_files)
|
82
|
+
BuildSettingHelper.change_other_c_flags_xcconfig_build_settings([hmap_name], pod_targets,
|
83
|
+
save_origin: @save_origin_header_search_paths)
|
130
84
|
end
|
131
85
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
86
|
+
# Cteate hmap files and vfs files
|
87
|
+
#
|
88
|
+
# @param [pod_targets] Pods project all target @see Pod#PodTarget
|
89
|
+
# @param [hmap_name] -I hmap file name and -iquote hmap file name
|
90
|
+
# @param [hmap_type] hmap file contains pod targets header type
|
91
|
+
#
|
92
|
+
def create_hmap_vfs_files(pod_targets, hmap_name, hmap_type = :public_header_files)
|
93
|
+
pod_targets.each { |target| from_header_mappings(target, hmap_type) }
|
94
|
+
Helper::Pods.write_vfs_yaml(pod_targets)
|
95
|
+
write_hmap_files(*Helper::Pods.hmap_files_paths(hmap_name))
|
136
96
|
end
|
137
97
|
|
138
|
-
def
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
98
|
+
def write_hmap_files(hmap_path_i, hmap_path_iquote)
|
99
|
+
print "\t - Save hmap file to path: "
|
100
|
+
puts hmap_path_i.to_s.yellow
|
101
|
+
print "\t - Save hmap file to path: "
|
102
|
+
puts hmap_path_iquote.to_s.yellow
|
103
|
+
@hmap_saver.write_to(hmap_path_i)
|
104
|
+
@hmap_saver_iquote.write_to(hmap_path_iquote)
|
143
105
|
end
|
144
106
|
end
|
145
107
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module HMap
|
2
|
+
class PodsSpecification
|
3
|
+
attr_reader :workspace_path, :analyze, :app_build_dir, :project_temp_dir
|
4
|
+
|
5
|
+
BUILD_DIR = 'BUILD_DIR'
|
6
|
+
PROJECT_TEMP_DIR = 'PROJECT_TEMP_DIR'
|
7
|
+
|
8
|
+
def self.instance
|
9
|
+
@instance ||= new
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@workspace_path = workspace
|
14
|
+
@analyze = pod_analyze
|
15
|
+
workspace_build_dir
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def workspace_build_dir
|
21
|
+
workspace_dic = xcodebuild('-list', workspace_path)['workspace']
|
22
|
+
scheme = workspace_dic['schemes'].first
|
23
|
+
build_settings = xcodebuild('analyze', workspace_path, scheme).first['buildSettings']
|
24
|
+
@app_build_dir = build_settings[BUILD_DIR]
|
25
|
+
@project_temp_dir = build_settings[PROJECT_TEMP_DIR]
|
26
|
+
end
|
27
|
+
|
28
|
+
def xcodebuild(action, workspace, scheme = nil)
|
29
|
+
command = %W[#{action} -workspace #{workspace} -json]
|
30
|
+
command += %W[-scheme #{scheme} -showBuildSettings] unless scheme.nil?
|
31
|
+
results = Executable.execute_command('xcodebuild', command, false)
|
32
|
+
JSON.parse(results) unless results.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def pod_analyze
|
36
|
+
podfile = Pod::Podfile.from_file(Pod::Config.instance.podfile_path)
|
37
|
+
lockfile = Pod::Lockfile.from_file(Pod::Config.instance.lockfile_path)
|
38
|
+
Pod::Installer::Analyzer.new(Pod::Config.instance.sandbox, podfile, lockfile).analyze
|
39
|
+
end
|
40
|
+
|
41
|
+
def workspace
|
42
|
+
podfile = Pod::Podfile.from_file(Pod::Config.instance.podfile_path)
|
43
|
+
user_project_paths = pod_analyze.targets.map(&:user_project_path).compact.uniq
|
44
|
+
if podfile.workspace_path
|
45
|
+
declared_path = podfile.workspace_path
|
46
|
+
path_with_ext = File.extname(declared_path) == '.xcworkspace' ? declared_path : "#{declared_path}.xcworkspace"
|
47
|
+
podfile_dir = File.dirname(podfile.defined_in_file || '')
|
48
|
+
absolute_path = File.expand_path(path_with_ext, podfile_dir)
|
49
|
+
Pathname.new(absolute_path)
|
50
|
+
elsif user_project_paths.count == 1
|
51
|
+
project = user_project_paths.first.basename('.xcodeproj')
|
52
|
+
Pod::Config.instance.installation_root + "#{project}.xcworkspace"
|
53
|
+
else
|
54
|
+
raise Informative, 'Could not automatically select an Xcode ' \
|
55
|
+
"workspace. Specify one in your Podfile like so:\n\n" \
|
56
|
+
" workspace 'path/to/Workspace.xcworkspace'\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/cocoapods-hmap/utils.rb
CHANGED
@@ -1,11 +1,31 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: false
|
2
2
|
|
3
3
|
require 'cocoapods'
|
4
4
|
|
5
5
|
module HMap
|
6
6
|
# A collection of utility functions used throughout cocoapods-hmap.
|
7
7
|
module Utils
|
8
|
-
|
8
|
+
# Converts the symbolic name of a platform to a string name suitable to be
|
9
|
+
# presented to the user.
|
10
|
+
#
|
11
|
+
# @param [Symbol] symbolic_name
|
12
|
+
# the symbolic name of a platform.
|
13
|
+
#
|
14
|
+
# @return [String] The string that describes the name of the given symbol.
|
15
|
+
#
|
16
|
+
def self.effective_platform_name(symbolic_name)
|
17
|
+
case symbolic_name
|
18
|
+
when :ios then %w[iphoneos iphonesimulator]
|
19
|
+
when :osx then %w[macosx]
|
20
|
+
when :watchos then %w[watchos watchsimulator]
|
21
|
+
when :tvos then %w[appletvos appletvsimulator]
|
22
|
+
else []
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.effective_platforms_names(platforms)
|
27
|
+
platforms.flat_map { |name| effective_platform_name(name) }.compact.uniq
|
28
|
+
end
|
9
29
|
|
10
30
|
def self.index_of_range(num, range)
|
11
31
|
num &= range - 1
|
@@ -72,69 +92,7 @@ module HMap
|
|
72
92
|
c.force_encoding(target_encoding)
|
73
93
|
})
|
74
94
|
end
|
75
|
-
|
76
|
-
def self.clean_target_build_setting(targets, build_setting)
|
77
|
-
target_xcconfig_path(targets) do |xc|
|
78
|
-
clean_build_setting_to_xcconfig(xc, build_setting)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.target_xcconfig_path(targets)
|
83
|
-
targets.each do |target|
|
84
|
-
raise ClassIncludedError.new(target.class, Pod::Target) unless target.is_a?(Pod::Target)
|
85
|
-
|
86
|
-
config_h = Pod::Target.instance_method(:build_settings).bind(target).call
|
87
|
-
config_h.each_key do |configuration_name|
|
88
|
-
xcconfig = target.xcconfig_path(configuration_name)
|
89
|
-
yield(xcconfig) if block_given?
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.chang_xcconfig_header_search_path(xcconfig, hmap_h, use_headermap: true, save_origin: true)
|
95
|
-
hmap_header_serach_paths = hmap_h.inject('') do |sum, hmap_n|
|
96
|
-
hmap_pod_root_path = "${PODS_ROOT}/Headers/#{HMAP_DIR}/#{hmap_n}"
|
97
|
-
sum + "\"#{hmap_pod_root_path}\" "
|
98
|
-
end
|
99
|
-
save_build_setting_to_xcconfig(xcconfig, hmap_header_serach_paths, HEAD_SEARCH_PATHS,
|
100
|
-
save_origin: save_origin) do |xc|
|
101
|
-
xc.attributes['USE_HEADERMAP'] = 'NO' unless use_headermap
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.save_build_setting_to_xcconfig(path, value, build_setting, save_origin: true)
|
106
|
-
xc = Xcodeproj::Config.new(path)
|
107
|
-
save_origin_build_setting = "SAVE_#{build_setting}"
|
108
|
-
hmap_build_setting = "HMAP_PODS_#{build_setting}"
|
109
|
-
origin_build_setting = xc.attributes[build_setting]
|
110
|
-
unless !origin_build_setting.nil? && origin_build_setting.include?(hmap_build_setting)
|
111
|
-
xc.attributes[save_origin_build_setting] =
|
112
|
-
origin_build_setting
|
113
|
-
end
|
114
|
-
|
115
|
-
value = "#{value} ${#{save_origin_build_setting}}" if save_origin
|
116
|
-
xc.attributes[hmap_build_setting] = value
|
117
|
-
xc.attributes[build_setting] = "${#{hmap_build_setting}}"
|
118
|
-
yield(xc) if block_given?
|
119
|
-
xc.save_as(path)
|
120
|
-
end
|
121
|
-
|
122
|
-
def self.clean_build_setting_to_xcconfig(path, build_setting)
|
123
|
-
xc = Xcodeproj::Config.new(path)
|
124
|
-
save_origin_build_setting = "SAVE_#{build_setting}"
|
125
|
-
hmap_build_setting = "HMAP_PODS_#{build_setting}"
|
126
|
-
origin_build_setting = xc.attributes[save_origin_build_setting]
|
127
|
-
puts "\t -xcconfig path: #{path}"
|
128
|
-
if origin_build_setting.nil?
|
129
|
-
puts "\t don't have #{save_origin_build_setting} in xcconfig file.".red
|
130
|
-
return
|
131
|
-
end
|
132
|
-
xc.attributes[build_setting] = origin_build_setting
|
133
|
-
xc.attributes.delete(save_origin_build_setting)
|
134
|
-
xc.attributes.delete(hmap_build_setting)
|
135
|
-
xc.attributes['USE_HEADERMAP'] = 'YES'
|
136
|
-
xc.save_as(path)
|
137
|
-
puts "\t clean finish."
|
138
|
-
end
|
139
95
|
end
|
140
96
|
end
|
97
|
+
|
98
|
+
|
data/lib/cocoapods-hmap/view.rb
CHANGED
data/lib/cocoapods_hmap.rb
CHANGED
@@ -6,10 +6,16 @@ module HMap
|
|
6
6
|
require_relative 'cocoapods-hmap/view'
|
7
7
|
require_relative 'cocoapods-hmap/hmap_struct'
|
8
8
|
require_relative 'cocoapods-hmap/utils'
|
9
|
-
require_relative 'cocoapods-hmap/pods_helper'
|
9
|
+
require_relative 'cocoapods-hmap/helper/pods_helper'
|
10
10
|
require_relative 'cocoapods-hmap/exceptions'
|
11
|
+
require_relative 'cocoapods-hmap/framework/framework_vfs'
|
12
|
+
require_relative 'cocoapods-hmap/hmap_save'
|
13
|
+
require_relative 'cocoapods-hmap/helper/xcconfig_helper'
|
14
|
+
require_relative 'cocoapods-hmap/pods_specification'
|
15
|
+
require_relative 'cocoapods-hmap/helper/build_setting_helper'
|
11
16
|
|
12
17
|
autoload :MapFileReader, 'cocoapods-hmap/hmap_reader'
|
13
18
|
autoload :MapFileWriter, 'cocoapods-hmap/hmap_writer'
|
14
19
|
autoload :MapFile, 'cocoapods-hmap/mapfile'
|
20
|
+
autoload :Executable, 'cocoapods-hmap/executable'
|
15
21
|
end
|
data/lib/cocoapods_plugin.rb
CHANGED
@@ -7,7 +7,7 @@ module Pod
|
|
7
7
|
# hook
|
8
8
|
module CocoaPodsHMapHook
|
9
9
|
HooksManager.register('cocoapods-mapfile', :post_install) do
|
10
|
-
Command::HMapGen.run(["--project-directory=#{Config.instance.installation_root}"
|
10
|
+
Command::HMapGen.run(["--project-directory=#{Config.instance.installation_root}"])
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoapods-mapfile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cat1237
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.6'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yaml-vfs
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.0.1
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.0.1
|
83
97
|
description: header_reader lets your read Xcode header map file. header-writer lets
|
84
98
|
your analyze the project pod dependencies and gen header map file for all pods.
|
85
99
|
email:
|
@@ -97,11 +111,17 @@ files:
|
|
97
111
|
- lib/cocoapods-hmap/command/hmap_gen.rb
|
98
112
|
- lib/cocoapods-hmap/command/hmap_reader.rb
|
99
113
|
- lib/cocoapods-hmap/exceptions.rb
|
114
|
+
- lib/cocoapods-hmap/executable.rb
|
115
|
+
- lib/cocoapods-hmap/framework/framework_vfs.rb
|
116
|
+
- lib/cocoapods-hmap/helper/build_setting_helper.rb
|
117
|
+
- lib/cocoapods-hmap/helper/pods_helper.rb
|
118
|
+
- lib/cocoapods-hmap/helper/xcconfig_helper.rb
|
100
119
|
- lib/cocoapods-hmap/hmap_reader.rb
|
120
|
+
- lib/cocoapods-hmap/hmap_save.rb
|
101
121
|
- lib/cocoapods-hmap/hmap_struct.rb
|
102
122
|
- lib/cocoapods-hmap/hmap_writer.rb
|
103
123
|
- lib/cocoapods-hmap/mapfile.rb
|
104
|
-
- lib/cocoapods-hmap/
|
124
|
+
- lib/cocoapods-hmap/pods_specification.rb
|
105
125
|
- lib/cocoapods-hmap/utils.rb
|
106
126
|
- lib/cocoapods-hmap/version.rb
|
107
127
|
- lib/cocoapods-hmap/view.rb
|
@@ -126,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
146
|
- !ruby/object:Gem::Version
|
127
147
|
version: '0'
|
128
148
|
requirements: []
|
129
|
-
rubygems_version: 3.
|
149
|
+
rubygems_version: 3.2.3
|
130
150
|
signing_key:
|
131
151
|
specification_version: 4
|
132
152
|
summary: Read or write header map file.
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cocoapods'
|
4
|
-
|
5
|
-
module HMap
|
6
|
-
# A collection of Helper functions used throughout cocoapods-hmap.
|
7
|
-
module Helper
|
8
|
-
# A collection of Pods Helper functions used throughout cocoapods-hmap.
|
9
|
-
module Pods
|
10
|
-
HEADER_EXTENSIONS = Pod::Sandbox::FileAccessor::HEADER_EXTENSIONS
|
11
|
-
def self.pod_analyze(config)
|
12
|
-
podfile = Pod::Podfile.from_file(config.podfile_path)
|
13
|
-
lockfile = Pod::Lockfile.from_file(config.lockfile_path)
|
14
|
-
Pod::Installer::Analyzer.new(config.sandbox, podfile, lockfile).analyze
|
15
|
-
end
|
16
|
-
|
17
|
-
# @!group Private helpers
|
18
|
-
|
19
|
-
# Returns the list of the paths founds in the file system for the
|
20
|
-
# attribute with given name. It takes into account any dir pattern and
|
21
|
-
# any file excluded in the specification.
|
22
|
-
#
|
23
|
-
# @param [Symbol] attribute
|
24
|
-
# the name of the attribute.
|
25
|
-
#
|
26
|
-
# @return [Array<Pathname>] the paths.
|
27
|
-
#
|
28
|
-
def self.paths_for_attribute(key, attribute, include_dirs: false)
|
29
|
-
file_patterns = key.spec_consumer.send(attribute)
|
30
|
-
options = {
|
31
|
-
exclude_patterns: key.spec_consumer.exclude_files,
|
32
|
-
dir_pattern: Pod::Sandbox::FileAccessor::GLOB_PATTERNS[attribute],
|
33
|
-
include_dirs: include_dirs
|
34
|
-
}
|
35
|
-
extensions = HEADER_EXTENSIONS
|
36
|
-
key.path_list.relative_glob(file_patterns, options).map do |f|
|
37
|
-
[f, key.path_list.root.join(f)] if extensions.include?(f.extname)
|
38
|
-
end.compact
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.pod_target_source_header(target, hmap_t)
|
42
|
-
target.header_mappings_by_file_accessor.keys.flat_map do |key|
|
43
|
-
paths_for_attribute(key, hmap_t)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.pod_target_source_header_map(target, hmap_t)
|
48
|
-
pod_target_source_header(target, hmap_t).each_with_object({}) do |f, sum|
|
49
|
-
file = f[1]
|
50
|
-
key = f[0].to_s
|
51
|
-
r_key = file.basename.to_s
|
52
|
-
sum[r_key] = [key, r_key].uniq
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|