يعد Cargo-Raze حاليًا منتجًا غير مدعوم وغير مدعوم .
يعد crate_universe
الموجود في rules_rust
منتجًا مدعومًا ويتم صيانته وله أهداف مماثلة.
نعتقد أن crate_universe
يدعم جميع الوظائف التي كانت مدعومة بواسطة Cargo-Raze. نحن نشجعك على محاولة الهجرة إليها. إذا وجدت دعمًا مفقودًا أو أخطاء، فيرجى تقديم مشكلة أو علاقات عامة ضد rules_rust
.
تمت أرشفة cargo-raze
لتعكس حقيقة أنه من غير المرجح أن تتم معالجة العلاقات العامة والقضايا المرفوعة ضدها.
يرجى التواصل مع #rust in the Bazel Slack إذا كنت مهتمًا بتولي صيانة هذا المشروع.
دعم تجريبي للمكون الإضافي Cargo لتقطير Cargo.toml على مستوى مساحة العمل إلى أهداف BUILD التي يمكن أن تعتمد عليها التعليمات البرمجية باستخدام Rules_rust بشكل مباشر.
هذا ليس أحد منتجات Google الرسمية (تجريبيًا أو غير ذلك)، إنه مجرد رمز مملوك لشركة Google.
يقوم هذا المشروع بتجميع منطق تحليل التبعية وبعض وظائف Cargo مثل الميزات وبناء البرامج النصية في قواعد قابلة للتنفيذ يمكن لـ Bazel تشغيلها لتجميع صناديق Rust. على الرغم من أنه يمكن استخدام قواعد Rust_rust القياسية لتجميع كود Rust من الصفر، إلا أن التفاصيل الدقيقة للنظام البيئي التبعي تجعل تحويل الأشجار التبعية بناءً على هذا النظام البيئي أمرًا مرهقًا، حتى بالنسبة للتعليمات البرمجية ذات التبعيات القليلة.
يمكن لـ Cargo-raze إنشاء أهداف قابلة للبناء في أحد الوضعين: البيع، أو عدم البيع. في وضع البائع، يستخدم المطورون الأمر الفرعي cargo vendor
العامة لاسترداد التبعيات المشار إليها بواسطة مساحة العمل الخاصة بهم Cargo.toml في الدلائل التي يتم تعبئتها بعد ذلك بملفات BUILD. في وضع عدم البيع، تقوم ميزة Cargo-raze بإنشاء قائمة مسطحة من ملفات BUILD، وماكرو على مستوى مساحة العمل يمكن استدعاؤه في ملف WORKSPACE لسحب التبعيات تلقائيًا بطريقة مشابهة لـ Cargo نفسها.
في كلتا الحالتين، الخطوة الأولى هي تحديد مكان وضع تبعيات Cargo في مساحة العمل. تم تصميم هذه المكتبة مع وضع monorepos في الاعتبار، حيث تقرر المنظمة مجموعة من التبعيات التي يشير إليها الجميع. من المفترض أن يتعاون أصحاب المصلحة في التبعيات لترقية التبعيات ذريًا، وإصلاح الأعطال عبر قاعدة التعليمات البرمجية الخاصة بهم في وقت واحد. في حالة عدم إمكانية ذلك، لا يزال من الممكن استخدام عملية مسح البضائع في سيناريو لا مركزي، ولكن من غير المرجح أن تتفاعل هذه المستودعات المنفصلة بشكل جيد مع التنفيذ الحالي.
بغض النظر عن النهج الذي تم اختياره، يجب إحضار قواعد الصدأ إلى مساحة العمل. هنا مثال:
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "rules_rust" ,
sha256 = "accb5a89cbe63d55dcdae85938e56ff3aa56f21eb847ed826a28a83db8500ae6" ,
strip_prefix = "rules_rust-9aa49569b2b0dacecc51c05cee52708b7255bd98" ,
urls = [
# Main branch as of 2021-02-19
"https://github.com/bazelbuild/rules_rust/archive/9aa49569b2b0dacecc51c05cee52708b7255bd98.tar.gz" ,
],
)
load ( "@rules_rust//rust:repositories.bzl" , "rust_repositories" )
rust_repositories ( edition = "2018" )
بالنسبة لمشروعات Bazel فقط، يجب على المستخدمين أولاً إنشاء ملف Cargo.toml قياسي يتضمن التبعيات محل الاهتمام. احرص على تضمين توجيه [lib]
حتى لا تشتكي شركة Cargo من فقدان ملفات المصدر لهذا الصندوق الوهمي. هنا مثال:
[ package ]
name = " compile_with_bazel "
version = " 0.0.0 "
# Mandatory (or Cargo tooling is unhappy)
[ lib ]
path = " fake_lib.rs "
[ dependencies ]
log = " =0.3.6 "
بمجرد وضع Cargo.toml القياسي، أضف توجيهات [package.metadata.raze]
في القسم التالي.
يجب أن تكون جميع إعدادات الشحن الأساسية تقريبًا قادرة على العمل في مكانها مع cargo-raze
. بافتراض أن مساحة عمل Cargo متداخلة الآن ضمن مساحة عمل Bazel، يمكن للمستخدمين ببساطة إضافة RazeSettings إلى ملفات Cargo.toml الخاصة بهم لاستخدامها في إنشاء ملفات Bazel
# Above this line should be the contents of your Cargo.toml file
[ package . metadata . raze ]
# The path at which to write output files.
#
# `cargo raze` will generate Bazel-compatible BUILD files into this path.
# This can either be a relative path (e.g. "foo/bar"), relative to this
# Cargo.toml file; or relative to the Bazel workspace root (e.g. "//foo/bar").
workspace_path = " //cargo "
# This causes aliases for dependencies to be rendered in the BUILD
# file located next to this `Cargo.toml` file.
package_aliases_dir = " . "
# The set of targets to generate BUILD rules for.
targets = [
" x86_64-apple-darwin " ,
" x86_64-pc-windows-msvc " ,
" x86_64-unknown-linux-gnu " ,
]
# The two acceptable options are "Remote" and "Vendored" which
# is used to indicate whether the user is using a non-vendored or
# vendored set of dependencies.
genmode = " Remote "
في المشاريع التي تستخدم مساحات عمل الشحن، يجب على المستخدمين تنظيم كافة إعدادات raze
الخاصة بهم في الحقل [workspace.metadata.raze]
في ملف Cargo.toml
ذي المستوى الأعلى والذي يحتوي على تعريف [workspace]
. يجب أن تكون هذه الإعدادات مطابقة لتلك التي تظهر في [package.metadata.raze]
في القسم السابق. ومع ذلك، قد يظل من الممكن وضع إعدادات الصندوق في ملفات Cargo.toml
الخاصة بأعضاء مساحة العمل:
# Above this line should be the contents of your package's Cargo.toml file
# Note that `some-dependency` is the name of an example dependency and
# `<0.3.0` is a semver version for the dependency crate's version. This
# should always be compaitble in some way with the dependency version
# specified in the `[dependencies]` section of the package defined in
# this file
[ package . metadata . raze . crates . some-dependency . '<0 . 3 . 0' ]
additional_flags = [
" --cfg=optional_feature_a " ,
" --cfg=optional_feature_b " ,
]
# This demonstrates that multiple crate settings may be defined.
[ package . metadata . raze . crates . some-other-dependency . '*' ]
additional_flags = [
" --cfg=special_feature " ,
]
في الوضع البعيد، يتم تحديد دليل مشابه لوضع البيع. في هذه الحالة، على الرغم من ذلك، فإنه يحتوي فقط على ملفات BUILD، وتعليمات البيع لـ WORKSPACE، والأسماء المستعارة للتبعيات الصريحة. مطلوب سباكة مختلفة قليلا.
هذا يخبر Raze بعدم توقع بيع التبعيات وإنشاء ملفات مختلفة.
أولا، قم بتثبيت Cargo-Raze.
$ cargo install cargo-raze
بعد ذلك، قم بتنفيذ عملية إزالة البضائع من داخل دليل البضائع
$ cargo raze
أخيرًا، قم باستدعاء وظيفة جلب المكتبة عن بعد داخل مساحة العمل الخاصة بك:
load ( "//cargo:crates.bzl" , "raze_fetch_remote_crates" )
# Note that this method's name depends on your gen_workspace_prefix setting.
# `raze` is the default prefix.
raze_fetch_remote_crates ()
هذا يخبر Bazel بمكان الحصول على التبعيات وكيفية بنائها: باستخدام الملفات التي تم إنشاؤها في //cargo
.
يمكنك الاعتماد على أي تبعيات صريحة في أي قاعدة Rust من خلال الاعتماد على //cargo:your_dependency_name
.
في وضع البيع، يتم تحديد الجذر مباشرة الذي سيحتوي على التبعيات الموردة ويصبح البوابة إلى قواعد البناء تلك. //cargo
أمر تقليدي، ولكن //third_party/cargo
قد يكون مرغوبًا فيه لتلبية الاحتياجات التنظيمية. لا يتم دعم البيع مباشرة إلى الجذر بشكل جيد بسبب الخصوصيات الخاصة بالتنفيذ، ولكن قد يتم دعمه في المستقبل. من الآن فصاعدًا، سيكون //cargo
هو الدليل المفترض.
أولاً، قم بتثبيت الأدوات المطلوبة للبيع وإنشاء أهداف قابلة للبناء.
$ cargo install cargo-raze
بعد ذلك، قم ببيع تبعياتك من داخل دليل الشحن/. سيؤدي هذا أيضًا إلى تحديث ملف Cargo.lock
الخاص بك.
$ cargo vendor --versioned-dirs
وأخيرًا، قم بإنشاء ملفات BUILD الخاصة بك، مرة أخرى من داخل دليل cargo/
$ cargo raze
يمكنك الآن الاعتماد على أي تبعيات صريحة في أي قاعدة Rust من خلال الاعتماد على //cargo:your_dependency_name
.
يمكن بناء Cargo-raze بالكامل في Bazel واستخدامه دون الحاجة إلى إعداد البضائع على الجهاز المضيف. للقيام بذلك، ما عليك سوى إضافة ما يلي إلى ملف WORKSPACE في مشروعك:
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "cargo_raze" ,
sha256 = "c664e258ea79e7e4ec2f2b57bca8b1c37f11c8d5748e02b8224810da969eb681" ,
strip_prefix = "cargo-raze-0.11.0" ,
url = "https://github.com/google/cargo-raze/archive/v0.11.0.tar.gz" ,
)
load ( "@cargo_raze//:repositories.bzl" , "cargo_raze_repositories" )
cargo_raze_repositories ()
load ( "@cargo_raze//:transitive_deps.bzl" , "cargo_raze_transitive_deps" )
cargo_raze_transitive_deps ()
مع تنفيذ ذلك، يمكن للمستخدمين تشغيل @cargo_raze//:raze
الهدف لإنشاء ملفات BUILD جديدة. على سبيل المثال:
bazel run @cargo_raze//:raze -- --manifest-path= $( realpath /Cargo.toml )
لاحظ أن المستخدمين الذين يستخدمون النمط الجيني vendored
سيظلون مضطرين إلى بيع تبعياتهم بطريقة ما، حيث أن cargo-raze
لا تقوم بذلك نيابةً عنك حاليًا.
تقوم بعض الصناديق بتنفيذ "برنامج نصي للإنشاء"، والذي، على الرغم من أنه غير مقيد تقنيًا فيما يمكن أن يفعله، إلا أنه عادةً ما يقوم بأحد الأشياء الشائعة القليلة.
يتم تعداد كافة الخيارات المذكورة أدناه في ملف src/settings.rs.
في بعض الحالات، يستخدم الصندوق المعلومات الأساسية فقط لإنشاء ملف مصدر Rust. يمكن بالفعل تنفيذ قواعد نصوص البناء هذه واستخدامها داخل Bazel من خلال تضمين توجيه في Cargo.toml الخاص بك قبل الإنشاء:
[ package . metadata . raze . crates . clang-sys . '0 . 21 . 1' ]
gen_buildrs = true
يخبر هذا الإعداد شركة Cargo-Raze بإنشاء هدف Rust_binary للبرنامج النصي للبناء وتوجيه مخرجاته التي تم إنشاؤها (نمط OUT_DIR) إلى الصندوق الأصلي.
تقوم بعض نصوص البناء بإصدار توجيهات مشروطة إلى stdout التي يعرف Cargo كيفية نشرها. لسوء الحظ، ليس من السهل إدارة معلومات التبعية الناتجة عن وقت البناء، لذا إذا كانت العلامات معروفة بشكل ثابت (ربما، نظرًا لأن هدف التجميع معروف بشكل ثابت)، فيمكن توفيرها من داخل Cargo.toml، بالطريقة التالية
[ package . metadata . raze . crates . unicase . '2 . 1 . 0' ]
additional_flags = [
# Rustc is 1.15, enable all optional settings
" --cfg=__unicase__iter_cmp " ,
" --cfg=__unicase__defauler_hasher " ,
]
يتم تسليم الأعلام المقدمة بهذه الطريقة مباشرة إلى روستك. قد يكون من المفيد الرجوع إلى قسم بناء البرنامج النصي في الوثائق لتفسير نصوص البناء وتوجيهات stdout التي تمت مواجهتها، والمتوفرة هنا: https://doc.rust-lang.org/cargo/reference/build-scripts.html
هناك طريقتان لتوفير مكتبات النظام التي يحتاجها الصندوق للتجميع. الأول هو بيع مكتبة النظام مباشرةً، وصياغة قاعدة بناء لها، وإضافة التبعيات إلى صندوق -sys
المقابل. بالنسبة لـ opensl، قد يبدو هذا جزئيًا كما يلي:
[ package . metadata . raze . crates . openssl-sys . '0 . 9 . 24' ]
additional_flags = [
# Vendored openssl is 1.0.2m
" --cfg=ossl102 " ,
" --cfg=version=102 " ,
]
additional_deps = [
" @//third_party/openssl:crypto " ,
" @//third_party/openssl:ssl " ,
]
[ package . metadata . raze . crates . openssl . '0 . 10 . 2' ]
additional_flags = [
# Vendored openssl is 1.0.2m
" --cfg=ossl102 " ,
" --cfg=version=102 " ,
" --cfg=ossl10x " ,
]
في بعض الحالات، قد يكون من الأفضل توصيل تبعية النظام المحلي مباشرة. للقيام بذلك، راجع قسم new_local_repository
في وثائق Bazel. بالنسبة للإصدار المترجم مسبقًا من llvm في مساحة العمل، قد يبدو هذا كما يلي:
new_local_repository (
name = "llvm" ,
build_file = "BUILD.llvm.bazel" ,
path = "/usr/lib/llvm-3.9" ,
)
في حالات قليلة، قد يلزم تجاوز صندوق النظام بالكامل. يمكن تسهيل ذلك عن طريق إزالة التبعيات وتكميلها في Cargo.toml، الإنشاء المسبق:
[ package . metadata . raze . crates . sdl2 . '0 . 31 . 0' ]
skipped_deps = [
" sdl2-sys-0.31.0 "
]
additional_deps = [
" @//cargo/overrides/sdl2-sys:sdl2_sys "
]
توفر بعض الصناديق ثنائيات مفيدة يمكن استخدامها كجزء من عملية التجميع: Bindgen هو مثال رائع. يقوم Bindgen بإنتاج ملفات مصدر Rust عن طريق معالجة ملفات C أو C++. يمكن إضافة توجيه إلى Cargo.toml لإخبار Bazel بكشف هذه الثنائيات لك:
[ package . metadata . raze . crates . bindgen . '0 . 32 . 2' ]
gen_buildrs = true # needed to build bindgen
extra_aliased_targets = [
" cargo_bin_bindgen "
]
تقوم ميزة Cargo-raze بوضع البادئات على الأهداف الثنائية مع cargo_bin_
، فبالرغم من أن Cargo تسمح للثنائيات والمكتبات بمشاركة نفس اسم الهدف، فإن Bazel لا يسمح بذلك.
في الوقت الحالي، لا تقوم شركة Cargo بجمع البيانات الوصفية حول الصناديق التي لا توفر أي مكتبات. وهذا يعني أن تحديدها في قسم [dependencies]
في ملف Cargo.toml
الخاص بك لن يؤدي إلى إنشاء أهداف Bazel. يحتوي Cargo-raze على حقل خاص للتعامل مع هذه الصناديق عند استخدام genmode = "Remote"
:
[ package . metadata . raze . binary_deps ]
wasm-bindgen-cli = " 0.2.68 "
في المقتطف أعلاه، تم تعريف صندوق wasm-bindgen-cli
على أنه تبعية ثنائية وسيضمن Cargo-raze تضمين البيانات الوصفية لهذا الصندوق وأي صندوق آخر محدد هنا في دليل الإخراج الناتج. سيتم إنشاء ملفات Lockfiles للأهداف المحددة ضمن [package.metadata.raze.binary_deps]
في دليل lockfiles
داخل المسار المحدد بواسطة workspace_path
.
لاحظ أن الحقل binary_deps
يمكن أن يدخل في مساحة العمل وبيانات تعريف الحزمة، ومع ذلك، يمكن أن يوجد تعريف واحد فقط للتبعية الثنائية في المرة الواحدة. إذا كان لديك حزم متعددة تعتمد على تبعية ثنائية واحدة، فيجب نقل هذا التعريف إلى بيانات تعريف مساحة العمل.
سيؤدي ضبط default_gen_buildrs على القيمة true إلى إنشاء ميزة "cargo-raze" لإنشاء نصوص برمجية للبناء لجميع الصناديق التي تتطلبها:
[ package . metadata . raze ]
workspace_path = " //cargo "
genmode = " Remote "
default_gen_buildrs = true
هذا الإعداد عبارة عن مقايضة بين الراحة والصحة. من خلال تمكينه، يجب أن تجد العديد من الصناديق تعمل دون الحاجة إلى تحديد أي علامات بشكل صريح، ودون الحاجة إلى تمكين البرامج النصية للبناء الفردي يدويًا. ولكن من خلال تشغيله، فإنك تسمح لجميع الصناديق التي تستخدمها بتشغيل تعليمات برمجية عشوائية في وقت الإنشاء، وقد لا تكون الإجراءات التي يقومون بها محكمة.
حتى مع تمكين هذا الإعداد، قد تظل بحاجة إلى توفير إعدادات إضافية لعدد قليل من الصناديق. على سبيل المثال، يحتاج الصندوق الحلقي إلى الوصول إلى الشجرة المصدر في وقت الإنشاء:
[ package . metadata . raze . crates . ring . '*' ]
compile_data_attr = " glob([ " **/*.der " ]) "
إذا كنت ترغب في تعطيل البرنامج النصي للبناء على صندوق فردي، يمكنك القيام بذلك على النحو التالي:
[ package . metadata . raze . crates . some_dependency . '*' ]
gen_buildrs = false
Bazel ("سريع"، "صحيح"، اختر اثنين) هو نظام بناء تم اختباره في المعركة وتستخدمه Google لتجميع مشاريع كبيرة ومتعددة اللغات دون تكرار الجهد ودون المساس بالصحة. وهو يحقق ذلك جزئيًا عن طريق الحد من الآليات التي يمكن لكائن تجميع معين استخدامها لاكتشاف التبعيات وإجبار الوحدات القابلة للبناء على التعبير عن المجموعة الكاملة لتبعياتها. ويتوقع أن تنتج مجموعتان متماثلتان من مدخلات هدف البناء نتيجة نهائية مكافئة لكل بايت.
في المقابل، تتم مكافأة المستخدمين بنظام بناء قابل للتخصيص وقابل للتوسيع يجمع أي نوع من الأهداف القابلة للتجميع ويسمح بالتعبير عن "التبعيات غير التقليدية"، مثل كائنات Protobuf، أو تظليل الرسومات المترجمة مسبقًا، أو التعليمات البرمجية التي تم إنشاؤها، مع الحفاظ على السرعة والصحيح.
من المحتمل أيضًا (على الرغم من أنه لم يتم إثباته بعد باستخدام المعايير) أن التطبيقات الكبيرة التي تم إنشاؤها مع أخذ نقاط قوة Bazel في الاعتبار: وحدات البناء عالية الدقة، سيتم تجميعها بشكل أسرع بشكل ملحوظ لأنها قادرة على التخزين المؤقت بشكل أكثر قوة وتجنب إعادة ترجمة أكبر قدر من التعليمات البرمجية أثناء التكرار.
للأفضل أو للأسوأ، يعتمد نظام Rust البيئي بشكل كبير على صناديق الشحن من أجل توفير الوظائف التي غالبًا ما تكون موجودة في المكتبات القياسية. يعد هذا في الواقع أمرًا رائعًا لتطور اللغة، لأنه يصف عملية منظمة لتحقيق الاستقرار (صندوق تجريبي -> صندوق 1.0 -> RFC -> إدراج في stdlib)، ولكنه يعني أنه يجب على الأشخاص الذين يفتقرون إلى الوصول إلى هذا النظام البيئي إعادة اختراع العديد من العجلات.
وبوضع ذلك جانبًا، هناك أيضًا صناديق رائعة تساعد مطوري Rust على التفاعل مع الأنظمة والمكتبات القياسية الصناعية والتي يمكنها تسريع عملية التطوير في اللغة بشكل كبير.
على الرغم من أن عبء محاكاة وظائف Cargo (حيثما أمكن ذلك على الإطلاق!) مرتفع، إلا أنه يبدو أن هذه هي الطريقة الوحيدة للحفاظ على الضمانات (الصحة وإمكانية التكرار) التي يعتمد عليها Bazel للحفاظ على أدائه. من الممكن والمحتمل مع طلبات RFC على متن الطائرة أن تصبح Cargo مرنة بدرجة كافية للسماح باستخدامها مباشرة للتجميع ولكن في هذه المرحلة الزمنية يبدو أن الحفاظ على ما يشبه تكافؤ الميزات هو في الواقع أسهل من تجنب كل الحواف الحادة التي قدمتها التعامل مع البضائع مثل مترجم Rust.
مع القليل من الجهد، من الممكن بناء كل شيء تقريبًا، بما في ذلك المشاريع التي تعتمد على opensl-sys. ستتطلب العديد من صناديق النظام تحديد مكتبة النظام التي تغلفها، وإما بيعها في المشروع، أو إخبار Bazel بمكان وجودها على نظامك. وقد يتطلب بعضها تعديلات طفيفة على المصدر، مثل إلغاء المتطلبات المتغيرة لبيئة الشحن ذات الترميز الثابت. يمكن أن تكون الإصلاحات غير تافهة في بعض الحالات، ولكن تم إنشاء عدد كبير من الصناديق الأكثر شيوعًا في مثال الريبو، وهو متاح على https://github.com/acmcarther/cargo-raze-crater
راجع هذه الأمثلة لتوفير تكوين الصندوق:
باستخدام الوضع المباع :
باستخدام الوضع البعيد :
تجميع OpenSSL :
القسم [package.metadata.raze]
مشتق من البنية المعلنة في impl/src/settings.rs.