مقدمه
تازه وارد بازل شده اید؟ شما در جای مناسب هستید. برای آشنایی ساده با استفاده از Bazel، این آموزش First Build را دنبال کنید. این آموزش عبارات کلیدی را همانطور که در زمینه Bazel استفاده می شود تعریف می کند و شما را با اصول اولیه گردش کار Bazel راهنمایی می کند. با شروع با ابزارهایی که نیاز دارید، سه پروژه را با پیچیدگی فزاینده ساخته و اجرا خواهید کرد و یاد خواهید گرفت که چگونه و چرا پیچیده تر می شوند.
در حالی که Bazel یک سیستم ساخت است که از ساختهای چند زبانه پشتیبانی میکند، این آموزش از یک پروژه C++ به عنوان مثال استفاده میکند و دستورالعملها و جریان کلی را ارائه میدهد که برای اکثر زبانها اعمال میشود.
زمان تخمینی تکمیل: 30 دقیقه
پیش نیازها
اگر قبلاً این کار را نکرده اید، با نصب Bazel شروع کنید. این آموزش از Git برای کنترل منبع استفاده می کند، بنابراین برای بهترین نتیجه، Git را نیز نصب کنید .
سپس، پروژه نمونه را از مخزن Bazel's GitHub با اجرای موارد زیر در ابزار خط فرمان انتخابی خود بازیابی کنید:
git clone https://github.com/bazelbuild/examples
پروژه نمونه این آموزش در پوشه examples/cpp-tutorial
قرار دارد.
در زیر به نحوه ساختار آن نگاه کنید:
examples
└── cpp-tutorial
├──stage1
│ ├── main
│ │ ├── BUILD
│ │ └── hello-world.cc
│ └── WORKSPACE
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
سه مجموعه فایل وجود دارد که هر مجموعه نشان دهنده یک مرحله در این آموزش است. در مرحله اول، شما یک هدف واحد را در یک بسته میسازید . در مرحله دوم، شما هم یک باینری و هم یک کتابخانه از یک بسته واحد خواهید ساخت. در مرحله سوم و آخر شما یک پروژه با بسته های متعدد می سازید و آن را با چندین هدف می سازید.
خلاصه: مقدمه
با نصب Bazel (و Git) و کلون کردن مخزن این آموزش، شما پایه و اساس اولین ساخت خود را با Bazel گذاشتید. برای تعریف برخی اصطلاحات و تنظیم فضای کاری خود به بخش بعدی بروید.
شروع شدن
فضای کاری را تنظیم کنید
قبل از اینکه بتوانید یک پروژه بسازید، باید فضای کاری آن را تنظیم کنید. فضای کاری دایرکتوری است که فایل های منبع پروژه شما و خروجی های ساخت Bazel را در خود نگه می دارد. همچنین حاوی این فایل های مهم است:
-
که دایرکتوری و محتویات آن را به عنوان یک فضای کاری Bazel شناسایی می کند و در ریشه ساختار دایرکتوری پروژه قرار دارد.WORKSPACE
file - یک یا چند
که به Bazel میگوید چگونه قسمتهای مختلف پروژه را بسازد. دایرکتوری در فضای کاری که حاوی یک فایلBUILD
filesBUILD
است یک بسته است. (اطلاعات بیشتر در مورد بسته ها در ادامه این آموزش.)
در پروژه های آینده، برای تعیین یک دایرکتوری به عنوان فضای کاری Bazel، یک فایل خالی به نام WORKSPACE
در آن دایرکتوری ایجاد کنید. برای اهداف این آموزش، یک فایل WORKSPACE
از قبل در هر مرحله وجود دارد.
توجه : وقتی Bazel پروژه را میسازد، همه ورودیها باید در یک فضای کاری باشند. فایل هایی که در فضاهای کاری مختلف قرار دارند مستقل از یکدیگر هستند مگر اینکه پیوند داده شوند. اطلاعات دقیق تر در مورد قوانین فضای کاری را می توان در این راهنما یافت.
فایل BUILD را درک کنید
یک فایل BUILD
شامل چندین نوع مختلف دستورالعمل برای Bazel است. هر فایل BUILD
حداقل به یک قانون به عنوان مجموعهای از دستورالعملها نیاز دارد که به Bazel میگوید چگونه خروجیهای مورد نظر مانند باینریهای اجرایی یا کتابخانهها را بسازد. هر نمونه از یک قانون ساخت در فایل BUILD
یک هدف نامیده می شود و به مجموعه خاصی از فایل های منبع و وابستگی ها اشاره می کند. یک هدف همچنین می تواند به اهداف دیگر اشاره کند.
به فایل BUILD
در دایرکتوری cpp-tutorial/stage1/main
نگاهی بیندازید:
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
در مثال ما، هدف hello-world
cc_binary rule
نشان میدهد. این قانون به Bazel می گوید که یک باینری اجرایی مستقل از فایل منبع hello-world.cc
بدون وابستگی بسازد.
خلاصه: شروع کردن
اکنون با برخی از اصطلاحات کلیدی و معنای آنها در زمینه این پروژه و به طور کلی بازل آشنا شدید. در قسمت بعدی مرحله 1 پروژه را ساخته و تست خواهید کرد.
مرحله 1: تک هدف، تک بسته
زمان ساخت قسمت اول پروژه فرا رسیده است. برای یک مرجع بصری، ساختار بخش مرحله 1 پروژه به شرح زیر است:
examples
└── cpp-tutorial
└──stage1
├── main
│ ├── BUILD
│ └── hello-world.cc
└── WORKSPACE
برای رفتن به دایرکتوری cpp-tutorial/stage1
موارد زیر را اجرا کنید:
cd cpp-tutorial/stage1
بعد اجرا کنید:
bazel build //main:hello-world
در برچسب هدف، قسمت //main:
محل فایل BUILD
نسبت به ریشه فضای کاری است و hello-world
نام هدف در فایل BUILD
است.
Bazel چیزی شبیه به این تولید می کند:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.267s, Critical Path: 0.25s
شما به تازگی اولین هدف Bazel خود را ساخته اید. Bazel خروجی های ساخت را در دایرکتوری bazel-bin
در ریشه فضای کاری قرار می دهد.
اکنون باینری تازه ساخته شده خود را تست کنید، که عبارت است از:
bazel-bin/main/hello-world
این منجر به یک پیام چاپ شده " Hello world
" می شود.
در اینجا نمودار وابستگی مرحله 1 آمده است:
خلاصه: مرحله 1
اکنون که اولین ساخت خود را تکمیل کرده اید، یک ایده اولیه از نحوه ساختار یک بیلد دارید. در مرحله بعد با افزودن یک هدف دیگر به پیچیدگی اضافه خواهید کرد.
مرحله 2: چندین هدف ساخت
در حالی که یک هدف واحد برای پروژه های کوچک کافی است، ممکن است بخواهید پروژه های بزرگتر را به چندین هدف و بسته تقسیم کنید. این امکان ساختهای افزایشی سریع را فراهم میکند - یعنی Bazel فقط آنچه را که تغییر کرده است بازسازی میکند - و با ساخت چندین بخش از یک پروژه به طور همزمان سرعت ساختهای شما را افزایش میدهد. این مرحله از آموزش یک هدف را اضافه می کند و مرحله بعدی یک بسته اضافه می کند.
این دایرکتوری است که برای مرحله 2 با آن کار می کنید:
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
به فایل BUILD
در دایرکتوری cpp-tutorial/stage2/main
در زیر نگاه کنید:
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
],
)
با این فایل BUILD
، Bazel ابتدا کتابخانه hello-greet
(با استفاده از cc_library rule
)، سپس باینری hello-world
می سازد. ویژگی deps
در هدف hello-world
به Bazel می گوید که کتابخانه hello-greet
برای ساختن باینری hello-world
مورد نیاز است.
قبل از اینکه بتوانید این نسخه جدید از پروژه را بسازید، باید دایرکتوری ها را تغییر دهید و با اجرای زیر به فهرست cpp-tutorial/stage2
:
cd ../stage2
اکنون می توانید باینری جدید را با استفاده از دستور آشنای زیر بسازید:
bazel build //main:hello-world
یک بار دیگر، Bazel چیزی شبیه به این تولید می کند:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.399s, Critical Path: 0.30s
اکنون می توانید باینری تازه ساخته شده خود را آزمایش کنید، که " Hello world
" دیگری را برمی گرداند:
bazel-bin/main/hello-world
اگر اکنون hello-greet.cc
تغییر دهید و پروژه را بازسازی کنید، Bazel فقط آن فایل را دوباره کامپایل می کند.
با نگاهی به نمودار وابستگی، میبینید که hello-world به همان ورودیهای قبلی بستگی دارد، اما ساختار ساخت متفاوت است:
خلاصه: مرحله 2
اکنون پروژه را با دو هدف ساخته اید. هدف hello-world
یک فایل منبع میسازد و به یک هدف دیگر بستگی دارد ( //main:hello-greet
)، که دو فایل منبع اضافی را میسازد. در قسمت بعدی یک قدم جلوتر رفته و بسته دیگری اضافه کنید.
مرحله 3: بسته های متعدد
این مرحله بعدی یک لایه دیگر از پیچیدگی اضافه می کند و یک پروژه با بسته های متعدد می سازد. به ساختار و محتویات دایرکتوری cpp-tutorial/stage3
در زیر نگاهی بیندازید:
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
می بینید که اکنون دو زیرمجموعه وجود دارد و هر کدام حاوی یک فایل BUILD
هستند. بنابراین، برای Bazel، فضای کاری اکنون شامل دو بسته است: lib
و main
.
به فایل lib/BUILD
نگاهی بیندازید:
cc_library(
name = "hello-time",
srcs = ["hello-time.cc"],
hdrs = ["hello-time.h"],
visibility = ["//main:__pkg__"],
)
و در فایل main/BUILD
:
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
"//lib:hello-time",
],
)
هدف hello-world
در بسته اصلی به هدف hello-time
در بسته lib
بستگی دارد (از این رو برچسب هدف //lib:hello-time
) - Bazel این را از طریق ویژگی deps
می داند. می توانید این را در نمودار وابستگی منعکس شده مشاهده کنید:
برای موفقیت ساخت، هدف //lib:hello-time
را در lib/BUILD
BUILD با استفاده از ویژگی visibility به طور واضح برای اهداف در main/BUILD
قابل مشاهده می کنید. این به این دلیل است که اهداف به طور پیش فرض فقط برای اهداف دیگر در همان فایل BUILD
قابل مشاهده هستند. Bazel از دید هدف برای جلوگیری از نشت مسائلی مانند کتابخانه های حاوی جزئیات پیاده سازی به API های عمومی استفاده می کند.
اکنون این نسخه نهایی پروژه را بسازید. با اجرای زیر به فهرست cpp-tutorial/stage3
:
cd ../stage3
یک بار دیگر دستور زیر را اجرا کنید:
bazel build //main:hello-world
Bazel چیزی شبیه به این تولید می کند:
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 0.167s, Critical Path: 0.00s
اکنون آخرین باینری این آموزش را برای پیام نهایی Hello world
آزمایش کنید:
bazel-bin/main/hello-world
خلاصه: مرحله 3
شما اکنون پروژه را به صورت دو بسته با سه هدف ساختهاید و وابستگیهای بین آنها را درک کردهاید، که شما را برای پیشبرد و ساخت پروژههای آینده با Bazel مجهز میکند. در بخش بعدی، نگاهی به نحوه ادامه سفر بازل خود بیندازید.
مراحل بعدی
شما اکنون اولین ساخت اولیه خود را با Bazel تکمیل کرده اید، اما این تازه شروع کار است. در اینجا چند منبع دیگر برای ادامه یادگیری با Bazel آورده شده است:
- برای ادامه تمرکز بر روی C++، در مورد موارد استفاده رایج ساخت C++ مطالعه کنید.
- برای شروع ساخت برنامه های دیگر با Bazel، به آموزش های جاوا ، برنامه اندروید یا برنامه iOS مراجعه کنید.
- برای کسب اطلاعات بیشتر در مورد کار با مخازن محلی و راه دور، در مورد وابستگی های خارجی بخوانید.
- برای کسب اطلاعات بیشتر در مورد سایر قوانین بازل، به این راهنمای مرجع مراجعه کنید.
ساختمان مبارک!