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
این دلالت می کنه که:
- قوانینی که پروژه شما استفاده می کند می تواند زنجیره های ابزار صحیح را از
//:myplatform
کند. - قوانینی که وابستگی های پروژه شما استفاده می کند می تواند زنجیره ابزار صحیح را از
//:myplatform
کند. - یا پروژه ها بسته به پشتیبانی شما
//:myplatform
یا پروژه شما از APIهای قدیمی (مانند--crosstool_top
) پشتیبانی می کند. -
//:myplatform
references [common declarations][Common Platform Declaration]{: .external}CPU
،OS
و سایر مفاهیم عمومی که از سازگاری خودکار بین پروژه پشتیبانی می کنند. - تمام پروژه های مربوطه
select()
خصوصیات ماشین را که توسط//:myplatform
می شود را درک می کنند. -
//: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 به سمت پلتفرم ها حرکت می کنند. اما این روند زمان می برد. این به سه دلیل اصلی است:
منطق قانون باید به روز شود تا اطلاعات ابزار را از API جدید Toolchain دریافت کنید (
ctx.toolchains
) و خواندن تنظیمات قدیمی مانند--cpu
و--crosstool_top
کنید. این نسبتاً ساده است.نگهبانان Toolchain باید زنجیره های ابزار را تعریف کرده و آنها را در دسترس کاربران قرار دهند (در مخازن GitHub و ورودی های
WORKSPACE
). این از نظر فنی ساده است، اما باید به صورت هوشمندانه سازماندهی شود تا تجربه کاربری آسانی داشته باشد.تعاریف پلتفرم نیز ضروری است (مگر اینکه برای همان دستگاهی که Bazel روی آن اجرا می شود، بسازید). به طور کلی، پروژه ها باید پلتفرم های خود را تعریف کنند.
پروژه های موجود باید مهاجرت کنند.
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++ مجهز به پلتفرم با نقشهبرداریهای پلتفرم ترکیب کنید ( مثلا ).
زبان های دیگر
- قوانین Bazel's Rust به طور کامل از پلتفرم ها پشتیبانی می کنند.
- قوانین Bazel's Go به طور کامل از سیستم عامل ها پشتیبانی می کنند ( جزئیات ).
اگر در حال طراحی قوانین برای یک زبان جدید هستید، از پلتفرم ها برای انتخاب زنجیره ابزار زبان خود استفاده کنید. برای یک قدم خوب به مستندات زنجیره ابزار مراجعه کنید.
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" }
کنید یا از نگاشت پلتفرم برای از هر دو سبک از طریق پنجره مهاجرت پشتیبانی کنید.
نحوه استفاده از پلتفرم های امروزی
اگر فقط می خواهید یک پروژه را بسازید یا به صورت متقابل کامپایل کنید، باید مستندات رسمی پروژه را دنبال کنید. تعیین چگونگی و زمان ادغام با پلتفرمها و ارزشی که ارائه میدهد به عهده نگهبانان زبان و پروژه است.
اگر شما یک پروژه، زبان یا نگهدارنده زنجیره ابزار هستید و بیلد شما به طور پیشفرض از پلتفرمها استفاده نمیکند، سه گزینه دارید (علاوه بر انتظار برای انتقال جهانی):
پرچم «استفاده از پلتفرمها» را برای زبانهای پروژه خود تلنگر بزنید ( در صورت وجود ) و هر آزمایشی را که نیاز دارید انجام دهید تا ببینید آیا پروژههایی که به آنها اهمیت میدهید کار میکنند یا خیر.
اگر پروژه هایی که به آنها اهمیت می دهید همچنان به پرچم های قدیمی مانند
--cpu
و--crosstool_top
، از آنها همراه با--platforms
استفاده کنید:bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...
این مقداری هزینه نگهداری دارد (شما باید به صورت دستی مطمئن شوید که تنظیمات مطابقت دارند). اما این باید در غیاب انتقال های مرتد کار کند.
با نگاشت تنظیمات
--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 تماس بگیرید.