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.
@@ -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.
@@ -0,0 +1,3 @@
1
+ include LICENSE
2
+ include README.md
3
+ recursive-include pyoneer_djinni_build/profiles *
@@ -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