cocoapods-mapfile 0.1.6 → 0.2.0
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/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
|