Cpp2Rust: C++를 안전한 Rust로 자동 번역

27 minutes ago 1
  • Cpp2Rust는 clang AST 기반의 구문 주도 번역기로, C++ 입력을 자동으로 완전히 안전한 Rust 코드로 변환함
  • 번역 과정은 clang으로 C++ 파일을 파싱해 AST를 만들고, AST를 순회하며 Rust 코드를 문자열로 생성한 뒤 rustfmt로 단일 .rs 파일을 출력함
  • 기본값은 참조 카운팅 모델이며, 디버깅과 성능 비교를 위해 --model=unsafe로 unsafe Rust 생성도 가능함
  • 생성된 코드는 libcc2rs 런타임 라이브러리에 의존하며, C 포인터는 null, 산술, 별칭을 모델링하는 Ptr<T>로 변환됨
  • 전체 프로그램 번역에는 compile_commands.json이 필요하며, CMake 프로젝트는 CMAKE_EXPORT_COMPILE_COMMANDS=ON 플래그로 생성할 수 있음

C++에서 안전한 Rust로 자동 변환

  • Cpp2Rust는 C++를 완전히 안전한 Rust로 자동 번역하는 도구임
  • clang의 AST를 기반으로 하는 구문 주도 번역기
  • 번역 알고리듬은 PLDI 2026에 게재된 논문 Cpp2Rust: Automatic Translation of C++ to Safe Rust에 설명돼 있음

번역 파이프라인

  • 입력 C++ 파일을 먼저 clang으로 파싱해 AST를 생성함
  • 이후 AST를 순회하며 Rust 코드를 문자열로 출력함
  • 필요한 경우 libcc2rs 런타임 라이브러리 호출을 삽입함
    • 예시는 raw pointer semantics 처리임
  • 마지막으로 rustfmt를 사용해 Rust 코드를 단일 .rs 파일로 정리함

안전한 Rust와 unsafe Rust 모델

  • 기본 동작은 참조 카운팅 모델을 사용하며, 완전히 안전한 Rust 출력을 생성함
  • unsafe Rust 생성기도 제공됨
    • 명령행 인자는 --model=unsafe
    • 용도는 디버깅과 성능 비교임

libcc2rs 런타임 라이브러리

  • 생성된 코드는 번역 과정을 단순화하기 위해 설계된 런타임 라이브러리에 의존함
  • C 포인터는 libcc2rs가 제공하는 Ptr<T> 타입으로 변환됨
  • Ptr<T>는 C 포인터 의미를 모델링함
    • null
    • 포인터 산술
    • 별칭
  • Rust의 borrow checker는 검사된 런타임 연산을 통해 만족함

빌드와 실행 흐름

  • Ubuntu 의존성 설치 예시는 libclang-22-dev, clang++-22, ninja-build, cmake, ruff를 포함함
  • 빌드는 cmake -GNinja .., ninja, ninja check 순서로 진행함
  • 단일 파일 번역 명령은 다음 형태임
./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs
  • unsafe Rust를 생성하려면 다음처럼 실행함
./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs --model=unsafe

최소 예제와 전체 프로그램 번역

  • hello.cpp의 printf("hello world\n") 예제는 Rust의 println!("hello world")를 포함한 코드로 변환됨
  • 변환된 hello.rs는 다음처럼 컴파일하고 실행함
rustc hello.rs -L ../libcc2rs/target/debug ./hello
  • 전체 프로그램 번역에는 compile_commands.json이 필요함
  • CMake에서는 다음 플래그로 compile_commands.json을 생성함
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
  • 전체 프로그램 번역 명령은 다음 형태임
./build/cpp2rust/cpp2rust --dir=<dir> -o <output>.rs
  • <dir>는 compile_commands.json이 들어 있는 디렉터리여야 함

테스트 명령

  • 전체 테스트는 ninja check로 실행함
  • 단위 테스트는 ninja check-unit로 실행함
  • libcc2rs 단위 테스트는 ninja check-libcc2rs로 실행함
  • libcc2rs-macros 단위 테스트는 ninja check-libcc2rs-macros로 실행함
  • 의도적으로 변경한 뒤 예상 출력을 재생성하려면 REPLACE_EXPECTED=1 ninja check-unit을 사용함
Read Entire Article