Class: KZ::KZGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/cocoapods-kz/helpers/kz_generator.rb

Instance Method Summary collapse

Constructor Details

#initialize(main_project) ⇒ KZGenerator

Returns a new instance of KZGenerator.



8
9
10
11
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 8

def initialize(main_project)
  @all_kz_pod_targets = KZGlobalHelper.instance.kz_analyzer.all_kz_pod_targets
  @main_project = main_project
end

Instance Method Details

#add_flexlib_xml_build_rules(project, native_target) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 22

def add_flexlib_xml_build_rules(project, native_target)
  return unless KZ::KZGlobalHelper.instance.have_flexLib_pod_target

  native_target.build_configurations.each do |config|
    config.build_settings["KZ_XML_FLEX_COMPILER"] = KZ.deal_path_for_xcconfig(FLEX_COMPLIER_PATH, false)
    config.build_settings["KZ_XML_FLEX_DIR"] = "${TARGET_TEMP_DIR}/XmlFlexs"
    config.build_settings["KZ_XML_FLEX_BUILD_DIR"] = "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.bundle"
  end

  xml_rule = new_build_rule(project, native_target, '[KZ] Custom Xml Build')
  xml_rule.file_type = 'text.xml'
  xml_rule.output_files = Array['${KZ_XML_FLEX_DIR}/${INPUT_FILE_BASE}.flex']
  xml_rule.script = KZ.deal_path_for_xcconfig(KZ_XML_BUILD_PATH, true)
end

#add_force_load_exe_path_build_phase(native_target, output_path) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 37

def add_force_load_exe_path_build_phase(native_target, output_path)
  return if KZ::KZGlobalHelper.instance.disable_generate_framework

  build_phase = native_target.new_shell_script_build_phase('[KZ] Froce Load File Output Path')
  build_phase.show_env_vars_in_log = '0'
  build_phase.output_paths = [output_path]
  build_phase.shell_script = KZ.deal_path_for_xcconfig(KZ_FIX_FORCE_LOAD_EXE, true)
end

#add_framework_generator_build_phase(native_target) ⇒ Object



13
14
15
16
17
18
19
20
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 13

def add_framework_generator_build_phase(native_target)
  return if KZ::KZGlobalHelper.instance.disable_generate_framework

  build_phase = native_target.new_shell_script_build_phase('[KZ] Generate Framework')
  build_phase.show_env_vars_in_log = '0'
  build_phase.output_paths = ['${KZ_FRAMEWORK_CACHE_PATH}/${PRODUCT_NAME}.xcframework']
  build_phase.shell_script = KZ.deal_path_for_xcconfig(KZ_GENERATOR_FRAMEWORK_PATH, true)
end

#clean_hmap_cache(kz_pod_target) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 146

def clean_hmap_cache(kz_pod_target)
  hmap_cache_path = kz_pod_target.pod_config_cache_path(false)

  Dir.foreach(hmap_cache_path) do |file_name|
    next if file_name == '.' || file_name == '..' || file_name == '.DS_Store'

    if file_name.end_with?(".hmap", ".json")
      FileUtils.rm(hmap_cache_path + file_name) if File.exist?(hmap_cache_path + file_name)
    end
  end if File.exist?(hmap_cache_path)
end

#create_hampObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 62

def create_hamp
  # 创建壳工程hmap
  main_sources_path = @main_project.project_dir + @main_project.root_object.display_name
  private_hmap_hash = {}
  traverse_folder(main_sources_path) do |header_path|
    header_pathname = Pathname.new(header_path)
    header_pathname_basename = header_pathname.basename.to_s

    header_hmap_value = {}
    header_hmap_value['suffix'] = header_pathname_basename
    header_hmap_value['prefix'] = header_pathname.dirname.to_s + '/'

    private_hmap_hash[header_pathname_basename] = header_hmap_value
  end

  unless private_hmap_hash.empty?
    save_hmap_file(private_hmap_hash, KZ_POD_CONFIG_ROOT, @main_project.root_object.display_name)
  end

  # 创建pod hmap
  @all_kz_pod_targets.each do |target_name, kz_pod_target|
    clean_hmap_cache(kz_pod_target)

    # 修复头文件导入方式
    all_repair_hmap_info = {}
    need_repair_import_targets = kz_pod_target.repair_import
    if need_repair_import_targets.count > 0
      need_repair_import_targets.each { |need_repair_import_target|
        repair_hmap_info = repair_hmap_info(need_repair_import_target)
        all_repair_hmap_info.merge!(repair_hmap_info)
      }
    end

    kz_pod_target.recursive_dependent_targets.each do |recursive_dependent_target|
      if recursive_dependent_target.need_repair_module_import
        header_paths = recursive_dependent_target.public_headers
        header_paths.each do |header_pathname|
          header_pathname_basename = header_pathname.basename.to_s

          header_hmap_value_quotes = {}
          header_hmap_value_quotes['suffix'] = header_pathname_basename
          header_hmap_value_quotes['prefix'] = recursive_dependent_target.product_basename + '/'
          all_repair_hmap_info["#{recursive_dependent_target.root_name}/#{header_pathname_basename}"] = header_hmap_value_quotes
        end
      end
    end

    if all_repair_hmap_info.count > 0
      hmap_cache_path = kz_pod_target.pod_config_cache_path(false)
      FileUtils.mkdir_p(hmap_cache_path) unless File.exist?(hmap_cache_path)

      save_hmap_file(all_repair_hmap_info, hmap_cache_path, target_name + '_repair')
      kz_pod_target.repair_header_search_path = hmap_cache_path + "#{target_name}_repair.hmap"
    end

    # 添加私有头文件引用
    if kz_pod_target.current_should_build?
      private_hamp_info = private_hmap_info(kz_pod_target)
      if private_hamp_info.count > 0
        hmap_cache_path = kz_pod_target.pod_config_cache_path(false)
        FileUtils.mkdir_p(hmap_cache_path) unless File.exist?(hmap_cache_path)

        save_hmap_file(private_hamp_info, hmap_cache_path, target_name)
        kz_pod_target.private_header_search_path = hmap_cache_path + "#{target_name}.hmap"
      end
    end
  end
end

#new_build_rule(project, native_target, name) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 46

def new_build_rule(project, native_target, name)
  new_rule = nil
  native_target.build_rules.each do |build_rule|
    new_rule = build_rule if build_rule.name == name
  end

  if new_rule == nil
    new_rule = project.new(Xcodeproj::Project::PBXBuildRule)
    native_target.build_rules << new_rule
  end

  new_rule.name = name
  new_rule.compiler_spec = 'com.apple.compilers.proxy.script'
  new_rule
end

#private_hmap_info(kz_pod_target) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 183

def private_hmap_info(kz_pod_target)
  header_paths = kz_pod_target.all_headers
  # 更新Headers
  if kz_pod_target.is_dev_pod
    header_paths.each do |header_pathname|
      symlink_path = kz_pod_target.local_private_headers_path + header_pathname.basename
      File.symlink(header_pathname, symlink_path) unless File.symlink?(symlink_path) || File.exist?(symlink_path)
    end
    kz_pod_target.use_local_private_headers_path = true
  end
  header_paths.each_with_object({}) do |header_pathname, hmap_info|
    header_pathname_basename = header_pathname.basename.to_s

    header_hmap_value_quotes = {}
    header_hmap_value_quotes['suffix'] = header_pathname_basename
    header_hmap_value_quotes['prefix'] = header_pathname.dirname.to_s + '/'
    hmap_info[header_pathname_basename] = header_hmap_value_quotes

    # pch
    pchfile_path = kz_pod_target.prefix_header_path
    if pchfile_path.exist?
      suffix = pchfile_path.basename.to_s
      hmap_info[suffix] = { 'suffix' => suffix, 'prefix' => "#{pchfile_path.dirname.to_s}/" }
    end

    unless kz_pod_target.is_dev_pod
      # 个别第三方在使用自己组件文件时,会使用#import <xx/xx.h>的方式
      hmap_info[kz_pod_target.product_basename + '/' + header_pathname_basename] = header_hmap_value_quotes
    end

    if kz_pod_target.current_uses_swift? && kz_pod_target.is_dev_pod
      # 修改SPBoss-Swift.h文件的导入方式
      swift_bridge_file_name = "#{kz_pod_target.name}-Swift.h"
      hmap_info[swift_bridge_file_name] = { 'suffix' => swift_bridge_file_name, 'prefix' => "#{kz_pod_target.name}/" }

      # 以SPBoss为例,在混编模式中,SPBoss-Swift.h会使用#import <SPBoss/SPBoss.h>方式导入swift需要使用的OC头文件
      # SPBoss中头文件会存在当前组件与framework的Headers中,有两份。SPBoss-Swift.h只在framework中
      # 编译默认从SPBoss-Swift.h找SPBoss.h,然后找SPBoss.h中的头文件也都会在framework中寻在,会造成与当前组件头文件重复
      # 需要重新将#import <SPBoss/SPBoss.h>方式修复为寻找当前组件中的SPBoss.h文件,而不是framework中的SPBoss.h
      if header_pathname_basename == "#{kz_pod_target.name}.h"
        hmap_info[kz_pod_target.name + '/' + header_pathname_basename] = header_hmap_value_quotes
      end
    end
  end
end

#repair_hmap_info(kz_pod_target) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 158

def repair_hmap_info(kz_pod_target)
  header_paths = kz_pod_target.public_headers
  header_paths.each_with_object({}) do |header_pathname, hmap_info|
    header_pathname_basename = header_pathname.basename.to_s

    header_hmap_value_quotes = {}
    header_hmap_value_quotes['suffix'] = header_pathname_basename
    header_hmap_value_quotes['prefix'] = header_pathname.dirname.to_s + '/'
    hmap_info[header_pathname_basename] = header_hmap_value_quotes

    header_hmap_value_slash = {}
    header_hmap_value_slash['suffix'] = header_pathname_basename
    prefix_name = kz_pod_target.product_basename
    if header_pathname.dirname.to_s.include?('.framework')
      header_pathname.dirname.to_s.split('/').each do |name|
        if name.include?('.framework')
          prefix_name = name.split('.').first
        end
      end
    end
    header_hmap_value_slash['prefix'] = prefix_name + '/'
    hmap_info[header_pathname_basename] = header_hmap_value_slash
  end
end

#save_hmap_file(hmap_hash, save_path, file_name) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 229

def save_hmap_file(hmap_hash, save_path, file_name)
  hmap_json = JSON.pretty_generate(hmap_hash)
  hmap_json_path = save_path + "#{file_name}.json"
  hmap_path = save_path + "#{file_name}.hmap"
  json_file = File.new(hmap_json_path, 'w')
  return unless json_file

  json_file.syswrite(hmap_json)
  system "#{HMAP_EXECUTE_PATH} convert #{hmap_json_path} #{hmap_path}"

  FileUtils.rm(hmap_json_path) unless KZ::KZGlobalHelper.instance.debug
end

#traverse_folder(folder_path) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 131

def traverse_folder(folder_path)
  Dir.foreach(folder_path) do |file_name|
    next if file_name == '.' || file_name == '..' || file_name == '.DS_Store'

    file_path = File.join(folder_path, file_name)
    if File.file?(file_path)
      yield(file_path) if file_name.end_with?('.h')
    elsif File.directory?(file_path)
      traverse_folder(file_path) do |path|
        yield(path)
      end
    end
  end
end