cocoapods-mapfile 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +65 -64
  3. data/lib/cocoapods_plugin.rb +16 -16
  4. data/lib/hmap/command/hmap_gen.rb +19 -27
  5. data/lib/hmap/command/hmap_reader.rb +5 -5
  6. data/lib/hmap/command/hmap_writer.rb +5 -3
  7. data/lib/hmap/command.rb +3 -1
  8. data/lib/hmap/constants.rb +198 -0
  9. data/lib/hmap/{executable.rb → helper/executable.rb} +5 -6
  10. data/lib/hmap/hmap/hmap_bucketstr.rb +20 -0
  11. data/lib/hmap/{hmap_reader.rb → hmap/hmap_reader.rb} +4 -20
  12. data/lib/hmap/{hmap_saver.rb → hmap/hmap_saver.rb} +11 -6
  13. data/lib/hmap/{hmap_struct.rb → hmap/hmap_struct.rb} +0 -0
  14. data/lib/hmap/hmap/hmap_writer.rb +52 -0
  15. data/lib/hmap/{mapfile.rb → hmap/mapfile.rb} +1 -1
  16. data/lib/hmap/user_interface.rb +22 -0
  17. data/lib/hmap/version.rb +1 -1
  18. data/lib/hmap/xc/context.rb +23 -0
  19. data/lib/hmap/xc/header_entry.rb +55 -0
  20. data/lib/hmap/xc/header_type.rb +32 -0
  21. data/lib/hmap/xc/pbx_helper.rb +68 -0
  22. data/lib/hmap/xc/product_helper.rb +36 -0
  23. data/lib/hmap/xc/resolver.rb +129 -0
  24. data/lib/hmap/xc/target/build_setting.rb +126 -0
  25. data/lib/hmap/xc/target/target.rb +76 -0
  26. data/lib/hmap/xc/target/target_context.rb +29 -0
  27. data/lib/hmap/xc/target/target_helper.rb +114 -0
  28. data/lib/hmap/xc/target/target_vfs.rb +122 -0
  29. data/lib/hmap/xc/target/xcconfig_helper.rb +109 -0
  30. data/lib/hmap/xc/workspace/project.rb +120 -0
  31. data/lib/hmap/xc/workspace/project_helper.rb +92 -0
  32. data/lib/hmap/xc/workspace/workspace.rb +83 -0
  33. data/lib/hmap.rb +16 -14
  34. metadata +58 -20
  35. data/lib/hmap/framework/framework_vfs.rb +0 -94
  36. data/lib/hmap/helper/build_setting_constants.rb +0 -13
  37. data/lib/hmap/helper/hmap_helper.rb +0 -212
  38. data/lib/hmap/helper/pods_helper.rb +0 -98
  39. data/lib/hmap/helper/xcconfig_helper.rb +0 -105
  40. data/lib/hmap/hmap_writer.rb +0 -99
  41. data/lib/hmap/pods_specification.rb +0 -65
@@ -1,23 +1,7 @@
1
1
  # frozen_string_literal: true
2
+ require 'hmap/hmap/hmap_struct'
2
3
 
3
4
  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
20
-
21
5
  # hmap file reader
22
6
  class MapFileReader
23
7
  # @return [String, nil] the filename loaded from, or nil if loaded from a binary
@@ -32,7 +16,7 @@ module HMap
32
16
  # @return [HMap::HMapHeader]
33
17
  attr_reader :header
34
18
 
35
- # @return [Hash<HMap::HMapBucket => HMap::HMapBucketStr>] an array of the file's bucktes
19
+ # @return [Hash<HMap::HMapBucket => HMap::BucketStr>] an array of the file's bucktes
36
20
  # @note bucktes are provided in order of ascending offset.
37
21
  attr_reader :bucktes
38
22
 
@@ -55,7 +39,7 @@ module HMap
55
39
  bucket_s = bucket.to_a.map do |key|
56
40
  string_t[key..-1].match(/[^\0]+/)[0]
57
41
  end
58
- HMapBucketStr.new(*bucket_s)
42
+ BucketStr.new(*bucket_s)
59
43
  end
60
44
  end
61
45
 
@@ -102,7 +86,7 @@ module HMap
102
86
 
103
87
  # description
104
88
  def description
105
- sum = " Header map: #{filename}\n" + header.description
89
+ sum = " Header map path: #{filename}\n" + header.description
106
90
  bucktes.each_with_index do |buckte_h, index|
107
91
  sum += "\t- Bucket: #{index}" + Utils.safe_encode(buckte_h.values[0].description, 'UTF-8') unless buckte_h.nil?
108
92
  sum
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'hmap/hmap/hmap_struct'
4
+ require 'hmap/hmap/mapfile'
5
+
3
6
  module HMap
4
7
  class HMapSaver
5
8
  attr_reader :string_table, :buckets, :headers
@@ -19,7 +22,7 @@ module HMap
19
22
  def header_to_hash(keys, headers, index, buckets)
20
23
  index = index.length
21
24
  keys.inject('') do |sum, bucket|
22
- buckte = HMapBucketStr.new(*bucket)
25
+ buckte = BucketStr.new(*bucket)
23
26
  string_t = buckte.bucket_to_string(headers, index + sum.length)
24
27
  buckets.push(buckte)
25
28
  sum + string_t
@@ -38,10 +41,12 @@ module HMap
38
41
  headers[key]
39
42
  end
40
43
 
41
- def add_to_bucket(buckets)
42
- values = buckets.map { |key| add_to_headers(key) }
43
- bucket = HMapBucket.new(*values)
44
- bucket.uuid = Utils.string_downcase_hash(buckets.first)
44
+ def add_to_bucket(buckte)
45
+ key = add_to_headers(buckte.key)
46
+ perfix = add_to_headers(buckte.perfix)
47
+ suffix = add_to_headers(buckte.suffix)
48
+ bucket = HMapBucket.new(key, perfix, suffix)
49
+ bucket.uuid = Utils.string_downcase_hash(buckte.key)
45
50
  @buckets << bucket
46
51
  end
47
52
 
@@ -50,7 +55,7 @@ module HMap
50
55
  end
51
56
 
52
57
  def write_to(path)
53
- MapFile.new(@string_table, @buckets).write(path)
58
+ MapFile.new(@string_table, @buckets).write(Pathname(path))
54
59
  end
55
60
  end
56
61
  end
File without changes
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hmap/xc/workspace/workspace'
4
+
5
+ module HMap
6
+ class HMapTarget
7
+ attr_reader :name, :target
8
+ end
9
+
10
+ # Helper module which returns handle method from MapFileWriter.
11
+ class MapFileWriter
12
+ # @param save_origin_header_search_paths save_origin_header_search_paths
13
+ # @param clean_hmap clean up all hmap setup
14
+ # @param allow_targets this targets will save origin build setting
15
+ # @param use_build_in_headermap option use Xcode header map
16
+ def initialize(use_origin, project_root, clean_hmap)
17
+ UserInterface.puts("[hmapfile] Workspace/project root: #{project_root}..............")
18
+ UserInterface.puts("[hmapfile] Analyzing dependencies..............")
19
+ Resolver.instance.installation_root = project_root
20
+ Resolver.instance.use_origin = use_origin
21
+ create_hmapfile(clean_hmap)
22
+ end
23
+
24
+ # Integrates the projects mapfile associated
25
+ # with the App project and Pods project.
26
+ #
27
+ # @param [clean] clean hmap dir @see #podfile
28
+ # @return [void]
29
+ #
30
+ def create_hmapfile(clean)
31
+ # {a,b}– Match pattern a or b.
32
+ # Though this looks like a regular expression quantifier, it isn't.
33
+ # For example, in regular expression, the pattern a{1,2} will match 1 or 2 'a' characters.
34
+ # In globbing, it will match the string a1 or a2.
35
+ paths = Dir.glob(File.join(Resolver.instance.installation_root, '*.{xcworkspace,xcodeproj}'))
36
+ workspace_paths = paths.select { |f| File.extname(f) == '.xcworkspace' }
37
+ xcs = if workspace_paths.nil?
38
+ project_paths = paths.select { |f| File.extname(f) == '.xcodeproj' }
39
+ Workspace.new_from_xcprojects(project_paths) unless project_paths.nil?
40
+ else
41
+ Workspace.new_from_xcworkspaces(workspace_paths)
42
+ end
43
+ xcs.each do |xc|
44
+ if clean
45
+ xc.remove_hmap_settings!
46
+ else
47
+ xc.write_save!
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -6,7 +6,7 @@ module HMap
6
6
  # @return mapfile string_table
7
7
  attr_reader :string_table
8
8
 
9
- # @return [Array<HMap::HMapBucketStr>] an array of the file's bucktes
9
+ # @return [Array<HMap::BucketStr>] an array of the file's bucktes
10
10
  # @note bucktes are provided in order of ascending offset.
11
11
  attr_reader :buckets
12
12
 
@@ -0,0 +1,22 @@
1
+ module HMap
2
+ # Manages the UI output so clients can customize it.
3
+ #
4
+ module UserInterface
5
+ # Prints a message to standard output.
6
+ #
7
+ # @return [void]
8
+ #
9
+ def self.puts(message)
10
+ STDOUT.puts message
11
+ end
12
+
13
+ # Prints a message to standard error.
14
+ #
15
+ # @return [void]
16
+ #
17
+ def self.warn(message)
18
+ STDERR.puts message
19
+ end
20
+ end
21
+ UI = UserInterface
22
+ end
data/lib/hmap/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HMap
4
- VERSION = '0.2.2'
4
+ VERSION = '0.2.3'
5
5
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HMap
4
+ class Context
5
+ attr_reader :build_root, :hmap_root, :temp_name, :build_dir, :temp_dir
6
+
7
+ def initialize(build_root, temp_dir, hmap_root, temp_name, build_dir)
8
+ @build_root = build_root
9
+ @temp_dir = temp_dir
10
+ @hmap_root = hmap_root
11
+ @temp_name = temp_name
12
+ @build_dir = build_dir || ''
13
+ end
14
+
15
+ def build_path(platform)
16
+ File.join(build_root, platform.to_s, build_dir)
17
+ end
18
+
19
+ def temp_path(platform)
20
+ File.join(temp_dir, platform.to_s, temp_name)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,55 @@
1
+ module HMap
2
+ class HeaderEntry
3
+ attr_reader :path, :extra_keys, :type
4
+
5
+ def initialize(path, extra_keys, type)
6
+ @path = path
7
+ @extra_keys = extra_keys
8
+ @type = type
9
+ end
10
+
11
+ def project_buckets
12
+ h_name = File.basename(path)
13
+ h_dir = File.dirname(path)
14
+ [BucketStr.new(h_name, "#{h_dir}/", h_name)]
15
+ end
16
+
17
+ def module_buckets(moudle_name)
18
+ h_name = File.basename(path)
19
+ module_p = "#{moudle_name}/"
20
+ [BucketStr.new(h_name, module_p, h_name)]
21
+ end
22
+
23
+ def full_module_buckets(moudle_name)
24
+ h_name = File.basename(path)
25
+ h_dir = File.dirname(path)
26
+ module_k = "#{moudle_name}/#{h_name}"
27
+ [BucketStr.new(module_k, "#{h_dir}/", h_name)]
28
+ end
29
+
30
+ def project_buckets_extra
31
+ h_name = File.basename(path)
32
+ h_dir = File.dirname(path)
33
+ buckets = []
34
+ buckets << BucketStr.new(h_name, "#{h_dir}/", h_name) unless extra_keys.include?(h_name)
35
+ buckets + extra_keys.map { |key| BucketStr.new(key, "#{h_dir}/", h_name) }
36
+ end
37
+
38
+ def module_buckets_extra(moudle_name)
39
+ h_name = File.basename(path)
40
+ module_p = "#{moudle_name}/"
41
+ buckets = []
42
+ buckets << BucketStr.new(h_name, module_p, h_name) unless extra_keys.include?(h_name)
43
+ buckets + extra_keys.map { |key| BucketStr.new(key, module_p, h_name) }
44
+ end
45
+
46
+ def full_module_buckets_extra(moudle_name)
47
+ h_name = File.basename(path)
48
+ h_dir = File.dirname(path)
49
+ module_k = "#{moudle_name}/#{h_name}"
50
+ buckets = []
51
+ buckets << BucketStr.new(module_k, "#{h_dir}/", h_name) unless extra_keys.include?(module_k)
52
+ buckets + extra_keys.map { |key| BucketStr.new(key, "#{h_dir}/", h_name) }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,32 @@
1
+
2
+ require 'hmap/xc/header_entry'
3
+
4
+ module HMap
5
+ module HeaderType
6
+ def public_entrys
7
+ return @public_entrys if defined?(@public_entrys)
8
+
9
+ @public_entrys = entrys.select { |entry| entry.type == :Public }
10
+ end
11
+
12
+ def private_entrys
13
+ return @private_entrys if defined?(@private_entrys)
14
+
15
+ @private_entrys = entrys.select { |entry| entry.type == :Private }
16
+ end
17
+
18
+ def project_entrys
19
+ return @project_entrys if defined?(@project_entrys)
20
+
21
+ @project_entrys = entrys.select { |entry| entry.type == :Project }
22
+ end
23
+
24
+ def use_vfs?
25
+ !public_entrys.empty? || !private_entrys.empty? || build_as_framework?
26
+ end
27
+
28
+ def headers_hash(*types)
29
+ Hash[types.map { |type| [type, send(type)] }]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,68 @@
1
+ module HMap
2
+ module PBXHelper
3
+ def self.get_groups(xct)
4
+ groups = xct.referrers.select { |e| e.is_a?(Constants::PBXGroup) } || []
5
+ groups += groups.flat_map { |g| get_groups(g) }
6
+ groups.compact.reverse
7
+ end
8
+
9
+ def self.group_paths(xct)
10
+ ps = get_groups(xct).map do |g|
11
+ s_hash = g.instance_variable_get('@simple_attributes_hash')
12
+ s_hash['path'] unless s_hash.nil?
13
+ end.compact
14
+ File.join(*ps)
15
+ end
16
+
17
+ def self.uses_swift?(target)
18
+ source_files = target.build_phases.flat_map do |phase|
19
+ phase.files if phase.is_a?(Constants::PBXSourcesBuildPhase)
20
+ end.compact
21
+ source_files.any? do |file|
22
+ path = file.file_ref.instance_variable_get('@simple_attributes_hash')['path'] || ''
23
+ File.extname(path) == '.swift'
24
+ end
25
+ end
26
+
27
+ def self.build_as_framework?(target)
28
+ target.symbol_type == :framework if target.respond_to?(:symbol_type)
29
+ end
30
+
31
+ def self.defines_module?(target)
32
+ return true if build_as_framework?(target)
33
+
34
+ bus = target.build_configuration_list.build_configurations.map do |bu|
35
+ bu.instance_variable_get('@simple_attributes_hash')['buildSettings'] || {}
36
+ end
37
+
38
+ bus.any? { |s| s['DEFINES_MODULE'] == 'YES' }
39
+ end
40
+
41
+ def self.projects(*p_paths)
42
+ return if p_paths.empty?
43
+
44
+ p_paths.flat_map do |pj|
45
+ project = Xcodeproj::Project.open(pj)
46
+ p_path = File.dirname(project.path)
47
+ project.root_object.project_references.map do |sp|
48
+ ff = sp[:project_ref]
49
+ path = ff.instance_variable_get('@simple_attributes_hash')['path'] || ''
50
+ full_path = File.join(p_path, path)
51
+ Xcodeproj::Project.open(full_path)
52
+ end << project
53
+ end
54
+ end
55
+
56
+ def self.project_references(project)
57
+ return if project.nil?
58
+
59
+ p_path = File.dirname(project.path)
60
+ project.root_object.project_references.map do |sp|
61
+ ff = sp[:project_ref]
62
+ path = ff.instance_variable_get('@simple_attributes_hash')['path'] || ''
63
+ full_path = File.join(p_path, path)
64
+ Xcodeproj::Project.open(full_path)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ require 'hmap/xc/resolver'
3
+ module HMap
4
+ class ProductPath
5
+ attr_reader :path, :build_setting, :name
6
+
7
+ def initialize(path)
8
+ @path = path
9
+ raise ArgumentError, "#{path}: can not get build directory" if @build_setting.nil?
10
+ end
11
+
12
+ def build_root
13
+ Pathname(build_setting[Constants::BUILD_DIR])
14
+ end
15
+
16
+ def obj_root
17
+ Pathname(build_setting[Constants::OBJROOT])
18
+ end
19
+ end
20
+
21
+ class WorkspaceProductPath < ProductPath
22
+ def initialize(path)
23
+ @name = File.basename(path, '.xcworkspace')
24
+ @build_setting = Resolver.instance.workspace_build_settings(path)
25
+ super
26
+ end
27
+ end
28
+
29
+ class ProjectProductPath < ProductPath
30
+ def initialize(path)
31
+ @name = File.basename(path, '.xcodeproj')
32
+ @build_setting = Resolver.instance.project_build_settings(path)
33
+ super
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hmap/helper/executable'
4
+
5
+ module HMap
6
+ class Resolver
7
+ # @return [Array<String>] The filenames that the Podfile can have ordered
8
+ # by priority.
9
+ #
10
+ PODFILE_NAMES = [
11
+ 'CocoaPods.podfile.yaml',
12
+ 'CocoaPods.podfile',
13
+ 'Podfile',
14
+ 'Podfile.rb'
15
+ ].freeze
16
+
17
+ attr_accessor :use_origin
18
+
19
+ def self.instance
20
+ @instance ||= new
21
+ end
22
+
23
+ # Sets the current config instance. If set to nil the config will be
24
+ # recreated when needed.
25
+ #
26
+ # @param [Config, Nil] the instance.
27
+ #
28
+ # @return [void]
29
+ #
30
+ class << self
31
+ attr_writer :instance
32
+ end
33
+
34
+ def workspace_build_settings(workspace)
35
+ workspace_dic = xcodebuild_list(workspace)['workspace']
36
+ schemes = workspace_dic['schemes'] || []
37
+ targets = xcodebuild_workspace(workspace, schemes[0]) || []
38
+ targets.first['buildSettings']
39
+ end
40
+
41
+ def project_build_settings(project_path)
42
+ targets = xcodebuild(project_path) || []
43
+ targets.first['buildSettings']
44
+ end
45
+
46
+ # @return [Pathname] the root of the workspace or project where is located.
47
+ #
48
+ def installation_root
49
+ @installation_root ||= begin
50
+ current_dir = Pathname.new(Dir.pwd.unicode_normalize)
51
+ current_path = current_dir
52
+ until current_path.root?
53
+ if podfile_path_in_dir(current_path)
54
+ installation_root = current_path
55
+ puts("[in #{current_path}]") unless current_path == current_dir
56
+ break
57
+ else
58
+ current_path = current_path.parent
59
+ end
60
+ end
61
+ installation_root || current_dir
62
+ end
63
+ end
64
+
65
+ attr_writer :installation_root
66
+ alias project_root installation_root
67
+
68
+ def verbose?
69
+ false
70
+ end
71
+
72
+ # @return [String] Executes xcodebuild list in the current working directory and
73
+ # returns its output (both STDOUT and STDERR).
74
+ #
75
+ def xcodebuild_list(workspace)
76
+ command = %W[-workspace #{workspace}]
77
+ command += %w[-json -list]
78
+ results = Executable.execute_command('xcodebuild', command, false)
79
+ JSON.parse(results) unless results.nil?
80
+ end
81
+
82
+ # @return [hash] Executes xcodebuild -workspace -scheme in the current working directory and
83
+ # returns its output (both STDOUT and STDERR).
84
+ #
85
+ def xcodebuild_workspace(workspace, scheme)
86
+ command = %W[-workspace #{workspace}]
87
+ command += %W[-scheme #{scheme}]
88
+ xcodebuild(command)
89
+ end
90
+
91
+ # @return [hash] Executes xcodebuild -project in the current working directory and
92
+ # returns its output (both STDOUT and STDERR).
93
+ #
94
+ def xcodebuild_project(project)
95
+ command = %W[-project #{project}]
96
+ xcodebuild(command)
97
+ end
98
+
99
+ private
100
+
101
+ # Returns the path of the Podfile in the given dir if any exists.
102
+ #
103
+ # @param [Pathname] dir
104
+ # The directory where to look for the Podfile.
105
+ #
106
+ # @return [Pathname] The path of the Podfile.
107
+ # @return [Nil] If not Podfile was found in the given dir
108
+ #
109
+ def podfile_path_in_dir(dir)
110
+ PODFILE_NAMES.each do |filename|
111
+ candidate = dir + filename
112
+ return candidate if candidate.file?
113
+ end
114
+ nil
115
+ end
116
+
117
+ # @return [hash] Executes xcodebuild in the current working directory, get build settings and
118
+ # returns its output as hash (both STDOUT and STDERR).
119
+ #
120
+ def xcodebuild(command)
121
+ command += %w[-json -showBuildSettings]
122
+ results = Executable.execute_command('xcodebuild', command, false)
123
+ index = results.index(/"action"/m)
124
+ reg = results[index..-1]
125
+ reg = "[\n{\n#{reg}"
126
+ JSON.parse(reg) unless results.nil?
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+ require 'hmap/xc/target/target_vfs'
3
+
4
+ module HMap
5
+ class Platform
6
+ attr_reader :configuration, :platform
7
+
8
+ def self.new_from_platforms(configuration, platforms)
9
+ Utils.effective_platforms_names(platforms).map { |pl| new(configuration, pl) }
10
+ end
11
+
12
+ def initialize(configuration, platform)
13
+ @configuration = configuration
14
+ @platform = platform
15
+ end
16
+
17
+ def to_s
18
+ "#{configuration}-#{platform}"
19
+ end
20
+ end
21
+ end
22
+
23
+ module HMap
24
+ class BuildSettings
25
+ attr_reader :type, :platform
26
+
27
+ def self.new_from_platforms(type, platforms, context)
28
+ platforms.map { |platform| new(type, platform.to_s, context) }
29
+ end
30
+
31
+ def initialize(type, platform, context)
32
+ @type = type
33
+ @platform = platform.to_s || ''
34
+ @context = context
35
+ end
36
+
37
+ def write_or_symlink(path, data, need_platform)
38
+ return if data.nil? && path.nil?
39
+
40
+ if data.nil?
41
+ dir = platform if type == :all_product_headers
42
+ path = Constants.instance.full_hmap_filepath(type, path, dir)
43
+ symlink_to(path, need_platform)
44
+ else
45
+ write(data, need_platform)
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def file_name
52
+ return @file_name if defined? @file_name
53
+
54
+ product_name = @context.product_name if @context.respond_to? :product_name
55
+ @file_name = Constants.instance.full_hmap_filename(type, product_name)
56
+ end
57
+
58
+ def hmap_filepath(need_platform)
59
+ platform = ''
60
+ platform = @platform if need_platform
61
+ hmap_root = File.join(@context.hmap_root, platform, @context.temp_name)
62
+ File.join(hmap_root, file_name)
63
+ end
64
+
65
+ def symlink_to(path, need_platform)
66
+ return unless path.exist?
67
+
68
+ filepath = Pathname.new(hmap_filepath(need_platform))
69
+ filepath.dirname.mkpath unless filepath.exist?
70
+ return if File.identical?(filepath, path)
71
+
72
+ filepath.make_symlink(path)
73
+ end
74
+
75
+ def write(data, need_platform)
76
+ path = Constants.instance.full_hmap_filepath(type, hmap_filepath(need_platform))
77
+ if type == :all_product_headers
78
+ da = data[platform] || []
79
+ TargetVFSWriter.new(da).write!(path)
80
+ else
81
+ HMapSaver.new_from_buckets(data).write_to(path)
82
+ end
83
+ end
84
+ end
85
+
86
+ class BuildSettingsWriter
87
+ attr_reader :platforms
88
+
89
+ # Initialize a new instance
90
+ #
91
+ # @param [Array<HMap::Platform>] platforms
92
+ # the platforms to lint.
93
+ #
94
+ # @param [HMap::Context] context
95
+ # the Project or target information.
96
+ #
97
+ def initialize(platforms, context)
98
+ @platforms = platforms
99
+ @context = context
100
+ end
101
+
102
+ def write_or_symlink(path, data, platforms = [])
103
+ build_settings.each do |setting|
104
+ type_data = data[setting.type] unless data.nil?
105
+ next if type_data.nil? && path.nil?
106
+
107
+ need_platform = platforms.include?(setting.type)
108
+ setting.write_or_symlink(path, type_data, need_platform)
109
+ end
110
+ end
111
+
112
+ private
113
+
114
+ def build_settings
115
+ return @build_settings if defined? @build_settings
116
+
117
+ @build_settings = Constants::HMAP_FILE_TYPE.flat_map do |type|
118
+ if @platforms.empty?
119
+ BuildSettings.new(type, nil, @context)
120
+ else
121
+ BuildSettings.new_from_platforms(type, @platforms, @context)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end