cpm-build 0.1.0__tar.gz
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.
- cpm_build-0.1.0/LICENSE +21 -0
- cpm_build-0.1.0/MANIFEST.in +3 -0
- cpm_build-0.1.0/PKG-INFO +190 -0
- cpm_build-0.1.0/README.md +160 -0
- cpm_build-0.1.0/cpm_build/__init__.py +1 -0
- cpm_build-0.1.0/cpm_build/android_build_context.py +60 -0
- cpm_build-0.1.0/cpm_build/argparse_enums.py +40 -0
- cpm_build-0.1.0/cpm_build/build_context.py +106 -0
- cpm_build-0.1.0/cpm_build/darwin_build_context.py +124 -0
- cpm_build-0.1.0/cpm_build/djinni_build.py +221 -0
- cpm_build-0.1.0/cpm_build/linux_build_context.py +7 -0
- cpm_build-0.1.0/cpm_build/print_prefixed.py +7 -0
- cpm_build-0.1.0/cpm_build/profiles/android +8 -0
- cpm_build-0.1.0/cpm_build/profiles/ios +8 -0
- cpm_build-0.1.0/cpm_build/profiles/linux +5 -0
- cpm_build-0.1.0/cpm_build/profiles/macos +8 -0
- cpm_build-0.1.0/cpm_build/profiles/windows +6 -0
- cpm_build-0.1.0/cpm_build/windows_build_context.py +66 -0
- cpm_build-0.1.0/cpm_build.egg-info/PKG-INFO +190 -0
- cpm_build-0.1.0/cpm_build.egg-info/SOURCES.txt +23 -0
- cpm_build-0.1.0/cpm_build.egg-info/dependency_links.txt +1 -0
- cpm_build-0.1.0/cpm_build.egg-info/requires.txt +1 -0
- cpm_build-0.1.0/cpm_build.egg-info/top_level.txt +1 -0
- cpm_build-0.1.0/setup.cfg +4 -0
- cpm_build-0.1.0/setup.py +32 -0
cpm_build-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 pyoneer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
cpm_build-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cpm_build
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Utility to package and distribute Djinni libraries easily.
|
|
5
|
+
Home-page: https://github.com/goudantongxue/cpm-build
|
|
6
|
+
Author: goudantongxue
|
|
7
|
+
Author-email: woshigoudan0913@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: djinni
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: conan>=2.0
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: author-email
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: keywords
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: requires-python
|
|
29
|
+
Dynamic: summary
|
|
30
|
+
|
|
31
|
+
# cpm-build
|
|
32
|
+
|
|
33
|
+
一个用于跨平台构建和打包 [Djinni](https://djinni.xlcpp.dev/) 库的 Python 命令行工具。
|
|
34
|
+
|
|
35
|
+
## 简介
|
|
36
|
+
|
|
37
|
+
`cpm-build` 是一个构建编排工具,旨在简化 Djinni 跨平台库的编译、构建和打包流程。通过统一的命令行接口,开发者可以轻松地为 Android、iOS、macOS、Windows 和 Linux 等多个平台构建原生库,并自动生成对应平台的分发包。
|
|
38
|
+
|
|
39
|
+
## 功能特性
|
|
40
|
+
|
|
41
|
+
- **多平台支持** — 支持 Android、iOS、macOS、Windows、Linux 五大平台
|
|
42
|
+
- **多架构编译** — 支持 x86_64、x86、armv8、armv7 等多种 CPU 架构
|
|
43
|
+
- **自动打包** — 自动生成平台专属分发包:
|
|
44
|
+
- **AAR**(Android Archive)— 用于 Android 项目集成
|
|
45
|
+
- **XCFramework** — 用于 iOS / macOS 项目集成
|
|
46
|
+
- **Swift Package** — 用于 Swift 包管理器集成
|
|
47
|
+
- **NuGet** — 用于 Windows / .NET 项目集成
|
|
48
|
+
- **Conan 集成** — 基于 Conan 2.0+ 进行依赖管理和构建配置
|
|
49
|
+
- **灵活配置** — 支持 Debug / Release 构建模式,可自定义构建目录和 Conan Profile
|
|
50
|
+
|
|
51
|
+
## 系统要求
|
|
52
|
+
|
|
53
|
+
- **Python** >= 3.10
|
|
54
|
+
- **Conan** >= 2.0
|
|
55
|
+
- **Git**(用于自动版本号提取)
|
|
56
|
+
- 各平台工具链:
|
|
57
|
+
- Android: [Android NDK](https://developer.android.com/ndk)(需设置 `ANDROID_NDK_HOME` 环境变量)
|
|
58
|
+
- iOS / macOS: [Xcode](https://developer.apple.com/xcode/)
|
|
59
|
+
- Windows: [Visual Studio 2022](https://visualstudio.microsoft.com/)
|
|
60
|
+
- Linux: GCC 11+
|
|
61
|
+
|
|
62
|
+
## 安装
|
|
63
|
+
|
|
64
|
+
### 通过 pip 安装
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install cpm-build
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 从源码安装
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
git clone https://github.com/goudantongxue/cpm-build.git
|
|
74
|
+
cd cpm-build
|
|
75
|
+
pip install .
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 快速开始
|
|
79
|
+
|
|
80
|
+
### 基本用法
|
|
81
|
+
|
|
82
|
+
在你的 Djinni 项目中创建构建脚本:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from cpm_build import DjinniBuild
|
|
86
|
+
|
|
87
|
+
djinni_build = DjinniBuild(lib_name='my_library')
|
|
88
|
+
djinni_build.main()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
然后通过命令行参数指定目标平台和架构:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# 构建 Android (armv8 + x86_64) 并打包为 AAR
|
|
95
|
+
python build.py --android armv8 x86_64 --package aar
|
|
96
|
+
|
|
97
|
+
# 构建 iOS + macOS 并打包为 XCFramework
|
|
98
|
+
python build.py --iphoneos armv8 --iphonesimulator armv8 x86_64 --macos armv8 x86_64 --package xcframework
|
|
99
|
+
|
|
100
|
+
# 构建 XCFramework 并生成 Swift Package
|
|
101
|
+
python build.py --iphoneos armv8 --iphonesimulator armv8 x86_64 --macos armv8 x86_64 --package xcframework swiftpackage
|
|
102
|
+
|
|
103
|
+
# 构建 Windows (x64) 并打包为 NuGet
|
|
104
|
+
python build.py --windows x86_64 --package nuget
|
|
105
|
+
|
|
106
|
+
# 构建 Linux (x86_64)
|
|
107
|
+
python build.py --linux x86_64
|
|
108
|
+
|
|
109
|
+
# 使用 Debug 模式构建
|
|
110
|
+
python build.py --android armv8 --configuration debug
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 命令行参数
|
|
114
|
+
|
|
115
|
+
| 参数 | 说明 | 默认值 |
|
|
116
|
+
|------|------|--------|
|
|
117
|
+
| `--configuration {release,debug}` | 构建配置(Release 或 Debug) | `release` |
|
|
118
|
+
| `--android [ARCH ...]` | 构建 Android 平台,可指定架构 | — |
|
|
119
|
+
| `--iphoneos [ARCH ...]` | 构建 iOS 真机平台,可指定架构 | — |
|
|
120
|
+
| `--iphonesimulator [ARCH ...]` | 构建 iOS 模拟器平台,可指定架构 | — |
|
|
121
|
+
| `--macos [ARCH ...]` | 构建 macOS 平台,可指定架构 | — |
|
|
122
|
+
| `--windows [ARCH ...]` | 构建 Windows 平台,可指定架构 | — |
|
|
123
|
+
| `--linux [ARCH ...]` | 构建 Linux 平台,可指定架构 | — |
|
|
124
|
+
| `--build-directory PATH` | 构建输出目录 | `build/` |
|
|
125
|
+
| `--build-profile PROFILE` | Conan 构建 Profile 名称 | `default` |
|
|
126
|
+
| `--package [TYPE ...]` | 打包类型:`xcframework`、`swiftpackage`、`aar`、`nuget` | — |
|
|
127
|
+
|
|
128
|
+
### 支持的架构
|
|
129
|
+
|
|
130
|
+
| 架构 | Conan 名称 | Android 名称 | Windows 名称 |
|
|
131
|
+
|------|-----------|-------------|-------------|
|
|
132
|
+
| `x86_64` | x86_64 | x86_64 | win10-x64 |
|
|
133
|
+
| `x86` | x86 | x86 | win10-x86 |
|
|
134
|
+
| `armv8` | armv8 | arm64-v8a | win10-arm64 |
|
|
135
|
+
| `armv7` | armv7 | armeabi-v7a | win10-arm |
|
|
136
|
+
|
|
137
|
+
## 项目结构
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
cpm-build/
|
|
141
|
+
├── profiles/ # Conan 构建 Profile(各平台配置)
|
|
142
|
+
│ ├── android # Android NDK Profile
|
|
143
|
+
│ ├── ios # iOS SDK Profile
|
|
144
|
+
│ ├── macos # macOS Profile
|
|
145
|
+
│ ├── windows # Windows MSVC Profile
|
|
146
|
+
│ └── linux # Linux GCC Profile
|
|
147
|
+
├── cpm_build/ # Python 主包
|
|
148
|
+
│ ├── __init__.py # 包入口,导出 DjinniBuild
|
|
149
|
+
│ ├── djinni_build.py # 主编排类,CLI 入口
|
|
150
|
+
│ ├── build_context.py # 构建上下文基类
|
|
151
|
+
│ ├── android_build_context.py # Android 构建逻辑
|
|
152
|
+
│ ├── darwin_build_context.py # iOS / macOS 构建逻辑
|
|
153
|
+
│ ├── windows_build_context.py # Windows 构建逻辑
|
|
154
|
+
│ ├── linux_build_context.py # Linux 构建逻辑
|
|
155
|
+
│ ├── argparse_enums.py # CLI 枚举定义
|
|
156
|
+
│ └── print_prefixed.py # 日志输出工具
|
|
157
|
+
├── .github/workflows/publish.yml # CI/CD:自动发布到 PyPI
|
|
158
|
+
├── setup.py # 包安装配置
|
|
159
|
+
├── requirements.txt # 开发依赖
|
|
160
|
+
├── LICENSE # MIT 许可证
|
|
161
|
+
└── README.md # 项目文档
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## DjinniBuild 配置参数
|
|
165
|
+
|
|
166
|
+
`DjinniBuild` 类支持以下初始化参数,用于自定义构建行为:
|
|
167
|
+
|
|
168
|
+
| 参数 | 类型 | 说明 | 默认值 |
|
|
169
|
+
|------|------|------|--------|
|
|
170
|
+
| `lib_name` | `str` | 库名称(必填) | — |
|
|
171
|
+
| `default_build_dir` | `Path` | 默认构建输出目录 | `build/` |
|
|
172
|
+
| `default_conan_build_profile` | `str \| Path` | 默认 Conan 构建 Profile | `default` |
|
|
173
|
+
| `working_directory` | `Path` | 项目根目录 | 当前工作目录 |
|
|
174
|
+
| `darwin_target_dir` | `Path` | Darwin 平台目标定义路径 | `lib/platform/darwin` |
|
|
175
|
+
| `android_target_dir` | `Path` | Android 平台目标定义路径 | `lib/platform/android` |
|
|
176
|
+
| `windows_target_dir` | `Path` | Windows 平台目标定义路径 | `lib/platform/windows` |
|
|
177
|
+
| `android_profile` | `str \| Path` | Android Conan Profile 路径 | 内置 Profile |
|
|
178
|
+
| `macos_profile` | `str \| Path` | macOS Conan Profile 路径 | 内置 Profile |
|
|
179
|
+
| `ios_profile` | `str \| Path` | iOS Conan Profile 路径 | 内置 Profile |
|
|
180
|
+
| `windows_profile` | `str \| Path` | Windows Conan Profile 路径 | 内置 Profile |
|
|
181
|
+
| `linux_profile` | `str \| Path` | Linux Conan Profile 路径 | 内置 Profile |
|
|
182
|
+
| `nupkg_dir` | `Path` | NuGet 包模板目录 | `lib/platform/windows/package` |
|
|
183
|
+
| `android_project_dir` | `Path` | Android 项目目录(用于 AAR 构建) | `lib/platform/android/package` |
|
|
184
|
+
| `swiftpackage_dir` | `Path` | Swift Package 目录 | `lib/platform/darwin/package` |
|
|
185
|
+
|
|
186
|
+
## 许可证
|
|
187
|
+
|
|
188
|
+
本项目基于 [MIT 许可证](LICENSE) 开源。
|
|
189
|
+
|
|
190
|
+
Copyright (c) 2025 pyoneer
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# cpm-build
|
|
2
|
+
|
|
3
|
+
一个用于跨平台构建和打包 [Djinni](https://djinni.xlcpp.dev/) 库的 Python 命令行工具。
|
|
4
|
+
|
|
5
|
+
## 简介
|
|
6
|
+
|
|
7
|
+
`cpm-build` 是一个构建编排工具,旨在简化 Djinni 跨平台库的编译、构建和打包流程。通过统一的命令行接口,开发者可以轻松地为 Android、iOS、macOS、Windows 和 Linux 等多个平台构建原生库,并自动生成对应平台的分发包。
|
|
8
|
+
|
|
9
|
+
## 功能特性
|
|
10
|
+
|
|
11
|
+
- **多平台支持** — 支持 Android、iOS、macOS、Windows、Linux 五大平台
|
|
12
|
+
- **多架构编译** — 支持 x86_64、x86、armv8、armv7 等多种 CPU 架构
|
|
13
|
+
- **自动打包** — 自动生成平台专属分发包:
|
|
14
|
+
- **AAR**(Android Archive)— 用于 Android 项目集成
|
|
15
|
+
- **XCFramework** — 用于 iOS / macOS 项目集成
|
|
16
|
+
- **Swift Package** — 用于 Swift 包管理器集成
|
|
17
|
+
- **NuGet** — 用于 Windows / .NET 项目集成
|
|
18
|
+
- **Conan 集成** — 基于 Conan 2.0+ 进行依赖管理和构建配置
|
|
19
|
+
- **灵活配置** — 支持 Debug / Release 构建模式,可自定义构建目录和 Conan Profile
|
|
20
|
+
|
|
21
|
+
## 系统要求
|
|
22
|
+
|
|
23
|
+
- **Python** >= 3.10
|
|
24
|
+
- **Conan** >= 2.0
|
|
25
|
+
- **Git**(用于自动版本号提取)
|
|
26
|
+
- 各平台工具链:
|
|
27
|
+
- Android: [Android NDK](https://developer.android.com/ndk)(需设置 `ANDROID_NDK_HOME` 环境变量)
|
|
28
|
+
- iOS / macOS: [Xcode](https://developer.apple.com/xcode/)
|
|
29
|
+
- Windows: [Visual Studio 2022](https://visualstudio.microsoft.com/)
|
|
30
|
+
- Linux: GCC 11+
|
|
31
|
+
|
|
32
|
+
## 安装
|
|
33
|
+
|
|
34
|
+
### 通过 pip 安装
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install cpm-build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 从源码安装
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
git clone https://github.com/goudantongxue/cpm-build.git
|
|
44
|
+
cd cpm-build
|
|
45
|
+
pip install .
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 快速开始
|
|
49
|
+
|
|
50
|
+
### 基本用法
|
|
51
|
+
|
|
52
|
+
在你的 Djinni 项目中创建构建脚本:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from cpm_build import DjinniBuild
|
|
56
|
+
|
|
57
|
+
djinni_build = DjinniBuild(lib_name='my_library')
|
|
58
|
+
djinni_build.main()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
然后通过命令行参数指定目标平台和架构:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 构建 Android (armv8 + x86_64) 并打包为 AAR
|
|
65
|
+
python build.py --android armv8 x86_64 --package aar
|
|
66
|
+
|
|
67
|
+
# 构建 iOS + macOS 并打包为 XCFramework
|
|
68
|
+
python build.py --iphoneos armv8 --iphonesimulator armv8 x86_64 --macos armv8 x86_64 --package xcframework
|
|
69
|
+
|
|
70
|
+
# 构建 XCFramework 并生成 Swift Package
|
|
71
|
+
python build.py --iphoneos armv8 --iphonesimulator armv8 x86_64 --macos armv8 x86_64 --package xcframework swiftpackage
|
|
72
|
+
|
|
73
|
+
# 构建 Windows (x64) 并打包为 NuGet
|
|
74
|
+
python build.py --windows x86_64 --package nuget
|
|
75
|
+
|
|
76
|
+
# 构建 Linux (x86_64)
|
|
77
|
+
python build.py --linux x86_64
|
|
78
|
+
|
|
79
|
+
# 使用 Debug 模式构建
|
|
80
|
+
python build.py --android armv8 --configuration debug
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 命令行参数
|
|
84
|
+
|
|
85
|
+
| 参数 | 说明 | 默认值 |
|
|
86
|
+
|------|------|--------|
|
|
87
|
+
| `--configuration {release,debug}` | 构建配置(Release 或 Debug) | `release` |
|
|
88
|
+
| `--android [ARCH ...]` | 构建 Android 平台,可指定架构 | — |
|
|
89
|
+
| `--iphoneos [ARCH ...]` | 构建 iOS 真机平台,可指定架构 | — |
|
|
90
|
+
| `--iphonesimulator [ARCH ...]` | 构建 iOS 模拟器平台,可指定架构 | — |
|
|
91
|
+
| `--macos [ARCH ...]` | 构建 macOS 平台,可指定架构 | — |
|
|
92
|
+
| `--windows [ARCH ...]` | 构建 Windows 平台,可指定架构 | — |
|
|
93
|
+
| `--linux [ARCH ...]` | 构建 Linux 平台,可指定架构 | — |
|
|
94
|
+
| `--build-directory PATH` | 构建输出目录 | `build/` |
|
|
95
|
+
| `--build-profile PROFILE` | Conan 构建 Profile 名称 | `default` |
|
|
96
|
+
| `--package [TYPE ...]` | 打包类型:`xcframework`、`swiftpackage`、`aar`、`nuget` | — |
|
|
97
|
+
|
|
98
|
+
### 支持的架构
|
|
99
|
+
|
|
100
|
+
| 架构 | Conan 名称 | Android 名称 | Windows 名称 |
|
|
101
|
+
|------|-----------|-------------|-------------|
|
|
102
|
+
| `x86_64` | x86_64 | x86_64 | win10-x64 |
|
|
103
|
+
| `x86` | x86 | x86 | win10-x86 |
|
|
104
|
+
| `armv8` | armv8 | arm64-v8a | win10-arm64 |
|
|
105
|
+
| `armv7` | armv7 | armeabi-v7a | win10-arm |
|
|
106
|
+
|
|
107
|
+
## 项目结构
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
cpm-build/
|
|
111
|
+
├── profiles/ # Conan 构建 Profile(各平台配置)
|
|
112
|
+
│ ├── android # Android NDK Profile
|
|
113
|
+
│ ├── ios # iOS SDK Profile
|
|
114
|
+
│ ├── macos # macOS Profile
|
|
115
|
+
│ ├── windows # Windows MSVC Profile
|
|
116
|
+
│ └── linux # Linux GCC Profile
|
|
117
|
+
├── cpm_build/ # Python 主包
|
|
118
|
+
│ ├── __init__.py # 包入口,导出 DjinniBuild
|
|
119
|
+
│ ├── djinni_build.py # 主编排类,CLI 入口
|
|
120
|
+
│ ├── build_context.py # 构建上下文基类
|
|
121
|
+
│ ├── android_build_context.py # Android 构建逻辑
|
|
122
|
+
│ ├── darwin_build_context.py # iOS / macOS 构建逻辑
|
|
123
|
+
│ ├── windows_build_context.py # Windows 构建逻辑
|
|
124
|
+
│ ├── linux_build_context.py # Linux 构建逻辑
|
|
125
|
+
│ ├── argparse_enums.py # CLI 枚举定义
|
|
126
|
+
│ └── print_prefixed.py # 日志输出工具
|
|
127
|
+
├── .github/workflows/publish.yml # CI/CD:自动发布到 PyPI
|
|
128
|
+
├── setup.py # 包安装配置
|
|
129
|
+
├── requirements.txt # 开发依赖
|
|
130
|
+
├── LICENSE # MIT 许可证
|
|
131
|
+
└── README.md # 项目文档
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## DjinniBuild 配置参数
|
|
135
|
+
|
|
136
|
+
`DjinniBuild` 类支持以下初始化参数,用于自定义构建行为:
|
|
137
|
+
|
|
138
|
+
| 参数 | 类型 | 说明 | 默认值 |
|
|
139
|
+
|------|------|------|--------|
|
|
140
|
+
| `lib_name` | `str` | 库名称(必填) | — |
|
|
141
|
+
| `default_build_dir` | `Path` | 默认构建输出目录 | `build/` |
|
|
142
|
+
| `default_conan_build_profile` | `str \| Path` | 默认 Conan 构建 Profile | `default` |
|
|
143
|
+
| `working_directory` | `Path` | 项目根目录 | 当前工作目录 |
|
|
144
|
+
| `darwin_target_dir` | `Path` | Darwin 平台目标定义路径 | `lib/platform/darwin` |
|
|
145
|
+
| `android_target_dir` | `Path` | Android 平台目标定义路径 | `lib/platform/android` |
|
|
146
|
+
| `windows_target_dir` | `Path` | Windows 平台目标定义路径 | `lib/platform/windows` |
|
|
147
|
+
| `android_profile` | `str \| Path` | Android Conan Profile 路径 | 内置 Profile |
|
|
148
|
+
| `macos_profile` | `str \| Path` | macOS Conan Profile 路径 | 内置 Profile |
|
|
149
|
+
| `ios_profile` | `str \| Path` | iOS Conan Profile 路径 | 内置 Profile |
|
|
150
|
+
| `windows_profile` | `str \| Path` | Windows Conan Profile 路径 | 内置 Profile |
|
|
151
|
+
| `linux_profile` | `str \| Path` | Linux Conan Profile 路径 | 内置 Profile |
|
|
152
|
+
| `nupkg_dir` | `Path` | NuGet 包模板目录 | `lib/platform/windows/package` |
|
|
153
|
+
| `android_project_dir` | `Path` | Android 项目目录(用于 AAR 构建) | `lib/platform/android/package` |
|
|
154
|
+
| `swiftpackage_dir` | `Path` | Swift Package 目录 | `lib/platform/darwin/package` |
|
|
155
|
+
|
|
156
|
+
## 许可证
|
|
157
|
+
|
|
158
|
+
本项目基于 [MIT 许可证](LICENSE) 开源。
|
|
159
|
+
|
|
160
|
+
Copyright (c) 2025 pyoneer
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .djinni_build import DjinniBuild
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from .build_context import BuildContext
|
|
2
|
+
from .argparse_enums import Architecture, BuildConfiguration
|
|
3
|
+
from .print_prefixed import print_prefixed
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AndroidBuildContext(BuildContext):
|
|
9
|
+
"""Build context for Android. This defines the logic for packaging all binaries into one AAR"""
|
|
10
|
+
|
|
11
|
+
def __init__(self,
|
|
12
|
+
working_directory: Path,
|
|
13
|
+
android_target: str,
|
|
14
|
+
android_target_dir: Path,
|
|
15
|
+
build_directory: Path,
|
|
16
|
+
host_profile: str | Path,
|
|
17
|
+
build_profile: str | Path,
|
|
18
|
+
architectures: list[Architecture],
|
|
19
|
+
configuration: BuildConfiguration,
|
|
20
|
+
android_project_dir: Path,
|
|
21
|
+
android_module_name: str):
|
|
22
|
+
super().__init__(working_directory, build_directory, host_profile, build_profile, architectures,
|
|
23
|
+
configuration)
|
|
24
|
+
self.android_project_dir = android_project_dir
|
|
25
|
+
self.android_project_target_dir = self.build_directory / 'package'
|
|
26
|
+
self.android_module_name = android_module_name
|
|
27
|
+
self.android_target = android_target
|
|
28
|
+
self.android_target_dir = android_target_dir
|
|
29
|
+
self.target_folder = Path('build') / self.configuration.value
|
|
30
|
+
|
|
31
|
+
def install(self):
|
|
32
|
+
for architecture in self.architectures:
|
|
33
|
+
self.conan_install(architecture=architecture)
|
|
34
|
+
|
|
35
|
+
def package(self):
|
|
36
|
+
"""copies all resources into the Android Studio project and builds it"""
|
|
37
|
+
print_prefixed('packaging to AAR:')
|
|
38
|
+
BuildContext._copy_directory(self.android_project_dir, self.android_project_target_dir)
|
|
39
|
+
for architecture in self.architectures:
|
|
40
|
+
lib_name = f'lib{self.android_target}.so'
|
|
41
|
+
BuildContext._copy_file(
|
|
42
|
+
src=self.build_directory / architecture.name / self.target_folder / self.android_target_dir / lib_name,
|
|
43
|
+
dst=self.android_project_target_dir / self.android_module_name / 'src' / 'main' / 'jniLibs' / architecture.value.android / lib_name
|
|
44
|
+
)
|
|
45
|
+
print_prefixed(f'copy `{self.android_target}.jar` to Android Studio Project')
|
|
46
|
+
jar_name = f'{self.android_target}.jar'
|
|
47
|
+
BuildContext._copy_file(
|
|
48
|
+
src=self.build_directory / self.architectures[0].name / self.target_folder / self.android_target_dir / jar_name,
|
|
49
|
+
dst=self.android_project_target_dir / self.android_module_name / 'libs' / jar_name
|
|
50
|
+
)
|
|
51
|
+
print_prefixed('build Android Studio Project')
|
|
52
|
+
ret = BuildContext._execute('./gradlew', [f'assemble{self.configuration.value}'],
|
|
53
|
+
working_dir=self.android_project_target_dir)
|
|
54
|
+
if ret != 0:
|
|
55
|
+
print_prefixed('building Android Studio Project has failed', file=sys.stderr)
|
|
56
|
+
exit(2)
|
|
57
|
+
BuildContext._copy_file(
|
|
58
|
+
src=self.android_project_target_dir / self.android_module_name / 'build' / 'outputs' / 'aar' / f'{self.android_module_name}-{self.configuration.name}.aar',
|
|
59
|
+
dst=self.android_project_target_dir / f'{self.android_module_name}.aar'
|
|
60
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from collections import namedtuple
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ArgparseEnum(Enum):
|
|
6
|
+
|
|
7
|
+
def __str__(self):
|
|
8
|
+
return self.name
|
|
9
|
+
|
|
10
|
+
@classmethod
|
|
11
|
+
def from_string(cls, string: str):
|
|
12
|
+
"""this is required for the enum to work with argparse"""
|
|
13
|
+
try:
|
|
14
|
+
return cls[string]
|
|
15
|
+
except KeyError:
|
|
16
|
+
raise ValueError()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BuildConfiguration(ArgparseEnum):
|
|
20
|
+
"""enum of all possible build configurations."""
|
|
21
|
+
release = 'Release'
|
|
22
|
+
debug = 'Debug'
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
ArchitectureDetails = namedtuple('ArchitectureName', 'conan android windows bit')
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Architecture(ArgparseEnum):
|
|
29
|
+
"""enum with all possible architectures that one can build for, and the names for them on each target platform"""
|
|
30
|
+
x86_64 = ArchitectureDetails(conan='x86_64', android='x86_64', windows='win10-x64', bit='64')
|
|
31
|
+
x86 = ArchitectureDetails(conan='x86', android='x86', windows='win10-x86', bit='32')
|
|
32
|
+
armv8 = ArchitectureDetails(conan='armv8', android='arm64-v8a', windows='win10-arm64', bit='64')
|
|
33
|
+
armv7 = ArchitectureDetails(conan='armv7', android='armeabi-v7a', windows='win10-arm', bit='32')
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class PackageType(ArgparseEnum):
|
|
37
|
+
xcframework = 'XCFramework'
|
|
38
|
+
swiftpackage = 'Swift Package'
|
|
39
|
+
aar = 'Android Archive'
|
|
40
|
+
nuget = 'NuGet'
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from .argparse_enums import Architecture, BuildConfiguration
|
|
2
|
+
from .print_prefixed import print_prefixed
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import shutil
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
class BuildContext:
|
|
10
|
+
"""Base class for all build contexts. Contains common code that is shared between builds for different
|
|
11
|
+
languages/platforms """
|
|
12
|
+
|
|
13
|
+
def __init__(self,
|
|
14
|
+
working_directory: Path,
|
|
15
|
+
build_directory: Path,
|
|
16
|
+
host_profile: str | Path,
|
|
17
|
+
build_profile: str | Path,
|
|
18
|
+
architectures: list[Architecture],
|
|
19
|
+
configuration: BuildConfiguration,
|
|
20
|
+
settings: list[str] = []):
|
|
21
|
+
self.working_directory = working_directory
|
|
22
|
+
self.host_profile = host_profile
|
|
23
|
+
self.build_profile = build_profile
|
|
24
|
+
self.build_directory = build_directory
|
|
25
|
+
self.packaging_directory = build_directory / 'package'
|
|
26
|
+
self.architectures = architectures
|
|
27
|
+
self.configuration = configuration
|
|
28
|
+
self.settings = [f'build_type={self.configuration.value}'] + settings
|
|
29
|
+
self.version = self._get_version()
|
|
30
|
+
|
|
31
|
+
def _get_version(self):
|
|
32
|
+
"""reads the version from the VERSION file in the working directory"""
|
|
33
|
+
version_file = self.working_directory / 'VERSION'
|
|
34
|
+
if version_file.exists():
|
|
35
|
+
return version_file.read_text().strip()
|
|
36
|
+
return "0.0.0"
|
|
37
|
+
|
|
38
|
+
def _run_conan(self, args: list[str]):
|
|
39
|
+
"""runs a conan CLI command via subprocess"""
|
|
40
|
+
cmd = ["conan"] + args
|
|
41
|
+
print_prefixed(f"Running: {' '.join(str(a) for a in cmd)}")
|
|
42
|
+
result = subprocess.run(cmd)
|
|
43
|
+
if result.returncode != 0:
|
|
44
|
+
print_prefixed(f"Conan command failed with return code {result.returncode}", file=sys.stderr)
|
|
45
|
+
sys.exit(result.returncode)
|
|
46
|
+
|
|
47
|
+
def build(self, settings: list[str] = []):
|
|
48
|
+
"""builds all selected architectures"""
|
|
49
|
+
for architecture in self.architectures:
|
|
50
|
+
print_prefixed(f'building for architecture {architecture.name}:')
|
|
51
|
+
all_settings = settings + self.settings + [f"arch={architecture.value.conan}"]
|
|
52
|
+
args = [
|
|
53
|
+
"build",
|
|
54
|
+
str(self.working_directory),
|
|
55
|
+
f"--output-folder={self.build_directory / architecture.name}",
|
|
56
|
+
f"--profile:host={self.host_profile}",
|
|
57
|
+
f"--profile:build={self.build_profile}",
|
|
58
|
+
]
|
|
59
|
+
for s in all_settings:
|
|
60
|
+
args.append(f"--settings:host={s}")
|
|
61
|
+
self._run_conan(args)
|
|
62
|
+
|
|
63
|
+
def conan_install(self, architecture: Architecture, settings: list[str] = []):
|
|
64
|
+
"""installs all conan dependencies defined in conanfile.py"""
|
|
65
|
+
print_prefixed(f'installing dependencies for architecture {architecture.name}:')
|
|
66
|
+
all_settings = settings + self.settings + [f"arch={architecture.value.conan}"]
|
|
67
|
+
args = [
|
|
68
|
+
"install",
|
|
69
|
+
str(self.working_directory),
|
|
70
|
+
f"--output-folder={self.build_directory / architecture.name}",
|
|
71
|
+
f"--profile:host={self.host_profile}",
|
|
72
|
+
f"--profile:build={self.build_profile}",
|
|
73
|
+
"--build=missing"
|
|
74
|
+
]
|
|
75
|
+
for s in all_settings:
|
|
76
|
+
args.append(f"--settings:host={s}")
|
|
77
|
+
self._run_conan(args)
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def _copy_directory(src_dir: Path, target_dir: Path, clean: bool = True):
|
|
81
|
+
print_prefixed(f"Copy directory '{src_dir}' to '{target_dir}'")
|
|
82
|
+
if target_dir.exists() and clean:
|
|
83
|
+
shutil.rmtree(target_dir)
|
|
84
|
+
shutil.copytree(src=src_dir, dst=target_dir, symlinks=True)
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def _copy_file(src: Path, dst: Path):
|
|
88
|
+
print_prefixed(f"Copy file '{src}' to '{dst}'")
|
|
89
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
90
|
+
shutil.copy(src, dst)
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def _clean(directory: Path):
|
|
94
|
+
"""deletes the given directory if it exists"""
|
|
95
|
+
if directory.exists():
|
|
96
|
+
shutil.rmtree(directory)
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def _execute(command: str, arguments: list[str], working_dir: Path = Path(os.getcwd())) -> int:
|
|
100
|
+
cwd = os.getcwd()
|
|
101
|
+
os.chdir(working_dir)
|
|
102
|
+
full_command = f'{command} {" ".join(arguments)}'
|
|
103
|
+
print_prefixed(f"Executing command '{full_command}'")
|
|
104
|
+
result = os.system(full_command)
|
|
105
|
+
os.chdir(cwd)
|
|
106
|
+
return result
|