Rust 컴파일러 개발 관련 명령어 모음집
notJoon @joonnot@hackers.pub
개요
러스트 컴파일러에 기여하면서 자주 사용하는 명령어와 일반적인 흐름에 대해 정리한 글입니다.
1. 기본 빌드 명령어
1.1 컴파일러 빌드
전체 컴파일러 빌드
./x.py build --stage 1
전체 컴파일러를 처음부터 빌드하거나 큰 변경사항 적용 시 사용. 하드웨어에 따라 다르지만 대략 5~10분 정도 소요됨.
특정 컴포넌트만 빌드
어떤 모듈만 수정/개발하는 경우 특정 컴포넌트만 빌드하는 것도 가능. 이 경우 전체 빌드보다 압도적으로 적은 시간 소요.
./x.py build --stage 1 compiler/rustc_[component_name]
# 예: ./x.py build --stage 1 compiler/rustc_parse
1.2 테스트 실행
기본 테스트 실행
# 특정 테스트 파일 실행
./x.py test tests/ui/[category]/[test-name].rs
# 여러 테스트 실행 (와일드카드 사용)
./x.py test tests/ui/[category]/[pattern]*.rs
# Stage 명시 (기본은 stage 2)
./x.py test tests/ui/[category]/[test-name].rs --stage 1
--bless 플래그
# 테스트의 예상 출력을 자동으로 업데이트
./x.py test tests/ui/[category]/[test-name].rs --bless
사용 사례:
- 새 테스트 작성 시:
.stderr
파일 자동 생성 - 에러 메시지 개선 시: 변경된 출력으로 예상값 업데이트
- 진단 메시지 추가 시: 새로운 help/note 메시지 반영
작동 방식:
- 실제 컴파일러 출력을
.stderr
파일로 저장 - 기존
.stderr
파일이 있으면 덮어씀
--force-rerun 플래그
테스트 결과 캐시를 무시하고 항상 재실행함.
./x.py test tests/ui/[category]/[test-name].rs --force-rerun
아래 상황에서 주로 사용:
- 테스트가 "ignored N up-to-date test" 메시지로 스킵될 때
- 캐시 문제가 의심될 때
- 동일 테스트를 연속으로 실행해야 할 때
2. Stage 시스템
2.1 Stage별 설명
-
Stage 0: 미리 컴파일된 부트스트랩 컴파일러
- 다음 단계 컴파일러를 빌드하는 데 사용
- 로컬 변경사항 반영 안됨
- 부트스트래핑 과정에만 사용
-
Stage 1: Stage 0으로 빌드한 컴파일러
- 변경사항이 여기서부터 반영됨
- 일반적인 개발과 테스트 과정에서 사용
-
Stage 2: Stage 1으로 빌드한 컴파일러
- 부트스트래핑 검증용 최종본
- Stage 1과 동일해야 함 (부트스트래핑 성공 확인)
- CI나 PR 제출 전 최종 검증용으로 사용
2.2 Stage별 사용 가이드
Stage 0 (부트스트랩 컴파일러)
# 경고: 테스트에 직접 사용하지 마세요!
./x.py test tests/ui/[test].rs --stage 0 # ❌ 실패할 가능성 높음
초기에 Stage 1 컴파일러를 빌드하는 도구로만 사용하고 이후 쓸 일은 없음.
Stage 1 (개발용 컴파일러)
# 일반적인 개발 워크플로우
./x.py build --stage 1
./x.py test tests/ui/[category]/ --stage 1
빠른 빌드 시간, 즉각적인 피드백이 필요한 일상적인 개발 과정 대부분에서 사용하게 됨.
Stage 2 (검증용 컴파일러)
# PR 제출 전 최종 검증
./x.py build --stage 2
./x.py test tests/ui/[category]/ # 기본값이 stage 2
Stage 1으로 빌드한 컴파일러로 부트스트래핑 일관성을 검증할 때 사용함. PR 올리기 전 최종 확인 용도로 사용하면 좋음.
3. UI 테스트 작성 가이드
3.1 테스트 파일 구조
// tests/ui/[category]/[descriptive-test-name].rs
fn main() {
// 버그를 재현하거나 기능을 테스트하는 코드
let problematic_code = example();
//~^ ERROR [expected error message]
//~| HELP [expected help message]
//~| NOTE [expected note message]
}
파일명 규칙:
issue-12345.rs:
특정 이슈 관련 테스트feature-name.rs:
특정 기능 테스트pattern-description.rs:
특정 패턴이나 케이스 테스트
3.2 에러 주석 문법
주석 기호와 의미
//~^ ERROR : 바로 위 줄에서 에러 예상
//~| HELP : 같은 에러의 도움말 메시지
//~| NOTE : 같은 에러의 노트 메시지
//~^^ ERROR : 2줄 위에서 에러 예상
//~v ERROR : 바로 아래 줄에서 에러 예상
각 주석의 역할:
ERROR:
컴파일 에러 메시지 검증HELP:
수정 제안 메시지 검증NOTE:
추가 설명 메시지 검증WARNING:
경고 메시지 검증
3.3 stderr 파일 생성/업데이트
# 새 테스트 작성 후 stderr 파일 생성
./x.py test tests/ui/[category]/[test-name].rs --bless
# 결과: tests/ui/[category]/[test-name].stderr 파일 자동 생성
stderr 파일의 역할:
- 컴파일러의 정확한 출력을 기록
- 회귀 테스트의 기준점 역할
- 에러 메시지 개선 추적
4. 디버깅 명령어
4.1 직접 컴파일러 실행
기본 실행
# 빌드된 컴파일러로 직접 테스트
./build/[target-triple]/stage1/bin/rustc [test-file].rs
# 예: ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc test.rs
- 테스트 프레임워크 없이 빠른 검증
- 간단한 동작 확인, 에러 메시지 직접 확인
디버그 어설션 활성화
RUSTFLAGS="-C debug-assertions=yes" ./build/[target]/stage1/bin/rustc [file].rs
debug_assert!
매크로 활성화로 내부 불변성 검사- 컴파일러 내부 로직 문제 디버깅 용도로 사용.
백트레이스 활성화
RUST_BACKTRACE=1 ./build/[target]/stage1/bin/rustc [file].rs
RUST_BACKTRACE=full ./build/[target]/stage1/bin/rustc [file].rs # 전체 백트레이스
- 패닉이나 ICE(Internal Compiler Error) 발생 시 스택 추적
- 컴파일러 크래시 원인 파악
5. 작업 흐름 예시
5.1 컴파일러 버그 수정 워크플로우
1단계: 문제 재현
# 이슈 재현을 위한 최소 테스트 케이스 작성.
#
# 만약 이슈에 Minimal reproduction이 있다면
echo '[problematic code]' > test.rs
# 현재 컴파일러 동작 확인
./build/[target]/stage1/bin/rustc test.rs
2단계: 코드 수정
말 그대로 코드 수정 단계. 작은 단위로 수정하고 자주 테스트하는 것이 가장 확실한 방법.
3단계: 빠른 빌드 및 검증
# 수정된 컴포넌트만 빌드 (빠름)
./x.py build --stage 1 compiler/rustc_[component]
# 수정 효과 즉시 확인
./build/[target]/stage1/bin/rustc test.rs
4단계: UI 테스트 작성
# 테스트 파일 생성
cat > tests/ui/[category]/issue-[number].rs << 'EOF'
// 문제를 재현하는 코드
[test code]
//~^ ERROR [expected error]
//~| HELP [expected help]
EOF
# stderr 파일 자동 생성
./x.py test tests/ui/[category]/issue-[number].rs --bless
중요: 회귀 방지를 위한 테스트 필수
5단계: 테스트 실행
# 단일 테스트 실행
./x.py test tests/ui/[category]/issue-[number].rs
# 관련 카테고리 전체 테스트
./x.py test tests/ui/[category]/
확인사항: 새 테스트 통과 + 기존 테스트 무결성
6단계: 최종 검증 (PR 제출 전)
# Stage 2 전체 빌드
./x.py build --stage 2
# 전체 테스트 스위트 실행
./x.py test tests/ui/[category]/
# 포맷 확인 (선택사항)
./x.py fmt --check
최소한의 CI 실패 요소 사전 검증 목적
6. 자주 발생하는 문제와 해결법
6.1 "Stage 0 runs on precompiled compiler" 에러
# ❌ 문제 상황
./x.py test tests/ui/[test].rs --stage 0
# ✅ 해결 방법
./x.py test tests/ui/[test].rs --stage 1
원인: Stage 0은 로컬 변경사항이 반영되지 않은 부트스트랩 컴파일러
해결: Stage 1 이상 사용
6.2 "ignored N up-to-date test" 메시지
# ❌ 문제 상황
./x.py test tests/ui/[test].rs
# 출력: "ignored 1 up-to-date test"
# ✅ 해결 방법
./x.py test tests/ui/[test].rs --force-rerun
원인: 테스트 결과가 캐시되어 있음
해결: --force-rerun
으로 캐시 무시
6.3 테스트 실패 후 stderr 업데이트
# ❌ 문제 상황
# 에러 메시지 변경으로 테스트 실패
# ✅ 해결 방법
./x.py test tests/ui/[test].rs --bless
원인: 컴파일러 출력이 변경되어 예상값과 불일치
해결: --bless
로 새로운 출력을 예상값으로 설정
6.4 빌드 시간 단축 방법
특정 컴포넌트만 빌드
# 느림: 전체 빌드
./x.py build --stage 1
# 빠름: 수정한 컴포넌트만 빌드
./x.py build --stage 1 compiler/rustc_[component]
빌드 병렬화
# CPU 코어 수 지정 (기본값: 자동 감지)
./x.py build --stage 1 -j [num_cores]
시스템 코어 수 - 1
정도가 적절
증분 빌드 활용
# 작은 변경사항은 증분 빌드로 충분
# clean 빌드는 큰 구조 변경 시에만
./x.py clean # 필요시에만 사용
7. 환경 변수
7.1 디버깅용 환경 변수
백트레이스 제어
RUST_BACKTRACE=1 # 기본 백트레이스
RUST_BACKTRACE=full # 전체 백트레이스 (모든 프레임)
- 패닉이나 ICE 발생 시 원인 추적
- 컴파일러 크래시 디버깅시 사용
디버그 어설션
RUSTFLAGS="-C debug-assertions=yes" # debug_assert! 활성화
- 컴파일러 내부 불변성 검사
컴파일러 로깅
RUSTC_LOG=rustc_[component]=debug # 특정 컴포넌트 로그
RUSTC_LOG=debug # 전체 디버그 로그
RUSTC_LOG=info # 정보 수준 로그
출력량이 매우 많을 수 있기 때문에 가능하다면 클로드 코드 같은 언어 모델에 맡기는걸 추천.