Cargo-raze는 현재 유지 관리 및 지원되지 않는 제품입니다 .
rules_rust
의 crate_universe
는 비슷한 목적으로 지원 및 유지 관리되는 제품입니다.
우리는 crate_universe
화물 파괴에서 지원되는 모든 기능을 지원한다고 믿습니다. 마이그레이션을 시도해 보시기 바랍니다. 누락된 지원이나 버그를 발견한 경우, rules_rust
에 대해 문제를 제기하거나 PR해 주세요.
cargo-raze
이에 대해 제기된 PR 및 문제가 해결될 가능성이 낮다는 현실을 반영하기 위해 보관되었습니다.
이 프로젝트의 유지 관리에 관심이 있으시면 Bazel Slack의 #rust에 문의하세요.
작업 공간 수준 Cargo.toml을 rule_rust를 사용하는 코드가 직접 의존할 수 있는 BUILD 대상으로 추출하기 위한 실험적 지원 Cargo 플러그인입니다.
이것은 공식 Google 제품(실험용이든 아니든)이 아니며 우연히 Google이 소유한 코드일 뿐입니다.
이 프로젝트는 종속성 해결 로직과 기능 및 빌드 스크립트와 같은 Cargo의 일부 기능을 Bazel이 Rust 크레이트를 컴파일하기 위해 실행할 수 있는 실행 가능한 규칙으로 합성합니다. 표준 rule_rust 규칙을 사용하여 Rust 코드를 처음부터 컴파일할 수 있지만 종속성 생태계의 세밀한 세분화로 인해 종속성이 거의 없는 코드의 경우에도 해당 생태계를 기반으로 종속성 트리를 변환하는 것이 번거롭습니다.
Cargo-raze는 Vendoring 또는 Non-Vendoring의 두 가지 모드 중 하나로 건설 가능한 목표를 생성할 수 있습니다. 벤더링 모드에서 개발자는 공통 cargo vendor
하위 명령을 사용하여 작업 공간 Cargo.toml에 표시된 종속성을 Cargo-raze가 BUILD 파일로 채우는 디렉터리로 검색합니다. 비공급업체 모드에서 Cargo-raze는 BUILD 파일의 단순 목록과 WORKSPACE 파일에서 호출하여 Cargo 자체와 유사한 방식으로 종속성을 자동으로 풀다운할 수 있는 작업공간 수준 매크로를 생성합니다.
두 경우 모두 첫 번째 단계는 작업 공간에서 Cargo 종속성을 어디에 배치할지 결정하는 것입니다. 이 라이브러리는 조직이 모든 사람이 가리키는 일련의 종속성을 결정하는 단일 저장소를 염두에 두고 설계되었습니다. 종속성의 이해관계자가 협력하여 종속성을 원자적으로 업그레이드하고 코드베이스 전체의 손상을 동시에 수정하도록 의도되었습니다. 이것이 가능하지 않은 경우에도 분산형 시나리오에서 화물 파괴를 사용할 수는 있지만 분리된 저장소가 현재 구현과 잘 상호 작용할 가능성은 거의 없습니다.
선택한 접근 방식에 관계없이 Rust_rules를 WORKSPACE로 가져와야 합니다. 예는 다음과 같습니다.
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을 생성해야 합니다. Cargo가 이 모의 크레이트에 대한 소스 파일 누락에 대해 불평하지 않도록 [lib]
지시문을 포함하도록 주의하세요. 예는 다음과 같습니다.
[ 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 작업 공간 아래에 중첩되어 있다고 가정하면 사용자는 Bazel 파일 생성에 사용할 Cargo.toml 파일에 RazeSettings를 추가하기만 하면 됩니다.
# 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]
정의가 포함된 최상위 Cargo.toml
파일의 [workspace.metadata.raze]
필드로 구성해야 합니다. 이러한 설정은 이전 섹션의 [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
다음으로, 화물 디렉터리 내에서 화물 raze를 실행하세요.
$ cargo raze
마지막으로 WORKSPACE 내에서 원격 라이브러리 가져오기 기능을 호출합니다.
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
에 생성된 파일을 사용합니다.
//cargo:your_dependency_name
에 따라 Rust 규칙의 명시 적 종속성에 의존할 수 있습니다.
벤더링 모드에서는 벤더 종속성을 수용하고 해당 빌드 규칙에 대한 게이트웨이가 될 루트가 직접 선택됩니다. //cargo
는 일반적이지만 //third_party/cargo
조직의 요구 사항을 충족하는 데 바람직할 수 있습니다. 구현별 특이성으로 인해 루트에 직접 공급하는 것은 잘 지원되지 않지만 향후 지원될 수 있습니다. 이제부터는 //cargo
가정된 디렉터리가 됩니다.
먼저 BUILDable 타겟을 벤더링하고 생성하는 데 필요한 도구를 설치합니다.
$ cargo install cargo-raze
그런 다음 화물/디렉토리 내에서 종속성을 공급하십시오. 그러면 Cargo.lock
파일도 업데이트됩니다.
$ cargo vendor --versioned-dirs
마지막으로, 다시 cargo/
디렉터리 내에서 BUILD 파일을 생성하세요.
$ cargo raze
이제 //cargo:your_dependency_name
에 따라 모든 Rust 규칙의 명시적인 종속성에 의존할 수 있습니다.
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 )
현재 cargo-raze
이 작업을 수행하지 않기 때문에 vendored
Genmode를 사용하는 사용자는 어떻게든 의존성을 공급해야 한다는 점에 유의하십시오.
일부 크레이트는 기술적으로 제한이 없지만 일반적으로 몇 가지 일반적인 작업 중 하나를 수행하는 "빌드 스크립트"를 실행합니다.
아래에 언급된 모든 옵션은 src/settings.rs 파일에 나열되어 있습니다.
어떤 경우에는 크레이트가 Rust 소스 파일을 생성하기 위해 기본 정보만 사용합니다. 이러한 빌드 스크립트 규칙은 생성 전에 Cargo.toml에 지시문을 포함하여 Bazel 내에서 실제로 실행하고 사용할 수 있습니다.
[ package . metadata . raze . crates . clang-sys . '0 . 21 . 1' ]
gen_buildrs = true
이 설정은 Cargo-raze가 빌드 스크립트에 대한 Rust_binary 대상을 생성하고 생성된(OUT_DIR 스타일) 출력을 상위 크레이트로 보내도록 지시합니다.
일부 빌드 스크립트는 Cargo가 전파하는 방법을 알고 있는 stdout에 조건부로 지시문을 내보냅니다. 안타깝게도 빌드 시 생성된 종속성 정보를 관리하는 것은 그리 간단하지 않습니다. 따라서 플래그가 정적으로 알려진 경우(아마도 컴파일 대상이 정적으로 알려져 있기 때문에) 다음과 같은 방식으로 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 " ,
]
이런 방식으로 제공된 플래그는 Rustc에 직접 전달됩니다. 발견된 빌드 스크립트 및 stdout 지시어를 해석하려면 문서의 빌드 스크립트 섹션을 참조하는 것이 도움이 될 수 있습니다. 여기에서 확인할 수 있습니다: https://doc.rust-lang.org/cargo/reference/build-scripts.html
크레이트가 컴파일하는 데 필요한 시스템 라이브러리를 제공하는 방법에는 두 가지가 있습니다. 첫 번째는 시스템 라이브러리를 직접 공급하고 이에 대한 BUILD 규칙을 만든 다음 해당 -sys
상자에 종속성을 추가하는 것입니다. openssl의 경우 부분적으로 다음과 같을 수 있습니다.
[ 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 " ,
]
어떤 경우에는 로컬 시스템 종속성을 직접 연결하는 것이 더 나을 수도 있습니다. 이렇게 하려면 Bazel 설명서의 new_local_repository
섹션을 참조하세요. WORKSPACE에 사전 컴파일된 llvm 버전의 경우 다음과 같을 수 있습니다.
new_local_repository (
name = "llvm" ,
build_file = "BUILD.llvm.bazel" ,
path = "/usr/lib/llvm-3.9" ,
)
어떤 경우에는 sys 크레이트를 완전히 재정의해야 할 수도 있습니다. 이는 사전 생성된 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은 C 또는 C++ 파일을 처리하여 Rust 소스 파일을 생성합니다. Bazel에 이러한 바이너리를 노출하도록 지시문을 Cargo.toml에 추가할 수 있습니다.
[ 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.toml
파일의 [dependencies]
섹션에 이를 지정해도 Bazel 대상이 생성되지 않음을 의미합니다. Cargo-raze에는 genmode = "Remote"
사용할 때 이러한 상자를 처리하는 특수 필드가 있습니다.
[ package . metadata . raze . binary_deps ]
wasm-bindgen-cli = " 0.2.68 "
위의 스니펫에서 wasm-bindgen-cli
크레이트는 바이너리 종속성으로 정의되어 있으며 Cargo-raze는 이 크레이트와 여기에 정의된 다른 크레이트에 대한 메타데이터가 결과 출력 디렉터리에 포함되도록 보장합니다. [package.metadata.raze.binary_deps]
에 지정된 대상에 대한 잠금 파일은 workspace_path
에 지정된 경로 내의 lockfiles
디렉터리에 생성됩니다.
binary_deps
필드는 작업 영역 및 패키지 메타데이터에 포함될 수 있지만 한 번에 하나의 바이너리 종속성 정의만 존재할 수 있습니다. 단일 바이너리 종속성에 의존하는 패키지가 여러 개 있는 경우 해당 정의를 작업 영역 메타데이터로 이동해야 합니다.
default_gen_buildrs를 true로 설정하면 화물 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("빠른", "올바른", 2개 선택)은 Google에서 중복된 노력 없이 그리고 정확성을 손상시키지 않고 엄청나게 큰 다국어 프로젝트를 컴파일하는 데 사용하는 전투 테스트를 거친 빌드 시스템입니다. 특정 컴파일 객체가 종속성을 발견하는 데 사용할 수 있는 메커니즘을 제한하고 빌드 가능한 단위가 전체 종속성 세트를 표현하도록 함으로써 이를 부분적으로 수행합니다. 두 개의 동일한 빌드 대상 입력 세트가 바이트 단위로 동등한 최종 결과를 생성할 것으로 예상합니다.
그 대가로 사용자는 모든 종류의 컴파일 가능한 대상을 컴파일하고 빠르고 정확한 상태를 유지하면서 Protobuf 개체, 미리 컴파일된 그래픽 셰이더 또는 생성된 코드와 같은 "비전통적인 종속성"을 표현할 수 있는 사용자 정의 가능하고 확장 가능한 빌드 시스템을 받게 됩니다.
또한 Bazel의 장점을 염두에 두고 구축된 대규모 애플리케이션(아직 벤치마크에서는 입증되지 않았지만)이 가능합니다. 즉, 고도로 세분화된 빌드 단위는 더 적극적으로 캐시하고 반복하는 동안 많은 코드를 재컴파일하지 않아도 되므로 훨씬 더 빠르게 컴파일될 것입니다.
좋건 나쁘건, Rust 생태계는 표준 라이브러리에 자주 존재하는 기능을 제공하기 위해 화물 상자에 크게 의존합니다. 이는 안정화를 위한 구조화된 프로세스(실험용 크레이트 -> 1.0 크레이트 -> RFC -> stdlib에 포함)를 설명하므로 실제로 언어 진화에 있어 환상적인 일입니다. 많은 바퀴를 재창조하십시오.
그 외에도 Rust 개발자가 언어 개발을 크게 가속화할 수 있는 업계 표준 시스템 및 라이브러리와 상호 작용하는 데 도움이 되는 환상적인 상자도 있습니다.
Cargo의 기능을 모방하는 부담은 높지만(가능한 경우!) Bazel이 성능을 유지하기 위해 의존하는 보장(정확성, 재현성)을 유지하는 유일한 방법인 것으로 보입니다. 기내 RFC를 사용하면 Cargo가 컴파일에 직접 사용할 수 있을 만큼 충분히 유연해질 가능성이 높지만 현 시점에서는 유사 기능 패리티를 유지하는 것이 실제로 도입된 모든 날카로운 모서리를 피하는 것보다 더 쉬운 것으로 보입니다. Cargo를 Rust 컴파일러처럼 취급합니다.
약간의 노력만 있으면 openssl-sys에 의존하는 프로젝트를 포함하여 거의 모든 것을 구축하는 것이 가능합니다. 많은 sys 크레이트에서는 자신이 래핑하는 시스템 라이브러리를 식별하고 이를 프로젝트에 공급하거나 Bazel에 시스템의 위치를 알려주어야 합니다. 일부는 하드코딩된 화물 환경 변수 요구 사항을 제거하는 등 사소한 소스 조정이 필요할 수 있습니다. 어떤 경우에는 수정이 간단하지 않을 수 있지만, 가장 인기 있는 크레이트 중 상당수가 https://github.com/acmcarther/cargo-raze-crater에서 사용할 수 있는 예시 저장소에 구축되어 있습니다.
크레이트 구성 제공에 대한 다음 예를 참조하세요.
공급업체 모드 사용 :
원격 모드 사용 :
OpenSSL 컴파일 :
[package.metadata.raze]
섹션은 impl/src/settings.rs에 선언된 구조체에서 파생됩니다.