التوثيق
التغليف
يحوّل nsh package التطبيق إلى شيء يمكنك تثبيته: .app لمحاكي iOS، و.ipa موقّع لأجهزة iOS، و.apk موقّع لنظام Android، و.app موقّع توقيعًا مؤقتًا (ad hoc) لنظام macOS، ومجلد مع .tar.gz لنظام Linux، ومجلد مع .zip لنظام Windows، أو موقع ثابت للويب. لا يحتاج إلى مشروع Xcode ولا إلى Gradle.
- تطبيق Rust (يحدد
nsh.jsonاسم"root"الخاص به) يُحزَّم من مجلده. يبنيnshمشغّل المنصة المستهدفة في وضع الإصدار (release) مع تضمين الـ crate الخاص بك وتركيب المكوّن الجذري، دون QuickJS. ويتطلب ذلك: Cargo، وهدف Rust الخاص بالمنصة (rustup target add …)، ولنظام Android الـ NDK. - تطبيق TSX يحدد نقطة دخوله. يوضع إصداره النهائي (مصغَّر، ومُترجم إلى bytecode لـ QuickJS، تمامًا كما يبنيه
nsh build --release) بجانب بيئة التشغيل الجاهزة التي تأتي مع NSH، ولذلك لا يحتاج إلى سلسلة أدوات Rust. أما التطبيق الذي يملك crate خاصًا به ("rust"دون"root") فتُبنى له مشغّلات مع الـ crate الخاص به.
# A Rust app, from its directory
nsh package --target ios-simulator --run # build, install and launch in the simulator
nsh package --target android --run # build, install and launch on a device or emulator
nsh package --target macos --run # build and launch on this Mac
nsh package --target linux --run # build and launch on this machine
nsh package --target windows --run # build and launch on this machine
nsh package --target web --run # build, serve on this machine and open in the browser
nsh package --target ios --sign "Apple Development: Jane Doe (ABCDE12345)" --profile Dev.mobileprovision
# A TSX app: the same with its entry
nsh package App.tsx --target ios-simulator --run
يُكتب الناتج في .nsh/out/ ما لم تمرّر --out. تعرض الأقسام التالية أمر كل هدف لتطبيق Rust؛ أما تطبيق TSX فيضيف إليه نقطة دخوله (nsh package App.tsx --target …).
#بيانات التطبيق الوصفية: nsh.json
يقرأ nsh package الملف nsh.json في مجلد التطبيق (بجانب ملف نقطة الدخول في تطبيق TSX). ينشئ nsh init ملفًا منه:
{
"name": "Gallery",
"id": "com.example.gallery",
"version": "1.0.0",
"build": 1,
"icon": "icon.png"
}
| المفتاح | النوع | القيمة الافتراضية | الاستخدام |
|---|---|---|---|
name | string | اسم مجلد نقطة الدخول | الاسم المعروض تحت الأيقونة (CFBundleDisplayName، وandroid:label في Android) واسم ملف الناتج. |
id | string | مطلوب | معرّف الحزمة (bundle identifier) / اسم حزمة Android، بصيغة النطاق المعكوس تحت نطاق تملكه. ويحدد أيضًا المكان الذي يحفظ فيه التطبيق تخزينه، فيكون لكل تطبيق تخزينه الخاص. يحذّر nsh package وnsh publish من القيمة النائبة com.example.. |
version | string | "1.0.0" | الإصدار الظاهر للمستخدم (CFBundleShortVersionString، versionName). |
build | number | 1 | رقم البناء (CFBundleVersion، versionCode). ارفعه مع كل إصدار ترفعه. |
icon | string | لا شيء | ملف PNG مربع، ويفضَّل أن يكون 1024×1024، مسارُه نسبي إلى nsh.json. |
يحتوي nsh.json أيضًا على rust وroot (الـ crates الخاصة بالتطبيق ومكوّنه الجذري، انظر البناء باستخدام Rust)، وtheme وappearance، وtailwind (انظر Tailwind) وcapabilities (انظر الصندوق الرملي والصلاحيات)؛ وتسرد بنية المشروع جميع المفاتيح. المفاتيح غير المعروفة تسبب خطأ.
يمكن تجاوز كل مفتاح أعلاه من سطر الأوامر، وهو أمر مفيد في CI:
nsh package --target android --app-version 1.4.0 --build 42
#الخيارات
| الخيار | الوصف |
|---|---|
--target <ios | ios-simulator | android | macos | linux | windows | web> | المنصة المراد البناء لها (مطلوب). |
-o, --out <dir> | مجلد الناتج. الافتراضي .nsh/out. |
--name <name> | الاسم المعروض. |
--id <id> | معرّف الحزمة، مثل com.example.app. |
--app-version <version> | الإصدار، مثل 1.2.0. |
--build <n> | رقم البناء. |
--icon <png> | أيقونة التطبيق: ملف PNG مربع، ويفضَّل أن يكون 1024×1024. |
--sign <identity> | iOS: هوية توقيع الشيفرة للأجهزة. |
--profile <file> | iOS: ملف التوفير (provisioning profile) للأجهزة (.mobileprovision). |
--keystore <file> | Android: مخزن مفاتيح للإصدار النهائي (الافتراضي: مفتاح التصحيح). |
--key-alias <alias> | Android: اسم المفتاح البديل (alias) في مخزن المفاتيح. |
--keystore-password <password> | Android: كلمة مرور مخزن المفاتيح؛ وتُقرأ أيضًا من NSH_KEYSTORE_PASSWORD. |
--abi <abi> | Android: واجهات ABI الخاصة بملف APK، مكررة أو مفصولة بفواصل (الافتراضي: arm64-v8a وarmeabi-v7a). |
--run | التثبيت والتشغيل بعد ذلك: في محاكي iOS، أو على جهاز Android أو المحاكي الذي يراه adb؛ وتُشغَّل تطبيقات macOS وLinux وWindows على هذا الجهاز؛ ويُقدَّم موقع الويب على هذا الجهاز ويُفتح في المتصفح. غير متاح لـ --target ios. |
#محاكي iOS
nsh package --target ios-simulator --run
يكتب .nsh/out/<Name>.app، موقّعًا توقيعًا مؤقتًا (ad hoc) (يحتاج المحاكي إلى توقيع لكن دون هوية). مع --run يشغّل محاكيًا إن لم يكن أي محاكٍ قيد التشغيل، ثم يثبّت التطبيق ويشغّله. يتطلب Xcode.
#أجهزة iOS
nsh package --target ios \
--sign "Apple Distribution: Example Inc (ABCDE12345)" \
--profile AppStore.mobileprovision
يكتب .nsh/out/<Name>.ipa، جاهزًا لـ TestFlight أو أدوات الرفع إلى App Store أو التثبيت المباشر (بحسب ملف التوفير). ما يحدث:
- يُنسخ ملف التوفير إلى التطبيق باسم
embedded.mobileprovision. - تأتي الاستحقاقات (entitlements) من ملف التوفير. يتحقق NSH من أن معرّف التطبيق في ملف التوفير يغطي
idالخاص بالتطبيق (تعمل ملفات التوفير ذات الرموز البديلة مثلTEAMID.*أوTEAMID.com.example.*) ويتوقف بخطأ في غير ذلك. - يُوقَّع التطبيق بالأمر
codesignباستخدام الهوية، ثم يُضغط في.ipa(Payload/<Name>.app).
اعثر على هوياتك بالأمر:
security find-identity -v -p codesigning
من دون --sign و--profile، يكتب NSH ملف .nsh/out/<Name>.app غير موقّع ويخبرك بذلك؛ ولا يمكن تثبيته على جهاز كما هو.
يدعم التطبيق iPhone وiPad، بالاتجاهين الرأسي والأفقي (الرأسي المقلوب على iPad فقط)، ويتطلب iOS 15.0 أو أحدث.
#Android
nsh package --target android --run
يكتب .nsh/out/<Name>.apk. يُجمَّع ملف APK مباشرة بأدوات البناء الخاصة بـ SDK (aapt2، zipalign، apksigner)، دون Gradle. المتطلبات:
- Android SDK، يُعثر عليه عبر
ANDROID_HOME(أوANDROID_SDK_ROOT، أو~/Library/Android/sdk)، مع أدوات البناء وحزمةplatforms;android-35. يخبرك NSH بأمرsdkmanagerعند غياب أي منها. - JDK، لإنشاء مخزن مفاتيح التصحيح في المرة الأولى.
- لتطبيق Rust، Android NDK (
sdkmanager "ndk;<version>"، أوANDROID_NDK_HOME)، الذي يبنيlibnsh.soالخاص به.
يستهدف التطبيق API 35 ويتطلب API 28 (Android 9) أو أحدث. يحتوي على شيفرة native لواجهات ABI الخاصة بالهواتف، arm64-v8a وarmeabi-v7a؛ ومع --run يحتوي أيضًا على واجهة الجهاز، مثل x86_64 في المحاكي. يتيح --abi اختيارها بنفسك، مثل --abi arm64-v8a للهواتف ذات 64 بت فقط، وهو أصغر APK:
nsh package --target android --abi arm64-v8a
#التوقيع للإصدار النهائي
من دون --keystore، يُوقَّع APK بمفتاح التصحيح القياسي (~/.android/debug.keystore، ويُنشأ إن لم يكن موجودًا)، ويحذّر NSH من أنه غير مخصص لإصدارات المتجر. للإصدار النهائي، أنشئ مخزن مفاتيح مرة واحدة ومرّره:
keytool -genkeypair -v -keystore release.jks -alias upload -keyalg RSA -keysize 2048 -validity 10000
NSH_KEYSTORE_PASSWORD=… nsh package --target android \
--keystore release.jks --key-alias upload
فضّل متغير البيئة على --keystore-password حتى لا تنتهي كلمة المرور في سجل الأوامر في الطرفية.
#macOS
nsh package --target macos --run
يكتب .nsh/out/<Name>.app: الملف التنفيذي في Contents/MacOS/، وnsh/assets/…، وnsh/app.json (عنوان النافذة ومظهر التطبيق)، وملف nsh/bundle.nshc الخاص بتطبيق TSX في Contents/Resources/. يُوقَّع التطبيق توقيعًا مؤقتًا (ad hoc) ويتطلب macOS 14 أو أحدث؛ ولتوزيعه، وقّعه بهوية Developer ID ووثّقه (notarize). انظر macOS.
#Linux
nsh package --target linux --run
يكتب .nsh/out/<Name>/ (الملف التنفيذي <Name>، وnsh/assets/…، وnsh/app.json مع عنوان النافذة ومعرّف التطبيق، وملف nsh/bundle.nshc الخاص بتطبيق TSX، و<id>.desktop والأيقونة <id>.png) ومثل ما يكتبه .nsh/out/<Name>.tar.gz. التحزيم على Linux: يُبنى المشغّل للجهاز الذي يُبنى عليه. يجب تثبيت GTK 4 (الإصدار 4.14 أو أحدث) وPango وWebKitGTK 6.0 (لعروض الويب) حيث يعمل التطبيق. لتثبيته وتثبيت ملف سطح المكتب: Linux.
#Windows
nsh package --target windows --run
يكتب .nsh\out\<Name>\ (الملف التنفيذي <Name>.exe بأيقونة التطبيق، وnsh\assets\…، وnsh\app.json مع عنوان النافذة ومعرّف التطبيق والإصدار والمظهر، وملف nsh\bundle.nshc الخاص بتطبيق TSX) ومثل ما يكتبه .nsh\out\<Name>.zip. لا يحتاج تطبيق TSX إلى أي أدوات؛ أما مشغّل تطبيق Rust فيُبنى باستخدام Visual Studio Build Tools. التحزيم على Windows: يُبنى المشغّل للجهاز الذي يُبنى عليه، وWindows وحده يستطيع تضمين الأيقونة. يعمل التطبيق من أي مكان يُنسخ إليه مجلده؛ ولا شيء يُثبَّت. انظر Windows.
#الويب
nsh package --target web --run
يكتب .nsh/out/<Name>/، وهو موقع ثابت: index.html، وmanifest.webmanifest، وسكربت الصفحة (nsh.<digest>.js)، وnsh.<digest>.wasm (محرّك تطبيق Rust والـ crate الخاص به؛ وفي تطبيق TSX بيئة التشغيل، بجانب وحدة ES الخاصة بالتطبيق app.<digest>.js)، وأصوله وأيقوناته، ويُسمّى كل منها بحسب محتواه ليتمكن المضيفون من تخزينه مؤقتًا إلى أجل غير محدد. انشر المجلد على أي خادم ويب أو CDN؛ ويقدّمه --run على http://127.0.0.1:4173/ لتفتحه. ترويسات التخزين المؤقت والتضمين: الويب.
#الأيقونات
قدّم ملف PNG مربعًا واحدًا، ويفضَّل أن يكون 1024×1024، في nsh.json ("icon": "icon.png") أو باستخدام --icon:
- iOS: يترجمه
actoolالتابع لـ Xcode إلى كتالوج أصول التطبيق (Assets.car)، الذي يشتق كل الأحجام التي يحتاجها iOS. - Android: يُغيَّر حجمه إلى 192×192 ويُستخدم أيقونةً للمشغّل (
mipmap-xxxhdpi). - macOS: يحوّله
sipsإلىAppIcon.icns. - Linux: يُنسخ باسم
<id>.png، الذي يسمّيه ملف.desktopبوصفهIcon. - Windows: يُغيَّر حجمه من 16 إلى 64 بكسل وإلى 256 بكسل ويُضمَّن في الملف التنفيذي أيقونةً له، وهي التي تعرضها النافذة ومستكشف الملفات (Explorer) وشريط المهام.
- الويب: يُغيَّر حجمه إلى 32 بكسل (favicon)، و180 (
apple-touch-icon)، و192 و512 (manifest تطبيق الويب).
من دون أيقونة، يعرض النظام أيقونته الافتراضية.
#ما بداخل الحزمة
حزمة تطبيق Rust هي مشغّله، مبنيًا مع الـ crate الخاص بك ومكوّنه الجذري مركّبًا، والأصول التي تسجّلها الـ crates الخاصة به (assets!()). أما حزمة تطبيق TSX فتحتوي على bytecode الخاص به، وملف capabilities.json (عندما يعلن عن صلاحيات)، والأصول التي يستوردها، بجانب بيئة التشغيل الجاهزة:
| الهدف | بيئة التشغيل | تطبيق TSX |
|---|---|---|
| iOS | الملف التنفيذي nsh-ios-app | <Name>.app/nsh/bundle.nshc، nsh/assets/… |
| Android | classes.dex، lib/<abi>/libnsh.so (بلا رموز، ومخزَّنة دون ضغط، ومحاذاة 16 KB) | assets/nsh/bundle.nshc، assets/nsh/assets/… |
| macOS | الملف التنفيذي nsh-macos-app، مُعاد تسميته <Name> | <Name>.app/Contents/Resources/nsh/bundle.nshc، nsh/assets/… |
| Linux | الملف التنفيذي nsh-linux-app، مُعاد تسميته <Name> | <Name>/nsh/bundle.nshc، nsh/assets/… |
| Windows | الملف التنفيذي nsh-windows-app.exe، مُعاد تسميته <Name>.exe | <Name>\nsh\bundle.nshc، nsh\assets\… |
| الويب | nsh.<digest>.wasm، nsh.<digest>.js | <Name>/app.<digest>.js، assets/…، index.html |
لا يسجّل التطبيق المحزَّم أي مكونات native؛ ولاستخدامها، ضمّن NSH في تطبيقك.
#العثور على بيئة التشغيل
يبني تطبيق Rust مشغّلاته بنفسه. أما تطبيقات TSX فيبحث nsh package عن بيئة التشغيل الجاهزة بجانب CLI (bin/../runtime في التوزيعة). وفي نسخة مستنسخة (checkout) من NSH يستخدم target/<triple>/<profile> وtarget/android/<profile>، بملف البناء (profile) الخاص بـ CLI نفسه (يستخدم CLI بوضع التصحيح بيئات تشغيل بوضع التصحيح): ابنِها باستخدام cargo build -p nsh-ios-app --target aarch64-apple-ios-sim (أو aarch64-apple-ios للأجهزة) وcargo xtask android (أضف --release لـ CLI بوضع الإصدار)؛ أما nsh-macos-app (على macOS) وnsh-linux-app (على Linux) وnsh-windows-app (على Windows) فتُبنى لهذا الجهاز في target/<profile> (cargo build -p nsh-macos-app، cargo build -p nsh-linux-app، cargo build -p nsh-windows-app)؛ وتُبنى بيئة تشغيل الويب بملف البناء web أيًّا كان ملف CLI، في target/wasm32-unknown-unknown/web/. ويوجّه متغير البيئة NSH_RUNTIME أداة CLI إلى مجلد آخر مرتّب مثل runtime/ في التوزيعة (ios/iphoneos، ios/iphonesimulator، android/release، macos، linux، windows، gpui، web، …).
#انظر أيضًا
- CLI: جميع الأوامر
- الحزم الموقّعة: التحديثات التي تنزّلها التطبيقات
- بنية المشروع:
nsh.jsonوملفات التطبيق