ساختن با پلتفرم

Bazel دارای پشتیبانی پیچیده برای پلتفرم های مدل سازی و زنجیره های ابزار است. ادغام این با پروژه های واقعی نیاز به همکاری دقیق بین صاحبان کد، نگهبانان قوانین و توسعه دهندگان اصلی Bazel دارد.

این صفحه هدف پلتفرم ها را خلاصه می کند و نحوه ساخت با آنها را نشان می دهد.

tl;dr: پلتفرم Bazel و APIهای زنجیره ابزار در دسترس هستند اما تا زمانی که همه قوانین زبان، select() ها و دیگر مراجع قدیمی به روز نشوند، در همه جا کار نمی کنند. این کار ادامه دارد. در نهایت همه بیلدها مبتنی بر پلتفرم خواهند بود. زیر را بخوانید تا ببینید بیلدهای شما در کجا قرار می گیرند.

برای اسناد رسمی بیشتر، نگاه کنید به:

زمینه

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

این یک اضافه شدن نسبتاً جدید به Bazel است. این الهام از مشاهده این بود که نگهبانان زبان قبلاً این کار را به روش‌های موقت و ناسازگار انجام می‌دادند. به عنوان مثال، قوانین ++C از --cpu و --crosstool_top برای تنظیم CPU هدف ساخت و زنجیره ابزار C++ استفاده می کنند. هیچ یک از اینها به درستی یک "سکو" را مدل نمی کند. تلاش های تاریخی برای انجام این کار باعث ساختن های نامناسب و نادرست شد. این پرچم‌ها همچنین کامپایل جاوا را کنترل نمی‌کنند، که رابط مستقل خود را با --java_toolchain است.

Bazel برای پروژه های بزرگ، چند زبانه و چند پلتفرمی در نظر گرفته شده است. این مستلزم حمایت اصولی تری از این مفاهیم است، از جمله API های واضحی که زبان و قابلیت همکاری پروژه را تشویق می کند. این چیزی است که این API های جدید برای این کار هستند.

مهاجرت

پلتفرم و APIهای زنجیره ابزار فقط زمانی کار می کنند که پروژه ها واقعاً از آنها استفاده کنند. این بی اهمیت نیست زیرا منطق قوانین پروژه، زنجیره های ابزار، وابستگی ها و select() باید از آنها پشتیبانی کند. این نیاز به یک توالی مهاجرت دقیق دارد تا همه پروژه ها و وابستگی های آنها به درستی کار کنند.

برای مثال، قوانین C++ Bazel از پلتفرم‌ها پشتیبانی می‌کنند. اما قوانین اپل اینطور نیست. پروژه C++ شما ممکن است به اپل اهمیتی ندهد. اما دیگران ممکن است. بنابراین هنوز فعال کردن پلتفرم‌ها در سطح جهانی برای تمام ساخت‌های ++C امن نیست.

بقیه این صفحه این توالی مهاجرت و چگونگی و زمان مناسب بودن پروژه های شما را توضیح می دهد.

هدف

انتقال پلت فرم Bazel زمانی کامل می شود که همه پروژه ها با فرم زیر ساخته شوند:

bazel build //:myproject --platforms=//:myplatform

این دلالت می کنه که:

  1. قوانینی که پروژه شما استفاده می کند می تواند زنجیره های ابزار صحیح را از //:myplatform کند.
  2. قوانینی که وابستگی های پروژه شما استفاده می کند می تواند زنجیره ابزار صحیح را از //:myplatform کند.
  3. یا پروژه ها بسته به پشتیبانی شما //:myplatform یا پروژه شما از APIهای قدیمی (مانند --crosstool_top ) پشتیبانی می کند.
  4. //:myplatform references [common declarations][Common Platform Declaration]{: .external} CPU ، OS و سایر مفاهیم عمومی که از سازگاری خودکار بین پروژه پشتیبانی می کنند.
  5. تمام پروژه های مربوطه select() خصوصیات ماشین را که توسط //:myplatform می شود را درک می کنند.
  6. //:myplatform در مکانی واضح و قابل استفاده مجدد تعریف می شود: در مخزن پروژه شما اگر پلتفرم منحصر به پروژه شما باشد، در غیر این صورت همه پروژه هایی که ممکن است از این پلت فرم استفاده کنند می توانند جایی را پیدا کنند.

APIهای قدیمی به محض دستیابی به این هدف حذف خواهند شد. سپس این روش استانداردی خواهد بود که پروژه‌ها پلتفرم‌ها و زنجیره‌های ابزار را انتخاب می‌کنند.

آیا باید از پلتفرم ها استفاده کنم؟

اگر فقط می خواهید یک پروژه را بسازید یا به صورت متقابل کامپایل کنید، باید مستندات رسمی پروژه را دنبال کنید.

اگر شما یک پروژه، زبان یا نگهدارنده زنجیره ابزار هستید، در نهایت می خواهید از API های جدید پشتیبانی کنید. اینکه منتظر بمانید تا انتقال جهانی کامل شود یا زودتر انتخاب کنید، بستگی به نیازهای ارزش / هزینه خاص شما دارد:

ارزش

  • می‌توانید select() را انتخاب کنید یا زنجیره‌های ابزار را بر اساس ویژگی‌هایی که به آن‌ها اهمیت می‌دهید، به‌جای پرچم‌های رمزگذاری‌شده مانند --cpu کنید. برای مثال، چندین CPU می‌توانند از یک مجموعه دستورالعمل پشتیبانی کنند.
  • ساخت های صحیح تر اگر در مثال بالا select() با --cpu انتخاب کنید، سپس یک CPU جدید اضافه کنید که از همان مجموعه دستورالعمل پشتیبانی می کند، select() نمی تواند CPU جدید را تشخیص دهد. اما یک select() در پلتفرم ها دقیق باقی می ماند.
  • تجربه کاربری ساده تر همه پروژه ها می دانند: --platforms=//:myplatform . بدون نیاز به چندین پرچم خاص زبان در خط فرمان.
  • طراحی زبان ساده تر همه زبان‌ها یک API مشترک برای تعریف زنجیره‌های ابزار، استفاده از زنجیره‌های ابزار و انتخاب زنجیره ابزار مناسب برای یک پلتفرم دارند.
  • اهداف را می توان در مرحله ساخت و آزمایش در صورتی که با پلت فرم هدف ناسازگار باشد نادیده گرفت.

هزینه ها

  • پروژه‌های وابسته که هنوز از پلتفرم‌ها پشتیبانی نمی‌کنند ممکن است به‌طور خودکار با شما کار نکنند.
  • کارکردن آنها ممکن است نیاز به تعمیر و نگهداری موقت اضافی داشته باشد.
  • وجود هم‌زمان APIهای جدید و قدیمی نیازمند راهنمایی دقیق‌تر کاربر برای جلوگیری از سردرگمی است.
  • تعاریف متعارف برای ویژگی های رایج مانند OS و CPU هنوز در حال تکامل هستند و ممکن است نیاز به مشارکت اولیه اضافی داشته باشند.
  • تعاریف متعارف برای زنجیره‌های ابزار خاص زبان هنوز در حال تکامل هستند و ممکن است نیاز به مشارکت اولیه اضافی داشته باشند.

بررسی API

platform مجموعه ای از اهداف constraint_value :

platform(
    name = "myplatform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

یک constraint_value یک ویژگی ماشینی است. مقادیر یکسان "نوع" تحت یک constraint_setting مشترک گروه بندی می شوند:

constraint_setting(name = "os")
constraint_value(
    name = "linux",
    constraint_setting = ":os",
)
constraint_value(
    name = "mac",
    constraint_setting = ":os",
)

toolchain یک قانون Starlark است. ویژگی‌های آن ابزارهای یک زبان را اعلام می‌کنند (مانند compiler = "//mytoolchain:custom_gcc" ). ارائه دهندگان آن این اطلاعات را به قوانینی منتقل می کنند که باید با این ابزارها ایجاد شوند.

زنجیره‌های ابزار مقدار constraint_value ماشین‌هایی را که می‌توانند هدف قرار دهند ( target_compatible_with = ["@platforms//os:linux"] ) و ماشین‌هایی که ابزارشان می‌توانند روی آن‌ها اجرا شوند، اعلام می‌کنند ( exec_compatible_with = ["@platforms//os:mac"] .

هنگام ساخت $ bazel build //:myproject --platforms=//:myplatform ، Bazel به طور خودکار یک ابزار زنجیره ای را انتخاب می کند که می تواند روی ماشین ساخت اجرا شود و برای //:myplatform باینری بسازد. این به عنوان وضوح زنجیره ابزار شناخته می شود.

مجموعه زنجیره های ابزار موجود را می توان در WORKSPACE با register_toolchains یا در خط فرمان با --extra_toolchains کرد.

برای غواصی عمیق تر اینجا را ببینید.

وضعیت

پشتیبانی از پلتفرم فعلی بین زبان ها متفاوت است. همه قوانین اصلی Bazel به سمت پلتفرم ها حرکت می کنند. اما این روند زمان می برد. این به سه دلیل اصلی است:

  1. منطق قانون باید به روز شود تا اطلاعات ابزار را از API جدید Toolchain دریافت کنید ( ctx.toolchains ) و خواندن تنظیمات قدیمی مانند --cpu و --crosstool_top کنید. این نسبتاً ساده است.

  2. نگهبانان Toolchain باید زنجیره های ابزار را تعریف کرده و آنها را در دسترس کاربران قرار دهند (در مخازن GitHub و ورودی های WORKSPACE ). این از نظر فنی ساده است، اما باید به صورت هوشمندانه سازماندهی شود تا تجربه کاربری آسانی داشته باشد.

    تعاریف پلتفرم نیز ضروری است (مگر اینکه برای همان دستگاهی که Bazel روی آن اجرا می شود، بسازید). به طور کلی، پروژه ها باید پلتفرم های خود را تعریف کنند.

  3. پروژه های موجود باید مهاجرت کنند. select() ها و انتقال ها نیز باید منتقل شوند. این بزرگترین چالش است. این به ویژه برای پروژه های چند زبانه چالش برانگیز است (که ممکن است اگر همه زبان ها نتوانند ---platforms را بخوانند --platforms ).

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

ویژگی های پلت فرم مشترک

ویژگی های پلتفرم مانند OS و CPU که در بین پروژه ها مشترک هستند باید در یک مکان استاندارد و متمرکز اعلام شوند. این کار سازگاری بین پروژه ای و بین زبانی را تشویق می کند.

برای مثال، اگر MyApp یک select() در constraint_value @myapp//cpus:arm داشته باشد و SomeCommonLib یک select() در @commonlib//constraints:arm داشته باشد، این حالت‌های «arm» خود را با معیارهای ناسازگار راه‌اندازی می‌کنند.

ویژگی‌های رایج جهانی در مخزن @platforms اعلام می‌شوند (بنابراین برچسب متعارف برای مثال بالا @platforms//cpu:arm است). ویژگی های مشترک زبان باید در مخزن زبان مربوطه خود اعلام شود.

پلتفرم های پیش فرض

به طور کلی، صاحبان پروژه باید پلتفرم های صریح را برای توصیف انواع ماشین هایی که می خواهند برای آن بسازند تعریف کنند. اینها سپس با --platforms می شوند.

وقتی ---platforms تنظیم نشده باشد، --platforms به طور پیش فرض platform نشان می دهد که ماشین ساخت محلی را نشان می دهد. این به طور خودکار در @local_config_platform//:host ایجاد می‌شود، بنابراین نیازی به تعریف صریح آن نیست. این OS و CPU ماشین محلی را با constraint_value value اعلام شده در @platforms .

C++

قوانین C++ Bazel از پلتفرم‌ها برای انتخاب زنجیره‌های ابزار هنگام تنظیم --incompatible_enable_cc_toolchain_resolution ( #7260 ) استفاده می‌کنند.

این بدان معنی است که می توانید یک پروژه ++C را با استفاده از:

bazel build //:my_cpp_project --platforms=//:myplatform

به جای میراث:

bazel build //:my_cpp_project` --cpu=... --crosstool_top=...  --compiler=...

اگر پروژه شما C++ خالص است و به پروژه‌های غیر C++ وابسته نیست، می‌توانید با خیال راحت از پلتفرم‌ها استفاده کنید تا زمانی که گزینه‌ها و انتقال‌های select شما سازگار باشند. برای راهنمایی بیشتر به #7260 و پیکربندی زنجیره های ابزار C++ مراجعه کنید.

این حالت به طور پیش فرض فعال نیست. این به این دلیل است که پروژه‌های اپل هنوز وابستگی‌های ++C را با --cpu و --crosstool_top ( مثلا ). بنابراین این بستگی به قوانین اپل دارد که به پلتفرم‌ها مهاجرت می‌کنند.

جاوا

قوانین جاوا Bazel از پلتفرم ها استفاده می کند.

این جایگزین پرچم های قدیمی --java_toolchain , --host_java_toolchain , --javabase و --host_javabase می شود.

برای یادگیری نحوه استفاده از پرچم های پیکربندی، به کتابچه راهنمای Bazel و Java مراجعه کنید. برای اطلاعات بیشتر، به سند طراحی مراجعه کنید.

اگر همچنان از پرچم‌های قدیمی استفاده می‌کنید، فرآیند مهاجرت را در شماره ۷۸۴۹ دنبال کنید.

اندروید

هنگام تنظیم --incompatible_enable_android_toolchain_resolution ، قوانین Android Bazel از پلتفرم‌ها برای انتخاب زنجیره‌های ابزار استفاده می‌کنند.

این به طور پیش فرض فعال نیست. اما مهاجرت در راه است.

سیب

قوانین اپل Bazel هنوز از پلتفرم هایی برای انتخاب زنجیره ابزار اپل پشتیبانی نمی کند.

آن‌ها همچنین از وابستگی‌های C++ مبتنی بر پلت‌فرم پشتیبانی نمی‌کنند، زیرا از --crosstool_top قدیمی برای تنظیم زنجیره ابزار C++ استفاده می‌کنند. تا زمانی که این مورد منتقل شود، می‌توانید پروژه‌های اپل را با C++ مجهز به پلتفرم با نقشه‌برداری‌های پلتفرم ترکیب کنید ( مثلا ).

زبان های دیگر

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

select()

پروژه ها می توانند select() را روی اهداف constraint_value انتخاب کنند اما پلتفرم های کامل را ندارند. این عمدی است به طوری که select() s تا حد امکان از انواع ماشین ها پشتیبانی می کند. یک کتابخانه با منابع خاص ARM باید از همه ماشین‌های مجهز به ARM پشتیبانی کند، مگر اینکه دلیلی برای دقیق‌تر بودن وجود داشته باشد.

برای انتخاب یک یا چند s constraint_value ، از:

config_setting(
    name = "is_arm",
    constraint_values = [
        "@platforms//cpu:arm",
    ],
)

این معادل انتخاب سنتی روی --cpu :

config_setting(
    name = "is_arm",
    values = {
        "cpu": "arm",
    },
)

جزئیات بیشتر در اینجا .

s را در --cpu , --crosstool_top و غیره select --platforms هنگام انتقال پروژه خود به پلتفرم ها، باید آنها را به constraint_values ​​تبدیل کنید یا از نگاشت پلت فرم برای پشتیبانی از هر دو سبک از طریق پنجره مهاجرت استفاده کنید.

انتقال ها

انتقال Starlark پرچم‌ها را در بخش‌هایی از نمودار ساخت شما تغییر می‌دهد. اگر پروژه شما از انتقالی استفاده می‌کند که --cpu ، --crossstool_top یا دیگر پرچم‌های قدیمی را تنظیم می‌کند، قوانینی که می‌خوانند --platforms این تغییرات را نمی‌بینند.

هنگام انتقال پروژه خود به پلتفرم‌ها، یا باید تغییراتی مانند return { "//command_line_option:cpu": "arm" } را به return { "//command_line_option:platforms": "//:my_arm_platform" } کنید یا از نگاشت پلت‌فرم برای از هر دو سبک از طریق پنجره مهاجرت پشتیبانی کنید.

نحوه استفاده از پلتفرم های امروزی

اگر فقط می خواهید یک پروژه را بسازید یا به صورت متقابل کامپایل کنید، باید مستندات رسمی پروژه را دنبال کنید. تعیین چگونگی و زمان ادغام با پلتفرم‌ها و ارزشی که ارائه می‌دهد به عهده نگهبانان زبان و پروژه است.

اگر شما یک پروژه، زبان یا نگهدارنده زنجیره ابزار هستید و بیلد شما به طور پیش‌فرض از پلتفرم‌ها استفاده نمی‌کند، سه گزینه دارید (علاوه بر انتظار برای انتقال جهانی):

  1. پرچم «استفاده از پلتفرم‌ها» را برای زبان‌های پروژه خود تلنگر بزنید ( در صورت وجود ) و هر آزمایشی را که نیاز دارید انجام دهید تا ببینید آیا پروژه‌هایی که به آنها اهمیت می‌دهید کار می‌کنند یا خیر.

  2. اگر پروژه هایی که به آنها اهمیت می دهید همچنان به پرچم های قدیمی مانند --cpu و --crosstool_top ، از آنها همراه با --platforms استفاده کنید:

    bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...
    

    این مقداری هزینه نگهداری دارد (شما باید به صورت دستی مطمئن شوید که تنظیمات مطابقت دارند). اما این باید در غیاب انتقال های مرتد کار کند.

  3. با نگاشت تنظیمات --cpu به پلتفرم‌های مربوطه و بالعکس، نگاشت‌های پلتفرم را برای پشتیبانی از هر دو سبک بنویسید.

نقشه برداری پلت فرم

نقشه‌برداری پلتفرم یک API موقت است که به منطق مبتنی بر پلتفرم و منطقی که از طریق پلتفرم پشتیبانی می‌شود، اجازه می‌دهد در یک ساختمان از طریق پنجره منسوخ شدن دومی وجود داشته باشند.

نقشه‌برداری پلتفرم، نقشه‌ای از یک platform() به مجموعه مربوطه از پرچم‌های قدیمی یا برعکس است. مثلا:

platforms:
  # Maps "--platforms=//platforms:ios" to "--cpu=ios_x86_64 --apple_platform_type=ios".
  //platforms:ios
    --cpu=ios_x86_64
    --apple_platform_type=ios

flags:
  # Maps "--cpu=ios_x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
  --cpu=ios_x86_64
  --apple_platform_type=ios
    //platforms:ios

  # Maps "--cpu=darwin --apple_platform_type=macos" to "//platform:macos".
  --cpu=darwin
  --apple_platform_type=macos
    //platforms:macos

Bazel از این استفاده می‌کند تا تضمین کند که همه تنظیمات، چه مبتنی بر پلتفرم و چه قدیمی، به طور مداوم در سراسر ساخت، از جمله از طریق انتقال اعمال می‌شوند.

به طور پیش‌فرض Bazel نگاشت‌ها را از فایل platform_mappings در ریشه فضای کاری شما می‌خواند. همچنین می توانید --platform_mappings=//:my_custom_mapping را تنظیم کنید.

برای جزئیات کامل اینجا را ببینید.

سوالات

برای پشتیبانی کلی و سؤالات در مورد جدول زمانی مهاجرت، با bazel-discuss@googlegroups.com یا صاحبان قوانین مربوطه تماس بگیرید.

برای بحث در مورد طراحی و تکامل APIهای پلتفرم/زنجیره ابزار، با bazel-dev@googlegroups.com تماس بگیرید.

همچنین ببینید