Rust 크로스 컴파일

개요

시작은 매우 빠른 속도를 가지며 매일 하는 C언어를 대체할 언어를 찾는 것이었습니다.

러스트라는 언어의 존재를 알게 된 지 1년은 조금 넘었지만

그동안 딱히 무엇을 위해 다루어야 할지 흥미가 없어 건드리지 않은 언어.

회사프로젝트에 구겨넣기를 결심하고 크로스 컴파일을 시도했습니다.


RUST

러스트의 장점은 조금만 검색해 보면 이것 저것 나옵니다.

하지만 제가 러스트를 하고자 했던 이유는 오로지 새로운 것에 대한 호기심입니다.

지금 하는 언어들도 제대로 못 하는 주제에 무슨 새로운 언어를 배우나 할 수 있겠지만

그게 무슨 상관입니까, 내가 재밌는 걸 하는 게 중요한 거지.


Hello World!

새로운 언어를 배우면서 가장 기초적인 Hello World!를 출력하는 걸 언제 마지막으로 했을까요?

적어도 년(Year) 단위가 넘었을 것입니다.

이번 기회에 새로운 마음가짐으로 간단한 출력하는 프로그램을 만들었습니다.

물론, 이곳에 적힌 것을 따라쳤을 뿐입니다.

1
2
3
fn main() {
println!("Hello, world!");
}

오랜만에 느끼는 감동입니다.


Cross Compile

첫 번째 개요에서 말했듯, 저는 러스트를 회사 프로젝트에 도입할 생각이었습니다.

그러니 제 컴퓨터가 아니라, 장비에서 실행될 수 있도록 크로스 컴파일이 필요합니다.

제대로 된 공부조차 하지 않고 무작정 몸통박치기부터 날리느라 머리가 다 깨졌지만 결과적으로 성공했으니 웃을 수 있습니다.

네이버 웹툰 <에이머>

저는 Cargo를 이용하여 컴파일했지만 사실 이건 rustc를 쓰는 것입니다.

자세한 내용은 이곳에 있습니다.

정말 간단하게 크로스 컴파일용 gcc를 설정으로 저장해 주면 끝납니다.

근데 멍청한 저는 이걸 성공하기까지 1시간 조금 넘게 걸렸을 뿐입니다.

1
2
3
4
# .config/cargo

[target.aarch64-unknown-linux-gnu]
linker = "실제 gcc 위치"

원하는 장비에서 실행되는 걸 확인했습니다.


Rust와 GCC?

아니, 일단 빌드된 것은 좋지만 갑자기 gcc는 왜 참조시켜야 하는 걸까요?

러스트는 사실 gcc로 이루어진 게 아닐까요?

사실은 C언어 이면서 다른 언어인척 속이는 세계의 몰래카메라일 가능성을 놓칠 수 없습니다.

그래서 저는 카메라를 찾기 위해 이곳 저곳을 쑤시고 다녔지만 결과는

정확하게 이거다!라고 말할 수 있는 건 못 찾았지만

대충 이건가…? 라고 찍을법한 내용은 찾았습니다.

일단 먼저 위에 썼던 Cargo의 설명 중 아래 내용을 봅시다.

Most Rust programmers don’t invoke rustc directly, but instead do it through Cargo.

대부분의 프로그래머들은 rustc를 직접적으로 호출하지 않고 Cargo를 거쳐 호출합니다.

결국 Cargo는 rustc명령어를 호출한다는 얘기입니다.

그 중 인자로 넘어간 것에서, 아래 내용을 볼 수 있었습니다.

-C linker=내가 넘긴 gcc 위치

위 주소로 들어가보면 linker로 gcc와 이것 저것을 설정할 수 있다고 합니다.

그러면, linker로 넘기는 옵션에 대해 더 자세한 설명은 이곳을 봐야합니다.

슬슬 머리가 아파오기 시작합니다. 하지만 걱정하지 마세요! 이후 더 아프니까요!

제가 일부 알아먹은 소리에 대해 살펴보면, -C 옵션은 codegen옵션입니다.

코드를 어떻게 생성(generate)할지 옵션을 주는 것이죠.

rustc는 단형화 과정을 거치는데, 이 때 생성될 코드들을 codegen 단위로 작게 분리합니다.

이 분리된 덩어리들은 사실 LLVM의 독립된 인스턴스가 생성합니다.

이후 링커가 분리된 덩어리들을 하나의 바이너리로 결합합니다.

이 때 여기서 LLVM과 GCC의 관계가 있습니다.

https://llvm.org/docs/GettingStarted.html#hardware

GCC 컴파일러 위에서도 LLVM이 돌아간다는 얘기입니다.

그러니 정확하게 얘기할 순 없지만 이 정보들을 가지고 보면,

대충 그렇지 않을까? 하는 추론정도는 할 수 있습니다.


Makefile

우리 회사는 빌드할 때 Makefile을 사용하기 때문에

이 명령어로도 빌드가 가능해야 합니다.

물론 그냥 빌드시 Cargo 명령어를 입력하도록 할 수 있지만

정확하게 어떤 옵션을 넘길건지 명시하는 게 좋습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
TARGET=hello.rs
EDITION=2018
ERROR_FORMAT=json
NAME=hello
LINKER=GCC 위치

all: build

build:
rustc --crate-name $(NAME) --edition=$(EDITION) $(TARGET) -C linker=$(LINKER) --target=aarch64-unknown-linux-gnu

clean:
rm -f $(NAME)

저는 정상적으로 빌드되는 걸 확인했습니다.

감사합니다.

작성자: raravel
주소: https://raravel.dev/20210407-1602/
저작권 고지: 이 블로그의 모든 기사는 별도로 명시하지 않는 한 CC BY-NC-SA 4.0 에 따라 라이선스가 부여됩니다.