فا نیکسی

Factor

محیط توسعه

تمام عبارت‌های Nix برای کامپایلر و محیط توسعه Factor را می‌توان در pkgs/top-level/factor-packages.nix یافت.

بسته پیش‌فرض factor-lang پشتیبانی از رابط کاربری گرافیکی توکار و مجموعه گزینش‌شده‌ای از اتصال‌های (bindings) کتابخانه C، برای نمونه برای صدا و اتصالات TLS را ارائه می‌دهد. همچنین این بسته شامل کتابخانه Fuel برای Emacs است که یک محیط توسعه یکپارچه را برای توسعه برنامه‌های Factor از جمله دسترسی به زمان اجرای Factor و مستندات آنلاین فراهم می‌سازد.

برای استفاده از کتابخانه‌هایی که کمتر استفاده می‌شوند و به اتصال‌های اضافی نیاز دارند، می‌توانید بسته factor-lang را بازنشانی کرده و اتصال‌های کتابخانه‌ای و/یا باینری‌های بیشتری را به PATH آن اضافه کنید. این بسته در pkgs/development/compilers/factor-lang/wrapper.nix تعریف شده است و چندین صفت را برای افزودن آن‌ها ارائه می‌دهد:

  • extraLibs مسیرهای /lib بسته‌ها را به پوشش‌دهنده (wrapper) اضافه می‌کند و تمام کتابخانه‌های اشتراکی را به یک کش ld.so می‌افزاید تا زمان اجرای Factor بتواند آن‌ها را به‌صورت پویا پیدا کند.
  • binPackages همان کار extraLibs را انجام می‌دهد و علاوه بر آن، بسته‌ها را به متغیر محیطی PATH متعلق به Factor اضافه می‌کند.
  • extraVocabs واژگان (vocabularies) Factor را که بخشی از کتابخانه استاندارد نیستند به درخت اضافه می‌کند. بسته‌ها برای پیدا شدن باید از ساختار ریشه واژگان پیش‌فرض پیروی کنند.
  • guiSupport تمام کتابخانه‌های گرافیکی لازم را برای فعال‌سازی GUI مربوط به Factor فرا می‌خواند. هنگام تصمیم برای ساخت و اجرای برنامه‌های کاربردی گرافیکی با این زمان اجرای Factor (حتی اگر از GUI مربوط به Factor برای برنامه‌نویسی استفاده نشود)، این مقدار باید روی true تنظیم شود. این آرگومان به‌طور پیش‌فرض true است.
  • enableDefaults می‌تواند غیرفعال شود تا تنها کتابخانه‌هایی که در extraLibs یا binPackages نام برده شده‌اند پوشش داده شوند. این امر وابستگی‌های زمان اجرا را به‌ویژه هنگام ارائه برنامه‌های Factor کاهش می‌دهد.

این بسته همچنین چندین صفت را که فهرست‌کننده کتابخانه‌ها و باینری‌های پوشش‌داده‌شده هستند تحویل می‌دهد، یعنی extraLibs و binPackages و همچنین defaultLibs و defaultBins. علاوه بر این، runtimeLibs الحاق تمام موارد فوق به‌منظور ارائه همه کتابخانه‌های پویا و لازم به عنوان "propagatedBuildInputs" است. در نهایت، extraVocabs به همان شکل جهت ترکیب پشته‌ای تحویل داده می‌شود و vocabTree کاملاً ترکیب‌شده به عنوان یک مسیر انبار تحویل داده می‌شود. این کار، ارجاع پلاگین‌های خارجی (مثلاً برای ویرایشگرها و محیط‌های توسعه یکپارچه) به ریشه‌های واژگان Factor را آسان‌تر می‌کند.

factorPackages بسته‌های Factor از‌پیش‌تنظیم‌شده را ارائه می‌دهد:

  • factorPackages.factor-lang بسته پیش‌فرض با پشتیبانی از GUI و چندین اتصال کتابخانه‌ای پیش‌فرض (مانند openssl، openal و غیره) است.
  • factorPackages.factor-no-gui پشتیبانی از GUI را خاموش می‌کند در حالی که اتصال‌های کتابخانه‌ای پیش‌فرض را حفظ می‌نماید.
  • factorPackages.factor-minimal عملاً بدون هیچ اتصال کتابخانه‌ای و باینری اضافی و بدون پشتیبانی از GUI ارائه می‌شود.
  • factorPackages.factor-minimal-gui بدون اتصال‌های کتابخانه‌ای اضافی اما شامل پشتیبانی از GUI ارائه می‌شود.

اسکلت‌بندی (Scaffolding) و ریشه واژگان work

Factor از مفهوم «داربست‌بندی» (scaffolding) برای ایجاد یک واژگان (vocabulary) جدید در یک فضای کاری شخصی استفاده می‌کند که ریشه آن در ریشه واژگان work قرار دارد. این مفهوم مقیاس‌پذیری چندان خوبی ندارد، زیرا فرض‌های زیادی را مطرح می‌کند که در نهایت همگی در نقطه‌ای نادرست از آب درمی‌آیند. در پیاده‌سازی فعلی، ریشه واژگان work به مسیر /var/lib/factor روی ماشین هدف اشاره می‌کند. این موضوع می‌تواند برای یک سیستم تک‌کاربره مناسب باشد. این مسیر را ایجاد کرده و دسترسی نوشتن آن را به کاربر خود بدهید. سپس، می‌توانید طبق دستورالعمل بسیاری از آموزش‌ها از کلمه scaffold-work استفاده کنید.

اگر این روش را دوست ندارید، می‌توانید با ایجاد یک فایل ~/.factor-roots در پوشه خانه خود، این مسئله را دور بزنید؛ این فایل شامل مسیرهایی است که می‌خواهید ریشه‌های اضافی واژگان Factor را نشان دهند، به ازای هر پوشه یک خط. از scaffold-vocab برای ایجاد واژگان خود در یکی از این ریشه‌های اضافی استفاده کنید. مستندات آنلاین Factor درباره نحوه استفاده از فریم‌ورک scaffolding بسیار جامع است.

بسته‌بندی واژگان Factor

تمام واژگان Factor که قرار است از طریق صفت (attribute) extraVocabs به یک محیط Factor اضافه شوند، باید از طرح‌بندی پوشه‌ای زیر پیروی کنند. پوشه سطح بالای آن باید یکی (یا چند مورد) از basis، core یا extra باشد. مسیر work به /var/lib/factor هدایت می‌شود و در انبار نیکس (Nix store) تحویل داده نشده یا مورد ارجاع قرار نمی‌گیرد؛ بخش مربوط به داربست‌بندی را ببینید. معمولاً باید از extra استفاده کنید، اما می‌توانید از سایر ریشه‌ها برای بازنویسی واژگان توکار (Built-in) استفاده نمایید. توجه داشته باشید که واژگان موجود در core بخشی از تصویر Factor هستند که محیط توسعه از روی آن اجرا می‌شود. این بدان معناست که کد موجود در آن واژگان از کدهای منبع بارگیری نمی‌شود، به طوری که برای کامپایل مجدد و بارگیری تعاریف تغییریافته باید refresh-all را فراخوانی کنید. در این موارد، توصیه می‌شود بسته factor-unwrapped را مستقیماً بازنویسی (override) کنید، که کتابخانه‌های اصلی Factor را کامپایل کرده و در تصویر پیش‌فرض Factor بسته‌بندی می‌کند.

طبق قرارداد Factor، واژگان foo.factor شما علاوه بر یکی از ریشه‌های واژگان که قبلاً ذکر شد، باید در پوشه‌ای با همان نام قرار گیرد، مانند extra/foo/foo.factor.

تمام واژگان اضافی Factor در pkgs/top-level/factor-packages.nix ثبت می‌شوند و تعاریف بسته آن‌ها معمولاً در development/compilers/factor-lang/vocabs/ قرار دارند.

با استفاده از تابع buildFactorVocab یک واژگان را بسته‌بندی کنید. فاز نصب (installPhase) پیش‌فرض آن، مدیریت نصب آن در مسیر out/lib/factor را بر عهده دارد. این تابع همچنین صفات خاص زیر را درک می‌کند:

  • vocabName مسیر واژگانی است که قرار است نصب شود. مقدار پیش‌فرض آن pname است.
  • vocabRoot ریشه واژگانی است که واژگان زیر آن نصب می‌شود. مقدار پیش‌فرض آن extra است. مگر اینکه بدانید چه کاری انجام می‌دهید، آن را تغییر ندهید. سایر ریشه‌های واژگان که به راحتی شناخته می‌شوند core و basis هستند که به شما امکان می‌دهند محیط زمان اجرای پیش‌فرض Factor را با یک بسته خارجی تغییر دهید.
  • extraLibs، extraVocabs و extraPaths معانی مشابهی با آنچه برای برنامه‌ها بیان شد دارند. آن‌ها اثر فوری ندارند و صرفاً هدایت می‌شوند. هنگام ساخت بسته‌های factor-lang و برنامه‌های Factor که از این واژگان مربوطه استفاده می‌کنند، این متغیرها ارزیابی شده و مسیرهای آن‌ها به محیط زمان اجرا اضافه می‌شوند.

این تابع چندین شکل از درخت‌های پوشهٔ سورس را درک می‌کند:

  1. پروژه‌های سادهٔ تک‌واژگانی که فایل‌های Factor و فایل‌های تکمیلی آن‌ها مستقیماً در ریشهٔ پروژه قرار دارند. تمامی فایل‌های .factor و .txt در out/lib/factor/<vocabRoot>/<vocabName> کپی می‌شوند.
  2. پروژه‌های پیچیده‌تر با چندین واژگان در کنار یکدیگر، برای مثال ./<vocabName> و ./<otherVocab>. تمامی پوشه‌ها به جز bin، doc و lib در out/lib/factor/<vocabRoot> کپی می‌شوند.
  3. پروژه‌های حتی پیچیده‌تری که شامل چندین ریشهٔ واژگان می‌شوند. واژگان‌ها باید زیر lib/factor/<root>/<vocab> قرار داشته باشند و واژگان اصلی نام‌دهنده در lib/factor/<vocabRoot>/<vocabName> باشد. تمامی پوشه‌های موجود در lib/factor در out/ کپی می‌شوند.

برای نمونه، بسته‌بندی الگوریتم Bresenham برای درون‌گذاری خط به این شکل است؛ برای مشاهده فایل کامل pkgs/development/compilers/factor-lang/vocabs/bresenham را ببینید:

{ factorPackages, fetchFromGitHub }:

factorPackages.buildFactorVocab {
  pname = "bresenham";
  version = "dev";

  src = fetchFromGitHub {
    owner = "Capital-EX";
    repo = "bresenham";
    rev = "58d76b31a17f547e19597a09d02d46a742bf6808";
    hash = "sha256-cfQOlB877sofxo29ahlRHVpN3wYTUc/rFr9CJ89dsME=";
  };
}

واژگان در lib/factor/extra قرار می‌گیرند، و فایل‌های اضافی مانند مجوزها و غیره طبق معمول در share/ قرار می‌گیرند و می‌توانند از طریق فاز postInstall به خروجی اضافه شوند. در صورتی که واژگان به یک کتابخانه مشترک (shared library) متصل شود یا باینری خاصی را فراخوانی کند که باید در محیط زمان اجرای کاربران آن وجود داشته باشد، به ترتیب صفات extraPaths و extraLibs را اضافه کنید. سپس این‌ها توسط تابع buildFactorApplication استخراج شده و به عنوان وابستگی‌های زمان اجرا اضافه می‌شوند.

ساخت برنامه‌ها

برنامه‌های Factor با استفاده از قابلیت deploy در Factor و به کمک تابع buildFactorApplication ساخته می‌شوند.

تابع buildFactorApplication

factorPackages.buildFactorApplication buildDesc

هنگام بسته‌بندی یک برنامه Factor با buildFactorApplication، رابط override آن باید شامل آرگومان factorPackages باشد. برای مثال:

{
  lib,
  fetchurl,
  factorPackages,
}:

factorPackages.buildFactorApplication (finalAttrs: {
  pname = "foo";
  version = "1.0";

  src = fetchurl {
    url = "https://some-forge.org/foo-${finalAttrs.version}.tar.gz";
  };
})

تابع buildFactorApplication برای بسته foo-1.0 انتظار ساختار کد منبع زیر را دارد و یک برنامه /bin/foo تولید می‌کند:

foo-1.0/
  foo/
    foo.factor
    deploy.factor
  <more files and directories>...

این تابع صفات اضافی vocabName و binName را برای مواجهه با انحرافات نام‌گذاری ارائه می‌دهد. فایل deploy.factor نحوه استقرار برنامه را کنترل می‌کند و در مستندات آنلاین Factor درباره قابلیت deploy مستند شده است.

از قلاب‌های preInstall یا postInstall برای کپی کردن فایل‌ها و پوشه‌های اضافی به out/ استفاده کنید. خود تابع فقط برنامه را در /lib/factor/ و یک ورپر (wrapper) را در /bin/ می‌سازد.

یک مثال پیچیده‌تر، نحوه مشخص کردن وابستگی‌های زمان اجرا و واژگان اضافی Factor را بر روی نمونه برنامه Factor یعنی painter نشان می‌دهد:

{
  lib,
  fetchFromGitHub,
  factorPackages,
  curl,
}:

factorPackages.buildFactorApplication (finalAttrs: {
  pname = "painter";
  version = "1";

  factor-lang = factorPackages.factor-minimal-gui;

  src = fetchFromGitHub {
    name = finalAttrs.vocabName;
    owner = "Capital-EX";
    repo = "painter";
    rev = "365797be8c4f82440bec0ad0a50f5a858a06c1b6";
    hash = "sha256-VdvnvKNGcFAtjWVDoxyYgRSyyyy0BEZ2MZGQ71O8nUI=";
  };

  sourceRoot = ".";

  enableUI = true;
  extraVocabs = [ factorPackages.bresenham ];

  extraPaths = with finalAttrs.factor-lang; binPackages ++ defaultBins ++ [ curl ];

})

استفاده از صفات src.name و sourceRoot به شکل مناسبی پوشه واژگان painter مورد نیاز برای کارکرد صحیح استقرار (deployment) را ایجاد می‌کند.

این امر بسته‌بند را ملزم می‌کند که مجموعه کامل باینری‌هایی را که قرار است در زمان اجرا در دسترس باشند، مشخص کند. این کار الگوی استاندارد بسته‌های برنامه را فعال می‌کند تا تمام وابستگی‌های زمان اجرا را به‌طور صریح و بدون تداخل زمان اجرای Factor مشخص کنند.

buildFactorApplication یک پوشش (wrapper) حول stdenv.mkDerivation است و تمام صفات آن را می‌پذیرد. صفات اضافی که توسط buildFactorApplication پشتیبانی می‌شوند:

buildDesc (تابع یا مجموعه ویژگی)

: یک توصیف ساخت مشابه stdenv.mkDerivation با صفات زیر:

vocabName (رشته؛ اختیاری)

: مسیر واژگانی است که باید مستقر شود، به صورت نسبی نسبت به ریشه کد منبع. بنابراین، پوشه foo/ از مثال بالا می‌تواند extra/deep/down/foo باشد. این ویژگی به شما اجازه می‌دهد ساختار درختی واژگان Factor را حفظ کرده و همان درخت کد منبع را به عنوان یک برنامه مستقل و همچنین به عنوان یک کتابخانه در محیط توسعه Factor از طریق صفت extraVocabs توزیع کنید.

binName (رشته؛ اختیاری)

: نام باینری حاصل در /bin/ است. مقدار پیش‌فرض آن آخرین بخش پوشه در vocabName است. همچنین به عنوان صفت meta.mainProgram اضافه می‌شود تا تسهیل‌کننده اجرای nix run باشد.

enableUI (بولین؛ اختیاری)

: به طور پیش‌فرض false است. هنگام ارائه یک برنامه گرافیکی، این مقدار را روی true تنظیم کنید.

extraLibs (فهرست؛ اختیاری)

: کتابخانه‌های اضافی را به عنوان وابستگی‌های زمان اجرا اضافه می‌کند. مقدار پیش‌فرض آن [] است و با runtimeLibs حاصل از بسته factor-langِ مورد استفاده ترکیب می‌شود. از factor-minimal برای کمینه کردن بستار (closure) کتابخانه‌های زمان اجرا استفاده کنید.

extraPaths (فهرست؛ اختیاری)

: باینری‌های اضافی را به متغیر محیطی PATH زمان اجرا اضافه می‌کند (بدون اینکه کتابخانه‌های آن‌ها را نیز اضافه کند). مقدار پیش‌فرض آن [] است و با defaultBins و binPackages حاصل از بسته factor-langِ مورد استفاده ترکیب می‌شود. از factor-minimal برای کمینه کردن بستار کتابخانه‌های زمان اجرا استفاده کنید.

deployScriptText (رشته؛ اختیاری)

: فایل واقعی Factor برای استقرار است که برای استقرار برنامه اجرا می‌شود. اگر نیاز به انجام محاسبات اضافی در طول استقرار دارید، می‌توانید آن را تغییر دهید.

factor-lang (بسته؛ اختیاری)

: بسته Factor مورد استفاده برای استقرار این برنامه را بازنویسی می‌کند، که همچنین بر پیوندهای کتابخانه‌ای پیش‌فرض و برنامه‌ها در متغیر محیطی PATH زمان اجرا تأثیر می‌گذارد. مقدار پیش‌فرض آن در صورت فعال بودن enableUI برابر با factor-lang و در صورت غیرفعال بودن آن برابر با factor-no-gui است. برنامه‌هایی که فقط از کتابخانه‌های Factor بدون برنامه‌ها یا پیوندهای خارجی استفاده می‌کنند، می‌توانند این مقدار را روی factor-minimal یا factor-minimal-gui تنظیم کنند.