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



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 64

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"] = FLEX_COMPLIER_PATH.to_s
    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 = %Q{FLEX_PATH=${KZ_XML_FLEX_DIR}/${INPUT_FILE_BASE}.flex
rm -rf ${FLEX_PATH}
$KZ_XML_FLEX_COMPILER $INPUT_FILE_PATH $FLEX_PATH
if [ -f $FLEX_PATH ] ; then
cp $FLEX_PATH $KZ_XML_FLEX_BUILD_DIR
exit 0
else
exit 1
fi}
end

#add_framework_generator_build_phase(native_target) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 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}/${FULL_PRODUCT_NAME}']
  build_phase.shell_script = %q{
if [ "${MACH_O_TYPE}" != "staticlib" ]; then
exit 0
fi

PRODUCT_DIR=${PODS_BUILD_DIR}/Debug-iphoneos/${TARGET_NAME}/${FULL_PRODUCT_NAME}
PRODUCT_SIMULATOR_DIR=${PODS_BUILD_DIR}/Debug-iphonesimulator/${TARGET_NAME}/${FULL_PRODUCT_NAME}
CURRENT_PRODUCT_DIR=${PODS_CONFIGURATION_BUILD_DIR}/${TARGET_NAME}

if [ -d "${KZ_FRAMEWORK_CACHE_PATH}" ]; then
rm -r "${KZ_FRAMEWORK_CACHE_PATH}"
fi
mkdir -p "${KZ_FRAMEWORK_CACHE_PATH}"

if [ -d "${KZ_FRAMEWORK_CACHE_PATH}/${FULL_PRODUCT_NAME}" ]; then
rm -r "${KZ_FRAMEWORK_CACHE_PATH}/${FULL_PRODUCT_NAME}"
fi
cp -r ${CURRENT_PRODUCT_DIR}/${FULL_PRODUCT_NAME} "${KZ_FRAMEWORK_CACHE_PATH}"

find "${CURRENT_PRODUCT_DIR}" -iname "*.bundle" | while read -r BUNDLE_FILE; do
BUNDLE_NAME=$(basename ${BUNDLE_FILE})
if [ -d "${KZ_FRAMEWORK_CACHE_PATH}/${BUNDLE_NAME}" ]; then
    rm -r "${KZ_FRAMEWORK_CACHE_PATH}/${BUNDLE_NAME}"
fi
cp -r ${BUNDLE_FILE} "${KZ_FRAMEWORK_CACHE_PATH}"
done

if [ -f ${PRODUCT_DIR}/${PRODUCT_NAME} ] && [ -f ${PRODUCT_SIMULATOR_DIR}/${PRODUCT_NAME} ]; then
lipo -create ${PRODUCT_DIR}/${PRODUCT_NAME} ${PRODUCT_SIMULATOR_DIR}/${PRODUCT_NAME} -output "${KZ_FRAMEWORK_CACHE_PATH}/${FULL_PRODUCT_NAME}/${PRODUCT_NAME}"
fi

if [ -d ${PRODUCT_DIR}/Modules/${PRODUCT_NAME}.swiftmodule ] && [ -d ${PRODUCT_SIMULATOR_DIR}/Modules/${PRODUCT_NAME}.swiftmodule ]; then
cp -r ${PRODUCT_DIR}/Modules/${PRODUCT_NAME}.swiftmodule "${KZ_FRAMEWORK_CACHE_PATH}/${FULL_PRODUCT_NAME}/Modules"
cp -r ${PRODUCT_SIMULATOR_DIR}/Modules/${PRODUCT_NAME}.swiftmodule "${KZ_FRAMEWORK_CACHE_PATH}/${FULL_PRODUCT_NAME}/Modules"
fi

PRODUCT_SWIFT_H=${PRODUCT_DIR}/Headers/${PRODUCT_NAME}-Swift.h
PRODUCT_SIMULATOR_SWIFT_H=${PRODUCT_SIMULATOR_DIR}/Headers/${PRODUCT_NAME}-Swift.h
TARGET_SWIFT_H=${KZ_FRAMEWORK_CACHE_PATH}/${FULL_PRODUCT_NAME}/Headers/${PRODUCT_NAME}-Swift.h
if [ -f $PRODUCT_SWIFT_H ] && [ -f $PRODUCT_SIMULATOR_SWIFT_H ]; then
ruby "$KZ_MERGE_SWIFT_H_PATH" "$PRODUCT_SWIFT_H" "$PRODUCT_SIMULATOR_SWIFT_H" "$TARGET_SWIFT_H"
fi
            }
end

#clean_hmap_cache(kz_pod_target) ⇒ Object



183
184
185
186
187
188
189
190
191
192
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 183

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
end

#create_hampObject



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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 103

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)
      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.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)
        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



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 87

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



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 219

def private_hmap_info(kz_pod_target)
  header_paths = kz_pod_target.all_headers
  # 更新Headers
  if kz_pod_target.is_dev_pod && kz_pod_target.should_build?
    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.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



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 194

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



265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 265

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



168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/cocoapods-kz/helpers/kz_generator.rb', line 168

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