Rust 1.99.1, FFI bool과 링크 오류 3가지를 고쳤다

소스에서 wcslen을 부른 적이 없는데, 새 Rust 컴파일러로 빌드하자 그 함수를 찾지 못한다는 링크 오류가 난다. 1.99.1로 올리면 이 오류도 사라질까?

Rust 1.99.1, FFI bool과 링크 오류 3가지를 고쳤다
세 줄 요약
  • 10월 15일 나온 Rust 1.99.1은 이전 릴리스에서 생긴 회귀 오류 3건을 수정했다.
  • x86_64 FFI의 bool 반환, wcslen 링크 실패, macOS rust-lld의 라이브러리 로드 문제가 대상이다.
  • 툴체인을 갱신한 뒤 실제 프로젝트 디렉터리에서 선택된 버전을 확인해야 한다.

빌드가 깨졌다고 항상 의존성이나 애플리케이션 코드를 고쳐야 하는 것은 아니다. Rust 1.99.1의 수정 대상에는 컴파일러가 만든 반환값과 링커의 동작이 포함된다. C와 Rust를 연결하거나 UEFI·macOS 빌드를 관리한다면, 실패한 경로가 이번 수정 조건에 해당하는지 먼저 볼 필요가 있다.

세 오류는 영향을 받는 조건부터 다르다

증상관련 조건1.99.1의 수정
FFI bool 반환의 원시 값이 0·1을 벗어난다x86_64에서 Rust 함수를 FFI로 호출한다ABI에 필요한 zero-extension을 복원한다.
wcslen 심볼을 찾지 못한다최적화가 해당 호출을 만들지만 함수가 없는 타깃이다compiler-builtins에 대체 구현을 제공한다.
rust-lld가 libLLVM.dylib를 못 읽는다macOS에서 rustup proxy 없이 컴파일러를 호출한다라이브러리 디렉터리를 찾는 rpath를 추가한다.

Rust 릴리스 팀의 발표는 세 항목을 이전 버전에서 발생한 회귀 수정으로 분류한다. 각각의 증상과 호출 조건을 따로 봐야 한다.

bool 문법이 아니라 FFI 반환 규약의 문제다

문제가 된 것은 x86_64에서 Rust 함수가 FFI 경계를 넘어 bool을 돌려줄 때다. 반환 레지스터의 1~7번 비트가 정해지지 않은 채 남아, 호출자가 0이나 1 이외의 원시 값을 관찰할 수 있었다. 수정은 반환형에 필요한 zero-extension을 다시 표시해 호출 규약에 맞추는 것이다.

공식 저장소의 재현 보고는 x86_64 Linux에서 gcc와 clang 모두로 문제가 나타났다고 설명한다. 따라서 이 항목은 ‘Rust의 모든 참·거짓 연산이 잘못된다’는 뜻이 아니다. 언어 사이에서 함수를 호출하는 경계를 점검해야 하는 문제다.

wcslen 누락과 macOS 라이브러리 경로는 별개다

wcslen 오류는 개발자가 소스에 그 함수를 직접 적지 않아도 생길 수 있다. LLVM의 관련 최적화가 함수 호출을 만들기 때문이다. 타깃 환경에 그 구현이 없으면 링크 단계에서 실패한다. Rust 발표는 특히 std를 쓰는 UEFI 프로젝트에 영향이 있었고, 유사한 사용자 코드 패턴에서도 재현됐다고 설명한다.

wcslen 이슈에는 UEFI 예제와 이전 버전에서는 성공했다는 보고가 남아 있다. 해결 방향은 프로그램에 같은 이름의 함수를 임의로 덧붙이는 것이 아니라, 수정된 툴체인이 제공하는 대체 구현을 사용하는 것이다.

macOS 오류는 실행할 링커가 자신의 라이브러리를 찾는 단계에서 발생했다. 재현 보고는 Apple silicon macOS에서 툴체인 내부의 rustc를 직접 실행해 WebAssembly 라이브러리를 링크할 때 실패하고, rustup proxy를 통하면 성공하는 조건을 제시한다. 모든 Mac의 일반적인 Rust 빌드가 같은 방식으로 실패했다는 보고는 아니다.

stable을 갱신해도 프로젝트의 고정 버전은 남는다

rustup으로 설치했다면 공식 발표가 제시한 stable 갱신 명령은 다음과 같다.

rustup update stable

그다음에는 실제 빌드하는 디렉터리에서 rustc --version으로 선택된 버전을 확인하는 편이 좋다. rustup의 선택 규칙에는 명령행의 툴체인 지정, RUSTUP_TOOLCHAIN, 디렉터리 override, rust-toolchain.toml, 기본 툴체인이 관여한다.

예를 들어 프로젝트 파일에 이전 버전이 고정돼 있다면 stable을 갱신했다는 사실만으로 그 프로젝트의 컴파일러가 바뀌었다고 판단할 수 없다. CI가 버전을 지정하는 경우도 해당 설정을 함께 봐야 한다. 수정된 툴체인을 선택한 뒤에는 처음 실패했던 FFI 호출이나 링크 작업을 같은 조건으로 다시 확인하는 것이 적용 여부를 판단하는 방법이다.

이번 업데이트에서 먼저 할 일은 자신의 오류 메시지, 타깃, 컴파일러 호출 방식을 이번 수정 조건과 대조하는 것이다. 이를 대조하면 소스 코드를 고쳐야 할 문제와 툴체인 수정으로 해결할 문제를 구분하기 쉬워진다.

자주 묻는 질문

wcslen을 직접 사용하지 않아도 관계있는가?

그렇다. 최적화 과정에서 호출이 생길 수 있어 소스의 함수 이름 검색만으로 영향 여부를 판단할 수 없다.

macOS에서 모든 Rust 빌드가 실패하는 문제인가?

아니다. 발표가 설명한 조건은 rustup proxy 없이 컴파일러를 호출했을 때 rust-lld가 라이브러리를 찾지 못하는 경우다.

stable을 업데이트하면 고정한 버전도 바뀌는가?

프로젝트의 버전 지정은 별도로 확인해야 한다. 기본 stable보다 우선하는 선택 설정이 있을 수 있다.