cocoapods-jxedt 0.0.9

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.
@@ -0,0 +1,210 @@
1
+ module Jxedt
2
+ class Sandbox
3
+ attr_accessor :sandbox
4
+
5
+ def initialize(path=nil)
6
+ @sandbox_path = path
7
+ end
8
+
9
+ def self.from_sandbox(sandbox)
10
+ search_path = Jxedt.config.binary_dir
11
+ binary_dir = search_path.empty? ? nil : sandbox.root + search_path
12
+ check_sandbox = Sandbox.new(binary_dir)
13
+ check_sandbox.sandbox = sandbox
14
+ check_sandbox
15
+ end
16
+
17
+ def binary_dir
18
+ @binary_dir ||= Pathname.new(@sandbox_path)
19
+ end
20
+
21
+ def target_paths
22
+ return [] if @sandbox_path.nil?
23
+ return [] unless binary_dir.exist?
24
+ return [] if @sandbox.source_lockfile.nil?
25
+ @targets ||= binary_dir.children().map do |target_path|
26
+ if target_path.directory? && (not target_path.children.empty?)
27
+ hash_key = @sandbox.source_lockfile.spec_checksums_hash_key(target_path.basename.to_s)
28
+ target_path if !(hash_key.nil?) && (target_path + "#{hash_key}.checksum").exist?
29
+ end
30
+ end.reject(&:nil?).uniq
31
+ @targets
32
+ end
33
+
34
+ def existed_target_names(name)
35
+ target_paths.select { |pair| "#{pair.basename}" == "#{name}" }.map { |pair| pair.basename }
36
+ end
37
+
38
+ def framework_folder_path_for_target_name(name)
39
+ target_paths.select { |pair| pair.basename == name }.last
40
+ end
41
+
42
+ def prebuild_vendored_frameworks(name)
43
+ target_path = target_paths.select { |pair| "#{pair.basename}" == "#{name}" }.last
44
+ return [] if target_path.nil?
45
+
46
+ configuration_enable = target_path.children().select { |path| "#{path.basename}" == 'Debug' || "#{path.basename}" == 'Release' }.count == 2
47
+ if configuration_enable
48
+ xcconfig_configuration_alias = Jxedt.config.xcconfig_configuration_alias
49
+ ["#{xcconfig_configuration_alias}-Release/*.{framework,xcframework}"]
50
+ else
51
+ ["*.{framework,xcframework}"]
52
+ end
53
+ end
54
+
55
+ def prebuild_bundles(name)
56
+ target_path = target_paths.select { |pair| "#{pair.basename}" == "#{name}" }.last
57
+ return [] if target_path.nil?
58
+
59
+ configuration_enable = target_path.children().select { |path| "#{path.basename}" == 'Debug' || "#{path.basename}" == 'Release' }.count == 2
60
+ if configuration_enable
61
+ xcconfig_configuration_alias = Jxedt.config.xcconfig_configuration_alias
62
+ ["#{xcconfig_configuration_alias}-Release/*.bundle"]
63
+ else
64
+ ["*.bundle"]
65
+ end
66
+ end
67
+ end
68
+
69
+ class Prebuild
70
+ def initialize(source_installer)
71
+ @source_installer = source_installer
72
+ end
73
+
74
+ def targets_to_prebuild
75
+ explicit_prebuild_pod_names = @source_installer.aggregate_targets.flat_map { |target|
76
+ target.target_definition.explicit_prebuild_pod_names
77
+ }.uniq
78
+
79
+ reject_prebuild_pod_names = @source_installer.aggregate_targets.flat_map { |target|
80
+ target.target_definition.reject_prebuild_pod_names
81
+ }.uniq
82
+
83
+ targets = @source_installer.pod_targets.select { |target|
84
+ next unless target.should_build?
85
+ next unless target.name == target.pod_name
86
+ next if reject_prebuild_pod_names.include?(target.pod_name)
87
+ explicit_prebuild_pod_names.include?(target.pod_name) || Jxedt.config.all_binary_enabled?
88
+ }
89
+ targets.reject! { |target| @source_installer.sandbox.local?(target.pod_name) } unless Jxedt.config.dev_pods_enabled?
90
+ targets.reject! { |target| Jxedt.config.excluded_pods.include?(target.pod_name) }
91
+ targets
92
+ end
93
+
94
+ def pods_to_prebuild
95
+ targets_to_prebuild.map(&:name).to_a
96
+ end
97
+
98
+ def build
99
+ check_sandbox = Jxedt::Sandbox.from_sandbox(@source_installer.sandbox)
100
+ existed_target_names = check_sandbox.target_paths.map { |pair| pair.basename.to_s }
101
+ targets = targets_to_prebuild.reject { |target| existed_target_names.include?(target.name.to_s) }
102
+
103
+ Pod::UI.puts "Prebuild total count: #{targets.size}"
104
+ Pod::UI.puts "Prebuild targets: #{ targets.map(&:name)}"
105
+ return if targets.empty?
106
+
107
+ require_relative 'pod-room/xcodebuild_command'
108
+
109
+ clear_output_path
110
+ case targets[0].platform.name
111
+ when :ios, :tvos, :watchos
112
+ Jxedt.config.support_configurations.each do |configuration|
113
+ Pod::UI.puts "Prebuild configuration: #{configuration}"
114
+ options = make_options
115
+ options[:configuration] = configuration
116
+ options[:targets] = targets
117
+ options[:output_path] = output_path + configuration
118
+ Jxedt::XcodebuildCommand.new(options).run
119
+ end
120
+ when :osx
121
+ Jxedt.config.support_configurations.each do |configuration|
122
+ Pod::UI.puts "Prebuild configuration: #{configuration}"
123
+ options = make_options
124
+ xcodebuild(
125
+ sandbox: options[:sandbox],
126
+ targets: targets,
127
+ configuration: configuration,
128
+ sdk: "macosx",
129
+ args: options[:args]
130
+ )
131
+ end
132
+ else
133
+ raise "Unsupported platform for '#{targets[0].name}': '#{targets[0].platform.name}'"
134
+ end
135
+
136
+ make_prebuild(targets)
137
+ clear_output_path
138
+ end
139
+
140
+ def make_prebuild(targets)
141
+ lockfile = @source_installer.lockfile
142
+ checksums = lockfile.internal_data["SPEC CHECKSUMS"] || {}
143
+ checkout_options = lockfile.internal_data["CHECKOUT OPTIONS"] || {}
144
+
145
+ # 目标binary路径
146
+ binary_path = output_path.parent
147
+ prebuild_targets = targets.map(&:name).to_a
148
+ prebuild_targets.map {|target_name|
149
+ target_path = binary_path + target_name
150
+ target_path.rmtree if target_path.exist?
151
+ }
152
+
153
+ # make prebuild files
154
+ configurations = Jxedt.config.support_configurations
155
+ Jxedt.config.support_configurations.each do |configuration|
156
+ configuration_path = output_path + configuration
157
+ next unless configuration_path.exist?
158
+
159
+ configuration_path.children().each do |child|
160
+ if child.directory? and (not child.children.empty?)
161
+ name = child.basename.to_s
162
+ next unless prebuild_targets.include?(name)
163
+
164
+ target_path = binary_path + name
165
+ target_path += configuration if configurations.size > 1
166
+ target_path.mkpath unless target_path.exist?
167
+ command = "cp -r #{child}/ #{target_path}"
168
+ `#{command}`
169
+
170
+ # touch checksum
171
+ checksum = nil
172
+ checksum = checkout_options[name][:commit] unless checkout_options[name].nil? # commitid有值则使用commitid
173
+ checksum = checksums[name] if checksum.nil?
174
+ `echo #{command} "\n" >> #{binary_path}/#{name}/#{checksum}.checksum` unless checksum.nil?
175
+ end
176
+ end
177
+ end
178
+ end
179
+
180
+ def make_options
181
+ options = {}
182
+ options[:sandbox] = @source_installer.sandbox
183
+ options[:build_dir] = build_dir
184
+ options[:output_path] = output_path
185
+ options[:clean_build] = Jxedt.config.clean_build?
186
+ options[:bitcode_enabled] = Jxedt.config.bitcode_enabled?
187
+ options[:device_build_enabled] = Jxedt.config.device_build_enabled?
188
+ options[:simulator_build_enabled] = Jxedt.config.simulator_build_enabled?
189
+ options[:disable_dsym] = Jxedt.config.disable_dsym?
190
+ options[:log_path] = Jxedt.config.build_log_path
191
+ options[:args] = Jxedt.config.build_args
192
+ options
193
+ end
194
+
195
+ def build_dir
196
+ sandbox = @source_installer.sandbox
197
+ sandbox.root.parent + "build"
198
+ end
199
+
200
+ def output_path
201
+ sandbox = @source_installer.sandbox
202
+ sandbox.root + Jxedt.config.binary_dir + "GeneratedFrameworks"
203
+ end
204
+
205
+ def clear_output_path
206
+ path = output_path
207
+ path.rmtree if path.exist?
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,103 @@
1
+ module Pod
2
+ class Target
3
+ # @since 1.5.0
4
+ class BuildSettings
5
+ # missing framework header search paths
6
+ def missing_framework_header_search_path(pt)
7
+ return [] unless pt.frame_header_search_paths_enable?
8
+
9
+ paths = []
10
+ pt.file_accessors.each do |file_accessor|
11
+ # xcframeworks
12
+ greater_than_or_equal_to_1_10_0 = Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.10.0')
13
+ greater_than_or_equal_to_1_11_0 = Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.11.0')
14
+ file_accessor.vendored_xcframeworks.map { |path|
15
+ if greater_than_or_equal_to_1_11_0
16
+ Xcode::XCFramework.new(file_accessor.spec.name, path)
17
+ else
18
+ Xcode::XCFramework.new(path)
19
+ end
20
+ }.each { |xcfwk|
21
+ xcfwk.slices.each { |slice|
22
+ fwk_name = slice.path.basename
23
+ if greater_than_or_equal_to_1_11_0
24
+ paths.push "${PODS_XCFRAMEWORKS_BUILD_DIR}/#{xcfwk.target_name}/#{fwk_name}/Headers"
25
+ elsif greater_than_or_equal_to_1_10_0
26
+ paths.push "${PODS_XCFRAMEWORKS_BUILD_DIR}/#{fwk_name.to_s.gsub(/\.framework$/, '')}/#{fwk_name}/Headers"
27
+ else
28
+ paths.push "${PODS_CONFIGURATION_BUILD_DIR}/#{fwk_name}/Headers"
29
+ end
30
+ }
31
+ }
32
+ # Cocoapods 1.9.x bugs
33
+ if Gem::Version.new(Pod::VERSION) < Gem::Version.new('1.10.0')
34
+ file_accessor.vendored_xcframeworks.each { |path|
35
+ Dir.glob("#{path.to_s}/**/*.framework").each do |fwk_path|
36
+ header_path = Pathname.new("#{fwk_path}/Headers")
37
+ next unless header_path.exist?
38
+ paths.push "${PODS_ROOT}/#{header_path.relative_path_from(pt.sandbox.root)}"
39
+ end
40
+ }
41
+ end
42
+
43
+ # frameworks
44
+ (file_accessor.vendored_frameworks - file_accessor.vendored_xcframeworks).each { |framework|
45
+ header_path = Pathname.new("#{framework}/Headers")
46
+ next unless header_path.exist?
47
+ paths.push "${PODS_ROOT}/#{header_path.relative_path_from(pt.sandbox.root)}"
48
+ }
49
+ end
50
+ replace_xcconfig_configuration_paths(paths)
51
+ paths.uniq
52
+ end
53
+
54
+ # replace different configuration xcconfig
55
+ def replace_xcconfig_configuration_paths(paths)
56
+ xcconfig_configuration_alias = Jxedt.config.xcconfig_configuration_alias
57
+ support_configurations = Jxedt.config.support_configurations
58
+ match_configuration = support_configurations.join('|')
59
+ paths.map! { |path|
60
+ if path =~ /#{xcconfig_configuration_alias}-(#{match_configuration})/
61
+ configuration = @configuration.to_s.downcase
62
+ matchs = support_configurations.select {|name| name.downcase == configuration }
63
+ path.gsub!(/#{xcconfig_configuration_alias}-(#{match_configuration})/, "#{xcconfig_configuration_alias}-#{matchs.first}") if matchs.count == 1
64
+ end
65
+ path
66
+ }
67
+ paths
68
+ end
69
+
70
+ # A subclass that generates build settings for a `PodTarget`
71
+ class AggregateTargetSettings
72
+ # @return [Array<String>]
73
+ alias_method :old_raw_header_search_paths, :_raw_header_search_paths
74
+ def _raw_header_search_paths
75
+ header_search_paths = old_raw_header_search_paths
76
+ header_search_paths.concat pod_targets.flat_map { |pt| missing_framework_header_search_path(pt) }
77
+ header_search_paths.uniq
78
+ end
79
+ end
80
+
81
+ # A subclass that generates build settings for a {PodTarget}
82
+ class PodTargetSettings
83
+ # @return [Array<String>]
84
+ alias_method :old_raw_header_search_paths, :_raw_header_search_paths
85
+ def _raw_header_search_paths
86
+ header_search_paths = old_raw_header_search_paths
87
+ header_search_paths.concat dependent_targets.flat_map { |pt| missing_framework_header_search_path(pt) } if target.should_build?
88
+ header_search_paths.uniq
89
+ end
90
+
91
+ # 按照规则替换framework_search_paths,兼容不同的configuration
92
+ # 从编译上来说,仅仅替换了framework_search_paths的路径就够了
93
+ # @return [Array<String>]
94
+ alias_method :old_raw_framework_search_paths, :_raw_framework_search_paths
95
+ def _raw_framework_search_paths
96
+ framework_search_paths = old_raw_framework_search_paths
97
+ replace_xcconfig_configuration_paths(framework_search_paths)
98
+ framework_search_paths
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,157 @@
1
+ module Pod
2
+ class Command
3
+ class JxedtCommand < Command
4
+ class Header < JxedtCommand
5
+ self.summary = 'header fix'
6
+ self.description = <<-DESC
7
+ 修改头文件引用问题。\n
8
+ 例如修改#import "AFNetworking.h"或#import <AFNetworking.h>这种头文件引用方式为#import <AFNetworking/AFNetworking.h>\n
9
+ 使用方式:\n
10
+ 到Podfile文件所在目录执行以下命令\n
11
+ 1. 修改某个组件的头文件引用\n
12
+ pod jxedt headerfix --name=PodA --dir=PodA RealPath --write\n
13
+ 2. 修改工程的头文件引用\n
14
+ pod jxedt headerfix --dir=project path --write\n
15
+ DESC
16
+ self.command = 'headerfix'
17
+ self.arguments = [
18
+ ]
19
+ def self.options
20
+ [
21
+ ['--name', '需要修改header引用的pod name。没有该参数则会认为修改的是工程中的文件'],
22
+ ['--dir', '需要修改的文件夹路径,一般情况下为pod组件的真实目录。如果修改的pod组件是development pods,也可以不传该参数。'],
23
+ ['--write', '修改命中的头文件引用,不写入则直接输出需要修改的文件和修改内容。默认false'],
24
+ ['--suffix', '处理的文件后缀,默认处理\'h,m,mm,pch\'后缀的文件'],
25
+ ['--header-regulation', 'header name的正则,默认为\'[\w+-]*\.h\',如果不满足也可以自定义'],
26
+ ]
27
+ end
28
+ def initialize(argv)
29
+ @pod_name = argv.option('name')
30
+ @dir = argv.option('dir')
31
+ @suffix = argv.option('suffix', 'h,m,mm,pch')
32
+ @force_write = argv.flag?('write', false)
33
+ @header_regulation = argv.option('header-regulation')
34
+ super
35
+ end
36
+
37
+ def validate!
38
+ super
39
+ help! 'A podspec name or dir is required.' if @pod_name.nil? && @dir.nil?
40
+ end
41
+
42
+ def run
43
+ @installer = installer_for_config
44
+ help! '请检查命令执行路径,需要在Podfile文件所在目录执行' if @installer.nil?
45
+
46
+ @installer.sandbox.prepare # sandbox prepare
47
+ @installer.resolve_dependencies # 解析依赖
48
+ # @installer.integrate # 不需要执行也可以解析依赖关系
49
+
50
+ process_target_files = process_target_files!
51
+ dependent_targets = dependent_targets!
52
+
53
+ # 查找
54
+ public_header_mapping = {}
55
+ dependent_targets.each {|target|
56
+ next unless target.should_build?
57
+
58
+ # 获取所有.h文件
59
+ all_header_files = target.all_files.select {|file| file.to_s =~ /#{header_name_regulation}$/ }
60
+ # 建立header文件和product_module_name的映射
61
+ public_header_mapping.merge! all_header_files.reduce({}) { |hash, file|
62
+ basename = File.basename(file)
63
+ hash.update(basename.to_s => target.product_module_name)
64
+ }
65
+ }
66
+
67
+ # 遍历需要处理的文件
68
+ record = []
69
+ process_target_files.each {|file_path|
70
+ changed = false
71
+ lines = File.readlines(file_path)
72
+ # 获取命中的行
73
+ File.foreach(file_path).with_index {|line, num|
74
+ matched = line =~ /^\s*#import\s*"#{header_name_regulation}"\s*\n$/ || line =~ /^\s*#import\s*<#{header_name_regulation}>\s*\n$/
75
+ next unless matched
76
+
77
+ header_name = line.match(/(?<=")#{header_name_regulation}(?=")/) || line.match(/(?<=<)#{header_name_regulation}(?=>)/)
78
+ next unless public_header_mapping.include?("#{header_name}")
79
+
80
+ project_module_name = public_header_mapping["#{header_name}"]
81
+ replace_line = "#import " << "<#{project_module_name}/#{header_name}>\n"
82
+ lines[num] = replace_line
83
+ changed = true
84
+ record << "#{file_path} 第#{num}行,#{line} => #{replace_line}"
85
+ }
86
+ File.open(file_path, 'w') { |f| f.write(lines.join) } if changed && @force_write
87
+ }
88
+ puts "需要修改的地方共有:#{record.size} 处"
89
+ puts JSON.pretty_generate(record) if record.size > 0
90
+ end
91
+
92
+ def installer_for_config
93
+ config = Pod::Config.instance
94
+ return if config.podfile.nil?
95
+ Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
96
+ end
97
+
98
+ def header_name_regulation
99
+ @regulation = @header_regulation || '[\w+-]*\.h' # header name的规则 [a-zA-Z0-9_+-]
100
+ @regulation
101
+ end
102
+
103
+ def process_target_files!
104
+ process_target_files = []
105
+ unless @dir.nil?
106
+ def walk(path, &action)
107
+ return unless path.exist?
108
+ path.children.each do |child|
109
+ result = action.call(child, &action)
110
+ walk(child, &action) if result and child.directory?
111
+ end
112
+ end
113
+
114
+ path = Pathname.new(@dir)
115
+ walk(path) do |child|
116
+ if child.directory? and [".framework", ".xcframework", ".bundle", ".dSYM"].include? child.extname
117
+ next false
118
+ elsif child.file?
119
+ suffix = @suffix.split(',').join('|')
120
+ process_target_files << (path + child) if child.to_s =~ /.*\.(#{suffix})$/
121
+ next true
122
+ else
123
+ next true
124
+ end
125
+ end
126
+ else
127
+ process_target_files = @installer.pod_targets.flat_map {|target|
128
+ suffix = @suffix.split(',').join('|')
129
+ target.all_files.select {|file| file.to_s =~ /.*\.(#{suffix})$/ } if target.pod_name.to_s == @pod_name
130
+ }.reject(&:nil?).uniq
131
+ end
132
+ process_target_files
133
+ end
134
+
135
+ def dependent_targets!
136
+ dependent_targets = @installer.pod_targets
137
+ unless @pod_name.nil?
138
+ # 递归查找依赖
139
+ def recursion_dependent_targets(target)
140
+ target.dependent_targets.flat_map {|t|
141
+ targets = [t]
142
+ targets += recursion_dependent_targets(t) if target.dependent_targets.size > 0
143
+ targets
144
+ }.reject(&:nil?)
145
+ end
146
+
147
+ # 获取依赖
148
+ dependent_targets = @installer.pod_targets.flat_map {|target|
149
+ recursion_dependent_targets(target) if target.pod_name.to_s == @pod_name
150
+ }.reject(&:nil?).uniq
151
+ end
152
+ dependent_targets
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,40 @@
1
+ require_relative 'options/options'
2
+ require_relative 'header/header'
3
+
4
+ module Pod
5
+ class Command
6
+ class JxedtCommand < Command
7
+ self.summary = 'cocoapods-jxedt插件命令工具。'
8
+
9
+ self.description = <<-DESC
10
+ cocoapods-jxedt插件命令工具。
11
+ DESC
12
+
13
+ self.command = 'jxedt'
14
+ self.abstract_command = true
15
+
16
+ def self.options
17
+ [
18
+ ['--version', 'Show cocoapods-jxedt version'],
19
+ ].concat(super)
20
+ end
21
+
22
+ def initialize(argv)
23
+ @version = argv.flag?('version', false)
24
+ super
25
+ end
26
+
27
+ def validate!
28
+ if @version
29
+ require 'cocoapods-jxedt/gem_version'
30
+ puts "#{CocoapodsJxedt::VERSION}"
31
+ return
32
+ end
33
+ super
34
+ end
35
+
36
+ def run
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ module Pod
2
+ class Command
3
+ class JxedtCommand < Command
4
+ class Options < JxedtCommand
5
+ self.summary = 'binary配置参数介绍'
6
+ self.description = <<-DESC
7
+ binary插件配置介绍
8
+ DESC
9
+ self.command = 'options'
10
+ self.arguments = [
11
+ ]
12
+ def self.options
13
+ []
14
+ end
15
+ def initialize(argv)
16
+ super
17
+ end
18
+
19
+ def validate!
20
+ super
21
+ end
22
+
23
+ def run
24
+ require 'cocoapods-jxedt/binary/config'
25
+ require 'json'
26
+
27
+ dsl_config = Jxedt::Config::APPLICABLE_DSL_CONFIG
28
+ puts JSON.pretty_generate(dsl_config)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1 @@
1
+ require 'cocoapods-jxedt/command/jxedt'
@@ -0,0 +1,3 @@
1
+ module CocoapodsJxedt
2
+ VERSION = "0.0.9"
3
+ end
@@ -0,0 +1,12 @@
1
+ class Module
2
+ def class_alias_method(to, from)
3
+ # https://tieba.baidu.com/p/5535445605?red_tag=0735709674 贴吧大神给出的方案
4
+ # 类方法可以看做singleton class(单例类)的实例方法,下面两个方法都可以,上面这个方式也适用于早期的ruby版本
5
+ (class << self;self;end).send(:alias_method, to, from)
6
+ # self.singleton_class.send(:alias_method, to, from)
7
+ end
8
+
9
+ def class_attr_accessor(symbol)
10
+ self.class.send(:attr_accessor, symbol)
11
+ end
12
+ end
@@ -0,0 +1 @@
1
+ require 'cocoapods-jxedt/gem_version'
@@ -0,0 +1,3 @@
1
+ require 'cocoapods-jxedt/command'
2
+ require 'cocoapods-jxedt/binary/main.rb'
3
+ require 'cocoapods-jxedt/tool'