cocoapods-bb-xcframework 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +19 -0
- data/README.md +76 -0
- data/lib/cocoapods-xcframework/command/muti_xcframework.rb +65 -0
- data/lib/cocoapods-xcframework/command/xcframework.rb +68 -0
- data/lib/cocoapods-xcframework/command.rb +2 -0
- data/lib/cocoapods-xcframework/config.rb +8 -0
- data/lib/cocoapods-xcframework/frameworker.rb +70 -0
- data/lib/cocoapods-xcframework/gem_version.rb +3 -0
- data/lib/cocoapods-xcframework/muti_frameworker.rb +57 -0
- data/lib/cocoapods-xcframework/util/cmd.rb +24 -0
- data/lib/cocoapods-xcframework/util/dir_util.rb +50 -0
- data/lib/cocoapods-xcframework/util/error_util.rb +13 -0
- data/lib/cocoapods-xcframework/util/git_util.rb +14 -0
- data/lib/cocoapods-xcframework/util/pod_util.rb +256 -0
- data/lib/cocoapods-xcframework/util.rb +5 -0
- data/lib/cocoapods-xcframework/xbuilder/xcode_xbuild.rb +21 -0
- data/lib/cocoapods-xcframework/xbuilder/xcodeproj_helper.rb +46 -0
- data/lib/cocoapods-xcframework/xbuilder.rb +273 -0
- data/lib/cocoapods-xcframework.rb +1 -0
- data/lib/cocoapods_plugin.rb +11 -0
- data/spec/command/framework_spec.rb +12 -0
- data/spec/spec_helper.rb +50 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f51e31cd2ec034bbc893a17b6335b903273fcd3eb0054cecd270bdf89c4483d3
|
4
|
+
data.tar.gz: 9ca7be68bdb56db497bd8c6a99e5870663f98458de65ddf9697c22a993bc5636
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2bc9b6c6c2051a583719ff4e10971387beecbb1a16662ca1c944beebbc9ca70963193e10d2dab59d18abd60d5483dae20c0c99067291441fa80f5b930dd55569
|
7
|
+
data.tar.gz: ddd788e2dbee253c008251002bb13c21417cf9b60049316e8b8cfefa1410bd9300b1116546b69347f087ac22059d3777877e8c4fdcfb0cc877358b58b6a166cc
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2021 humin <humin1102@126.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# cocoapods-bb-xcframework
|
2
|
+
|
3
|
+
- 你是不是发现 `cocoapods-packager` 不能支持 `Swift`?
|
4
|
+
- 你是不是发现 `cocoapods-packager` 不能支持 `m1`?
|
5
|
+
- 你是不是发现 `cocoapods-packager` 不能支持 `GCC module`?
|
6
|
+
- 你是不是发现 `cocoapods-packager` 不能支持 `watch` 和 `tv`?
|
7
|
+
- 那你不妨试试我们这个插件~,美滋滋哦~
|
8
|
+
本插件可以帮助开发者快速的创建一个`OC`/`Swift`的`xcframework`。
|
9
|
+
|
10
|
+
## feat
|
11
|
+
- 支持 `Swift`/`Object-C` 生成 `framework`
|
12
|
+
- 支持 `Xcode` 新特性: `xcframework`
|
13
|
+
- 支持 `cocoapods` 绝大多数属性
|
14
|
+
- 支持 `subspec` 打包
|
15
|
+
- 支持二进制库是否生成符号表,默认生成,详见`pod xcframework --help`
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
$ gem install cocoapods-bb-xcframework
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
$ pod xcframework NAME [SOURCE]
|
23
|
+
更多请看
|
24
|
+
$pod xcframework --help
|
25
|
+
|
26
|
+
```
|
27
|
+
% pod xcframework --help
|
28
|
+
Usage:
|
29
|
+
|
30
|
+
$ pod xcframework NAME [SOURCE]
|
31
|
+
|
32
|
+
Package a podspec into a xcframework.
|
33
|
+
|
34
|
+
Options:
|
35
|
+
|
36
|
+
--no-force Overwrite existing
|
37
|
+
files.
|
38
|
+
--configuration Build the
|
39
|
+
specified
|
40
|
+
configuration
|
41
|
+
(e.g. Debug).
|
42
|
+
Defaults to
|
43
|
+
Release
|
44
|
+
--spec-sources=private,https://github.com/CocoaPods/Specs.git The sources to
|
45
|
+
pull dependent
|
46
|
+
pods from
|
47
|
+
(defaults to
|
48
|
+
https://github.com/CocoaPods/Specs.git)
|
49
|
+
--subspecs Only include the
|
50
|
+
given subspecs
|
51
|
+
--use-modular-headers pakcage uses
|
52
|
+
modular headers
|
53
|
+
during packaging
|
54
|
+
--no-static-library package not use
|
55
|
+
static library
|
56
|
+
--enable-bitcode package enable
|
57
|
+
bitcode
|
58
|
+
--no-symbols package not use
|
59
|
+
symbols
|
60
|
+
--allow-root Allows CocoaPods
|
61
|
+
to run as root
|
62
|
+
--silent Show nothing
|
63
|
+
--verbose Show more
|
64
|
+
debugging
|
65
|
+
information
|
66
|
+
--no-ansi Show output
|
67
|
+
without ANSI codes
|
68
|
+
--help Show help banner
|
69
|
+
of specified
|
70
|
+
command
|
71
|
+
```
|
72
|
+
|
73
|
+
## Q&A
|
74
|
+
### 而且本插件支持`apple`的全平台的`framework`创建,如下图
|
75
|
+
|
76
|
+
![all](img/allplatform.png)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
# This is an example of a cocoapods plugin adding a top-level subcommand
|
4
|
+
# to the 'pod' command.
|
5
|
+
#
|
6
|
+
# You can also create subcommands of existing or new commands. Say you
|
7
|
+
# wanted to add a subcommand to `list` to show newly deprecated pods,
|
8
|
+
# (e.g. `pod list deprecated`), there are a few things that would need
|
9
|
+
# to change.
|
10
|
+
#
|
11
|
+
# - move this file to `lib/pod/command/list/deprecated.rb` and update
|
12
|
+
# the class to exist in the the Pod::Command::List namespace
|
13
|
+
# - change this class to extend from `List` instead of `Command`. This
|
14
|
+
# tells the plugin system that it is a subcommand of `list`.
|
15
|
+
# - edit `lib/cocoapods_plugins.rb` to require this file
|
16
|
+
#
|
17
|
+
# @todo Create a PR to add your plugin to CocoaPods/cocoapods.org
|
18
|
+
# in the `plugins.json` file, once your plugin is released.
|
19
|
+
#
|
20
|
+
class MutiXCFramework < Command
|
21
|
+
self.summary = 'Package some podspec into a xcframework.'
|
22
|
+
self.arguments = [
|
23
|
+
CLAide::Argument.new('NAME', true),
|
24
|
+
CLAide::Argument.new('SOURCE', false)
|
25
|
+
]
|
26
|
+
include Config::Mixin
|
27
|
+
|
28
|
+
def self.options
|
29
|
+
[
|
30
|
+
['--no-force', 'Overwrite existing files.'],
|
31
|
+
['--configuration', 'Build the specified configuration (e.g. Debug). Defaults to Release'],
|
32
|
+
['--spec-sources=private,https://github.com/CocoaPods/Specs.git', 'The sources to pull dependent pods from (defaults to https://github.com/CocoaPods/Specs.git)'],
|
33
|
+
['--use-modular-headers', 'pakcage uses modular headers during packaging'],
|
34
|
+
['--no-static-library', 'package not use static library'],
|
35
|
+
['--enable-bitcode', 'package enable bitcode'],
|
36
|
+
['--no-symbols', 'package not use symbols']
|
37
|
+
].concat super
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(argv)
|
41
|
+
@name = argv.shift_argument
|
42
|
+
@source = argv.shift_argument
|
43
|
+
@spec_sources = argv.option('spec-sources', 'https://github.com/CocoaPods/Specs.git').split(',')
|
44
|
+
@configuration = argv.option('configuration', 'Release')
|
45
|
+
@use_modular_headers = argv.option('use-modular-headers', true)
|
46
|
+
@force = argv.flag?('force', true)
|
47
|
+
@use_static_library = argv.flag?('static-library', true)
|
48
|
+
@enable_bitcode = argv.flag?('enable-bitcode',false)
|
49
|
+
@symbols = argv.flag?('symbols',true)
|
50
|
+
config.static_library_enable = @use_static_library
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate!
|
55
|
+
super
|
56
|
+
help! 'A file written some pods need package is needed' unless @name
|
57
|
+
end
|
58
|
+
|
59
|
+
def run
|
60
|
+
frameworker = MutiFrameworker.new(@name, @source, @spec_sources, @configuration, @force, @use_modular_headers, @enable_bitcode, @symbols)
|
61
|
+
frameworker.run
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
# This is an example of a cocoapods plugin adding a top-level subcommand
|
4
|
+
# to the 'pod' command.
|
5
|
+
#
|
6
|
+
# You can also create subcommands of existing or new commands. Say you
|
7
|
+
# wanted to add a subcommand to `list` to show newly deprecated pods,
|
8
|
+
# (e.g. `pod list deprecated`), there are a few things that would need
|
9
|
+
# to change.
|
10
|
+
#
|
11
|
+
# - move this file to `lib/pod/command/list/deprecated.rb` and update
|
12
|
+
# the class to exist in the the Pod::Command::List namespace
|
13
|
+
# - change this class to extend from `List` instead of `Command`. This
|
14
|
+
# tells the plugin system that it is a subcommand of `list`.
|
15
|
+
# - edit `lib/cocoapods_plugins.rb` to require this file
|
16
|
+
#
|
17
|
+
# @todo Create a PR to add your plugin to CocoaPods/cocoapods.org
|
18
|
+
# in the `plugins.json` file, once your plugin is released.
|
19
|
+
#
|
20
|
+
class XCFramework < Command
|
21
|
+
self.summary = 'Package a podspec into a xcframework.'
|
22
|
+
self.arguments = [
|
23
|
+
CLAide::Argument.new('NAME', true),
|
24
|
+
CLAide::Argument.new('SOURCE', false)
|
25
|
+
]
|
26
|
+
include Config::Mixin
|
27
|
+
|
28
|
+
def self.options
|
29
|
+
[
|
30
|
+
['--no-force', 'Overwrite existing files.'],
|
31
|
+
['--configuration', 'Build the specified configuration (e.g. Debug). Defaults to Release'],
|
32
|
+
['--spec-sources=private,https://github.com/CocoaPods/Specs.git', 'The sources to pull dependent pods from (defaults to https://github.com/CocoaPods/Specs.git)'],
|
33
|
+
['--subspecs', 'Only include the given subspecs'],
|
34
|
+
['--use-modular-headers', 'pakcage uses modular headers during packaging'],
|
35
|
+
['--no-static-library', 'package not use static library'],
|
36
|
+
['--enable-bitcode', 'package enable bitcode'],
|
37
|
+
['--no-symbols', 'package not use symbols'] # 符号表
|
38
|
+
].concat super
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(argv)
|
42
|
+
@name = argv.shift_argument
|
43
|
+
@source = argv.shift_argument
|
44
|
+
@spec_sources = argv.option('spec-sources', 'https://github.com/CocoaPods/Specs.git').split(',')
|
45
|
+
subspecs = argv.option('subspecs')
|
46
|
+
@subspecs = subspecs.split(',') unless subspecs.nil?
|
47
|
+
@configuration = argv.option('configuration', 'Release')
|
48
|
+
@use_modular_headers = argv.option('use-modular-headers', true)
|
49
|
+
@force = argv.flag?('force', true)
|
50
|
+
@use_static_library = argv.flag?('static-library',true)
|
51
|
+
@enable_bitcode = argv.flag?('enable-bitcode',false)
|
52
|
+
@symbols = argv.flag?('symbols',true)
|
53
|
+
config.static_library_enable = @use_static_library
|
54
|
+
super
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate!
|
58
|
+
super
|
59
|
+
help! 'A Pod name is required.' unless @name
|
60
|
+
end
|
61
|
+
|
62
|
+
def run
|
63
|
+
frameworker = Frameworker.new(@name, @source, @spec_sources, @subspecs, @configuration, @force, @use_modular_headers, @enable_bitcode, @symbols)
|
64
|
+
frameworker.run
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Pod
|
2
|
+
class Frameworker
|
3
|
+
include PodUtil
|
4
|
+
include DirUtil
|
5
|
+
include Config::Mixin
|
6
|
+
def initialize(name, source, spec_sources, subspecs, configuration, force, use_modular_headers=true, enable_bitcode=false, symbols=true)
|
7
|
+
@name = name
|
8
|
+
@source = source
|
9
|
+
@spec_sources = spec_sources
|
10
|
+
@subspecs = subspecs
|
11
|
+
@configuration = configuration
|
12
|
+
@force = force
|
13
|
+
@use_modular_headers = use_modular_headers
|
14
|
+
@enable_bitcode = enable_bitcode
|
15
|
+
@symbols = symbols
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
spec = spec_with_path @name
|
20
|
+
@is_spec_from_path = true if spec
|
21
|
+
spec ||= spec_with_name @name
|
22
|
+
|
23
|
+
target_dir, work_dir = create_working_directory_by_spec spec, @force
|
24
|
+
build_framework spec, work_dir, target_dir
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_framework spec, work_dir, target_dir
|
28
|
+
build_in_sandbox(work_dir, spec, target_dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_in_sandbox work_dir, spec, target_dir
|
32
|
+
config.installation_root = Pathname.new work_dir
|
33
|
+
config.sandbox_root = "#{work_dir}/Pods"
|
34
|
+
sandbox = build_static_sandbox
|
35
|
+
|
36
|
+
sandbox_installer = installation_root(
|
37
|
+
sandbox,
|
38
|
+
spec,
|
39
|
+
@subspecs,
|
40
|
+
@spec_sources,
|
41
|
+
true,
|
42
|
+
@use_modular_headers,
|
43
|
+
@enable_bitcode
|
44
|
+
)
|
45
|
+
|
46
|
+
perform_build(
|
47
|
+
sandbox,
|
48
|
+
sandbox_installer,
|
49
|
+
spec,
|
50
|
+
target_dir
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
# def perform_build platform, sandbox, installer, spec
|
55
|
+
def perform_build sandbox, installer, spec, target_dir
|
56
|
+
sandbox_root = config.sandbox_root.to_s
|
57
|
+
builder = Pod::XBuilder.new(
|
58
|
+
installer,
|
59
|
+
Dir.pwd,
|
60
|
+
sandbox_root,
|
61
|
+
spec,
|
62
|
+
@configuration,
|
63
|
+
@symbols
|
64
|
+
)
|
65
|
+
builder.build
|
66
|
+
builder.outputs target_dir
|
67
|
+
target_dir
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Pod
|
2
|
+
class MutiFrameworker
|
3
|
+
include Pod::PodUtil
|
4
|
+
include Pod::GitUtil
|
5
|
+
include Pod::DirUtil
|
6
|
+
include Config::Mixin
|
7
|
+
def initialize(name, source, spec_sources, configuration, force, use_modular_headers)
|
8
|
+
@name = name
|
9
|
+
@source = source
|
10
|
+
@spec_sources = spec_sources
|
11
|
+
@configuration = configuration
|
12
|
+
@force = force
|
13
|
+
@use_modular_headers = use_modular_headers
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
configs = muti_config_with_file @name
|
18
|
+
target_dir, work_dir = create_working_directory_by_spec "xcframeworks", @force
|
19
|
+
prepare_git_with_configs configs, work_dir
|
20
|
+
build_frameworks configs, work_dir, target_dir
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_frameworks configs, work_dir, target_dir
|
24
|
+
config.installation_root = Pathname.new work_dir
|
25
|
+
config.sandbox_root = "#{work_dir}/Pods"
|
26
|
+
sandbox = build_static_sandbox
|
27
|
+
|
28
|
+
sandbox_installer = installation_root_muti(
|
29
|
+
sandbox,
|
30
|
+
configs,
|
31
|
+
@spec_sources,
|
32
|
+
@use_modular_headers
|
33
|
+
)
|
34
|
+
perform_build(
|
35
|
+
sandbox,
|
36
|
+
sandbox_installer,
|
37
|
+
configs,
|
38
|
+
target_dir
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def perform_build sandbox, installer, configs, target_dir
|
43
|
+
sandbox_root = config.sandbox_root.to_s
|
44
|
+
builder = Pod::XBuilder.new(
|
45
|
+
installer,
|
46
|
+
Dir.pwd,
|
47
|
+
sandbox_root,
|
48
|
+
configs,
|
49
|
+
@configuration
|
50
|
+
)
|
51
|
+
builder.build
|
52
|
+
builder.outputs_muti target_dir
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Pod
|
2
|
+
class Cmmd
|
3
|
+
class << self
|
4
|
+
def sh! command
|
5
|
+
UI.puts command
|
6
|
+
output = `#{command}`.lines.to_a
|
7
|
+
if $?.exitstatus != 0
|
8
|
+
Pod::ErrorUtil.error_report command,output
|
9
|
+
Process.exit -1
|
10
|
+
end
|
11
|
+
output
|
12
|
+
end
|
13
|
+
|
14
|
+
def sh? command
|
15
|
+
UI.puts command
|
16
|
+
output = `#{command}`.lines.to_a
|
17
|
+
if $?.exitstatus != 0
|
18
|
+
Pod::ErrorUtil.error_report command,output
|
19
|
+
end
|
20
|
+
output
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Pod
|
2
|
+
module DirUtil
|
3
|
+
def create_target_directory_path_by_spec spec,force
|
4
|
+
target_dir = "#{Dir.pwd}/#{spec.name}-#{spec.version}"
|
5
|
+
|
6
|
+
if File.exist? target_dir
|
7
|
+
if @force
|
8
|
+
Pathname.new(target_dir).rmtree
|
9
|
+
else
|
10
|
+
UI.warn "Target directory '#{target_dir}' already exists."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
target_dir
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_working_directory_by_spec spec,force
|
17
|
+
if spec.is_a? String
|
18
|
+
return create_working_directory_by_name spec,force
|
19
|
+
end
|
20
|
+
target_dir = create_target_directory_path_by_spec spec,force
|
21
|
+
# Pathname.new(target_dir).mkdir
|
22
|
+
work_dir = Dir.tmpdir + '/frameworks-' + Array.new(8) { rand(36).to_s(36) }.join
|
23
|
+
|
24
|
+
Pathname.new(work_dir).mkdir
|
25
|
+
[target_dir, work_dir]
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_target_directory_path_by_name name, force
|
29
|
+
target_dir = "#{Dir.pwd}/#{name}-muti"
|
30
|
+
|
31
|
+
if File.exist? target_dir
|
32
|
+
if @force
|
33
|
+
Pathname.new(target_dir).rmtree
|
34
|
+
else
|
35
|
+
UI.warn "Target directory '#{target_dir}' already exists."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
target_dir
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_working_directory_by_name name, force
|
42
|
+
target_dir = create_target_directory_path_by_name name,force
|
43
|
+
# Pathname.new(target_dir).mkdir
|
44
|
+
work_dir = Dir.tmpdir + '/frameworks-' + Array.new(8) { rand(36).to_s(36) }.join
|
45
|
+
|
46
|
+
Pathname.new(work_dir).mkdir
|
47
|
+
[target_dir, work_dir]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Pod
|
2
|
+
module GitUtil
|
3
|
+
def prepare_git_with_configs configs, work_dir
|
4
|
+
index = 0
|
5
|
+
configs.each do |config|
|
6
|
+
name = config["name"]
|
7
|
+
git_url = config["git_url"]
|
8
|
+
git_branch = config["git_branch"]
|
9
|
+
command = "git clone #{git_url} -b #{git_branch} #{work_dir}/#{name}"
|
10
|
+
Cmmd.sh! command
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
module Pod
|
2
|
+
module PodUtil
|
3
|
+
include Config::Mixin
|
4
|
+
|
5
|
+
def to_native_platform name
|
6
|
+
case name
|
7
|
+
when 'iphoneos' then 'ios'
|
8
|
+
when 'macOS' then 'osx'
|
9
|
+
when 'appletvos' then 'tvos'
|
10
|
+
when 'watchos' then 'watchos'
|
11
|
+
when 'ios' then 'ios'
|
12
|
+
when 'macos' then 'osx'
|
13
|
+
when 'tvos' then 'tvos'
|
14
|
+
else
|
15
|
+
name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def muti_config_with_file(path)
|
20
|
+
return nil if path.nil?
|
21
|
+
path = Pathname.new(path)
|
22
|
+
path = Pathname.new(Dir.pwd).join(path) unless path.absolute?
|
23
|
+
@path = path.expand_path
|
24
|
+
content = File.open(path, 'rb').read
|
25
|
+
result = JSON.parse content
|
26
|
+
if not result.is_a? Array
|
27
|
+
UI.error "#{path} format not support"
|
28
|
+
exit -1
|
29
|
+
end
|
30
|
+
result
|
31
|
+
end
|
32
|
+
|
33
|
+
def spec_with_path(path)
|
34
|
+
return if path.nil?
|
35
|
+
path = Pathname.new(path)
|
36
|
+
path = Pathname.new(Dir.pwd).join(path) unless path.absolute?
|
37
|
+
return unless path.exist?
|
38
|
+
@path = path.expand_path
|
39
|
+
|
40
|
+
if @path.directory?
|
41
|
+
raise @path + ': is a directory.'
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
unless ['.podspec', '.json'].include? @path.extname
|
46
|
+
raise @path + ': is not a podspec.'
|
47
|
+
return
|
48
|
+
end
|
49
|
+
|
50
|
+
Specification.from_file(@path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def spec_with_name(name)
|
54
|
+
return if name.nil?
|
55
|
+
|
56
|
+
set = Pod::Config.instance.sources_manager.search(Dependency.new(name))
|
57
|
+
return nil if set.nil?
|
58
|
+
|
59
|
+
set.specification.root
|
60
|
+
end
|
61
|
+
|
62
|
+
def build_static_sandbox
|
63
|
+
Sandbox.new(config.sandbox_root)
|
64
|
+
end
|
65
|
+
|
66
|
+
def installation_root sandbox, spec, subspecs, sources,use_frameworks = true,use_modular_headers = true, enable_bitcode = false
|
67
|
+
podfile = podfile_from_spec(
|
68
|
+
@path,
|
69
|
+
spec,
|
70
|
+
subspecs,
|
71
|
+
sources,
|
72
|
+
use_frameworks,
|
73
|
+
use_modular_headers
|
74
|
+
)
|
75
|
+
|
76
|
+
installer = Installer.new(sandbox, podfile)
|
77
|
+
installer.repo_update = true
|
78
|
+
installer.install!
|
79
|
+
|
80
|
+
unless installer.nil?
|
81
|
+
installer.pods_project.targets.each do |target|
|
82
|
+
target.build_configurations.each do |configuration|
|
83
|
+
if enable_bitcode && configuration.name == "Release"
|
84
|
+
configuration.build_settings['ENABLE_BITCODE'] = 'YES'
|
85
|
+
configuration.build_settings['BITCODE_GENERATION_MODE'] = 'bitcode'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
if target.name == spec.name
|
89
|
+
target.build_configurations.each do |configuration|
|
90
|
+
configuration.build_settings['CLANG_MODULES_AUTOLINK'] = 'NO'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
installer.pods_project.save
|
95
|
+
end
|
96
|
+
installer
|
97
|
+
end
|
98
|
+
|
99
|
+
def installation_root_muti sandbox, configs, sources, use_frameworks = true, use_modular_headers = true, enable_bitcode = false
|
100
|
+
podfile = podfile_from_muti_configs(
|
101
|
+
configs,
|
102
|
+
sources,
|
103
|
+
use_frameworks,
|
104
|
+
use_modular_headers
|
105
|
+
)
|
106
|
+
installer = Installer.new(sandbox, podfile)
|
107
|
+
installer.repo_update = true
|
108
|
+
installer.install!
|
109
|
+
|
110
|
+
specs = configs.map do |cfg|
|
111
|
+
cfg["name"]
|
112
|
+
end
|
113
|
+
unless installer.nil?
|
114
|
+
installer.pods_project.targets.each do |target|
|
115
|
+
target.build_configurations.each do |configuration|
|
116
|
+
if enable_bitcode && configuration.name == "Release"
|
117
|
+
configuration.build_settings['ENABLE_BITCODE'] = 'YES'
|
118
|
+
configuration.build_settings['BITCODE_GENERATION_MODE'] = 'bitcode'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
if specs.include? target.name
|
122
|
+
target.build_configurations.each do |configuration|
|
123
|
+
configuration.build_settings['CLANG_MODULES_AUTOLINK'] = 'NO'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
installer.pods_project.save
|
128
|
+
end
|
129
|
+
installer
|
130
|
+
end
|
131
|
+
|
132
|
+
def podfile_from_spec path, spec, subspecs, sources, use_frameworks = true, use_modular_headers=true
|
133
|
+
options = Hash.new
|
134
|
+
options[:podspec] = path.to_s
|
135
|
+
options[:subspecs] = spec.subspecs.map do |sub|
|
136
|
+
sub.base_name
|
137
|
+
end
|
138
|
+
options[:subspecs] = subspecs if subspecs
|
139
|
+
# 非常奇怪,如果传一个空的数组过去就会出问题!!
|
140
|
+
if options[:subspecs].length == 0
|
141
|
+
options[:subspecs] = nil
|
142
|
+
end
|
143
|
+
static_library_enable = config.static_library_enable?
|
144
|
+
Pod::Podfile.new do
|
145
|
+
sources.each {|s| source s}
|
146
|
+
spec.available_platforms.each do |plt|
|
147
|
+
target "#{spec.name}-#{plt.name}" do
|
148
|
+
platform(plt.name, spec.deployment_target(plt.name))
|
149
|
+
pod(spec.name, options)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
install!('cocoapods',:integrate_targets => false,:deterministic_uuids => false)
|
154
|
+
if static_library_enable
|
155
|
+
use_frameworks! :linkage => :static if use_frameworks
|
156
|
+
else
|
157
|
+
use_frameworks! if use_frameworks
|
158
|
+
end
|
159
|
+
use_modular_headers! if use_modular_headers
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def podfile_from_muti_configs configs, sources, use_frameworks = true, use_modular_headers = true
|
164
|
+
installation_root = config.installation_root.to_s
|
165
|
+
static_library_enable = config.static_library_enable?
|
166
|
+
Pod::Podfile.new do
|
167
|
+
sources.each {|s| source s}
|
168
|
+
configs.each do |cfg|
|
169
|
+
pod_spec_path = installation_root + "/#{cfg["name"]}/#{cfg["name"]}.podspec"
|
170
|
+
pod_spec_json_path = pod_spec_path + ".json"
|
171
|
+
(Pathname.glob(pod_spec_path) + Pathname.glob(pod_spec_json_path)).each do |real_path|
|
172
|
+
spec = Pod::Specification.from_file real_path.to_s
|
173
|
+
options = Hash.new
|
174
|
+
options[:podspec] = real_path.to_s
|
175
|
+
if cfg["subspecs"]
|
176
|
+
options[:subspecs] = cfg["subspecs"]
|
177
|
+
else
|
178
|
+
options[:subspecs] = spec.subspecs.map do |sub|
|
179
|
+
sub.base_name
|
180
|
+
end
|
181
|
+
end
|
182
|
+
# 非常奇怪,如果传一个空的数组过去就会出问题!!
|
183
|
+
if options[:subspecs].length == 0
|
184
|
+
options[:subspecs] = nil
|
185
|
+
end
|
186
|
+
spec.available_platforms.each do |plt|
|
187
|
+
target "#{spec.name}-#{plt.name}" do
|
188
|
+
puts "#{plt.name} #{spec.name} #{options}"
|
189
|
+
platform(plt.name, spec.deployment_target(plt.name))
|
190
|
+
pod(spec.name, options)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
install!('cocoapods',
|
196
|
+
:integrate_targets => false,
|
197
|
+
:deterministic_uuids => false)
|
198
|
+
|
199
|
+
if static_library_enable
|
200
|
+
use_frameworks! :linkage => :static if use_frameworks
|
201
|
+
else
|
202
|
+
use_frameworks! if use_frameworks
|
203
|
+
end
|
204
|
+
use_modular_headers! if use_modular_headers
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def generic_new_podspec_hash spec
|
209
|
+
spec_hash = spec.to_hash
|
210
|
+
[
|
211
|
+
"source_files",
|
212
|
+
"resources",
|
213
|
+
"resource_bundles",
|
214
|
+
"prefix_header_contents",
|
215
|
+
"prefix_header_file",
|
216
|
+
"header_dir",
|
217
|
+
"header_mappings_dir",
|
218
|
+
"script_phase",
|
219
|
+
"public_header_files",
|
220
|
+
"private_header_files",
|
221
|
+
"vendored_frameworks",
|
222
|
+
"vendored_libraries",
|
223
|
+
"exclude_files",
|
224
|
+
"preserve_paths",
|
225
|
+
"module_map",
|
226
|
+
"subspec"
|
227
|
+
].each do |key|
|
228
|
+
spec_hash.delete "#{key}"
|
229
|
+
end
|
230
|
+
spec_hash
|
231
|
+
end
|
232
|
+
|
233
|
+
def fix_header_file spec_hash, xcframework_path
|
234
|
+
puts "Dir.glob(#{xcframework_path}/*/) : #{Dir.glob("#{xcframework_path}/*/")}"
|
235
|
+
Dir.glob("#{xcframework_path}/*/").each do |file|
|
236
|
+
['ios','macos','tvos', 'watchos'].each do |prefix|
|
237
|
+
last_path = file.split("/").last
|
238
|
+
if last_path =~ /#{prefix}/ and not last_path =~ /simulator/
|
239
|
+
platform = to_native_platform prefix
|
240
|
+
if spec_hash[platform]
|
241
|
+
spec_hash[platform]["public_header_files"] = "#{spec_hash[:vendored_frameworks]}/#{last_path}/*/Headers/*.h"
|
242
|
+
spec_hash[platform]["source_files"] = "#{spec_hash[:vendored_frameworks]}/#{last_path}/*/Headers/*.h"
|
243
|
+
else
|
244
|
+
spec_hash[platform] = {
|
245
|
+
"public_header_files" => "#{spec_hash[:vendored_frameworks]}/#{last_path}/*/Headers/*.h",
|
246
|
+
"source_files" => "#{spec_hash[:vendored_frameworks]}/#{last_path}/*/Headers/*.h"
|
247
|
+
}
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
puts spec_hash.to_json
|
253
|
+
spec_hash
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Pod
|
2
|
+
class XBuilder
|
3
|
+
module XcodeXBuilder
|
4
|
+
def xcode_xbuild(defines, configuration, work_dir, build_dir = 'export')
|
5
|
+
if defined?(Pod::DONT_CODESIGN)
|
6
|
+
defines = "#{defines} CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_REQUIRED=NO"
|
7
|
+
end
|
8
|
+
pwd = Pathname.pwd
|
9
|
+
Dir.chdir work_dir
|
10
|
+
command = "xcodebuild #{defines} BUILD_DIR=#{build_dir} BUILD_LIBRARY_FOR_DISTRIBUTION=YES clean build -configuration #{configuration} -alltargets 2>&1"
|
11
|
+
UI.puts("XBuilder command:#{command}")
|
12
|
+
output = `#{command}`.lines.to_a
|
13
|
+
Dir.chdir pwd
|
14
|
+
if $?.exitstatus != 0
|
15
|
+
Pod::ErrorUtil.error_report command,output
|
16
|
+
Process.exit -1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
module Pod
|
3
|
+
class XBuilder
|
4
|
+
module XcodeProjHelper
|
5
|
+
include PodUtil
|
6
|
+
def modify_xcode_project_sdk_to_simullator path
|
7
|
+
sdks = xcode_sdks
|
8
|
+
project = Xcodeproj::Project.open path
|
9
|
+
|
10
|
+
project.targets.each do |target|
|
11
|
+
simulator_sdk = to_native_simulator_platform target.sdk
|
12
|
+
if not simulator_sdk.nil?
|
13
|
+
canonicalName = sdks[simulator_sdk]["canonicalName"]
|
14
|
+
target.build_configurations.each do |configuration|
|
15
|
+
configuration.build_settings["SDKROOT"] = canonicalName
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
project.save
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def xcode_sdks
|
24
|
+
return @x_sdks if @x_sdks
|
25
|
+
outputs = `xcodebuild -showsdks -json`
|
26
|
+
sdks = JSON.parse outputs
|
27
|
+
@x_sdks = {}
|
28
|
+
sdks.each do |sdk|
|
29
|
+
@x_sdks[sdk["platform"]] = sdk
|
30
|
+
end
|
31
|
+
@x_sdks
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_native_simulator_platform name
|
35
|
+
case name
|
36
|
+
when 'iphoneos' then 'iphonesimulator'
|
37
|
+
when 'macOS' then nil
|
38
|
+
when 'appletvos' then 'appletvsimulator'
|
39
|
+
when 'watchos' then 'watchsimulator'
|
40
|
+
else
|
41
|
+
name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,273 @@
|
|
1
|
+
require 'cocoapods-xcframework/xbuilder/xcode_xbuild'
|
2
|
+
require 'cocoapods-xcframework/xbuilder/xcodeproj_helper'
|
3
|
+
module Pod
|
4
|
+
class XBuilder
|
5
|
+
include XcodeXBuilder
|
6
|
+
include XcodeProjHelper
|
7
|
+
include PodUtil
|
8
|
+
include Config::Mixin
|
9
|
+
def initialize(installer, source_dir, sandbox_root, spec, configuration, symbols=true)
|
10
|
+
# def initialize(platform, installer, source_dir, sandbox_root, spec, config)
|
11
|
+
# @platform = platform
|
12
|
+
@installer = installer
|
13
|
+
@source_dir = source_dir
|
14
|
+
@sandbox_root = sandbox_root
|
15
|
+
@spec = spec
|
16
|
+
@muti = @spec.is_a? Array
|
17
|
+
@configs = @spec if @muti
|
18
|
+
@spec = "muti" if @muti
|
19
|
+
|
20
|
+
@configuration = configuration
|
21
|
+
@outputs = Hash.new
|
22
|
+
@symbols = symbols
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
UI.puts("Building framework #{@spec} with configuration #{@configuration}")
|
27
|
+
UI.puts "Work dir is :#{@sandbox_root}"
|
28
|
+
# defines = "GCC_PREPROCESSOR_DEFINITIONS='$(inherited) PodsDummy_Pods_#{@spec.name}=PodsDummy_PodPackage_#{@spec.name}'"
|
29
|
+
defines = ""
|
30
|
+
if @configuration == 'Debug'
|
31
|
+
defines << 'GCC_GENERATE_DEBUGGING_SYMBOLS=YES ONLY_ACTIVE_ARCH=NO'
|
32
|
+
else
|
33
|
+
if @symbols
|
34
|
+
defines << "GCC_GENERATE_DEBUGGING_SYMBOLS=YES" # Release模式需要符号表应于问题排查(二进制切源码操作) by hm 21/10/13
|
35
|
+
else
|
36
|
+
defines << "GCC_GENERATE_DEBUGGING_SYMBOLS=NO" # 去除符号表
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
build_all_device defines
|
41
|
+
|
42
|
+
collect_xc_frameworks
|
43
|
+
|
44
|
+
collect_bundles
|
45
|
+
end
|
46
|
+
|
47
|
+
def collect_xc_frameworks
|
48
|
+
if @muti
|
49
|
+
collect_muti_xcframworks
|
50
|
+
else
|
51
|
+
collect_single_xcframeworks
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def collect_muti_xcframworks
|
56
|
+
@outputs[:xcframework] = Hash.new
|
57
|
+
@configs.each do |cfg|
|
58
|
+
export_dir = "#{@sandbox_root}/export/**/#{cfg["name"]}.framework"
|
59
|
+
frameworks = Pathname.glob(export_dir)
|
60
|
+
@outputs[:xcframework][cfg["name"]] = create_xc_framework_by_frameworks frameworks, cfg["name"]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def collect_single_xcframeworks
|
65
|
+
export_dir = "#{@sandbox_root}/export/**/#{@spec.name}.framework"
|
66
|
+
frameworks = Pathname.glob(export_dir)
|
67
|
+
@outputs[:xcframework] = create_xc_framework_by_frameworks frameworks, @spec.name
|
68
|
+
end
|
69
|
+
|
70
|
+
def collect_bundles
|
71
|
+
if @muti
|
72
|
+
colelct_muti_bundles
|
73
|
+
else
|
74
|
+
collect_single_bundles
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def colelct_muti_bundles
|
79
|
+
@outputs[:bundle] = Hash.new
|
80
|
+
@configs.each do |cfg|
|
81
|
+
# "" 这个是用来代表mac os的 macos 没有后缀奇怪吧
|
82
|
+
["iphoneos","","appletvos","watchos"].each do |plat|
|
83
|
+
export_dir = "#{@sandbox_root}/export/*-#{plat}/**/#{cfg["name"]}.bundle/**"
|
84
|
+
Pathname.glob(export_dir).each do |bundle|
|
85
|
+
if bundle.to_s.include? "#{@spec.name}.bundle/Info.plist"
|
86
|
+
return
|
87
|
+
end
|
88
|
+
target_path = "#{@sandbox_root}/bundle/#{cfg["name"]}"
|
89
|
+
@outputs[:bundle][cfg["name"]] = target_path
|
90
|
+
native_platform = to_native_platform plat
|
91
|
+
path = Pathname.new "#{target_path}/#{native_platform}"
|
92
|
+
if not path.exist?
|
93
|
+
path.mkpath
|
94
|
+
end
|
95
|
+
FileUtils.cp_r(Dir["#{bundle}"],"#{path}")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def collect_single_bundles
|
102
|
+
# "" 这个是用来代表mac os的 macos 没有后缀奇怪吧
|
103
|
+
["iphoneos","","appletvos","watchos"].each do |plat|
|
104
|
+
export_dir = "#{@sandbox_root}/export/*-#{plat}/**/#{@spec.name}.bundle/**"
|
105
|
+
Pathname.glob(export_dir).each do |bundle|
|
106
|
+
if bundle.to_s.include? "#{@spec.name}.bundle/Info.plist"
|
107
|
+
return
|
108
|
+
end
|
109
|
+
@outputs[:bundle] = "#{@sandbox_root}/bundle"
|
110
|
+
native_platform = to_native_platform plat
|
111
|
+
path = Pathname.new "#{@sandbox_root}/bundle/#{native_platform}"
|
112
|
+
if not path.exist?
|
113
|
+
path.mkpath
|
114
|
+
end
|
115
|
+
FileUtils.cp_r(Dir["#{bundle}"],"#{path}")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def create_xc_framework_by_frameworks frameworks, spec_name
|
121
|
+
command = 'xcodebuild -create-xcframework '
|
122
|
+
frameworks.each do |framework|
|
123
|
+
command << "-framework #{framework} "
|
124
|
+
end
|
125
|
+
command << "-output #{@sandbox_root}/#{spec_name}.xcframework 2>&1"
|
126
|
+
output = `#{command}`.lines.to_a
|
127
|
+
UI.puts("make xcframework command:#{command}")
|
128
|
+
UI.puts("make xcframework output:#{output}")
|
129
|
+
if $?.exitstatus != 0
|
130
|
+
Pod::ErrorUtil.error_report command,output
|
131
|
+
Process.exit -1
|
132
|
+
end
|
133
|
+
"#{@sandbox_root}/#{spec_name}.xcframework"
|
134
|
+
end
|
135
|
+
|
136
|
+
def build_all_device defines
|
137
|
+
# build general first because simulator will exchange SDKROOT to simulat sdk
|
138
|
+
build_general_device defines
|
139
|
+
build_simulator_device defines
|
140
|
+
end
|
141
|
+
|
142
|
+
def build_general_device defines
|
143
|
+
UI.puts("--- Building framework #{@spec} with general device")
|
144
|
+
xcode_xbuild(
|
145
|
+
defines,
|
146
|
+
@configuration,
|
147
|
+
@sandbox_root
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
def build_simulator_device defines
|
152
|
+
UI.puts("--- Building framework #{@spec} with simulator device")
|
153
|
+
modify_xcode_project_sdk_to_simullator "#{@sandbox_root}/Pods.xcodeproj"
|
154
|
+
xcode_xbuild(
|
155
|
+
defines,
|
156
|
+
@configuration,
|
157
|
+
@sandbox_root
|
158
|
+
)
|
159
|
+
end
|
160
|
+
|
161
|
+
def outputs target_dir
|
162
|
+
if not File.exist? target_dir
|
163
|
+
Pathname.new(target_dir).mkdir
|
164
|
+
end
|
165
|
+
outputs_xcframework target_dir
|
166
|
+
outputs_bundle target_dir
|
167
|
+
new_spec_hash = generic_new_podspec_hash @spec
|
168
|
+
new_spec_hash[:vendored_frameworks] = "#{@spec.name}.xcframework"
|
169
|
+
new_spec_hash = fix_header_file new_spec_hash, "#{target_dir}/#{@spec.name}.xcframework"
|
170
|
+
find_bundles(target_dir).each do |plat, value|
|
171
|
+
if new_spec_hash[plat]
|
172
|
+
new_spec_hash[plat]["resource_bundles"] = value
|
173
|
+
else
|
174
|
+
new_spec_hash[plat] = {
|
175
|
+
"resource_bundles" => value
|
176
|
+
}
|
177
|
+
end
|
178
|
+
end
|
179
|
+
require 'json'
|
180
|
+
spec_json = JSON.pretty_generate(new_spec_hash) << "\n"
|
181
|
+
File.open("#{target_dir}/#{@spec.name}.podspec.json",'wb+') do |f|
|
182
|
+
f.write(spec_json)
|
183
|
+
end
|
184
|
+
UI.puts "result export at :#{target_dir}"
|
185
|
+
target_dir
|
186
|
+
end
|
187
|
+
|
188
|
+
def find_bundles target_dir
|
189
|
+
bundle_root = "#{target_dir}/bundle/"
|
190
|
+
pattern = "#{bundle_root}*"
|
191
|
+
result = {}
|
192
|
+
Pathname.glob(pattern).each do |bundle|
|
193
|
+
bundle_relative_path = bundle.to_s.gsub(bundle_root, "")
|
194
|
+
plat = bundle_relative_path
|
195
|
+
result[plat] = {
|
196
|
+
"#{@spec.name}" => "bundle/" + bundle_relative_path + "/*"
|
197
|
+
}
|
198
|
+
end
|
199
|
+
result
|
200
|
+
end
|
201
|
+
|
202
|
+
def outputs_xcframework target_dir
|
203
|
+
command = "cp -rp #{@outputs[:xcframework]} #{target_dir} 2>&1"
|
204
|
+
output = `#{command}`.lines.to_a
|
205
|
+
if $?.exitstatus != 0
|
206
|
+
Pod::ErrorUtil.error_report command,output
|
207
|
+
Process.exit -1
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def outputs_bundle target_dir
|
212
|
+
if @outputs[:bundle]
|
213
|
+
FileUtils.cp_r(Dir[@outputs[:bundle]],target_dir)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def outputs_muti target_dir
|
218
|
+
if not File.exist? target_dir
|
219
|
+
Pathname.new(target_dir).mkdir
|
220
|
+
end
|
221
|
+
outputs_xcframework_muti target_dir
|
222
|
+
outputs_bundle_muti target_dir
|
223
|
+
generic_new_podspec_hash_muti target_dir
|
224
|
+
end
|
225
|
+
|
226
|
+
def generic_new_podspec_hash_muti target_dir
|
227
|
+
work_dir = config.installation_root
|
228
|
+
@configs.map do |cfg|
|
229
|
+
podspec_path = "#{work_dir}/#{cfg["name"]}/#{cfg["name"]}.podspec"
|
230
|
+
if not File.exist? podspec_path
|
231
|
+
podspec_path = "#{podspec_path}.json"
|
232
|
+
end
|
233
|
+
podspec = Pod::Specification.from_file podspec_path
|
234
|
+
new_spec_hash = generic_new_podspec_hash podspec
|
235
|
+
new_spec_hash[:vendored_frameworks] = "#{podspec.name}.xcframework"
|
236
|
+
new_spec_hash = fix_header_file new_spec_hash, "#{target_dir}/#{@spec.name}.xcframework"
|
237
|
+
find_bundles("#{target_dir}/#{podspec.name}").each do |plat, value|
|
238
|
+
if new_spec_hash[plat]
|
239
|
+
new_spec_hash[plat]["resource_bundles"] = value
|
240
|
+
else
|
241
|
+
new_spec_hash[plat] = {
|
242
|
+
"resource_bundles" => value
|
243
|
+
}
|
244
|
+
end
|
245
|
+
end
|
246
|
+
require 'json'
|
247
|
+
spec_json = JSON.pretty_generate(new_spec_hash) << "\n"
|
248
|
+
File.open("#{target_dir}/#{podspec.name}/#{podspec.name}.podspec.json",'wb+') do |f|
|
249
|
+
f.write(spec_json)
|
250
|
+
end
|
251
|
+
UI.puts "result export at :#{target_dir}/#{podspec.name}"
|
252
|
+
"#{target_dir}/#{podspec.name}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def outputs_xcframework_muti target_dir
|
257
|
+
@outputs[:xcframework].each do |name, path|
|
258
|
+
target_dir_path = "#{target_dir}/#{name}/"
|
259
|
+
Pathname.new(target_dir_path).mkpath
|
260
|
+
FileUtils.cp_r(path, target_dir_path)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def outputs_bundle_muti target_dir
|
265
|
+
@outputs[:bundle].each do |name, path|
|
266
|
+
target_dir_path = "#{target_dir}/#{name}/bundle/"
|
267
|
+
Pathname.new(target_dir_path).mkpath
|
268
|
+
FileUtils.cp_r(path, target_dir_path)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-xcframework/gem_version'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
require 'cocoapods-xcframework/gem_version.rb'
|
3
|
+
require 'cocoapods-xcframework/config'
|
4
|
+
require 'cocoapods-xcframework/util'
|
5
|
+
require 'cocoapods-xcframework/xbuilder'
|
6
|
+
require 'cocoapods-xcframework/frameworker'
|
7
|
+
require 'cocoapods-xcframework/muti_frameworker'
|
8
|
+
|
9
|
+
|
10
|
+
#这个放在最后一个
|
11
|
+
require 'cocoapods-xcframework/command'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
describe Command::XCFramework do
|
5
|
+
describe 'CLAide' do
|
6
|
+
it 'registers it self' do
|
7
|
+
Command.parse(%w{ xcframework }).should.be.instance_of Command::XCFramework
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
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
|
+
#-----------------------------------------------------------------------------#
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cocoapods-bb-xcframework
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- humin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-10-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cocoapods
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.10.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.10.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.3'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.3'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
description: 把podspec打包成xcframework的小工具。packager pod to a xcframework
|
62
|
+
email:
|
63
|
+
- humin1102@126.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- lib/cocoapods-xcframework.rb
|
71
|
+
- lib/cocoapods-xcframework/command.rb
|
72
|
+
- lib/cocoapods-xcframework/command/muti_xcframework.rb
|
73
|
+
- lib/cocoapods-xcframework/command/xcframework.rb
|
74
|
+
- lib/cocoapods-xcframework/config.rb
|
75
|
+
- lib/cocoapods-xcframework/frameworker.rb
|
76
|
+
- lib/cocoapods-xcframework/gem_version.rb
|
77
|
+
- lib/cocoapods-xcframework/muti_frameworker.rb
|
78
|
+
- lib/cocoapods-xcframework/util.rb
|
79
|
+
- lib/cocoapods-xcframework/util/cmd.rb
|
80
|
+
- lib/cocoapods-xcframework/util/dir_util.rb
|
81
|
+
- lib/cocoapods-xcframework/util/error_util.rb
|
82
|
+
- lib/cocoapods-xcframework/util/git_util.rb
|
83
|
+
- lib/cocoapods-xcframework/util/pod_util.rb
|
84
|
+
- lib/cocoapods-xcframework/xbuilder.rb
|
85
|
+
- lib/cocoapods-xcframework/xbuilder/xcode_xbuild.rb
|
86
|
+
- lib/cocoapods-xcframework/xbuilder/xcodeproj_helper.rb
|
87
|
+
- lib/cocoapods_plugin.rb
|
88
|
+
- spec/command/framework_spec.rb
|
89
|
+
- spec/spec_helper.rb
|
90
|
+
homepage: https://github.com/humin1102/cocoapods-bb-xcframework
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubygems_version: 3.1.4
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: 把podspec打包成xcframework的小工具。packager pod to a xcframework
|
113
|
+
test_files:
|
114
|
+
- spec/command/framework_spec.rb
|
115
|
+
- spec/spec_helper.rb
|