ios_double_source 0.1.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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib_blur/core/auto_build.rb +162 -0
- data/lib_blur/core/build_item.rb +39 -0
- data/lib_blur/core/commit.rb +10 -0
- data/lib_blur/core/config.rb +44 -0
- data/lib_blur/core/cost.rb +43 -0
- data/lib_blur/core/git_helper.rb +94 -0
- data/lib_blur/core/github_fork.rb +74 -0
- data/lib_blur/core/github_helper.rb +97 -0
- data/lib_blur/core/gitlab_helper.rb +270 -0
- data/lib_blur/core/hook_manager.rb +21 -0
- data/lib_blur/core/podspec.rb +92 -0
- data/lib_blur/core/push.rb +54 -0
- data/lib_blur/core/repo.rb +161 -0
- data/lib_blur/core/repo_cocoapods.rb +46 -0
- data/lib_blur/core/repo_module.rb +120 -0
- data/lib_blur/core/repo_module_binary.rb +175 -0
- data/lib_blur/core/repo_module_source.rb +155 -0
- data/lib_blur/core/repo_xcode.rb +27 -0
- data/lib_blur/core/repo_xcode_package.rb +199 -0
- data/lib_blur/core/repo_xcode_shell.rb +101 -0
- data/lib_blur/core/util/file_helper.rb +62 -0
- data/lib_blur/core/util/request.rb +50 -0
- data/lib_blur/core/util/string.rb +37 -0
- data/lib_blur/ios_double_source.rb +5 -0
- data/lib_blur/version.rb +4 -0
- metadata +145 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'repo'
|
3
|
+
require_relative 'build_item'
|
4
|
+
module Build
|
5
|
+
class RepoModule < Repo
|
6
|
+
attr_accessor :build_item
|
7
|
+
attr_accessor :pod_name
|
8
|
+
attr_accessor :pod_version
|
9
|
+
attr_accessor :third
|
10
|
+
attr_accessor :snapshot
|
11
|
+
attr_accessor :pod_version_final
|
12
|
+
attr_accessor :podspec_json_path
|
13
|
+
attr_accessor :podspec_content
|
14
|
+
attr_accessor :framework_name
|
15
|
+
attr_accessor :project_id
|
16
|
+
def initialize(path, ssh_url, branch, pod_name, pod_version, third, build_item)
|
17
|
+
super(path, ssh_url, branch)
|
18
|
+
@pod_name = pod_name
|
19
|
+
@pod_version = pod_version
|
20
|
+
@third = third.to_s.downcase == "true"
|
21
|
+
@build_item = build_item
|
22
|
+
validate
|
23
|
+
analyzer
|
24
|
+
end
|
25
|
+
def validate
|
26
|
+
if pod_name.empty?or pod_version.empty?
|
27
|
+
error = "pod_name pod_version 均不能为空"
|
28
|
+
pusher.push("❌ 打包失败", error)
|
29
|
+
Process.exit(-1)
|
30
|
+
end
|
31
|
+
if pod_name == "xxx" or pod_version == "xxx" or ssh_url == "xxx" or branch == "xxx"
|
32
|
+
error = "pod_name pod_version ssh_url branch 任一个都不能为xxx"
|
33
|
+
pusher.push("❌ 打包失败", error)
|
34
|
+
Process.exit(-1)
|
35
|
+
end
|
36
|
+
if pod_version.include?("SNAPSHOT")
|
37
|
+
error = "版本号里不能带SNAPSHOT,如需SNAPSHOT请使用snapshot参数"
|
38
|
+
pusher.push("❌ 打包失败", error)
|
39
|
+
Process.exit(-1)
|
40
|
+
end
|
41
|
+
if self.third and self.build_item.snapshot
|
42
|
+
error = "三方库不能打SNAPSHOT包"
|
43
|
+
pusher.push("❌ 打包失败", error)
|
44
|
+
Process.exit(-1)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def analyzer
|
48
|
+
@pod_version_final = self.build_item.snapshot ? pod_version+"-SNAPSHOT" : pod_version
|
49
|
+
end
|
50
|
+
def build_binary
|
51
|
+
build_item.real_device or build_item.simulator
|
52
|
+
end
|
53
|
+
def update_binary
|
54
|
+
source_files_array = Array.new
|
55
|
+
if podspec_content["source_files"].class == Array
|
56
|
+
source_files_array = podspec_content["source_files"]
|
57
|
+
else
|
58
|
+
source_files_array << podspec_content["source_files"]
|
59
|
+
end
|
60
|
+
sub_specs = podspec_content["subspecs"]
|
61
|
+
if sub_specs
|
62
|
+
sub_specs.each do |sub_spec|
|
63
|
+
if podspec_content["source_files"].class == Array
|
64
|
+
source_files_array = source_files_array + sub_spec["source_files"]
|
65
|
+
else
|
66
|
+
source_files_array << sub_spec["source_files"]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
have_implementation = false
|
71
|
+
source_files_array.each do |source_files|
|
72
|
+
source_files_path = "#{self.path}/#{source_files}"
|
73
|
+
if FileHelper.have_implementation_files(source_files_path)
|
74
|
+
have_implementation = true
|
75
|
+
break
|
76
|
+
end
|
77
|
+
end
|
78
|
+
if not have_implementation or pod_name == "MUCDebugPlugins"
|
79
|
+
build_item.real_device = false
|
80
|
+
build_item.simulator = false
|
81
|
+
warn = "当前组件无实现文件或定制为不需要打二进制"
|
82
|
+
puts warn
|
83
|
+
pusher.push("【⚠️组件不构建二进制提醒】", warn)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
def get_commit_msg
|
87
|
+
committer = podspec_content["committer"]
|
88
|
+
commit_time = podspec_content["commitTime"]
|
89
|
+
commit_id = podspec_content["commitID"]
|
90
|
+
"#{self.pod_name} #{self.pod_version_final} (#{committer} #{commit_time} #{commit_id})"
|
91
|
+
end
|
92
|
+
def git_commit(commit_msg = nil)
|
93
|
+
commit_msg = get_commit_msg
|
94
|
+
super commit_msg
|
95
|
+
end
|
96
|
+
def git_tag
|
97
|
+
current = Dir.pwd
|
98
|
+
Dir.chdir(self.path)
|
99
|
+
dir_name = File.basename(self.path)
|
100
|
+
puts "\n⏩ 推送版本号tag(#{dir_name})"
|
101
|
+
discard_pull
|
102
|
+
if self.build_item.snapshot or self.third
|
103
|
+
git_tag_delete_local(pod_version_final)
|
104
|
+
git_tag_delete_origin(pod_version_final)
|
105
|
+
end
|
106
|
+
git_tag_local(pod_version_final)
|
107
|
+
git_tag_origin(pod_version_final)
|
108
|
+
Dir.chdir(current)
|
109
|
+
end
|
110
|
+
def git_clone(only_head)
|
111
|
+
super
|
112
|
+
project_obj = gitlab_helper.fetch_project(pod_name, http_url, can_raise: true)
|
113
|
+
unless project_obj
|
114
|
+
return
|
115
|
+
end
|
116
|
+
@project_id = project_obj.id
|
117
|
+
puts "查询(#{http_url})项目ID: #{@project_id} 群组ID:#{project_obj.namespace.id}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'fileutils'
|
3
|
+
require_relative 'repo_module'
|
4
|
+
require_relative 'util/file_helper'
|
5
|
+
module Build
|
6
|
+
class RepoModuleBinary < RepoModule
|
7
|
+
attr_accessor :framework_binary_path
|
8
|
+
def copy_framework(repo_xcode_package, repo_module_source)
|
9
|
+
build_real_device = build_item.real_device
|
10
|
+
build_simulator = build_item.simulator
|
11
|
+
if not build_real_device and not build_simulator
|
12
|
+
return
|
13
|
+
end
|
14
|
+
@framework_name = repo_module_source.framework_name
|
15
|
+
origin_framework_real_device = "#{repo_xcode_package.real_device_archive_path}/Products/Library/Frameworks/#{framework_name}.framework"
|
16
|
+
origin_framework_simulator = "#{repo_xcode_package.simulator_archive_path}/Products/Library/Frameworks/#{framework_name}.framework"
|
17
|
+
if build_real_device and not File.exist?(origin_framework_real_device)
|
18
|
+
error = "真机架构framework不存在"
|
19
|
+
pusher.push("❌ 打包失败", error)
|
20
|
+
Process.exit(-1)
|
21
|
+
end
|
22
|
+
if build_simulator and not File.exist?(origin_framework_simulator)
|
23
|
+
error = "模拟器架构framework不存在"
|
24
|
+
pusher.push("❌ 打包失败", error)
|
25
|
+
Process.exit(-1)
|
26
|
+
end
|
27
|
+
@framework_binary_path = "#{self.path}/#{framework_name}.xcframework"
|
28
|
+
command = "xcodebuild -create-xcframework"
|
29
|
+
if build_real_device
|
30
|
+
command += " -framework \"#{origin_framework_real_device}\""
|
31
|
+
end
|
32
|
+
if build_simulator
|
33
|
+
command += " -framework \"#{origin_framework_simulator}\""
|
34
|
+
end
|
35
|
+
command += " -output \"#{framework_binary_path}\""
|
36
|
+
puts "\n⏩ 合并并拷贝framework(#{File.basename(self.path)}): #{command}"
|
37
|
+
res = system command
|
38
|
+
unless res == true
|
39
|
+
error = "合并framework失败"
|
40
|
+
pusher.push("❌ 打包失败", error)
|
41
|
+
Process.exit(-1)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
def copy_resources(repo_xcode_package, repo_module_source)
|
45
|
+
puts "\n⏩ 拷贝资源文件到framework中(#{File.basename(self.path)}):"
|
46
|
+
bundle_path_array = repo_xcode_package.resource_bundles_paths
|
47
|
+
resource_paths = repo_xcode_package.resource_paths
|
48
|
+
if bundle_path_array.length == 0
|
49
|
+
puts "源码podspec里未指定resource_bundles"
|
50
|
+
end
|
51
|
+
if resource_paths.length == 0
|
52
|
+
puts "源码podspec里未指定resource"
|
53
|
+
end
|
54
|
+
result_array = bundle_path_array + resource_paths
|
55
|
+
puts "读取到的资源文件路径如下"
|
56
|
+
puts result_array
|
57
|
+
if result_array.length == 0
|
58
|
+
puts "为空不拷贝"
|
59
|
+
return
|
60
|
+
end
|
61
|
+
framework_path_array = Array.new
|
62
|
+
framework = "#{repo_module_source.framework_name}.framework"
|
63
|
+
FileHelper.recursion_find(self.path, framework, framework_path_array)
|
64
|
+
puts "以上资源文件需要分别拷贝到如下路径中"
|
65
|
+
puts framework_path_array
|
66
|
+
framework_path_array.each { |framework_path|
|
67
|
+
result_array.each { |bundle_path|
|
68
|
+
bundle_name = File.basename(bundle_path)
|
69
|
+
des_bundle_path = "#{framework_path}/#{bundle_name}"
|
70
|
+
unless File.exist?(des_bundle_path)
|
71
|
+
FileUtils.cp_r(bundle_path, framework_path)
|
72
|
+
end
|
73
|
+
}
|
74
|
+
}
|
75
|
+
puts "拷贝资源文件完成"
|
76
|
+
end
|
77
|
+
def copy_podspec(repo_xcode_package, repo_module_source)
|
78
|
+
build_real_device = build_item.real_device
|
79
|
+
build_simulator = build_item.simulator
|
80
|
+
if not build_real_device and not build_simulator
|
81
|
+
return
|
82
|
+
end
|
83
|
+
puts "\n⏩ 拷贝podspec文件到framework中(#{File.basename(self.path)}):"
|
84
|
+
@podspec_json_path = "#{self.path}/#{self.pod_name}.podspec.json"
|
85
|
+
source_files_dir = build_real_device ? "*arm64*" : "*simulator*"
|
86
|
+
@podspec_content = repo_module_source.podspec_content
|
87
|
+
podspec_content.delete("license")
|
88
|
+
podspec_content.delete("module_map")
|
89
|
+
podspec_content.delete("public_header_files")
|
90
|
+
podspec_content.delete("private_header_files")
|
91
|
+
podspec_content.delete("exclude_files")
|
92
|
+
podspec_content.delete("prefix_header_file")
|
93
|
+
if pod_name == "libwebp" or pod_name == "libcmark"
|
94
|
+
podspec_content.delete("prepare_command")
|
95
|
+
end
|
96
|
+
podspec_content["source"] = {} #二进制后, 只从tag读取,去除其他的标志信息
|
97
|
+
podspec_content["source"]["git"] = self.ssh_url
|
98
|
+
podspec_content["source"]["tag"] = self.pod_version_final
|
99
|
+
podspec_content["source_files"] = "**/*/#{source_files_dir}/*.framework/Headers/*.h"
|
100
|
+
podspec_content["version"] = self.pod_version_final
|
101
|
+
podspec_content["vendored_frameworks"] = "*.xcframework"
|
102
|
+
resources = podspec_content["resources"] ? podspec_content["resources"] : podspec_content["resource"]
|
103
|
+
podspec_content["resources"] = []
|
104
|
+
if resources
|
105
|
+
podspec_content.delete("resource")
|
106
|
+
resources_array = resources.class == Array ? resources : [resources]
|
107
|
+
resources_array.each { |resource|
|
108
|
+
resource_path = "#{repo_module_source.path}/#{resource}"
|
109
|
+
Dir[resource_path].select{|real_path|
|
110
|
+
resource_name = File.basename(real_path)
|
111
|
+
podspec_content["resources"] << "**/*/#{source_files_dir}/*.framework/#{resource_name}"
|
112
|
+
}
|
113
|
+
}
|
114
|
+
end
|
115
|
+
resource_bundles = podspec_content["resource_bundles"] ? podspec_content["resource_bundles"] : podspec_content["resource_bundle"]
|
116
|
+
if resource_bundles
|
117
|
+
podspec_content.delete("resource_bundles")
|
118
|
+
podspec_content.delete("resource_bundle")
|
119
|
+
resource_bundles_array = resource_bundles.class == Array ? resource_bundles : [resource_bundles]
|
120
|
+
resource_bundles_array.each { |resource_bundle|
|
121
|
+
if resource_bundle.class == Hash
|
122
|
+
resource_bundle.each_key {|key|
|
123
|
+
podspec_content["resources"] << "**/*/#{source_files_dir}/*.framework/#{key}.bundle"
|
124
|
+
}
|
125
|
+
end
|
126
|
+
}
|
127
|
+
end
|
128
|
+
podspec_content["resources"] << "**/*/#{source_files_dir}/*.framework/*.podspec.json"
|
129
|
+
podspec_content["address"] = self.http_url
|
130
|
+
podspec_content["frameworkSize"] = self.size_format
|
131
|
+
podspec_content["archive"] = repo_xcode_package.debug_mode ? "Debug" : "Release"
|
132
|
+
if podspec_content.has_key?("swift_version")
|
133
|
+
podspec_content["pod_target_xcconfig"] = {"BUILD_LIBRARY_FOR_DISTRIBUTION": true}
|
134
|
+
end
|
135
|
+
subspecs = podspec_content["subspecs"]
|
136
|
+
if subspecs.respond_to?(:each)
|
137
|
+
subspecs.each do |subspec|
|
138
|
+
subspec.delete("resources")
|
139
|
+
subspec.delete("resource_bundles")
|
140
|
+
subspec.delete("exclude_files")
|
141
|
+
subspec.delete("public_header_files")
|
142
|
+
subspec.delete("project_header_files")
|
143
|
+
if subspec["ios"] and subspec["ios"].class == Hash
|
144
|
+
sun = subspec["ios"]
|
145
|
+
sun.delete("resources")
|
146
|
+
sun.delete("resource_bundles")
|
147
|
+
sun.delete("exclude_files")
|
148
|
+
sun.delete("public_header_files")
|
149
|
+
sun.delete("project_header_files")
|
150
|
+
sun.delete("source_files")
|
151
|
+
end
|
152
|
+
subspec["source_files"] = "placeholder.m"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
new_file = File.new(podspec_json_path, "w+")
|
156
|
+
if new_file
|
157
|
+
new_file.syswrite(JSON.pretty_generate(podspec_content))
|
158
|
+
end
|
159
|
+
framework_real_device_path = "#{framework_binary_path}/ios-arm64/#{framework_name}.framework"
|
160
|
+
if File.directory?(framework_real_device_path)
|
161
|
+
FileUtils.cp(podspec_json_path, framework_real_device_path)
|
162
|
+
end
|
163
|
+
framework_simulator_path = "#{framework_binary_path}/ios-x86_64-simulator/#{framework_name}.framework"
|
164
|
+
if File.directory?(framework_simulator_path)
|
165
|
+
FileUtils.cp(podspec_json_path, framework_simulator_path)
|
166
|
+
end
|
167
|
+
puts "拷贝完成"
|
168
|
+
end
|
169
|
+
def git_tag
|
170
|
+
if build_item.real_device or build_item.simulator
|
171
|
+
super
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'fileutils'
|
3
|
+
require 'json'
|
4
|
+
require_relative 'podspec'
|
5
|
+
require_relative 'repo_module'
|
6
|
+
require_relative 'util/string'
|
7
|
+
require_relative 'util/file_helper'
|
8
|
+
module Build
|
9
|
+
class RepoModuleSource < RepoModule
|
10
|
+
def validate
|
11
|
+
super
|
12
|
+
if self.branch.start_with?("release_")
|
13
|
+
branch_version = self.branch.gsub("release_", "")
|
14
|
+
if branch_version != self.pod_version
|
15
|
+
error = "以release_开头的分支,后边应该跟版本号,且打包的版本号与跟的版本号一致,例如当前#{self.branch}, 打包版本应该是#{branch_version}"
|
16
|
+
pusher.push("❌ 打包失败", error)
|
17
|
+
Process.exit(-1)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
version_pure_number = self.pod_version.gsub(".","").is_number?
|
21
|
+
if self.branch != "master" and self.branch != self.pod_version and not self.third #特殊处理
|
22
|
+
if version_pure_number and not self.branch.start_with?("release_")
|
23
|
+
error = "三段式的版本号打包,应使用release_开头的分支来打包,且打包的版本号与跟的版本号一致,例如当前#{self.pod_version},打包分支应该是release_#{self.pod_version}"
|
24
|
+
pusher.push("❌ 打包失败", error)
|
25
|
+
Process.exit(-1)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def lock_branch_if_need
|
30
|
+
if build_item.snapshot
|
31
|
+
puts "当前源码仓库为SNAPSHOT包,无需锁死分支"
|
32
|
+
return
|
33
|
+
end
|
34
|
+
if third
|
35
|
+
puts "当前打包为三方库,无需锁死分支"
|
36
|
+
return
|
37
|
+
end
|
38
|
+
puts "当前源码仓库(ID:#{project_id})打包模式为正式包,需锁死分支 #{branch}"
|
39
|
+
gitlab_helper.lock_branch(project_id, branch)
|
40
|
+
setting_url = "#{page_url}/-/settings/repository#js-protected-branches-settings"
|
41
|
+
pusher.push("【✅组件分支已锁死无法提交】", "配置地址 #{setting_url}")
|
42
|
+
end
|
43
|
+
def force_cover_validate(repo_cocoapods_source)
|
44
|
+
if build_item.force_cover
|
45
|
+
puts "不校验commit信息是否包含上次,原因:force_cover = false"
|
46
|
+
return
|
47
|
+
end
|
48
|
+
unless ssh_url.is_gitlab_url
|
49
|
+
puts "不校验commit信息是否包含上次,原因:当前组件仓库非gitlab url, url = #{ssh_url}"
|
50
|
+
return
|
51
|
+
end
|
52
|
+
pod_name_path = "#{repo_cocoapods_source.path}/#{pod_name}"
|
53
|
+
unless File.directory?(pod_name_path)
|
54
|
+
puts "不校验commit信息是否包含上次,原因:repo_cocoapods_source没有当前组件文件夹"
|
55
|
+
return
|
56
|
+
end
|
57
|
+
pod_version_path = "#{pod_name_path}/#{pod_version_final}"
|
58
|
+
unless File.directory?(pod_version_path)
|
59
|
+
puts "不校验commit信息是否包含上次,原因:repo_cocoapods_source组件文件夹没有当前版本文件夹"
|
60
|
+
return
|
61
|
+
end
|
62
|
+
podspec_json_path = "#{pod_version_path}/#{pod_name}.podspec.json"
|
63
|
+
unless File.exist?(podspec_json_path)
|
64
|
+
puts "不校验commit信息是否包含上次,原因:repo_cocoapods_source组件文件夹没有podspec.json文件"
|
65
|
+
return
|
66
|
+
end
|
67
|
+
json = File.read(podspec_json_path)
|
68
|
+
podspec_content = JSON.parse(json)
|
69
|
+
commit_id = podspec_content["commitID"]
|
70
|
+
committer = podspec_content["committer"]
|
71
|
+
commit_msg = podspec_content["commitMsg"]
|
72
|
+
commit_time = podspec_content["commitTime"]
|
73
|
+
unless commit_id
|
74
|
+
puts "不校验commit信息是否包含上次,原因:repo_cocoapods_source的podspec.json 读取commitID为空"
|
75
|
+
return
|
76
|
+
end
|
77
|
+
contain = self.gitlab_helper.branch_contain_commit(project_id, branch, commit_id)
|
78
|
+
puts "\n⏩ (#{File.basename(self.path)})上次发布的commit信息是:"
|
79
|
+
puts "#{commit_id} #{commit_msg} #{commit_msg} #{commit_time}"
|
80
|
+
if contain
|
81
|
+
puts "校验commit信息是否包含上次:校验通过"
|
82
|
+
else
|
83
|
+
error = "当前发布分支#{branch}不包含上次发布的#{committer}提交, 请先合并分支再打包或手动选择强制覆盖"
|
84
|
+
pusher.push("❌ 打包失败", error)
|
85
|
+
Process.exit(-1)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
def update_podspec
|
89
|
+
podspec_path = "#{self.path}/#{self.pod_name}.podspec"
|
90
|
+
@podspec_json_path = "#{podspec_path}.json"
|
91
|
+
if File.exist?(podspec_path) # 生成json文件
|
92
|
+
command = "pod ipc spec #{podspec_path} >> #{podspec_json_path}"
|
93
|
+
res = system command
|
94
|
+
unless res == true
|
95
|
+
error = "命令执行失败: #{command}"
|
96
|
+
pusher.push("❌ 打包失败", error)
|
97
|
+
Process.exit(-1)
|
98
|
+
end
|
99
|
+
FileUtils.rm_rf(podspec_path)
|
100
|
+
end
|
101
|
+
unless File.exist?(podspec_json_path)
|
102
|
+
error = "podspec文件不存在"
|
103
|
+
pusher.push("❌ 打包失败", error)
|
104
|
+
Process.exit(-1)
|
105
|
+
end
|
106
|
+
podspec = Podspec.new(podspec_json_path)
|
107
|
+
podspec_content = podspec.podspec_content
|
108
|
+
podspec_content.delete("license")
|
109
|
+
podspec_content["source"]["git"] = ssh_url
|
110
|
+
unless self.third
|
111
|
+
podspec_content["version"] = pod_version_final
|
112
|
+
podspec_content["source"]["tag"] = pod_version_final
|
113
|
+
end
|
114
|
+
if pod_name == "CocoaHTTPServer"
|
115
|
+
podspec_content["pod_target_xcconfig"] = {'GCC_PREPROCESSOR_DEFINITIONS' => ['$(inherited)', 'DD_LEGACY_MACROS=1']}
|
116
|
+
elsif pod_name == "Protobuf"
|
117
|
+
podspec_content["pod_target_xcconfig"] = {'GCC_PREPROCESSOR_DEFINITIONS' => ['$(inherited)', 'GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1']}
|
118
|
+
end
|
119
|
+
if pod_name == "MLeaksFinder"
|
120
|
+
podspec_content["public_header_files"] << "MLeaksFinder/MLeaksMessenger.h"
|
121
|
+
end
|
122
|
+
podspec_content["address"] = http_url
|
123
|
+
podspec_content["committer"] = last_commit.committer
|
124
|
+
podspec_content["commitID"] = last_commit.commit_id
|
125
|
+
podspec_content["commitMsg"] = last_commit.commit_msg
|
126
|
+
podspec_content["commitTime"] = last_commit.commit_time
|
127
|
+
podspec_content["desc"] = "这是一份自动生成的文件, 请勿手动修改"
|
128
|
+
@podspec_content = podspec_content
|
129
|
+
__update_framework_name(podspec_content)
|
130
|
+
new_file = File.new(podspec_json_path, "w+")
|
131
|
+
if new_file
|
132
|
+
new_file.syswrite(JSON.pretty_generate(podspec_content))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
private
|
136
|
+
def __update_framework_name(podspec_content)
|
137
|
+
framework_name = podspec_content["module_name"]
|
138
|
+
header_dir = podspec_content["header_dir"]
|
139
|
+
if framework_name.nil?
|
140
|
+
framework_name = header_dir ? header_dir : pod_name
|
141
|
+
end
|
142
|
+
framework_name = framework_name.gsub("-", "_")
|
143
|
+
framework_name = framework_name.gsub("+", "_")
|
144
|
+
@framework_name = framework_name
|
145
|
+
end
|
146
|
+
public def git_tag
|
147
|
+
unless self.third
|
148
|
+
super
|
149
|
+
end
|
150
|
+
if self.third and build_item.force_cover
|
151
|
+
super
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'repo'
|
3
|
+
module Build
|
4
|
+
class RepoXCode < Repo
|
5
|
+
attr_reader :xcworkspace
|
6
|
+
attr_reader :scheme
|
7
|
+
def initialize(path, ssh_url, branch, xcworkspace = nil, scheme = nil)
|
8
|
+
super(path, ssh_url, branch)
|
9
|
+
@xcworkspace = xcworkspace
|
10
|
+
@scheme = scheme
|
11
|
+
end
|
12
|
+
def pod_update
|
13
|
+
current = FileUtils.pwd
|
14
|
+
Dir.chdir(self.path)
|
15
|
+
dir_name = File.basename(self.path)
|
16
|
+
command = "pod update"
|
17
|
+
puts "\n⏩ (#{dir_name})执行命令: #{command}"
|
18
|
+
res = system command
|
19
|
+
unless res == true
|
20
|
+
error = "git命令执行失败: #{command}"
|
21
|
+
pusher.push("❌ 打包失败", error)
|
22
|
+
Process.exit(-1)
|
23
|
+
end
|
24
|
+
Dir.chdir(current)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'repo_xcode'
|
3
|
+
require_relative 'repo_module_source'
|
4
|
+
require_relative 'build_item'
|
5
|
+
require_relative 'util/file_helper'
|
6
|
+
require_relative 'hook_manager'
|
7
|
+
module Build
|
8
|
+
class RepoXcodePackage < RepoXCode
|
9
|
+
attr_accessor :debug_mode
|
10
|
+
attr_accessor :real_device_archive_path
|
11
|
+
attr_accessor :simulator_archive_path
|
12
|
+
attr_accessor :resource_bundles_paths
|
13
|
+
attr_accessor :resource_paths
|
14
|
+
def initialize(path, ssh_url, branch, xcworkspace, scheme)
|
15
|
+
super(path, ssh_url, branch, xcworkspace, scheme)
|
16
|
+
@debug_mode = false
|
17
|
+
@resource_bundles_paths = Array.new
|
18
|
+
@resource_paths = Array.new
|
19
|
+
end
|
20
|
+
def copy_yaml_from_repo(repo_xcode_shell)
|
21
|
+
third_party_yaml = "#{repo_xcode_shell.path}/PodfileThirdParty.yaml"
|
22
|
+
if File.exist?(third_party_yaml)
|
23
|
+
FileUtils.cp(third_party_yaml, self .path)
|
24
|
+
end
|
25
|
+
module_yaml = "#{repo_xcode_shell.path}/PodfileModule.yaml"
|
26
|
+
if File.exist?(module_yaml)
|
27
|
+
FileUtils.cp(module_yaml, self .path)
|
28
|
+
end
|
29
|
+
hooker = HookManager.instance
|
30
|
+
hooker.trigger_hook(Status::XCODE_PACKAGE_COPY_YAML, self.path)
|
31
|
+
end
|
32
|
+
def generate_local_yaml(repo_module_source)
|
33
|
+
local_yaml_path = "#{self.path}/PodfileLocal.yaml"
|
34
|
+
pod_name = repo_module_source.pod_name
|
35
|
+
dependencies_content = {}
|
36
|
+
dependencies_content["QUICK_BUILD"] = true
|
37
|
+
dependencies_content["PODS"] = []
|
38
|
+
pod_item_array = get_pod_in_self(pod_name)
|
39
|
+
if pod_item_array.size > 0
|
40
|
+
pod_item_array.each { |pod_item|
|
41
|
+
dependency = create_local_yaml_pod(pod_name, repo_module_source.path)
|
42
|
+
dependency["subspecs"] = pod_item["subspecs"]
|
43
|
+
dependency["configurations"] = pod_item["configurations"]
|
44
|
+
dependency["pod"] = pod_item["pod"]
|
45
|
+
dependencies_content["PODS"] << dependency
|
46
|
+
__update_debug_mode(pod_item)
|
47
|
+
}
|
48
|
+
else
|
49
|
+
dependency = create_local_yaml_pod(pod_name, repo_module_source.path)
|
50
|
+
dependencies_content["PODS"] << dependency
|
51
|
+
end
|
52
|
+
File.open(local_yaml_path, 'w') { |file|
|
53
|
+
file.write(dependencies_content.to_yaml)
|
54
|
+
}
|
55
|
+
end
|
56
|
+
def get_pod_in_self(pod_name)
|
57
|
+
third_party_yaml = "#{self.path}/PodfileThirdParty.yaml"
|
58
|
+
module_yaml = "#{self.path}/PodfileModule.yaml"
|
59
|
+
result = get_pod_in_yaml(pod_name, third_party_yaml)
|
60
|
+
if result.size > 0
|
61
|
+
return result
|
62
|
+
end
|
63
|
+
get_pod_in_yaml(pod_name, module_yaml)
|
64
|
+
end
|
65
|
+
def get_pod_in_yaml(pod_name, yaml_path)
|
66
|
+
pods_array = Array.new
|
67
|
+
result = []
|
68
|
+
yaml_content = YAML.load_file(yaml_path)
|
69
|
+
pods_array |= yaml_content["PODS"] ? yaml_content["PODS"] : []
|
70
|
+
pods_array.each { |item|
|
71
|
+
if item["pod"] == pod_name
|
72
|
+
result << item
|
73
|
+
elsif item["pod"] != nil and item["pod"].include?(pod_name+"/") #子仓库形式
|
74
|
+
result << item
|
75
|
+
end
|
76
|
+
}
|
77
|
+
result
|
78
|
+
end
|
79
|
+
def create_local_yaml_pod(pod_name, module_source_path)
|
80
|
+
dependency = {}
|
81
|
+
dependency["pod"] = pod_name
|
82
|
+
dependency["path"] = module_source_path
|
83
|
+
dependency["inhibit_warnings"] = true
|
84
|
+
dependency
|
85
|
+
end
|
86
|
+
public
|
87
|
+
def archive(repo_module_source)
|
88
|
+
do_archive(false)
|
89
|
+
if repo_module_source.build_item.simulator
|
90
|
+
do_archive(true)
|
91
|
+
else
|
92
|
+
puts "不构建模拟器"
|
93
|
+
end
|
94
|
+
update_resource_bundles_paths(repo_module_source)
|
95
|
+
update_resource_paths(repo_module_source)
|
96
|
+
end
|
97
|
+
private
|
98
|
+
def __update_debug_mode(pod_item)
|
99
|
+
configurations = pod_item["configurations"]
|
100
|
+
unless configurations
|
101
|
+
return
|
102
|
+
end
|
103
|
+
if configurations.class == Array
|
104
|
+
res = true
|
105
|
+
configurations.each { |config|
|
106
|
+
if config.to_s.downcase == "release"
|
107
|
+
res = false
|
108
|
+
break
|
109
|
+
end
|
110
|
+
}
|
111
|
+
@debug_mode = res
|
112
|
+
elsif configurations.class == String
|
113
|
+
@debug_mode = true
|
114
|
+
if configurations.downcase.include?("release")
|
115
|
+
@debug_mode = false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
@debug_mode = false
|
119
|
+
end
|
120
|
+
private
|
121
|
+
def do_archive(simulator = false)
|
122
|
+
current = Dir.pwd
|
123
|
+
Dir.chdir(self.path)
|
124
|
+
product_dir = simulator ? "ios_simulator" : "ios"
|
125
|
+
archive_path = "#{self.path}/build/#{product_dir}"
|
126
|
+
debug_mode_str = debug_mode ? "Debug" : "Release"
|
127
|
+
destination = simulator ? "iOS Simulator" : "iOS"
|
128
|
+
valid_arch = simulator ? " VALID_ARCHS=\"x86_64\"" : ""
|
129
|
+
if simulator
|
130
|
+
@simulator_archive_path = "#{archive_path}.xcarchive"
|
131
|
+
else
|
132
|
+
@real_device_archive_path = "#{archive_path}.xcarchive"
|
133
|
+
end
|
134
|
+
command = "xcodebuild archive"
|
135
|
+
command += " -workspace \"#{self.xcworkspace}\""
|
136
|
+
command += " -scheme \"#{self.scheme}\""
|
137
|
+
command += " -configuration #{debug_mode_str}"
|
138
|
+
command += " -destination \"generic/platform=#{destination}\""
|
139
|
+
command += " -allowProvisioningUpdates -allowProvisioningDeviceRegistration"
|
140
|
+
command += " -archivePath #{archive_path}"
|
141
|
+
command += valid_arch
|
142
|
+
command += " SKIP_INSTALL=NO"
|
143
|
+
command += " BUILD_LIBRARY_FOR_DISTRIBUTION=YES"
|
144
|
+
command += " -quiet"
|
145
|
+
build_type_string = simulator ? "模拟器" : "真机"
|
146
|
+
puts "\n⏩ 开始编译构建#{build_type_string}"
|
147
|
+
puts "#{build_type_string}构建命令: #{command}"
|
148
|
+
res = system command
|
149
|
+
unless res == true
|
150
|
+
puts "构建命令: #{command}"
|
151
|
+
error = "编译失败(#{build_type_string})"
|
152
|
+
pusher.push("❌ 编译失败", error)
|
153
|
+
Process.exit(-1)
|
154
|
+
end
|
155
|
+
puts "#{build_type_string}构建完成"
|
156
|
+
Dir.chdir(current)
|
157
|
+
end
|
158
|
+
private
|
159
|
+
def update_resource_bundles_paths(repo_module_source)
|
160
|
+
podspec_content = repo_module_source.podspec_content
|
161
|
+
applications_path = "#{self.real_device_archive_path}/Products/Applications"
|
162
|
+
unless Dir.exist?applications_path
|
163
|
+
applications_path = "#{self.simulator_archive_path}/Products/Applications"
|
164
|
+
end
|
165
|
+
resource_bundles = podspec_content["resource_bundles"] ? podspec_content["resource_bundles"] : podspec_content["resource_bundle"]
|
166
|
+
unless resource_bundles
|
167
|
+
return
|
168
|
+
end
|
169
|
+
unless resource_bundles.class == Hash
|
170
|
+
error = "resource_bundles写法必须是key-value结构"
|
171
|
+
pusher.push("❌ 打包失败", error)
|
172
|
+
Process.exit(-1)
|
173
|
+
end
|
174
|
+
bundle_path_array = Array.new
|
175
|
+
resource_bundles.each_key { |bundle_name|
|
176
|
+
bundle = "#{bundle_name}.bundle"
|
177
|
+
FileHelper.recursion_find(applications_path, bundle, bundle_path_array)
|
178
|
+
}
|
179
|
+
@resource_bundles_paths = bundle_path_array
|
180
|
+
end
|
181
|
+
def update_resource_paths(repo_module_source)
|
182
|
+
podspec_content = repo_module_source.podspec_content
|
183
|
+
resources = podspec_content["resources"] ? podspec_content["resources"] : podspec_content["resource"]
|
184
|
+
unless resources
|
185
|
+
return
|
186
|
+
end
|
187
|
+
resources_array = resources.class == Array ? resources : [resources]
|
188
|
+
if resources_array.length === 0
|
189
|
+
return
|
190
|
+
end
|
191
|
+
resources_array.each { |resource|
|
192
|
+
resource_path = "#{repo_module_source.path}/#{resource}"
|
193
|
+
Dir[resource_path].select{|real_path|
|
194
|
+
@resource_paths << real_path
|
195
|
+
}
|
196
|
+
}
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|