cocoapods-util 0.0.11
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/.gitignore +4 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +54 -0
- data/Rakefile +13 -0
- data/cocoapods-util.gemspec +25 -0
- data/lib/cocoapods-util/CocoapodsUtilHook.rb +18 -0
- data/lib/cocoapods-util/cocoapods-extend/extend.rb +2 -0
- data/lib/cocoapods-util/cocoapods-extend/install/list.rb +140 -0
- data/lib/cocoapods-util/cocoapods-extend/install.rb +15 -0
- data/lib/cocoapods-util/cocoapods-extend/repo/push.rb +40 -0
- data/lib/cocoapods-util/cocoapods-extend/repo/push_helper.rb +36 -0
- data/lib/cocoapods-util/cocoapods-extend/repo.rb +15 -0
- data/lib/cocoapods-util/command/util.rb +28 -0
- data/lib/cocoapods-util/command.rb +1 -0
- data/lib/cocoapods-util/gem_version.rb +3 -0
- data/lib/cocoapods-util/hooks/installer.rb +4 -0
- data/lib/cocoapods-util/libsource/source.rb +81 -0
- data/lib/cocoapods-util/libsource/source_linker.rb +184 -0
- data/lib/cocoapods-util/package/helper/builder.rb +194 -0
- data/lib/cocoapods-util/package/helper/framework.rb +61 -0
- data/lib/cocoapods-util/package/helper/framework_builder.rb +147 -0
- data/lib/cocoapods-util/package/helper/library_builder.rb +47 -0
- data/lib/cocoapods-util/package/helper/pod_utils.rb +126 -0
- data/lib/cocoapods-util/package/package.rb +177 -0
- data/lib/cocoapods-util/user_interface/build_failed_report.rb +15 -0
- data/lib/cocoapods-util/xcframework/xcframework.rb +66 -0
- data/lib/cocoapods-util/xcframework/xcramework_build.rb +133 -0
- data/lib/cocoapods-util.rb +1 -0
- data/lib/cocoapods_plugin.rb +3 -0
- data/spec/command/util_spec.rb +12 -0
- data/spec/spec_helper.rb +50 -0
- metadata +126 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
class Util < Command
|
4
|
+
class Package < Util
|
5
|
+
private
|
6
|
+
|
7
|
+
def build_static_sandbox
|
8
|
+
static_sandbox_root = Pathname.new(config.sandbox_root)
|
9
|
+
Sandbox.new(static_sandbox_root)
|
10
|
+
end
|
11
|
+
|
12
|
+
def install_pod(platform_name, sandbox)
|
13
|
+
podfile = podfile_from_spec(
|
14
|
+
@path,
|
15
|
+
@spec.name,
|
16
|
+
platform_name,
|
17
|
+
@spec.deployment_target(platform_name),
|
18
|
+
@subspecs,
|
19
|
+
@spec_sources,
|
20
|
+
@use_modular_headers,
|
21
|
+
@dependency_config
|
22
|
+
)
|
23
|
+
|
24
|
+
static_installer = Installer.new(sandbox, podfile)
|
25
|
+
static_installer.install!
|
26
|
+
|
27
|
+
unless static_installer.nil?
|
28
|
+
# default build settings
|
29
|
+
default_build_settings = Hash.new
|
30
|
+
default_build_settings["CLANG_MODULES_AUTOLINK"] = "NO"
|
31
|
+
default_build_settings["GCC_GENERATE_DEBUGGING_SYMBOLS"] = "YES" # 生成Debug编译信息
|
32
|
+
default_build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" unless @xcframework # 非xcframework排除ios simulator 64位架构
|
33
|
+
default_build_settings["EXCLUDED_ARCHS[sdk=appletvsimulator*]"] = "arm64" unless @xcframework # 非xcframework排除tvos simulator 64位架构
|
34
|
+
default_build_settings["BUILD_LIBRARY_FOR_DISTRIBUTION"] = "YES" # 编译swift生成swiftinterface文件
|
35
|
+
|
36
|
+
# merge user setting
|
37
|
+
default_build_settings.merge!(@build_settings) unless @build_settings.empty?
|
38
|
+
|
39
|
+
static_installer.pods_project.targets.each do |target|
|
40
|
+
target.build_configurations.each do |config|
|
41
|
+
default_build_settings.each { |key, value| config.build_settings[key.to_s] = value.to_s }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
static_installer.pods_project.save
|
45
|
+
end
|
46
|
+
|
47
|
+
static_installer
|
48
|
+
end
|
49
|
+
|
50
|
+
def podfile_from_spec(path, spec_name, platform_name, deployment_target, subspecs, sources, use_modular_headers, dependency_config)
|
51
|
+
options = {}
|
52
|
+
if path
|
53
|
+
if @local
|
54
|
+
options[:path] = path
|
55
|
+
else
|
56
|
+
options[:podspec] = path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
options[:subspecs] = subspecs if subspecs
|
60
|
+
Pod::Podfile.new do
|
61
|
+
sources.each { |s| source s }
|
62
|
+
platform(platform_name, deployment_target)
|
63
|
+
pod(spec_name, options) unless dependency_config.keys.include?(spec_name)
|
64
|
+
|
65
|
+
dependency_config.each do |name, config|
|
66
|
+
dependency_options = {}
|
67
|
+
config.each do |key, value|
|
68
|
+
dependency_options[key.to_sym] = value
|
69
|
+
end
|
70
|
+
pod(name, dependency_options)
|
71
|
+
end
|
72
|
+
|
73
|
+
use_modular_headers! if use_modular_headers
|
74
|
+
install!('cocoapods',
|
75
|
+
:integrate_targets => false,
|
76
|
+
:deterministic_uuids => false)
|
77
|
+
|
78
|
+
target('packager') do
|
79
|
+
inherit! :complete
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def binary_only?(spec)
|
85
|
+
deps = spec.dependencies.map { |dep| spec_with_name(dep.name) }
|
86
|
+
[spec, *deps].each do |specification|
|
87
|
+
%w(vendored_frameworks vendored_libraries).each do |attrib|
|
88
|
+
if specification.attributes_hash[attrib]
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
false
|
95
|
+
end
|
96
|
+
|
97
|
+
def spec_with_name(name)
|
98
|
+
return if name.nil?
|
99
|
+
|
100
|
+
set = Pod::Config.instance.sources_manager.search(Dependency.new(name))
|
101
|
+
return nil if set.nil?
|
102
|
+
|
103
|
+
set.specification.root
|
104
|
+
end
|
105
|
+
|
106
|
+
def spec_with_path(path)
|
107
|
+
return if path.nil? || !Pathname.new(path).exist?
|
108
|
+
|
109
|
+
@path = Pathname.new(path).expand_path
|
110
|
+
|
111
|
+
if @path.directory?
|
112
|
+
help! @path + ': is a directory.'
|
113
|
+
return
|
114
|
+
end
|
115
|
+
|
116
|
+
unless ['.podspec', '.json'].include? @path.extname
|
117
|
+
help! @path + ': is not a podspec.'
|
118
|
+
return
|
119
|
+
end
|
120
|
+
|
121
|
+
Specification.from_file(@path)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'cocoapods-util/package/helper/pod_utils'
|
2
|
+
require 'cocoapods-util/package/helper/builder'
|
3
|
+
require 'cocoapods-util/package/helper/framework'
|
4
|
+
|
5
|
+
require 'tmpdir'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module Pod
|
9
|
+
class Command
|
10
|
+
class Util < Command
|
11
|
+
class Package < Util
|
12
|
+
self.summary = '通过podspec编译静态库(library/framework/xcframework)'
|
13
|
+
self.description = "本插件属于在cocoapods-packager的基础上做的修改,支持编译swift。另外支持use_modular_headers!、排除模拟器、排除特定架构、编译xcframework等。"
|
14
|
+
self.arguments = [
|
15
|
+
CLAide::Argument.new('NAME', true),
|
16
|
+
CLAide::Argument.new('SOURCE', false)
|
17
|
+
]
|
18
|
+
|
19
|
+
def self.options
|
20
|
+
[
|
21
|
+
['--force', 'Overwrite existing files.'],
|
22
|
+
['--library', 'Generate static library.'],
|
23
|
+
['--framework', 'Generate static framework.'],
|
24
|
+
['--xcframework', 'Generate static xcframework.'],
|
25
|
+
['--local', 'Use local state rather than published versions.'],
|
26
|
+
['--configuration', 'Build the specified configuration (e.g. Debug). Defaults to Release'],
|
27
|
+
['--subspecs', 'Only include the given subspecs'],
|
28
|
+
['--spec-sources=private,https://github.com/CocoaPods/Specs.git', 'The sources to pull dependent ' \
|
29
|
+
'pods from (defaults to https://github.com/CocoaPods/Specs.git)'],
|
30
|
+
['--exclude-sim', '排除模拟器架构,仅编译真机对应的架构。'],
|
31
|
+
['--use-modular-headers', '开启use_modular_headers!'],
|
32
|
+
['--dependency-config={}', '依赖的pod文件配置,为一个json dictionary,可以配置branch、tag、source源等。配置方式:{"PodA":{"git":"xxx","branch":"xxx"},"PodB":{"source":"xxx"}}'],
|
33
|
+
['--contains-resources', '生成的framework中是否包含bundle文件,默认不把bundle文件放到framework中。'],
|
34
|
+
['--platforms=ios,osx,watchos,tvos,all', '选择编译的平台架构,默认`all`,编译全部平台。'],
|
35
|
+
['--build-settings={}', 'xcode build_settings。{"EXCLUDED_ARCHS[sdk=iphonesimulator*]":"arm64"}']
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(argv)
|
40
|
+
@framework = argv.flag?('framework')
|
41
|
+
@xcframework = argv.flag?('xcframework')
|
42
|
+
@library = argv.flag?('library')
|
43
|
+
@local = argv.flag?('local', false)
|
44
|
+
@package_type = if @xcframework
|
45
|
+
:static_xcframework
|
46
|
+
elsif @framework
|
47
|
+
:static_framework
|
48
|
+
elsif @library
|
49
|
+
:static_library
|
50
|
+
else
|
51
|
+
:static_library
|
52
|
+
end
|
53
|
+
@force = argv.flag?('force')
|
54
|
+
@exclude_sim = argv.flag?('exclude-sim', false)
|
55
|
+
@use_modular_headers = argv.flag?('use-modular-headers', false)
|
56
|
+
@name = argv.shift_argument
|
57
|
+
@source = argv.shift_argument
|
58
|
+
@spec_sources = argv.option('spec-sources', 'https://github.com/CocoaPods/Specs.git').split(',')
|
59
|
+
|
60
|
+
subspecs = argv.option('subspecs')
|
61
|
+
@subspecs = subspecs.split(',') unless subspecs.nil?
|
62
|
+
|
63
|
+
@framework_contains_resources = argv.flag?('contains-resources', false)
|
64
|
+
@platforms = argv.option('platforms', 'all')
|
65
|
+
@build_settings = JSON.parse(argv.option('build-settings', '{}'))
|
66
|
+
|
67
|
+
dependency_config = argv.option('dependency-config', '{}')
|
68
|
+
@dependency_config = JSON.parse(dependency_config)
|
69
|
+
|
70
|
+
@config = argv.option('configuration', 'Release')
|
71
|
+
|
72
|
+
@source_dir = Dir.pwd
|
73
|
+
@is_spec_from_path = false
|
74
|
+
@spec = spec_with_path(@name)
|
75
|
+
@is_spec_from_path = true if @spec
|
76
|
+
@spec ||= spec_with_name(@name)
|
77
|
+
super
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate!
|
81
|
+
super
|
82
|
+
help! 'A podspec name or path is required.' unless @spec
|
83
|
+
help! '--local option can only be used when a local `.podspec` path is given.' if @local && !@is_spec_from_path
|
84
|
+
help! '编译静态库.a不允许设置包含resources' if !(@framework || @xcframework) && @framework_contains_resources
|
85
|
+
end
|
86
|
+
|
87
|
+
def run
|
88
|
+
if @spec.nil?
|
89
|
+
help! 'Unable to find a podspec with path or name.'
|
90
|
+
return
|
91
|
+
end
|
92
|
+
|
93
|
+
target_dir, work_dir = create_working_directory
|
94
|
+
return if target_dir.nil?
|
95
|
+
build_package
|
96
|
+
|
97
|
+
`mv "#{work_dir}" "#{target_dir}"`
|
98
|
+
Dir.chdir(@source_dir)
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def build_in_sandbox(platform)
|
104
|
+
config.installation_root = Pathname.new(Dir.pwd)
|
105
|
+
config.sandbox_root = 'Pods'
|
106
|
+
|
107
|
+
static_sandbox = build_static_sandbox()
|
108
|
+
static_installer = install_pod(platform.name, static_sandbox)
|
109
|
+
|
110
|
+
begin
|
111
|
+
perform_build(platform, static_sandbox, static_installer)
|
112
|
+
ensure # in case the build fails; see Builder#xcodebuild.
|
113
|
+
Pathname.new(config.sandbox_root).rmtree
|
114
|
+
FileUtils.rm_f('Podfile.lock')
|
115
|
+
# clean build
|
116
|
+
FileUtils.rm_rf('build')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def build_package
|
121
|
+
platforms = @platforms.split(',')
|
122
|
+
all_platforms = platforms.include?('all')
|
123
|
+
@spec.available_platforms.each do |platform|
|
124
|
+
if all_platforms || platforms.include?(platform.name.to_s)
|
125
|
+
build_in_sandbox(platform)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def create_target_directory
|
131
|
+
target_dir = "#{@source_dir}/#{@spec.name}-#{@spec.version}"
|
132
|
+
if File.exist? target_dir
|
133
|
+
if @force
|
134
|
+
Pathname.new(target_dir).rmtree
|
135
|
+
else
|
136
|
+
UI.puts "Target directory '#{target_dir}' already exists."
|
137
|
+
return nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
target_dir
|
141
|
+
end
|
142
|
+
|
143
|
+
def create_working_directory
|
144
|
+
target_dir = create_target_directory
|
145
|
+
return if target_dir.nil?
|
146
|
+
|
147
|
+
work_dir = Dir.tmpdir + '/cocoapods-' + Array.new(8) { rand(36).to_s(36) }.join
|
148
|
+
UI.puts "work_dir: #{work_dir}" if @verbose
|
149
|
+
Pathname.new(work_dir).mkdir
|
150
|
+
Dir.chdir(work_dir)
|
151
|
+
|
152
|
+
[target_dir, work_dir]
|
153
|
+
end
|
154
|
+
|
155
|
+
def perform_build(platform, static_sandbox, static_installer)
|
156
|
+
static_sandbox_root = config.sandbox_root.to_s
|
157
|
+
|
158
|
+
builder = Pod::Builder.new(
|
159
|
+
platform,
|
160
|
+
static_installer,
|
161
|
+
@source_dir,
|
162
|
+
static_sandbox_root,
|
163
|
+
static_sandbox.public_headers.root,
|
164
|
+
@spec,
|
165
|
+
@config,
|
166
|
+
@exclude_sim,
|
167
|
+
@framework_contains_resources,
|
168
|
+
@verbose
|
169
|
+
)
|
170
|
+
|
171
|
+
builder.build(@package_type)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'cocoapods-util/xcframework/xcramework_build.rb'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Util < Command
|
6
|
+
class XCFramework < Util
|
7
|
+
self.summary = '根据传入framework在同目录下生成xcframework'
|
8
|
+
self.description = <<-DESC
|
9
|
+
根据传入framework在同目录下生成xcframework
|
10
|
+
DESC
|
11
|
+
self.command = 'xcframework'
|
12
|
+
self.arguments = [
|
13
|
+
CLAide::Argument.new('FRAMEWORK_PATH', true)
|
14
|
+
]
|
15
|
+
|
16
|
+
def self.options
|
17
|
+
[
|
18
|
+
['--force', '覆盖已经存在的文件'],
|
19
|
+
['--create-swiftinterface', '有编译swift文件的framework,如果不包含swiftinterface则无法生成xcframework。
|
20
|
+
设置该参数会生成一个swiftinterface文件解决create失败的问题。']
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(argv)
|
25
|
+
@file_path = argv.shift_argument
|
26
|
+
@force = argv.flag?('force')
|
27
|
+
@create_swiftinterface = argv.flag?('create-swiftinterface')
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate!
|
32
|
+
super
|
33
|
+
help! '必须传入framework路径或名称.' unless @file_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
# 获取真实路径,~ 为进程所有者的主目录
|
38
|
+
@file_path = File.expand_path(@file_path)
|
39
|
+
if !File.exist?(@file_path) || !(@file_path =~ /\.framework$/)
|
40
|
+
help! "路径不存在或传入的路径不是framework文件"
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
source_dir = File.dirname(@file_path)
|
45
|
+
framework_name = File.basename(@file_path, ".framework")
|
46
|
+
|
47
|
+
target_dir = "#{source_dir}/#{framework_name}.xcframework"
|
48
|
+
if File.exist?(target_dir)
|
49
|
+
if @force
|
50
|
+
Pathname.new(target_dir).rmtree
|
51
|
+
else
|
52
|
+
help! "#{target_dir}已经存在,使用`--force`可以覆盖已有文件"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
builder = XCFrameworkBuilder.new(
|
57
|
+
framework_name,
|
58
|
+
source_dir,
|
59
|
+
@create_swiftinterface
|
60
|
+
)
|
61
|
+
builder.build_static_xcframework
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Pod
|
2
|
+
class XCFrameworkBuilder
|
3
|
+
def initialize(name, source_dir, create_swiftinterface)
|
4
|
+
@name = name
|
5
|
+
@source_dir = source_dir
|
6
|
+
@create_swiftinterface = create_swiftinterface
|
7
|
+
end
|
8
|
+
|
9
|
+
def build_static_xcframework
|
10
|
+
framework_path = "#{@source_dir}/#{@name}.framework"
|
11
|
+
# 可执行文件名称
|
12
|
+
lib_file = "#{@name}"
|
13
|
+
# 可执行文件完整路径
|
14
|
+
lib_path = "#{framework_path}/#{lib_file}"
|
15
|
+
# 可执行文件不存在,退出
|
16
|
+
unless File.exist? lib_path
|
17
|
+
UI.puts("没有找到可执行文件,请检查输入的framework")
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
# 如果可执行文件为软链接类型,获取realpath
|
21
|
+
if File.ftype(lib_path) == 'link'
|
22
|
+
lib_file = File.readlink(lib_path)
|
23
|
+
lib_path = "#{framework_path}/#{lib_file}"
|
24
|
+
end
|
25
|
+
|
26
|
+
framework_paths = Array.new
|
27
|
+
# 获取可执行文件的支持架构
|
28
|
+
archs = `lipo -archs #{lib_path}`.split
|
29
|
+
os_archs = sim_archs = []
|
30
|
+
if archs.empty?
|
31
|
+
UI.puts "framework文件中没有检查到任何编译架构,请使用`lipo -info`或`lipo -archs`检查文件支持的架构。"
|
32
|
+
return
|
33
|
+
elsif archs.count == 1
|
34
|
+
framework_paths += [framework_path]
|
35
|
+
else
|
36
|
+
platform = `strings #{lib_path} | grep -E -i '/Platforms/.*\.platform/' | head -n 1`.chomp!
|
37
|
+
if platform =~ /iPhone[^\.]*\.platform/ # iphoneos iphonesimulator
|
38
|
+
os_archs = archs & ['arm64', 'armv7', 'armv7s']
|
39
|
+
sim_archs = archs & ['i386', 'x86_64']
|
40
|
+
elsif platform =~ /MacOSX.platform/ # macosx
|
41
|
+
os_archs = ['arm64', 'x86_64']
|
42
|
+
elsif platform =~ /Watch[^\.]*\.platform/ # watchos watchsimulator
|
43
|
+
os_archs = archs & ['armv7k', 'arm64_32']
|
44
|
+
sim_archs = archs & ['arm64', 'i386', 'x86_64']
|
45
|
+
elsif platform =~ /AppleTV[^\.]*\.platform/ # appletvos appletvsimulator
|
46
|
+
os_archs = archs & ['arm64']
|
47
|
+
sim_archs = archs & ['x86_64'] # 'arm64' 'x86_64'
|
48
|
+
else
|
49
|
+
os_archs = archs & ['arm64', 'armv7', 'armv7s']
|
50
|
+
sim_archs = archs & ['i386', 'x86_64']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# 1. remove os/simulator paths
|
55
|
+
clean_intermediate_path
|
56
|
+
|
57
|
+
# 2. copy os framework
|
58
|
+
if os_archs.count > 0
|
59
|
+
path = Pathname.new("#{@source_dir}/#{os_target_path}")
|
60
|
+
path.mkdir unless path.exist?
|
61
|
+
`cp -a #{framework_path} #{path}/`
|
62
|
+
|
63
|
+
fwk_path = "#{path}/#{@name}.framework"
|
64
|
+
framework_paths += ["#{fwk_path}"]
|
65
|
+
`lipo -extract #{os_archs.join(' -extract ')} "#{fwk_path}/#{lib_file}" -output "#{fwk_path}/#{lib_file}"`
|
66
|
+
end
|
67
|
+
# 3. copy simulation framework
|
68
|
+
if sim_archs.count > 0
|
69
|
+
path = Pathname.new("#{@source_dir}/#{simulator_target_path}")
|
70
|
+
path.mkdir unless path.exist?
|
71
|
+
`cp -a #{framework_path} #{path}/`
|
72
|
+
|
73
|
+
fwk_path = "#{path}/#{@name}.framework"
|
74
|
+
framework_paths += ["#{fwk_path}"]
|
75
|
+
`lipo -extract #{sim_archs.join(' -extract ')} "#{fwk_path}/#{lib_file}" -output "#{fwk_path}/#{lib_file}"`
|
76
|
+
end
|
77
|
+
|
78
|
+
# 4. generate xcframework
|
79
|
+
begin
|
80
|
+
generate_xcframework(framework_paths)
|
81
|
+
ensure # in case the create-xcframework fails; remove the temp directory.
|
82
|
+
clean_intermediate_path
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def generate_xcframework(framework_paths)
|
87
|
+
UI.puts("Generate #{@name}.xcframework")
|
88
|
+
|
89
|
+
framework_paths.each { |framework_path|
|
90
|
+
# check_swiftmodule
|
91
|
+
swiftmodule_path = Dir.glob("#{framework_path}/Modules/*.swiftmodule").first
|
92
|
+
unless swiftmodule_path.nil?
|
93
|
+
if Dir.glob("#{swiftmodule_path}/*.swiftinterface").empty?
|
94
|
+
unless @create_swiftinterface
|
95
|
+
UI.puts "Framework中包含swiftmodule文件,但是没有swiftinterface,无法创建xcframework,请检查Framework文件。或者使用`--create-swiftinterface`参数"
|
96
|
+
return
|
97
|
+
end
|
98
|
+
arm_swiftinterface = Pathname.new("#{swiftmodule_path}/arm.swiftinterface")
|
99
|
+
File.new(arm_swiftinterface, "w+").close
|
100
|
+
end
|
101
|
+
end
|
102
|
+
}
|
103
|
+
|
104
|
+
# build xcframework
|
105
|
+
command = "xcodebuild -create-xcframework -framework #{framework_paths.join(' -framework ')} -output #{@source_dir}/#{@name}.xcframework 2>&1"
|
106
|
+
output = `#{command}`.lines.to_a
|
107
|
+
result = $?
|
108
|
+
# show error
|
109
|
+
if result.exitstatus != 0
|
110
|
+
puts UI::BuildFailedReport.report(command, output)
|
111
|
+
Process.exit
|
112
|
+
end
|
113
|
+
UI.puts("Generate #{@name}.xcframework succees")
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
def clean_intermediate_path
|
118
|
+
[os_target_path, simulator_target_path].each do |path|
|
119
|
+
file_path = "#{@source_dir}/#{path}"
|
120
|
+
if File.exist? file_path
|
121
|
+
FileUtils.rm_rf(file_path)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def os_target_path
|
127
|
+
"#{@name}_temp_os"
|
128
|
+
end
|
129
|
+
def simulator_target_path
|
130
|
+
"#{@name}_temp_simulator"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-util/gem_version'
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
ROOT = Pathname.new(File.expand_path('../../', __FILE__))
|
3
|
+
$:.unshift((ROOT + 'lib').to_s)
|
4
|
+
$:.unshift((ROOT + 'spec').to_s)
|
5
|
+
|
6
|
+
require 'bundler/setup'
|
7
|
+
require 'bacon'
|
8
|
+
require 'mocha-on-bacon'
|
9
|
+
require 'pretty_bacon'
|
10
|
+
require 'pathname'
|
11
|
+
require 'cocoapods'
|
12
|
+
|
13
|
+
Mocha::Configuration.prevent(:stubbing_non_existent_method)
|
14
|
+
|
15
|
+
require 'cocoapods_plugin'
|
16
|
+
|
17
|
+
#-----------------------------------------------------------------------------#
|
18
|
+
|
19
|
+
module Pod
|
20
|
+
|
21
|
+
# Disable the wrapping so the output is deterministic in the tests.
|
22
|
+
#
|
23
|
+
UI.disable_wrap = true
|
24
|
+
|
25
|
+
# Redirects the messages to an internal store.
|
26
|
+
#
|
27
|
+
module UI
|
28
|
+
@output = ''
|
29
|
+
@warnings = ''
|
30
|
+
|
31
|
+
class << self
|
32
|
+
attr_accessor :output
|
33
|
+
attr_accessor :warnings
|
34
|
+
|
35
|
+
def puts(message = '')
|
36
|
+
@output << "#{message}\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
def warn(message = '', actions = [])
|
40
|
+
@warnings << "#{message}\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
def print(message)
|
44
|
+
@output << message
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#-----------------------------------------------------------------------------#
|