[Rust] build.rs를 통한 빌드 스크립트 구성

Rust로 프로그램을 작성하다보면, 가끔은 C/C++ 기반의 방대한 환경을 활용해야 할 일이 있다.
이건 그런 상황에서만 주로 사용하는 조금은 deep한 기능이다.

Rust에서 C로 작성된 코드를 갖다쓴다고 하면, C 코드를 직접 동적 라이브러리나 정적 라이브러리로 말아서, 직접 링크한 다음에 배포할 수도 있을 것이다.

하지만 그러면 크로스컴파일에 제동이 좀 걸린다. 제대로 빌드와 배포를 수행하려면 그냥 그 머신에서 바로바로 C 코드를 컴파일하고 Rust도 컴파일해서 쭉 뽑는게 좋은데... build script는 딱 그걸 위한 보조기능이다.

아래와 같이 프로젝트 내에 C 소스코드가 포함되어있다고 가정하겠다.

이걸 build script를 써서 연동해보겠다.




기본설정

우선 cargo.toml에서 build를 build.rs로 지정해준다.
그러면 저게 build script 진입점이 될 것이다.

build-dependencies에는 c 컴파일용 cc 크레이트를 추가했다.
딱 build script 실행 컨텍스트 상에서만 적용되는 종속성 설정인데, c 컴파일 외에도 이것저것 더 할게 있다면 더 추가하면 된다.




build script 작성

build script를 작성하는 법은 일반적인 main.rs를 작성하는 법과 크게 다르지 않다.

fn main() {
    // hello.c 파일이 변경될때마다 재빌드 하도록 한다.
    println!("cargo:rerun-if-changed=src/hello.c");

    // c 컴파일러로 컴파일해서 정적 링크
    cc::Build::new().file("src/hello.c").compile("hello");
}

다만 위와 같이 표준 출력을 통해 cargo에 특정 옵션을 전달할 수 있다는 점이 다르다.
이러면 cc로 컴파일을 한 다음에 자동으로 정적 링킹을 해줄 것이다.

저래놓고 cargo build나 cargo run으로 컴파일을 한번 돌려보면

build 디렉터리에 결과물들이 적당히 떨어진다.


저기서 발생한 표준출력도 텍스트파일로 저장되니, 디버깅할일이 있다면 까보면 된다.




갖다쓰기

방금 cc로 컴파일한 결과물을 갖다써보자.

방법은 그다지 어려울건 없다.
자동으로 링크를 해주기 때문에 컨텍스트에 자동으로 들어오고, extern 구문을 통해 프로토타입만 작성해준다.

이것도 원본 함수가 Rust 함수는 아니기 때문에 호출 자체는 unsafe다.

그러면

돌기는 잘 돌 것이다.

이런식으로 쓰면 된다.


참조
https://doc.rust-lang.org/cargo/reference/build-scripts.html
https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/cargo/reference/build-scripts.html