cocoapods-util 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
#-----------------------------------------------------------------------------#
|