cj-tauri 0.0.0-stage → 1.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.
- package/LICENSE +21 -0
- package/README.md +68 -3
- package/bin/cj-tauri.js +287 -0
- package/cjpm.toml +52 -0
- package/cli/cjpm.toml +13 -0
- package/cli/src/doctor.cj +304 -0
- package/cli/src/main.cj +121 -0
- package/cli/src/project.cj +754 -0
- package/cli/src/resolve.cj +348 -0
- package/cli/src/scaffold.cj +361 -0
- package/cli/src/util.cj +159 -0
- package/cli/templates/app/README.md +80 -0
- package/cli/templates/app/capabilities/default.json +7 -0
- package/cli/templates/app/cjpm.toml +17 -0
- package/cli/templates/app/src/main.cj +88 -0
- package/cli/templates/app/ui/index.html +118 -0
- package/cli/templates/app-react/README.md +67 -0
- package/cli/templates/app-react/capabilities/default.json +7 -0
- package/cli/templates/app-react/cjpm.toml +17 -0
- package/cli/templates/app-react/src/main.cj +102 -0
- package/cli/templates/app-react/ui/index.html +25 -0
- package/cli/templates/app-react/ui/package.json +19 -0
- package/cli/templates/app-react/ui/src/App.css +67 -0
- package/cli/templates/app-react/ui/src/App.jsx +124 -0
- package/cli/templates/app-react/ui/src/main.jsx +6 -0
- package/cli/templates/app-react/ui/vite.config.js +24 -0
- package/cli/templates/app-vue/README.md +60 -0
- package/cli/templates/app-vue/capabilities/default.json +7 -0
- package/cli/templates/app-vue/cjpm.toml +17 -0
- package/cli/templates/app-vue/src/main.cj +102 -0
- package/cli/templates/app-vue/ui/index.html +25 -0
- package/cli/templates/app-vue/ui/package.json +18 -0
- package/cli/templates/app-vue/ui/src/App.vue +176 -0
- package/cli/templates/app-vue/ui/src/main.js +4 -0
- package/cli/templates/app-vue/ui/vite.config.js +24 -0
- package/cli/templates/ohos-pc/AppScope/app.json5 +13 -0
- package/cli/templates/ohos-pc/AppScope/resources/base/element/string.json +8 -0
- package/cli/templates/ohos-pc/AppScope/resources/base/media/background.png +0 -0
- package/cli/templates/ohos-pc/AppScope/resources/base/media/foreground.png +0 -0
- package/cli/templates/ohos-pc/AppScope/resources/base/media/layered_image.json +6 -0
- package/cli/templates/ohos-pc/README.md +79 -0
- package/cli/templates/ohos-pc/build-hap.sh +190 -0
- package/cli/templates/ohos-pc/build-profile.json5 +46 -0
- package/cli/templates/ohos-pc/entry/build-profile.json5 +26 -0
- package/cli/templates/ohos-pc/entry/cjpm.toml +43 -0
- package/cli/templates/ohos-pc/entry/hvigorfile.ts +6 -0
- package/cli/templates/ohos-pc/entry/oh-package.json5 +9 -0
- package/cli/templates/ohos-pc/entry/src/main/cangjie/ability_stage.cj +17 -0
- package/cli/templates/ohos-pc/entry/src/main/cangjie/app_host.cj +94 -0
- package/cli/templates/ohos-pc/entry/src/main/cangjie/index.cj +167 -0
- package/cli/templates/ohos-pc/entry/src/main/cangjie/main_ability.cj +139 -0
- package/cli/templates/ohos-pc/entry/src/main/module.json5 +49 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/base/element/color.json +8 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/base/element/string.json +16 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/base/media/background.png +0 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/base/media/foreground.png +0 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/base/media/layered_image.json +6 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/base/media/startIcon.png +0 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/base/profile/main_pages.json +2 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/rawfile/capabilities.json +6 -0
- package/cli/templates/ohos-pc/entry/src/main/resources/rawfile/index.html +92 -0
- package/cli/templates/ohos-pc/hvigor/hvigor-config.json5 +5 -0
- package/cli/templates/ohos-pc/hvigorfile.ts +6 -0
- package/cli/templates/ohos-pc/oh-package.json5 +10 -0
- package/native/build_linux.sh +79 -0
- package/native/build_win.bat +62 -0
- package/native/core/bridge_core.c +1626 -0
- package/native/core/bridge_core.h +618 -0
- package/native/core/bridge_js.h +108 -0
- package/native/platforms/harmonyos/README.md +106 -0
- package/native/platforms/linux/bridge_linux.c +2485 -0
- package/native/platforms/windows/bridge_win.c +3248 -0
- package/native/test_host_win.c +60 -0
- package/native/tests/gtk_threading_probe.c +143 -0
- package/native/tests/test_bridge_core.c +1228 -0
- package/package.json +51 -6
- package/prebuilt/win32-x64/cj-tauri.exe +0 -0
- package/src/api_system.cj +67 -0
- package/src/app.cj +940 -0
- package/src/arkweb_proxy.cj +56 -0
- package/src/arkweb_script.cj +154 -0
- package/src/capability.cj +409 -0
- package/src/capability_loader.cj +76 -0
- package/src/clipboard_bridge.cj +55 -0
- package/src/dragdrop.cj +26 -0
- package/src/embedded_assets.cj +98 -0
- package/src/hexutil.cj +53 -0
- package/src/host.cj +604 -0
- package/src/host_arkweb.cj +740 -0
- package/src/host_factory.cj +48 -0
- package/src/host_webkit.cj +548 -0
- package/src/host_webview2.cj +548 -0
- package/src/hotkey.cj +66 -0
- package/src/ipc_hub.cj +337 -0
- package/src/ipc_message.cj +286 -0
- package/src/jsutil.cj +33 -0
- package/src/log_bridge.cj +107 -0
- package/src/logging.cj +127 -0
- package/src/menu.cj +197 -0
- package/src/plugin.cj +299 -0
- package/src/plugins/clipboard/plugin_clipboard.cj +144 -0
- package/src/plugins/dialog/plugin_dialog.cj +209 -0
- package/src/plugins/fs/plugin_fs.cj +194 -0
- package/src/plugins/http/plugin_http.cj +459 -0
- package/src/plugins/log/plugin_log.cj +105 -0
- package/src/plugins/menu/plugin_menu.cj +150 -0
- package/src/plugins/mqtt/mqtt_codec.cj +661 -0
- package/src/plugins/mqtt/plugin_mqtt.cj +1446 -0
- package/src/plugins/notification/plugin_notification.cj +146 -0
- package/src/plugins/plugins.cj +5 -0
- package/src/plugins/redis/plugin_redis.cj +2409 -0
- package/src/plugins/redis/redis_codec.cj +556 -0
- package/src/plugins/serial/plugin_serial.cj +442 -0
- package/src/plugins/serial/serial_bridge.cj +186 -0
- package/src/plugins/shell/plugin_shell.cj +230 -0
- package/src/plugins/sqlite/plugin_sqlite.cj +697 -0
- package/src/plugins/sqlite/sqlite_ffi.cj +206 -0
- package/src/plugins/store/plugin_store.cj +287 -0
- package/src/plugins/ws/plugin_ws.cj +470 -0
- package/src/process_hidden.cj +174 -0
- package/src/scope.cj +391 -0
- package/src/shell_event.cj +69 -0
- package/src/tests/capability_test.cj +243 -0
- package/src/tests/fake_host.cj +186 -0
- package/src/tests/host_route_test.cj +108 -0
- package/src/tests/ipc_hub_test.cj +487 -0
- package/src/tests/jsutil_test.cj +62 -0
- package/src/tests/logging_test.cj +62 -0
- package/src/tests/menu_test.cj +108 -0
- package/src/tests/mqtt_codec_test.cj +405 -0
- package/src/tests/plugin_clipboard_test.cj +222 -0
- package/src/tests/plugin_dialog_test.cj +237 -0
- package/src/tests/plugin_http_test.cj +124 -0
- package/src/tests/plugin_menu_test.cj +98 -0
- package/src/tests/plugin_notification_test.cj +205 -0
- package/src/tests/plugin_serial_test.cj +269 -0
- package/src/tests/plugin_shell_test.cj +189 -0
- package/src/tests/plugin_sqlite_test.cj +230 -0
- package/src/tests/plugin_store_test.cj +260 -0
- package/src/tests/plugin_test.cj +542 -0
- package/src/tests/plugin_ws_test.cj +40 -0
- package/src/tests/process_hidden_test.cj +129 -0
- package/src/tests/redis_codec_test.cj +396 -0
- package/src/tests/scope_test.cj +350 -0
- package/src/tests/shell_event_test.cj +67 -0
- package/src/tests/system_host_test.cj +81 -0
- package/src/tests/urlutil_test.cj +53 -0
- package/src/tests/version_test.cj +75 -0
- package/src/tests/window_registry_test.cj +123 -0
- package/src/tray.cj +90 -0
- package/src/urlutil.cj +159 -0
- package/src/version.cj +44 -0
- package/src/window.cj +51 -0
- package/src/window_registry.cj +116 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 yangyongzhen
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,3 +1,68 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# cj-tauri
|
|
2
|
+
|
|
3
|
+
用[仓颉语言](https://cangjie-lang.cn)写桌面应用的脚手架 CLI——把 Tauri 的三件套带到仓颉:
|
|
4
|
+
仓颉后端(静态编译)+ 系统 WebView 前端(HTML/CSS/JS),三件套与 Tauri 一致 ——
|
|
5
|
+
WebView 宿主、IPC 双向桥(`invoke` / `resolve` / `event`)、能力安全模型(capability 白名单)。
|
|
6
|
+
|
|
7
|
+
- 仓库与完整文档:<https://atomgit.com/qq8864/cj-tauri>
|
|
8
|
+
- 当前状态:**Windows(WebView2)、Linux(WebKitGTK)与鸿蒙 PC(ArkWeb)均已实机跑通**
|
|
9
|
+
|
|
10
|
+
## 前置条件:仓颉 SDK
|
|
11
|
+
|
|
12
|
+
**这个包不替代仓颉 SDK**。应用后端就是仓颉代码,`cj-tauri dev` / `build` 要调用 SDK 里的 `cjc` / `cjpm`
|
|
13
|
+
把你的应用编译出来。所以请先装 SDK(验证版本 **1.2.0**,含 **stdx**),并让本包能找到它:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Linux / macOS
|
|
17
|
+
export CANGJIE_HOME=/opt/cangjie/cangjie
|
|
18
|
+
|
|
19
|
+
# Windows cmd
|
|
20
|
+
set CANGJIE_HOME=D:\Program Files (x86)\Cangjie
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
不设 `CANGJIE_HOME` 时,本包会探测常见安装位置(Windows `D:\Program Files (x86)\Cangjie`、
|
|
24
|
+
Linux `/opt/cangjie/cangjie`)。装好后自检:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx cj-tauri info # 打印框架 / 项目 / stdx / SDK / cjpm / C 桥 的解析结果
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
没装 SDK 时本包会直接给出提示与安装说明,而不是抛一句 `cjpm: command not found`。
|
|
31
|
+
另外 `npx cj-tauri --version` 不需要 SDK 也能查版本。
|
|
32
|
+
|
|
33
|
+
## 用法
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx cj-tauri create myapp # 创建项目(默认模板:内联 HTML,零 Node)
|
|
37
|
+
cd myapp
|
|
38
|
+
npx cj-tauri dev # 构建 C 桥 + cjpm build + 启动窗口
|
|
39
|
+
|
|
40
|
+
npx cj-tauri create myapp-vue --template vue # Vue 3 + Vite
|
|
41
|
+
npx cj-tauri create myapp-react --template react # React 18 + Vite
|
|
42
|
+
|
|
43
|
+
npm i -g cj-tauri # 也可以全局安装,之后直接用 cj-tauri <子命令>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
| 子命令 | 作用 |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `create <项目名> [--template app\|vue\|react]` | 生成工程(`src/` + `ui/` + `capabilities/` + `cjpm.toml`) |
|
|
49
|
+
| `dev` | 构建 C 桥 + `cjpm build` + 启动应用;Vite 模板会接管 dev server(HMR) |
|
|
50
|
+
| `build` | 构建 C 桥 + `cjpm build` |
|
|
51
|
+
| `run` | 运行已构建产物 |
|
|
52
|
+
| `info` | 环境自检(排障先跑它) |
|
|
53
|
+
| `help` | 帮助 |
|
|
54
|
+
|
|
55
|
+
## 这个包装层做了什么
|
|
56
|
+
|
|
57
|
+
- **跨平台入口**:Windows / Linux / Git Bash 都是同一条 `cj-tauri` 命令,不再分 `.bat` 与 `.sh`;
|
|
58
|
+
- **环境自检**:`cjpm` 与 SDK 运行时库的定位、`PATH` / `LD_LIBRARY_PATH` 的拼装都在这里完成;
|
|
59
|
+
- **CLI 本体的获取**:优先用包内预编译二进制(`prebuilt/<平台-架构>/`),没有则把 CLI 源码拷到
|
|
60
|
+
`~/.cache/cj-tauri/<版本>/` 下用本机 `cjpm build` 一次并缓存 —— 不往安装目录写产物,避免全局安装只读;
|
|
61
|
+
- **数据目录**:Linux/macOS 用 `$XDG_CACHE_HOME/cj-tauri`(默认 `~/.cache/cj-tauri`),Windows 用 `%LOCALAPPDATA%\cj-tauri`。
|
|
62
|
+
|
|
63
|
+
已知限制:首次 `dev` / `build` 会把 C 桥构建到**框架目录的 `native/`** 下(应用 `cjpm.toml` 的
|
|
64
|
+
链接参数指向那里),所以包安装目录需要可写;如果装在只读路径下,请改用仓库内运行方式。
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
[MIT](https://atomgit.com/qq8864/cj-tauri/blob/main/LICENSE) © 2026 yangyongzhen
|
package/bin/cj-tauri.js
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* cj-tauri npm 包启动器(跨平台:Windows / Linux,Git Bash 亦可)
|
|
4
|
+
*
|
|
5
|
+
* 职责:把「仓颉环境自检 + 平台差异 + CLI 本体的构建与缓存 + 退出码传递」收进一个入口,
|
|
6
|
+
* 让 npm 安装后的用法与仓库内一致:
|
|
7
|
+
*
|
|
8
|
+
* npx cj-tauri create myapp
|
|
9
|
+
* npx cj-tauri dev
|
|
10
|
+
*
|
|
11
|
+
* 与仓库内 cli/cj-tauri.sh、cli/cj-tauri.bat 的关系:那两个是**开发用**启动器(假定在仓库里跑),
|
|
12
|
+
* 本文件是**发布用**入口(在任意目录跑)。PATH / LD_LIBRARY_PATH 的拼装规则与它们保持一致,
|
|
13
|
+
* 改动其中一处请三处一起改。
|
|
14
|
+
*
|
|
15
|
+
* CLI 可执行文件的解析顺序(对应「优先预编译、缺失回落源码构建」的打包策略):
|
|
16
|
+
* 1. 包内预编译 <pkg>/prebuilt/<平台-架构>/cj-tauri[.exe] —— 打 tarball 时若本机有产物就带上
|
|
17
|
+
* 2. 本机缓存 <缓存>/<版本>/<平台-架构>/cj-tauri[.exe] —— 首次构建后复用
|
|
18
|
+
* 3. 源码构建 把 <pkg>/cli 拷到缓存目录再 `cjpm build`;不往安装目录写产物,
|
|
19
|
+
* 因为全局安装的包目录可能是只读的
|
|
20
|
+
*
|
|
21
|
+
* 仓颉 SDK(cjc + cjpm + stdx)是硬前置:应用的**后端**就是仓颉代码,没 SDK 连编译都做不了。
|
|
22
|
+
* 缺 SDK 时这里给出可操作的提示,而不是让 cjpm 报 "command not found"。
|
|
23
|
+
*/
|
|
24
|
+
'use strict';
|
|
25
|
+
|
|
26
|
+
const fs = require('fs');
|
|
27
|
+
const os = require('os');
|
|
28
|
+
const path = require('path');
|
|
29
|
+
const { spawnSync } = require('child_process');
|
|
30
|
+
|
|
31
|
+
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
32
|
+
const PKG = JSON.parse(fs.readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf8'));
|
|
33
|
+
const VERSION = PKG.version;
|
|
34
|
+
const IS_WIN = process.platform === 'win32';
|
|
35
|
+
const PLATFORM_KEY = `${process.platform}-${process.arch}`;
|
|
36
|
+
const CLI_FILE = IS_WIN ? 'cj-tauri.exe' : 'cj-tauri';
|
|
37
|
+
/** 构建产物在 cjpm 的默认输出位置,包内 CLI 与本机构建时同名 */
|
|
38
|
+
const BUILT_CLI_FILE = IS_WIN ? 'main.exe' : 'main';
|
|
39
|
+
|
|
40
|
+
/** 诊断输出走 stderr:与仓库内启动器一致,不污染子命令的 stdout(stdout 要能被脚本消费) */
|
|
41
|
+
function note(msg) {
|
|
42
|
+
process.stderr.write(`[cj-tauri] ${msg}\n`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 只有带上 CJ_TAURI_VERBOSE=1 才打印「用了哪份 CLI」这类细节(默认安静,排障时可开) */
|
|
46
|
+
function verbose(msg) {
|
|
47
|
+
if (process.env.CJ_TAURI_VERBOSE) note(msg);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** 取第一个存在的路径 */
|
|
51
|
+
function firstExisting(candidates) {
|
|
52
|
+
for (const p of candidates) {
|
|
53
|
+
if (p && fs.existsSync(p)) {
|
|
54
|
+
return p;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 解析仓颉 SDK 根目录:CANGJIE_HOME 优先,其次按平台探常见安装位置。
|
|
62
|
+
* 与 cli/src/resolve.cj 的取向一致(那边还能从 PATH 里的 cjc 反推,这里只做静态探测)。
|
|
63
|
+
*/
|
|
64
|
+
function resolveCangjieHome() {
|
|
65
|
+
const env = process.env.CANGJIE_HOME;
|
|
66
|
+
if (env && !fs.existsSync(env)) {
|
|
67
|
+
note(`告警: CANGJIE_HOME=${env} 目录不存在,继续按默认路径探测`);
|
|
68
|
+
}
|
|
69
|
+
const defaults = IS_WIN
|
|
70
|
+
? ['D:\\Program Files (x86)\\Cangjie', 'C:\\Cangjie']
|
|
71
|
+
: ['/opt/cangjie/cangjie', path.join(os.homedir(), 'cangjie')];
|
|
72
|
+
return firstExisting([env, ...defaults]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 本平台运行时库目录。
|
|
77
|
+
* SDK 里可能同时装了多个平台的运行时(linux* 与 windows* 并存),必须按宿主平台挑,
|
|
78
|
+
* 挑错会变成「找不到 libcangjie-runtime.so / 找不到 DLL」。
|
|
79
|
+
* (macOS 与鸿蒙尚未实机验证,这里只做前缀匹配,不额外发明平台标识。)
|
|
80
|
+
*/
|
|
81
|
+
function resolveRuntimeDir(home) {
|
|
82
|
+
const base = path.join(home, 'runtime', 'lib');
|
|
83
|
+
if (!fs.existsSync(base)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const prefix = IS_WIN ? 'windows' : (process.platform === 'darwin' ? 'darwin' : 'linux');
|
|
87
|
+
const hit = fs.readdirSync(base).find((n) => n.toLowerCase().startsWith(prefix));
|
|
88
|
+
return hit ? path.join(base, hit) : null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** 找 cjpm:SDK 的 tools/bin 优先,其次 PATH(与两个开发启动器的顺序一致) */
|
|
92
|
+
function resolveCjpm(home) {
|
|
93
|
+
const exe = IS_WIN ? 'cjpm.exe' : 'cjpm';
|
|
94
|
+
const inSdk = path.join(home, 'tools', 'bin', exe);
|
|
95
|
+
if (fs.existsSync(inSdk)) {
|
|
96
|
+
return inSdk;
|
|
97
|
+
}
|
|
98
|
+
for (const dir of (process.env.PATH || '').split(path.delimiter)) {
|
|
99
|
+
if (!dir) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const p = path.join(dir, exe);
|
|
103
|
+
if (fs.existsSync(p)) {
|
|
104
|
+
return p;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 拼装子进程环境。
|
|
112
|
+
* PATH = 运行时库目录 + bin + tools/bin + tools/lib + ~/.cjpm/bin + 原 PATH
|
|
113
|
+
* LD_LIBRARY_PATH = 运行时库目录 + third_party/llvm/lib(仅非 Windows)
|
|
114
|
+
* Linux 上动态库不走 PATH,少了 LD_LIBRARY_PATH,CLI 会直接因 libcangjie-runtime.so 起不来。
|
|
115
|
+
* CJ_TAURI_ROOT 指向包根(包就是一棵「框架根」:含 cjpm.toml 与 cli/templates),
|
|
116
|
+
* CLI 靠它定位模板与框架源码;用户已显式设置时不覆盖。
|
|
117
|
+
*/
|
|
118
|
+
function buildEnv(home, runtimeDir) {
|
|
119
|
+
const env = Object.assign({}, process.env);
|
|
120
|
+
const parts = [];
|
|
121
|
+
if (runtimeDir) {
|
|
122
|
+
parts.push(runtimeDir);
|
|
123
|
+
}
|
|
124
|
+
parts.push(path.join(home, 'bin'), path.join(home, 'tools', 'bin'), path.join(home, 'tools', 'lib'));
|
|
125
|
+
parts.push(path.join(os.homedir(), '.cjpm', 'bin'));
|
|
126
|
+
env.PATH = parts.join(path.delimiter) + path.delimiter + (env.PATH || '');
|
|
127
|
+
|
|
128
|
+
if (!IS_WIN) {
|
|
129
|
+
const ld = [];
|
|
130
|
+
if (runtimeDir) {
|
|
131
|
+
ld.push(runtimeDir);
|
|
132
|
+
}
|
|
133
|
+
ld.push(path.join(home, 'third_party', 'llvm', 'lib'));
|
|
134
|
+
if (env.LD_LIBRARY_PATH) {
|
|
135
|
+
ld.push(env.LD_LIBRARY_PATH);
|
|
136
|
+
}
|
|
137
|
+
env.LD_LIBRARY_PATH = ld.join(':');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!env.CJ_TAURI_ROOT) {
|
|
141
|
+
env.CJ_TAURI_ROOT = PKG_ROOT;
|
|
142
|
+
}
|
|
143
|
+
return env;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** 缓存根:Linux/macOS 走 XDG 惯例,Windows 走 LOCALAPPDATA */
|
|
147
|
+
function cacheRoot() {
|
|
148
|
+
if (IS_WIN) {
|
|
149
|
+
const base = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
150
|
+
return path.join(base, 'cj-tauri');
|
|
151
|
+
}
|
|
152
|
+
const base = process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache');
|
|
153
|
+
return path.join(base, 'cj-tauri');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** 缺 SDK 时的提示:给可操作的下一步,而不是把 cjpm 的 not found 甩给用户 */
|
|
157
|
+
function printMissingSdkHint(reason) {
|
|
158
|
+
const lines = [
|
|
159
|
+
`错误: 找不到仓颉 SDK(cjc / cjpm)${reason}`,
|
|
160
|
+
'cj-tauri 要把应用后端编译成仓颉可执行文件,所以必须先装仓颉 SDK(含 stdx)。',
|
|
161
|
+
'请安装 SDK 1.2.0 以上版本,然后把 CANGJIE_HOME 指向 SDK 根目录:',
|
|
162
|
+
IS_WIN
|
|
163
|
+
? ' Windows: set CANGJIE_HOME=D:\\Program Files (x86)\\Cangjie'
|
|
164
|
+
: ' Linux : export CANGJIE_HOME=/opt/cangjie/cangjie',
|
|
165
|
+
'安装说明: https://atomgit.com/qq8864/cj-tauri/blob/main/docs/使用文档.md',
|
|
166
|
+
'设好后自检: cj-tauri info',
|
|
167
|
+
'Cangjie SDK not found (cjc/cjpm). Set CANGJIE_HOME to your SDK root, then run: cj-tauri info',
|
|
168
|
+
];
|
|
169
|
+
for (const line of lines) {
|
|
170
|
+
note(line);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** 包内预编译二进制(打包机有 CLI 产物时才会存在) */
|
|
175
|
+
function prebuiltCliPath() {
|
|
176
|
+
return path.join(PKG_ROOT, 'prebuilt', PLATFORM_KEY, CLI_FILE);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** 本机缓存里的 CLI(源码构建后的产物落在这里,供后续复用) */
|
|
180
|
+
function cachedCliPath() {
|
|
181
|
+
return path.join(cacheRoot(), VERSION, PLATFORM_KEY, CLI_FILE);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** 递归拷贝,跳过产物目录(target 里有几 MB 编译中间物,且不该带进缓存) */
|
|
185
|
+
function copyDir(from, to, skipNames) {
|
|
186
|
+
fs.mkdirSync(to, { recursive: true });
|
|
187
|
+
for (const entry of fs.readdirSync(from, { withFileTypes: true })) {
|
|
188
|
+
if (skipNames.includes(entry.name)) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const src = path.join(from, entry.name);
|
|
192
|
+
const dst = path.join(to, entry.name);
|
|
193
|
+
if (entry.isDirectory()) {
|
|
194
|
+
copyDir(src, dst, skipNames);
|
|
195
|
+
} else {
|
|
196
|
+
fs.copyFileSync(src, dst);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 用本机 cjpm 构建 CLI 本体,产物落缓存。
|
|
203
|
+
* 刻意把源码拷到缓存目录再构建:`cjpm build` 会写 target/,
|
|
204
|
+
* 而全局安装的包目录可能是只读的(系统 node_modules 尤其如此)。
|
|
205
|
+
*/
|
|
206
|
+
function buildCli(env, cjpm) {
|
|
207
|
+
const buildDir = path.join(cacheRoot(), VERSION, 'build', 'cli');
|
|
208
|
+
note(`首次运行:正在构建 CLI 本体(${cjpm} build)...`);
|
|
209
|
+
fs.rmSync(buildDir, { recursive: true, force: true });
|
|
210
|
+
copyDir(path.join(PKG_ROOT, 'cli'), buildDir, ['target']);
|
|
211
|
+
|
|
212
|
+
const r = spawnSync(cjpm, ['build'], { cwd: buildDir, env, stdio: 'inherit' });
|
|
213
|
+
const produced = path.join(buildDir, 'target', 'release', 'bin', BUILT_CLI_FILE);
|
|
214
|
+
if (r.status !== 0 || !fs.existsSync(produced)) {
|
|
215
|
+
note(`错误: CLI 本体构建失败(cjpm 退出码 ${r.status === null ? 'null' : r.status})`);
|
|
216
|
+
note(` 可手动重试: cd "${buildDir}" && cjpm build`);
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const dst = cachedCliPath();
|
|
221
|
+
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
222
|
+
fs.copyFileSync(produced, dst);
|
|
223
|
+
if (!IS_WIN) {
|
|
224
|
+
fs.chmodSync(dst, 0o755);
|
|
225
|
+
}
|
|
226
|
+
note(`CLI 本体已缓存: ${dst}`);
|
|
227
|
+
return dst;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** 解析要执行的 CLI:预编译 → 缓存 → 现场构建 */
|
|
231
|
+
function resolveCli(env, cjpm) {
|
|
232
|
+
const prebuilt = prebuiltCliPath();
|
|
233
|
+
if (fs.existsSync(prebuilt)) {
|
|
234
|
+
verbose(`使用包内预编译 CLI: ${prebuilt}`);
|
|
235
|
+
return prebuilt;
|
|
236
|
+
}
|
|
237
|
+
const cached = cachedCliPath();
|
|
238
|
+
if (fs.existsSync(cached)) {
|
|
239
|
+
verbose(`使用缓存 CLI: ${cached}`);
|
|
240
|
+
return cached;
|
|
241
|
+
}
|
|
242
|
+
return buildCli(env, cjpm);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function main() {
|
|
246
|
+
const argv = process.argv.slice(2);
|
|
247
|
+
const home = resolveCangjieHome();
|
|
248
|
+
const cjpm = home ? resolveCjpm(home) : null;
|
|
249
|
+
|
|
250
|
+
if (!home || !cjpm) {
|
|
251
|
+
// --version 不需要 SDK:版本直接读 package.json(与 CLI 的 cliVersion() 同源,
|
|
252
|
+
// scripts/check-version.sh 会校验两者一致),让没装 SDK 的人也能查版本号。
|
|
253
|
+
if (['--version', '-V', '-v'].includes(argv[0])) {
|
|
254
|
+
process.stdout.write(`cj-tauri ${VERSION}\n`);
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
printMissingSdkHint(home ? '(SDK 里没有 tools/bin/cjpm)' : '(CANGJIE_HOME 未设置或指向的目录不存在)');
|
|
258
|
+
return 1;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const runtimeDir = resolveRuntimeDir(home);
|
|
262
|
+
if (!runtimeDir) {
|
|
263
|
+
note(`告警: 在 ${path.join(home, 'runtime', 'lib')} 下没找到本平台运行时库目录`);
|
|
264
|
+
}
|
|
265
|
+
const env = buildEnv(home, runtimeDir);
|
|
266
|
+
const cli = resolveCli(env, cjpm);
|
|
267
|
+
if (!cli) {
|
|
268
|
+
return 1;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// stdio 全继承:CLI 的进度(含 dev 的桥/构建日志)与窗口输出直达终端。
|
|
272
|
+
// 不 detach,Ctrl-C 时终端把 SIGINT 发给**整个前台进程组**,本进程与 CLI 同时收到:
|
|
273
|
+
// CLI 自己会收掉 dev server 与子进程,这里只需如实回传状态码。
|
|
274
|
+
const r = spawnSync(cli, argv, { stdio: 'inherit', env });
|
|
275
|
+
if (r.error) {
|
|
276
|
+
note(`错误: 启动 CLI 失败: ${r.error.message}`);
|
|
277
|
+
return 1;
|
|
278
|
+
}
|
|
279
|
+
if (r.signal) {
|
|
280
|
+
// 按 shell 惯例回 128+n,让脚本能区分「被打断」与「正常失败」
|
|
281
|
+
return 128 + (os.constants.signals[r.signal] || 0);
|
|
282
|
+
}
|
|
283
|
+
return r.status === null ? 1 : r.status;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// 用 exitCode 而不是 process.exit():后者可能截断还没 flush 的 stdout 缓冲
|
|
287
|
+
process.exitCode = main();
|
package/cjpm.toml
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
cjc-version = "1.0.5"
|
|
3
|
+
name = "cjTauri"
|
|
4
|
+
description = "仓颉版 Tauri:轻量跨端混合开发框架(WebView 宿主 + IPC 桥 + 能力安全模型)"
|
|
5
|
+
version = "1.1.0"
|
|
6
|
+
target-dir = ""
|
|
7
|
+
output-type = "static"
|
|
8
|
+
compile-option = ""
|
|
9
|
+
override-compile-option = ""
|
|
10
|
+
link-option = ""
|
|
11
|
+
package-configuration = {}
|
|
12
|
+
|
|
13
|
+
[dependencies]
|
|
14
|
+
|
|
15
|
+
[target.x86_64-unknown-linux-gnu]
|
|
16
|
+
# -lsqlite3:sqlite 插件直连发行版系统库(D-018 第 8 条);Windows 侧未落地,故 mingw 段不加
|
|
17
|
+
link-option = "-Lnative -lcjtbridge -lsqlite3 -lwebkit2gtk-4.1 -lgtk-3 -lgdk-3 -lglib-2.0 -lgio-2.0 -lsoup-3.0 -ljavascriptcoregtk-4.1 -lgobject-2.0"
|
|
18
|
+
|
|
19
|
+
[target.x86_64-unknown-linux-gnu.bin-dependencies]
|
|
20
|
+
path-option = ["${CANGJIE_STDX}"]
|
|
21
|
+
|
|
22
|
+
[target.x86_64-w64-mingw32]
|
|
23
|
+
# -lsqlite3:sqlite 插件子包需要(导入库 libsqlite3.a 由 sqlite3.def 生成,DLL 本身不入库——
|
|
24
|
+
# 跑 sqlite 相关测试/应用时本机自备 native/sqlite3.dll;不碰 sqlite 的应用不引用它就不链接)
|
|
25
|
+
link-option = "-Lnative -lcjtbridge -lsqlite3"
|
|
26
|
+
|
|
27
|
+
[target.x86_64-w64-mingw32.bin-dependencies]
|
|
28
|
+
path-option = ["${CANGJIE_STDX}"]
|
|
29
|
+
|
|
30
|
+
[target.aarch64-linux-ohos]
|
|
31
|
+
# 鸿蒙目标(真机 / 鸿蒙 PC):交叉编译工具链与 sysroot 由 DevEco 仓颉套件提供,
|
|
32
|
+
# 四个路径全部走环境变量展开——hvigor 构建时由插件注入前两个,命令行交叉编译时自行 export 同名变量。
|
|
33
|
+
# 照抄 DevEco 生成的工程(TestCj2)同一串参数,避免两套口径。
|
|
34
|
+
# 末尾的 `--dy-std` 不可省:鸿蒙上应用模块(entry)是 `output-type = "dynamic"` 且用动态 std,
|
|
35
|
+
# 框架包若按默认的静态 std 编,两者混进同一个 .so 就会出现**两套 std 运行时**——表象是
|
|
36
|
+
# 启动即崩在框架包全局初始化(`cjTauri::package_global_init` → 跨包 `_CGP*` 包初始化符号
|
|
37
|
+
# 解析到模块内偏移、跳到未映射地址 0x50xxx),窗口起不来且 hilog 只有一行 SIGSEGV。
|
|
38
|
+
# 只加在鸿蒙段:桌面两平台仍是静态 std,产物形态不变。
|
|
39
|
+
compile-option = "-B \"${DEVECO_CANGJIE_HOME}/build-tools/third_party/llvm/bin\" -B \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/clang/15.0.4/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/aarch64-linux-ohos\" --sysroot \"${DEVECO_OH_NATIVE_HOME}/sysroot\" --dy-std"
|
|
40
|
+
|
|
41
|
+
[target.aarch64-linux-ohos.bin-dependencies]
|
|
42
|
+
# stdx 必须用鸿蒙版(官方发布 cangjie-stdx-ohos-aarch64-<cjc 版本>.zip,桌面版 ABI 不通);
|
|
43
|
+
# CANGJIE_OHOS_LIBS 指 DevEco 套件的 api/lib/linux_ohos_aarch64_cjnative/ohos(仓颉标准库 + ohos API 绑定)。
|
|
44
|
+
#
|
|
45
|
+
# 后两项是 ArkUI 的**宏库**与 kit 绑定,hvigor 构建时由 cangjie-build-support 注入
|
|
46
|
+
# (cangjie-path-impl.js 的 getBuildEnvByAbi):AARCH64_MACRO_LIBS = <sdk>/api/macro/ohos
|
|
47
|
+
# (`lib-macro_ohos.arkui.state_macro_manage.dll` 就在里面),AARCH64_KIT_LIBS =
|
|
48
|
+
# .../linux_ohos_aarch64_cjnative/kit。**宏库目录漏挂的症状极具误导性**:`@Component` 的
|
|
49
|
+
# 声明能解析到(.cjo 在 ohos 目录里),但宏实现库找不到,报的是
|
|
50
|
+
# `macro evaluation has failed for macro call 'Component'`——看着像「宏不能用在框架包里」。
|
|
51
|
+
# 命令行交叉编译时这两个变量要自己 export,取值见上。
|
|
52
|
+
path-option = ["D:/cangjie-stdx-ohos/linux_ohos_aarch64_cjnative/dynamic/stdx", "C:/Users/yang/.cangjie-sdk/6.1/cangjie/api/lib/linux_ohos_aarch64_cjnative/ohos", "${AARCH64_MACRO_LIBS}", "${AARCH64_KIT_LIBS}"]
|
package/cli/cjpm.toml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
cjc-version = "1.0.5"
|
|
3
|
+
name = "cli"
|
|
4
|
+
description = "cj-tauri CLI:脚手架 create / dev / build / run / info"
|
|
5
|
+
version = "1.1.0"
|
|
6
|
+
target-dir = ""
|
|
7
|
+
output-type = "executable"
|
|
8
|
+
compile-option = ""
|
|
9
|
+
override-compile-option = ""
|
|
10
|
+
link-option = ""
|
|
11
|
+
package-configuration = {}
|
|
12
|
+
|
|
13
|
+
[dependencies]
|