외부 저장소 사용하기
rust-lang/rust git 저장소는 rust-lang 조직에 속한 다른 여러 저장소에 의존합니다. 의존성을 사용하는 주요 방식은 세 가지입니다.
- crates.io를 통한 Cargo 의존성으로 사용(예:
rustc-rayon) - git(예:
clippy) 또는 josh(예:miri) 서브트리로 사용 - git 서브모듈로 사용(예:
cargo)
일반적인 원칙은 다음과 같습니다.
- 생태계의 다른 사람들에게도 유용할 수 있는 라이브러리에는 crates.io를 사용하십시오.
- 컴파일러 내부에 의존하고, 호환성을 깨는 변경이 있을 때 함께 업데이트해야 하는 도구에는 서브트리를 사용하십시오.
- 컴파일러와 독립적인 도구에는 서브모듈을 사용하십시오.
외부 의존성(서브트리)
다음 외부 프로젝트는 어떤 형태로든 subtree를 사용하여 관리됩니다.
- clippy
- miri
- portable-simd
- rustfmt
- rust-analyzer
- rustc_codegen_cranelift
- rustc_codegen_gcc
- rustc-dev-guide
- compiler-builtins(컴파일러 내장 함수)
- stdarch
submodule 의존성(아래에서 설명합니다)과 달리, subtree 의존성은 트리 안에서 직접 업데이트할 수 있는 일반 파일과 디렉터리일 뿐입니다. 하지만 가능하다면 이러한 도구에 한정된 개선 사항, 버그 수정 등은 각 도구의 업스트림 저장소에 직접 제출해야 합니다. 예외적으로, 새로운 도구 기능이나 테스트를 구현하는 데 rustc 변경이 필요한 경우에는 하나의 통합된 rustc PR에서 진행해야 합니다.
마찬가지로, rustc 변경으로 인해 어떤 서브트리 의존성의 빌드가 깨진다면 그에 대한 수정 사항도 해당 rustc PR에 포함해야 합니다.
subtree 의존성은 현재 서로 다른 두 가지 방식으로 관리됩니다.
git subtree사용- josh 도구 사용하기
mirirust-analyzerrustc-dev-guidecompiler-builtinsstdarch
Josh 서브트리
josh 도구는 git 서브트리의 대안으로, git 히스토리를 다른 방식으로 관리하며 큰 저장소에서도 확장성이 더 좋습니다. josh로 작업하려면 전용 도구가 필요합니다. 동기화를 돕기 위해 rustc-josh-sync라는 보조 도구를 제공하며, 이 도구는 아래에서 설명합니다.
Josh 서브트리 동기화하기
Josh 서브트리 업데이트에는 rustc-josh-sync라는 전용 도구를 사용합니다. 아래 명령은 모든 Josh 서브트리에 사용할 수 있지만, miri는 풀을 할 때 몇 가지 추가 단계를 수행해야 한다는 점에 유의하십시오.
다음 명령으로 이 도구를 설치할 수 있습니다:
cargo install --locked --git https://github.com/rust-lang/josh-sync
풀(rust-lang/rust의 변경 사항을 서브트리로 동기화)과 푸시(서브트리의 변경 사항을 rust-lang/rust로 동기화)는 모두 서브트리 저장소에서 수행합니다(따라서 먼저 터미널에서 해당 저장소의 체크아웃 디렉터리로 이동하십시오).
풀 수행하기
- 서브트리에 PR을 생성하는 데 사용할 새 브랜치를 체크아웃하십시오
- 풀 명령을 실행하십시오
rustc-josh-sync pull - 브랜치를 자신의 포크에 푸시하고 서브트리 저장소에 PR을 생성하십시오
ghCLI가 설치되어 있다면rustc-josh-sync가 PR을 대신 생성해 줄 수 있습니다.
푸시 수행하기
참고: 진행하기 전에 josh-sync README에 있는 Git 관련 안내를 살펴보십시오.
- 푸시 명령을 실행하여
<gh-username>계정의rustc포크에<branch-name>이라는 이름의 브랜치를 생성하십시오rustc-josh-sync push <branch-name> <gh-username> <branch-name>에서rust-lang/rust로 PR을 생성하십시오
새 Josh 서브트리 의존성 만들기
저장소 의존성을 git subtree 또는 git submodule에서 josh로 옮기려면 이 가이드를 참고하십시오.
git 서브트리 동기화하기
서브트리 기반 의존성에 적용된 변경 사항은 이 저장소와 업스트림 도구 저장소 사이에서 주기적으로 동기화해야 합니다.
서브트리 동기화는 일반적으로 각 도구의 메인테이너가 담당합니다. 다른 사용자도 동기화 PR을 제출할 수 있지만, 그렇게 하려면 로컬 git 설치를 수정하고 매우 정확한 일련의 지침을 따라야 합니다. 이 지침은 몇 가지 유용한 팁 및 요령과 함께 Clippy 기여 가이드의 서브트리 변경 사항 동기화 섹션에 문서화되어 있습니다. 이 지침은 서브트리 기반의 모든 도구에 적용할 수 있으니, 해당 도구에 맞는 서브트리 디렉터리와 원격 저장소를 올바르게 사용하는지만 확인하십시오.
동기화 과정은 subtree push와 subtree pull의 두 방향으로 진행됩니다.
subtree push는 이 저장소의 사본에서 일어난 모든 변경 사항을 가져와, 로컬 변경 사항과 일치하는 커밋을 원격 저장소에 생성합니다. 서브트리를 건드린 모든 로컬 커밋은 원격 저장소에 커밋을 하나씩 생성하지만, 파일을 지정된 디렉터리에서 도구 저장소의 루트로 옮기도록 수정됩니다.
subtree pull은 마지막 subtree pull 이후 도구 저장소에서 발생한 모든 변경 사항을 가져와, 도구의 변경 사항을 Rust 저장소의 지정된 디렉터리로 옮기는 병합 커밋과 함께 이 커밋들을 rustc 저장소에 추가합니다.
항상 push를 먼저 수행하고 이를 도구의 기본 브랜치에 병합시키는 것을 권장합니다. 그러면 pull을 수행할 때 충돌 없이 병합됩니다. 풀 도중에 충돌을 해결하는 것도 분명히 가능하지만, PR이 충분히 빨리 병합되지 않아 새로운 충돌이 생기면 충돌 해석을 다시 해야 할 수도 있습니다. git subtree pull의 결과를 리베이스하려고 하지 마십시오. 병합 커밋을 리베이스하는 것은 일반적으로 좋지 않은 생각입니다.
항상 서브트리 디렉터리를 가리키는 -P 접두사와 그에 대응하는 원격 저장소를 지정해야 합니다. 디렉터리나 저장소를 잘못 지정하면 엉뚱한 디렉터리를 엉뚱한 원격 저장소에 push하려는 아주 골치 아픈 병합이 발생합니다. 다행히도 rustc에서 pull한 커밋이나 원격에 push한 브랜치 중 하나를 버리기만 하면 아무런 문제 없이 이를 중단하고 다시 시도할 수 있습니다. 이런 일이 일어나면 갑자기 동기화하려는 커밋이 수천 개나 생기기 때문에 대개 꽤 분명하게 알 수 있습니다.
새 서브트리 의존성 생성하기
기존 저장소로부터 새 서브트리 의존성을 생성하려면 (이 저장소의 루트 디렉터리에서!) 다음을 호출하십시오.
git subtree add -P src/tools/clippy https://github.com/rust-lang/rust-clippy.git master
이렇게 하면 새 커밋이 생성되며, 이 커밋은 어떤 상황에서도 리베이스해서는 안 됩니다! 리베이스해야 한다면 커밋을 삭제하고 작업을 다시 수행하십시오.
이제 완료되었습니다. src/tools/clippy 디렉터리는 마치 Clippy가 rustc 모노레포의 일부인 것처럼 동작하므로, 여러분(또는 서브트리를 동기화하는 다른 사람들) 외에는 실제로 git subtree를 사용할 필요가 없습니다.
외부 의존성(서브모듈)
Rust를 빌드할 때는 git 서브모듈로 추적되는 외부 git 저장소도 사용합니다. 전체 목록은 .gitmodules 파일에서 찾을 수 있습니다. 이 프로젝트 중 일부는 필수이며(표준 라이브러리를 위한 stdarch 등), 일부는 선택 사항입니다(src/doc/book 등).
서브모듈 사용법은 Git 사용하기 장에서 더 자세히 다룹니다.
일부 서브모듈은 빌드되지 않거나 테스트가 통과하지 않는 “깨진” 상태에 있는 것이 허용됩니다. 예를 들어 The Rust Reference 같은 문서 책이 그렇습니다. 이러한 프로젝트의 메인테이너는 프로젝트가 깨진 상태일 때 알림을 받으며, 가능한 한 빨리 이를 수정해야 합니다. 현재 상태는 toolstate 웹사이트에서 추적됩니다. 자세한 내용은 Forge의 Toolstate 장에서 찾을 수 있습니다. 실제로 문서의 toolstate가 깨지는 경우는 매우 드뭅니다.
베타 채널과 안정 채널에서는 깨지는 것이 허용되지 않으며, PR이 병합되기 전에 반드시 해결해야 합니다. 또한 베타 분기 직전 한 주 동안에는 main에서도 깨지는 것이 허용되지 않습니다.