DYXCFrameworkBuilder 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/.idea/.gitignore +8 -0
- data/.idea/DYXCFrameworkBuilder.iml +72 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/ARCHITECTURE.md +163 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +143 -0
- data/README.md +338 -0
- data/Rakefile +4 -0
- data/bin/xcbuilder +230 -0
- data/lib/DYXCFrameworkBuilder/builder.rb +136 -0
- data/lib/DYXCFrameworkBuilder/config.rb +122 -0
- data/lib/DYXCFrameworkBuilder/framework_podspec_generator.rb +157 -0
- data/lib/DYXCFrameworkBuilder/framework_publisher.rb +131 -0
- data/lib/DYXCFrameworkBuilder/oss_uploader.rb +210 -0
- data/lib/DYXCFrameworkBuilder/podspec_parser.rb +113 -0
- data/lib/DYXCFrameworkBuilder/version.rb +5 -0
- data/lib/DYXCFrameworkBuilder/xcframework_builder.rb +483 -0
- data/lib/DYXCFrameworkBuilder/yaml_generator.rb +292 -0
- data/lib/DYXCFrameworkBuilder.rb +45 -0
- data/sig/DYXCFrameworkBuilder.rbs +4 -0
- metadata +114 -0
data/README.md
ADDED
@@ -0,0 +1,338 @@
|
|
1
|
+
# DYXCFrameworkBuilder
|
2
|
+
|
3
|
+
一个用于将iOS私有库编译成XCFramework的Ruby工具。支持通过YAML配置文件进行自动化构建,可以跳过编译警告。
|
4
|
+
|
5
|
+
## 安装
|
6
|
+
|
7
|
+
克隆仓库并安装依赖:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
git clone <repository-url>
|
11
|
+
cd DYXCFrameworkBuilder
|
12
|
+
bundle install
|
13
|
+
```
|
14
|
+
|
15
|
+
## 使用方法
|
16
|
+
|
17
|
+
### 1. 创建配置文件
|
18
|
+
|
19
|
+
首先创建一个YAML配置文件模板:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
bundle exec xcbuilder --create-config build_config.yml
|
23
|
+
|
24
|
+
# 或者从 .podspec 文件自动生成配置
|
25
|
+
bundle exec xcbuilder --from-podspec MyLibrary.podspec
|
26
|
+
|
27
|
+
# 或者一键生成配置并自动构建
|
28
|
+
bundle exec xcbuilder --from-podspec-build MyLibrary.podspec
|
29
|
+
|
30
|
+
# 或者完整工作流(生成、构建、发布)
|
31
|
+
bundle exec xcbuilder --from-podspec-publish MyLibrary.podspec
|
32
|
+
|
33
|
+
# 或者仅生成 framework podspec 文件
|
34
|
+
bundle exec xcbuilder --generate-framework-podspec MyLibrary.podspec
|
35
|
+
|
36
|
+
# 或者完整自动化流程:构建 → OSS 上传 → 生成 podspec → 发布私有库
|
37
|
+
bundle exec xcbuilder --from-podspec-auto MyLibrary.podspec
|
38
|
+
```
|
39
|
+
|
40
|
+
### 2. 编辑配置文件
|
41
|
+
|
42
|
+
编辑生成的`build_config.yml`文件,配置你的项目信息:
|
43
|
+
|
44
|
+
```yaml
|
45
|
+
---
|
46
|
+
project:
|
47
|
+
path: "./MyLibrary.xcworkspace" # 工作空间文件路径(.xcworkspace或.xcodeproj)
|
48
|
+
scheme: MyLibrary # Scheme名称(必需)
|
49
|
+
target: MyLibrary # Target名称(可选,如果与scheme不同时使用)
|
50
|
+
configuration: Release # 构建配置
|
51
|
+
output:
|
52
|
+
directory: "./build" # 输出目录
|
53
|
+
framework_name: MyLibrary.xcframework # 输出的XCFramework名称
|
54
|
+
platforms:
|
55
|
+
ios: # iOS设备
|
56
|
+
deployment_target: '11.0'
|
57
|
+
architectures:
|
58
|
+
- arm64
|
59
|
+
- x86_64
|
60
|
+
ios_simulator: # iOS模拟器
|
61
|
+
deployment_target: '11.0'
|
62
|
+
architectures:
|
63
|
+
- arm64
|
64
|
+
- x86_64
|
65
|
+
build_settings:
|
66
|
+
enable_bitcode: false # 是否启用bitcode
|
67
|
+
skip_warnings: true # 跳过编译警告
|
68
|
+
swift_version: '5.0' # Swift版本
|
69
|
+
```
|
70
|
+
|
71
|
+
### 3. 执行构建
|
72
|
+
|
73
|
+
使用配置文件构建XCFramework:
|
74
|
+
|
75
|
+
```bash
|
76
|
+
bundle exec xcbuilder -f build_config.yml -v
|
77
|
+
```
|
78
|
+
|
79
|
+
### 4. 从 .podspec 文件自动生成配置
|
80
|
+
|
81
|
+
🎉 **新功能**: 可以直接从 `.podspec` 文件自动生成 YAML 配置文件!
|
82
|
+
|
83
|
+
**仅生成配置文件:**
|
84
|
+
```bash
|
85
|
+
bundle exec xcbuilder --from-podspec MyLibrary.podspec
|
86
|
+
```
|
87
|
+
|
88
|
+
**一键生成配置并自动构建 XCFramework:**
|
89
|
+
```bash
|
90
|
+
bundle exec xcbuilder --from-podspec-build MyLibrary.podspec
|
91
|
+
```
|
92
|
+
|
93
|
+
**🚀 完整工作流:生成、构建、发布到私有仓库:**
|
94
|
+
```bash
|
95
|
+
bundle exec xcbuilder --from-podspec-publish MyLibrary.podspec
|
96
|
+
```
|
97
|
+
|
98
|
+
**📦 仅生成 Framework Podspec 文件:**
|
99
|
+
```bash
|
100
|
+
bundle exec xcbuilder --generate-framework-podspec MyLibrary.podspec
|
101
|
+
```
|
102
|
+
|
103
|
+
**🚀 完整自动化流程(推荐):**
|
104
|
+
```bash
|
105
|
+
bundle exec xcbuilder --from-podspec-auto MyLibrary.podspec
|
106
|
+
```
|
107
|
+
|
108
|
+
**自动解析的内容:**
|
109
|
+
- `name` → `scheme` 和 `target`
|
110
|
+
- `version` → 版本信息(保存在 metadata 中)
|
111
|
+
- `ios.deployment_target` → `deployment_target`
|
112
|
+
- 自动在 `Example/` 目录下查找 `.xcworkspace` 文件
|
113
|
+
- 自动设置 `framework_name` 为 `{name}.xcframework`
|
114
|
+
- 输出目录自动设置为 podspec 文件同级的 `./build` 目录
|
115
|
+
|
116
|
+
**目录结构要求:**
|
117
|
+
```
|
118
|
+
MyLibrary.podspec
|
119
|
+
Example/
|
120
|
+
├── MyLibrary.xcworkspace # 自动查找
|
121
|
+
└── ...
|
122
|
+
```
|
123
|
+
|
124
|
+
生成配置后会自动在 podspec 同级目录创建 `build_config.yml` 文件。
|
125
|
+
|
126
|
+
### 🎯 完整发布工作流
|
127
|
+
|
128
|
+
使用 `--from-podspec-publish` 可以实现完整的自动化流程:
|
129
|
+
|
130
|
+
1. **解析原始 podspec** → 提取 name、version、deployment_target 等信息
|
131
|
+
2. **生成构建配置** → 自动创建 build_config.yml
|
132
|
+
3. **构建 XCFramework** → 执行完整构建过程
|
133
|
+
4. **生成发布 podspec** → 创建发布用的 podspec 文件
|
134
|
+
5. **发布到私有仓库** → 自动执行 `pod repo push` 命令
|
135
|
+
|
136
|
+
**生成的发布 podspec 特点:**
|
137
|
+
- 文件名:`{原始名称}.podspec` (例如:`DYBase.podspec`,与原 podspec 文件名保持一致)
|
138
|
+
- 内容名称:`{原始名称}` (例如:`DYBase`)
|
139
|
+
- 版本:`{原始版本}-xc` (例如:`1.0.0-xc`)
|
140
|
+
- 来源:`{ :http => 'https://...' }` hash 格式
|
141
|
+
- 配置:添加 `s.vendored_frameworks = 'FrameworkName.xcframework'`
|
142
|
+
- 兼容:保持原始的 deployment_target 和其他配置
|
143
|
+
|
144
|
+
### 📦 仅生成 Framework Podspec
|
145
|
+
|
146
|
+
有时您可能需要单独生成 framework podspec 文件,而不执行构建过程(比如已经有现成的 XCFramework):
|
147
|
+
|
148
|
+
```bash
|
149
|
+
bundle exec xcbuilder --generate-framework-podspec MyLibrary.podspec
|
150
|
+
```
|
151
|
+
|
152
|
+
**使用场景:**
|
153
|
+
- 已经手动构建了 XCFramework,只需要生成发布用的 podspec
|
154
|
+
- 需要预先查看生成的 podspec 内容
|
155
|
+
- 分离构建和发布流程,便于 CI/CD 管道管理
|
156
|
+
|
157
|
+
**生成的文件:**
|
158
|
+
- 文件路径:`./build/MyLibrary.podspec` (保存在 build 目录中,与原 podspec 文件名保持一致)
|
159
|
+
- 内容中的 name:`MyLibrary` (保持原始名称)
|
160
|
+
- 版本:`1.0.0-xc` (原始版本 + `-xc` 后缀)
|
161
|
+
- 源地址:`{ :http => 'https://f.diyiedu.com/iOS/frameworks/2025/08/07/1.0.0/MyLibrary.xcframework.zip' }`
|
162
|
+
- XCFramework 配置:`s.vendored_frameworks = 'MyLibrary.xcframework'`
|
163
|
+
|
164
|
+
### 🚀 完整自动化流程(推荐)
|
165
|
+
|
166
|
+
完整的一键自动化流程,从 podspec 到最终发布的全流程:
|
167
|
+
|
168
|
+
```bash
|
169
|
+
bundle exec xcbuilder --from-podspec-auto MyLibrary.podspec
|
170
|
+
```
|
171
|
+
|
172
|
+
**工作流程:**
|
173
|
+
1. **Step 1**: 自动生成 YAML 配置并构建 XCFramework
|
174
|
+
2. **Step 2**: 自动上传到阿里云 OSS 并获取下载地址
|
175
|
+
3. **Step 3**: 生成包含 OSS 下载地址的 framework podspec
|
176
|
+
4. **Step 4**: 自动发布到私有 CocoaPods 仓库
|
177
|
+
|
178
|
+
### ☁️ 阿里云 OSS 上传功能
|
179
|
+
|
180
|
+
阿里云 OSS 自动上传功能,可以将构建好的 XCFramework 自动上传到 OSS 并生成包含 OSS 下载地址的 podspec 文件。
|
181
|
+
|
182
|
+
```bash
|
183
|
+
# 推荐使用完整自动化流程
|
184
|
+
bundle exec xcbuilder --from-podspec-auto MyLibrary.podspec
|
185
|
+
```
|
186
|
+
|
187
|
+
**OSS 上传特点:**
|
188
|
+
- 自动压缩 XCFramework 为 zip 格式
|
189
|
+
- 按日期和版本组织存储路径:`iOS/frameworks/2025/08/07/1.0.0/MyLibrary.xcframework.zip`
|
190
|
+
- 支持 OSS 签名验证和安全上传
|
191
|
+
- 上传失败时自动回退到 GitLab URL 格式
|
192
|
+
- 生成的 podspec 使用 OSS 下载地址
|
193
|
+
|
194
|
+
**环境变量配置:**
|
195
|
+
```bash
|
196
|
+
export ALIBABA_CLOUD_ACCESS_KEY_ID="your_access_key_id"
|
197
|
+
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="your_access_key_secret"
|
198
|
+
export OSS_BUCKET="your_bucket_name"
|
199
|
+
export OSS_ENDPOINT="oss-cn-hangzhou.aliyuncs.com"
|
200
|
+
```
|
201
|
+
|
202
|
+
**依赖要求:**
|
203
|
+
- `aliyun-sdk ~> 0.8.0` - 阿里云官方 Ruby SDK
|
204
|
+
- `rubyzip ~> 2.3` - ZIP 文件处理
|
205
|
+
|
206
|
+
**上传路径格式:**
|
207
|
+
```
|
208
|
+
iOS/frameworks/YYYY/MM/DD/version/FrameworkName.xcframework.zip
|
209
|
+
```
|
210
|
+
|
211
|
+
**版本处理策略:**
|
212
|
+
- OSS 上传路径使用原始 podspec 版本(如:`1.2.3`)
|
213
|
+
- 生成的私有 podspec 使用带后缀版本(如:`1.2.3-xc`)
|
214
|
+
|
215
|
+
**自动发布流程:**
|
216
|
+
1. 解析原始 podspec 文件
|
217
|
+
2. 构建 XCFramework
|
218
|
+
3. 上传到阿里云 OSS(使用原始版本)
|
219
|
+
4. 生成 framework podspec(使用带 `-xc` 后缀版本)
|
220
|
+
5. 自动发布到 `ios-specs` 私有仓库
|
221
|
+
|
222
|
+
**使用场景:**
|
223
|
+
- 需要使用 CDN 加速下载的场景
|
224
|
+
- 不便使用 GitLab 作为下载源的环境
|
225
|
+
- 需要独立的文件存储服务
|
226
|
+
|
227
|
+
**五种工作模式:**
|
228
|
+
1. **仅生成模式** (`--from-podspec`): 只生成 YAML 配置文件,方便检查和调整配置
|
229
|
+
2. **自动构建模式** (`--from-podspec-build`): 生成配置后立即自动构建 XCFramework,一步到位!
|
230
|
+
3. **🎯 完整发布模式** (`--from-podspec-publish`): 生成配置 → 构建 XCFramework → 生成发布用 podspec → 发布到私有仓库
|
231
|
+
4. **📦 仅生成 Podspec 模式** (`--generate-framework-podspec`): 只生成用于发布的 framework podspec 文件
|
232
|
+
5. **🚀 完整自动化模式** (`--from-podspec-auto`): 生成配置 → 构建 XCFramework → 上传到阿里云 OSS → 生成 podspec → 发布到私有仓库(推荐)
|
233
|
+
|
234
|
+
### 🔧 测试命令
|
235
|
+
|
236
|
+
**测试 OSS 上传功能:**
|
237
|
+
```bash
|
238
|
+
bundle exec xcbuilder --test-oss-upload path/to/existing.xcframework
|
239
|
+
```
|
240
|
+
|
241
|
+
### 5. 项目类型支持
|
242
|
+
|
243
|
+
工具智能支持两种项目类型:
|
244
|
+
|
245
|
+
**Workspace项目(推荐用于使用CocoaPods/Carthage的项目):**
|
246
|
+
```yaml
|
247
|
+
project:
|
248
|
+
path: "./MyLibrary.xcworkspace"
|
249
|
+
```
|
250
|
+
|
251
|
+
**Xcode项目:**
|
252
|
+
```yaml
|
253
|
+
project:
|
254
|
+
path: "./MyLibrary.xcodeproj"
|
255
|
+
```
|
256
|
+
|
257
|
+
**智能检测:**
|
258
|
+
如果只提供项目名称,工具会自动查找:
|
259
|
+
```yaml
|
260
|
+
project:
|
261
|
+
path: "./MyLibrary" # 会自动查找 .xcworkspace 或 .xcodeproj
|
262
|
+
```
|
263
|
+
|
264
|
+
### 6. 命令行参数
|
265
|
+
|
266
|
+
你也可以直接通过命令行参数构建(不使用配置文件):
|
267
|
+
|
268
|
+
```bash
|
269
|
+
bundle exec xcbuilder -p MyProject.xcworkspace -t MyTarget -o ./output -v
|
270
|
+
```
|
271
|
+
|
272
|
+
## 命令行选项
|
273
|
+
|
274
|
+
- `-f, --config FILE` - YAML配置文件路径
|
275
|
+
- `-p, --project PATH` - 项目文件路径
|
276
|
+
- `-t, --target TARGET` - 目标名称
|
277
|
+
- `-c, --configuration CONFIG` - 构建配置(Debug/Release)
|
278
|
+
- `-o, --output OUTPUT` - 输出目录
|
279
|
+
- `-s, --sdk SDK` - SDK(iphoneos/iphonesimulator)
|
280
|
+
- `-v, --verbose` - 详细输出
|
281
|
+
- `--create-config FILE` - 创建配置文件模板
|
282
|
+
- `--from-podspec PODSPEC` - 从 podspec 文件生成配置
|
283
|
+
- `--from-podspec-build PODSPEC` - 从 podspec 生成配置并构建
|
284
|
+
- `--from-podspec-publish PODSPEC` - 从 podspec 生成配置、构建并发布
|
285
|
+
- `--generate-framework-podspec PODSPEC` - 仅生成 framework podspec 文件
|
286
|
+
- `--from-podspec-auto PODSPEC` - 完整自动化流程(推荐)
|
287
|
+
- `--test-oss-upload XCFRAMEWORK` - 测试 OSS 上传功能
|
288
|
+
- `-h, --help` - 显示帮助信息
|
289
|
+
- `--version` - 显示版本信息
|
290
|
+
|
291
|
+
## 特性
|
292
|
+
|
293
|
+
- ✅ 支持YAML配置文件
|
294
|
+
- ✅ 智能支持.xcworkspace和.xcodeproj
|
295
|
+
- ✅ 自动跳过编译警告
|
296
|
+
- ✅ 支持多架构构建
|
297
|
+
- ✅ 支持iOS设备和模拟器
|
298
|
+
- ✅ 自动生成XCFramework
|
299
|
+
- ✅ 详细的构建日志
|
300
|
+
- ✅ 阿里云 OSS 自动上传
|
301
|
+
- ✅ 自动生成发布用 podspec
|
302
|
+
- ✅ 自动发布到私有 CocoaPods 仓库
|
303
|
+
|
304
|
+
## 开发
|
305
|
+
|
306
|
+
安装依赖:
|
307
|
+
|
308
|
+
```bash
|
309
|
+
bin/setup
|
310
|
+
```
|
311
|
+
|
312
|
+
运行交互式控制台:
|
313
|
+
|
314
|
+
```bash
|
315
|
+
bin/console
|
316
|
+
```
|
317
|
+
|
318
|
+
## 示例
|
319
|
+
|
320
|
+
### 完整的构建流程
|
321
|
+
|
322
|
+
1. 创建配置文件:
|
323
|
+
```bash
|
324
|
+
bundle exec xcbuilder --create-config my_library_config.yml
|
325
|
+
```
|
326
|
+
|
327
|
+
2. 编辑配置文件,设置你的项目路径和参数
|
328
|
+
|
329
|
+
3. 执行构建:
|
330
|
+
```bash
|
331
|
+
bundle exec xcbuilder -f build_config.yml -v
|
332
|
+
```
|
333
|
+
|
334
|
+
4. 构建完成后,你会在指定的输出目录找到生成的`.xcframework`文件
|
335
|
+
|
336
|
+
## 贡献
|
337
|
+
|
338
|
+
欢迎提交Issue和Pull Request。
|
data/Rakefile
ADDED
data/bin/xcbuilder
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "optparse"
|
6
|
+
require "DYXCFrameworkBuilder"
|
7
|
+
|
8
|
+
class BuilderCLI
|
9
|
+
def initialize
|
10
|
+
@options = {}
|
11
|
+
@parser = create_option_parser
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
begin
|
16
|
+
@parser.parse!(into: @options)
|
17
|
+
|
18
|
+
# 只有当没有特殊命令处理时才调用XCFrameworkBuilder
|
19
|
+
# 特殊命令在option回调中处理并exit,不会到达这里
|
20
|
+
DYXCFrameworkBuilder::XCFrameworkBuilder.new(@options).build
|
21
|
+
|
22
|
+
rescue SystemExit
|
23
|
+
# 允许正常的exit调用通过
|
24
|
+
raise
|
25
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
|
26
|
+
puts "Error: #{e.message}"
|
27
|
+
puts @parser
|
28
|
+
exit 1
|
29
|
+
rescue => e
|
30
|
+
puts "Error: #{e.message}"
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def create_option_parser
|
38
|
+
OptionParser.new do |opts|
|
39
|
+
opts.banner = "Usage: xcbuilder [options]"
|
40
|
+
|
41
|
+
opts.on("-f", "--config FILE", "YAML configuration file path") do |file|
|
42
|
+
@options[:config_path] = file
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("-p", "--project PATH", "Project path") do |path|
|
46
|
+
@options[:project_path] = path
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("-t", "--target TARGET", "Target name") do |target|
|
50
|
+
@options[:target] = target
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on("-c", "--configuration CONFIG", "Build configuration (Debug/Release)") do |config|
|
54
|
+
@options[:configuration] = config
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on("-o", "--output OUTPUT", "Output directory") do |output|
|
58
|
+
@options[:output_dir] = output
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on("-s", "--sdk SDK", "SDK (iphoneos/iphonesimulator)") do |sdk|
|
62
|
+
@options[:sdk] = sdk
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on("-v", "--verbose", "Verbose output") do
|
66
|
+
@options[:verbose] = true
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("--create-config FILE", "Create configuration template file") do |file|
|
70
|
+
DYXCFrameworkBuilder::XCFrameworkBuilder.create_config_template(file)
|
71
|
+
puts "Configuration template created at: #{file}"
|
72
|
+
puts "Please edit the configuration file and run with -f option"
|
73
|
+
exit
|
74
|
+
end
|
75
|
+
|
76
|
+
opts.on("--from-podspec PODSPEC", "Generate configuration from .podspec file") do |podspec|
|
77
|
+
config_path = DYXCFrameworkBuilder::XCFrameworkBuilder.generate_config_from_podspec(podspec)
|
78
|
+
puts ""
|
79
|
+
puts "You can now build with:"
|
80
|
+
puts " xcbuilder -f #{config_path} -v"
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.on("--from-podspec-build PODSPEC", "Generate configuration and build XCFramework automatically") do |podspec|
|
85
|
+
DYXCFrameworkBuilder::XCFrameworkBuilder.generate_config_from_podspec(podspec, nil, true)
|
86
|
+
exit
|
87
|
+
end
|
88
|
+
|
89
|
+
opts.on("--from-podspec-publish PODSPEC", "Generate, build, and publish XCFramework to private repository") do |podspec|
|
90
|
+
DYXCFrameworkBuilder::XCFrameworkBuilder.generate_config_from_podspec(podspec, nil, true, true)
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
|
94
|
+
opts.on("--generate-framework-podspec PODSPEC", "Generate framework podspec only (without building)") do |podspec|
|
95
|
+
begin
|
96
|
+
parser = DYXCFrameworkBuilder::PodspecParser.new(podspec)
|
97
|
+
xcframework_path = File.join(parser.output_directory, parser.framework_name)
|
98
|
+
|
99
|
+
framework_info = DYXCFrameworkBuilder::FrameworkPodspecGenerator.generate_from_original(
|
100
|
+
parser,
|
101
|
+
xcframework_path
|
102
|
+
)
|
103
|
+
|
104
|
+
puts ""
|
105
|
+
puts "🎉 Framework podspec generated successfully!"
|
106
|
+
puts "📄 File: #{framework_info[:path]}"
|
107
|
+
puts "📦 Name: #{framework_info[:name]}"
|
108
|
+
puts "🔢 Version: #{framework_info[:version]}"
|
109
|
+
puts "🌐 Source: #{framework_info[:download_url]}"
|
110
|
+
puts ""
|
111
|
+
puts "💡 You can now:"
|
112
|
+
puts " 1. Upload the XCFramework to: #{framework_info[:download_url].sub('@', '')}"
|
113
|
+
puts " 2. Publish the podspec: pod repo push ios-specs #{framework_info[:path]}"
|
114
|
+
rescue => e
|
115
|
+
puts "❌ Error: #{e.message}"
|
116
|
+
exit 1
|
117
|
+
end
|
118
|
+
exit
|
119
|
+
end
|
120
|
+
|
121
|
+
opts.on("--from-podspec-oss PODSPEC", "Generate, build, upload to OSS, and generate framework podspec") do |podspec|
|
122
|
+
DYXCFrameworkBuilder::XCFrameworkBuilder.generate_config_from_podspec(podspec, nil, true, false, true)
|
123
|
+
exit
|
124
|
+
end
|
125
|
+
|
126
|
+
opts.on("--from-podspec-auto PODSPEC", "Complete auto workflow: build XCFramework, upload to OSS, generate podspec, and publish to private repo") do |podspec|
|
127
|
+
DYXCFrameworkBuilder::XCFrameworkBuilder.generate_config_from_podspec(podspec, nil, true, false, true, true)
|
128
|
+
exit
|
129
|
+
end
|
130
|
+
|
131
|
+
opts.on("--test-oss-upload XCFRAMEWORK_PATH", "Test OSS upload with existing XCFramework") do |xcframework_path|
|
132
|
+
begin
|
133
|
+
# 验证 XCFramework 路径
|
134
|
+
unless File.exist?(xcframework_path)
|
135
|
+
puts "❌ Error: XCFramework not found at: #{xcframework_path}"
|
136
|
+
exit 1
|
137
|
+
end
|
138
|
+
|
139
|
+
# 从路径提取框架名称和模拟版本
|
140
|
+
framework_name = File.basename(xcframework_path, '.xcframework')
|
141
|
+
test_version = "test_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
|
142
|
+
|
143
|
+
puts "🧪 Testing OSS upload functionality..."
|
144
|
+
puts "📦 Framework: #{framework_name}"
|
145
|
+
puts "🔢 Test Version: #{test_version}"
|
146
|
+
puts "📁 XCFramework Path: #{xcframework_path}"
|
147
|
+
puts "="*60
|
148
|
+
|
149
|
+
# 执行 OSS 上传测试
|
150
|
+
uploader = DYXCFrameworkBuilder::OSSUploader.new
|
151
|
+
result = uploader.upload_xcframework(
|
152
|
+
xcframework_path,
|
153
|
+
framework_name,
|
154
|
+
test_version
|
155
|
+
)
|
156
|
+
|
157
|
+
if result[:success]
|
158
|
+
puts ""
|
159
|
+
puts "🎉 OSS upload test completed successfully!"
|
160
|
+
puts "🌐 Download URL: #{result[:download_url]}"
|
161
|
+
puts "📊 File Size: #{(result[:file_size] / 1024.0 / 1024.0).round(2)} MB"
|
162
|
+
puts "📂 OSS Path: #{result[:oss_path]}"
|
163
|
+
else
|
164
|
+
puts ""
|
165
|
+
puts "❌ OSS upload test failed!"
|
166
|
+
puts "🔍 Error: #{result[:error]}"
|
167
|
+
exit 1
|
168
|
+
end
|
169
|
+
|
170
|
+
rescue => e
|
171
|
+
puts "❌ Test failed with error: #{e.message}"
|
172
|
+
puts "🔍 Please check your OSS configuration and network connection."
|
173
|
+
exit 1
|
174
|
+
end
|
175
|
+
exit
|
176
|
+
end
|
177
|
+
|
178
|
+
opts.on("-h", "--help", "Show this help message") do
|
179
|
+
puts opts
|
180
|
+
puts ""
|
181
|
+
puts "Examples:"
|
182
|
+
puts " # Create a configuration template"
|
183
|
+
puts " xcbuilder --create-config build_config.yml"
|
184
|
+
puts ""
|
185
|
+
puts " # Generate configuration from .podspec file"
|
186
|
+
puts " xcbuilder --from-podspec MyLibrary.podspec"
|
187
|
+
puts ""
|
188
|
+
puts " # Generate configuration and build XCFramework automatically"
|
189
|
+
puts " xcbuilder --from-podspec-build MyLibrary.podspec"
|
190
|
+
puts ""
|
191
|
+
puts " # Complete workflow: generate, build, and publish to private repository"
|
192
|
+
puts " xcbuilder --from-podspec-publish MyLibrary.podspec"
|
193
|
+
puts ""
|
194
|
+
puts " # Generate framework podspec only (for manual upload and publish)"
|
195
|
+
puts " xcbuilder --generate-framework-podspec MyLibrary.podspec"
|
196
|
+
puts ""
|
197
|
+
puts " # Generate, build, upload to OSS, and generate framework podspec"
|
198
|
+
puts " xcbuilder --from-podspec-oss MyLibrary.podspec"
|
199
|
+
puts ""
|
200
|
+
puts " # Complete auto workflow: build XCFramework, upload to OSS, generate podspec, and publish to private repo"
|
201
|
+
puts " xcbuilder --from-podspec-auto MyLibrary.podspec"
|
202
|
+
puts ""
|
203
|
+
puts " # Test OSS upload with existing XCFramework"
|
204
|
+
puts " xcbuilder --test-oss-upload ./build/MyLibrary.xcframework"
|
205
|
+
puts ""
|
206
|
+
puts " # Build using configuration file"
|
207
|
+
puts " xcbuilder -f build_config.yml -v"
|
208
|
+
puts ""
|
209
|
+
puts " # Build with direct parameters"
|
210
|
+
puts " xcbuilder -p MyProject.xcodeproj -t MyTarget -o ./output"
|
211
|
+
exit
|
212
|
+
end
|
213
|
+
|
214
|
+
opts.on("--version", "Show version") do
|
215
|
+
puts "DYXCFrameworkBuilder version #{DYXCFrameworkBuilder::VERSION}"
|
216
|
+
exit
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
if __FILE__ == $0
|
223
|
+
# 全量
|
224
|
+
# ARGV << '--from-podspec-auto' << '/Users/leigeng/Desktop/diyi/Module/DYBase/DYBase.podspec' << '-v' if ARGV.empty?
|
225
|
+
# 仅生成 Framework Podspec 文件:**
|
226
|
+
# ARGV << '--generate-framework-podspec' << '/Users/leigeng/Desktop/diyi/Module/DYBase/DYBase.podspec' << '-v' if ARGV.empty?
|
227
|
+
# 全部流程
|
228
|
+
ARGV << '--from-podspec-auto' << '/Users/leigeng/Desktop/diyi/Module/DYBase/DYBase.podspec' << '-v' if ARGV.empty?
|
229
|
+
BuilderCLI.new.run
|
230
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'config'
|
4
|
+
require_relative 'xcframework_builder'
|
5
|
+
|
6
|
+
module DYXCFrameworkBuilder
|
7
|
+
# Main builder facade that coordinates the build process
|
8
|
+
class Builder
|
9
|
+
attr_reader :options, :config, :verbose
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = options
|
13
|
+
@config_path = options[:config_path]
|
14
|
+
@verbose = options[:verbose] || false
|
15
|
+
|
16
|
+
load_configuration
|
17
|
+
end
|
18
|
+
|
19
|
+
def build
|
20
|
+
if @config
|
21
|
+
build_from_config
|
22
|
+
else
|
23
|
+
build_from_options
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.create_config_template(path)
|
28
|
+
Config.create_template(path)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def load_configuration
|
34
|
+
if @config_path
|
35
|
+
@config = Config.new(@config_path)
|
36
|
+
else
|
37
|
+
# Create a simple config from direct options for backward compatibility
|
38
|
+
@config = create_config_from_options
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_config_from_options
|
43
|
+
# Create a minimal config object from direct options
|
44
|
+
if has_required_options?
|
45
|
+
SimpleConfig.new(@options)
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_required_options?
|
52
|
+
required_options = [:project_path, :target, :output_dir]
|
53
|
+
required_options.all? { |opt| @options[opt] && !@options[opt].empty? }
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_from_config
|
57
|
+
log "Starting XCFramework build from configuration"
|
58
|
+
|
59
|
+
builder = CoreBuilder.new(@config, verbose: @verbose)
|
60
|
+
result = builder.build
|
61
|
+
|
62
|
+
log "✅ Build completed successfully!"
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
def build_from_options
|
67
|
+
if @config
|
68
|
+
build_from_config
|
69
|
+
else
|
70
|
+
validate_options
|
71
|
+
log "Starting XCFramework build from command line options"
|
72
|
+
log "Project: #{@options[:project_path]}"
|
73
|
+
log "Target: #{@options[:target]}"
|
74
|
+
log "Configuration: #{@options[:configuration] || 'Release'}"
|
75
|
+
log "Output: #{@options[:output_dir]}"
|
76
|
+
log "SDK: #{@options[:sdk]}"
|
77
|
+
|
78
|
+
# For direct options, create a simple build process
|
79
|
+
# This is a fallback implementation
|
80
|
+
log "⚠️ Using direct options mode. For full features, use configuration file mode."
|
81
|
+
log "Use 'builder --create-config config.yml' to create a configuration template."
|
82
|
+
|
83
|
+
raise Error, "Direct options mode not fully implemented. Please use configuration file mode."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_options
|
88
|
+
required_options = [:project_path, :target, :output_dir]
|
89
|
+
missing_options = required_options.select { |opt| @options[opt].nil? || @options[opt].empty? }
|
90
|
+
|
91
|
+
if missing_options.any?
|
92
|
+
raise Error, "Missing required options: #{missing_options.join(', ')}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def log(message)
|
97
|
+
if @verbose
|
98
|
+
puts "[INFO] #{message}"
|
99
|
+
else
|
100
|
+
puts message
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Simple config class for backward compatibility with direct options
|
106
|
+
class SimpleConfig
|
107
|
+
attr_reader :project_path, :scheme, :target, :configuration, :output_dir,
|
108
|
+
:platforms, :enable_bitcode, :skip_warnings
|
109
|
+
|
110
|
+
def initialize(options)
|
111
|
+
@project_path = options[:project_path]
|
112
|
+
@scheme = options[:target] # Use target as scheme for simplicity
|
113
|
+
@target = options[:target]
|
114
|
+
@configuration = options[:configuration] || 'Release'
|
115
|
+
@output_dir = options[:output_dir]
|
116
|
+
@enable_bitcode = false
|
117
|
+
@skip_warnings = true
|
118
|
+
|
119
|
+
# Default platforms configuration
|
120
|
+
@platforms = {
|
121
|
+
'ios' => {
|
122
|
+
'deployment_target' => '11.0',
|
123
|
+
'architectures' => ['arm64']
|
124
|
+
},
|
125
|
+
'ios_simulator' => {
|
126
|
+
'deployment_target' => '11.0',
|
127
|
+
'architectures' => ['arm64', 'x86_64']
|
128
|
+
}
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
def framework_name
|
133
|
+
"#{@scheme}.xcframework"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|