🦀

rustcコマンドについてざっくり調べる

2023/01/25に公開

cargoではなくrustcコマンドについて調べる。

背景としては、Rust-for-Linuxのビルドコードを読んでいて、cargoではなくrustcを使っているようなので。cargoはrustcのまあフロントエンドみたいなアレだと理解しているが (例えばcargo build --verboseすると、実際に実行されている長大なオプション群付きのrustcコマンドが表示される。)、rustc自体を直接知りたくなった。またそういった背景なのでRust-for-Linuxのビルドに使われているオプションが多いかも。

調べる方法は主に2つ。

$ rustc -vV
rustc 1.68.0-nightly (1e4f90061 2023-01-11)
binary: rustc
commit-hash: 1e4f90061cc4bc566f99ab21b1f101182b10cf0c
commit-date: 2023-01-11
host: x86_64-unknown-linux-gnu
release: 1.68.0-nightly
LLVM version: 15.0.6

基本

rustcコマンドはinputとしてrustファイルを受け取り、それをコンパイルする。

$ rustc ./hello.rs
$ ./hello
Hello!

rustcコマンドにはcrate rootのファイルを渡すだけで良い。moduleの関係も解決してくれる。例えば

mod foo;

fn main() {
    foo::hello();
}

というファイルもコンパイルできる。(foo module = foo.rsが正しく存在すれば。)

オプション

オプションを調べていく。

--cfg SPEC

#[cfg(...)]cfg!(...)に使うcompilation environmentを設定する。

例えば、

// main.rs

#[cfg(not(hi))]
fn hello() {
    println!("hello");
}

#[cfg(hi)]
fn hello() {
    println!("hi");
}

fn main() {
    hello();

    if cfg!(hi) {
        println!("cfg == hi");
    } else {
        println!("cfg != hi");
    }
}
$ rustc ./src/main.rs && ./main
hello
cfg != hi
$ rustc --cfg hi ./src/main.rs && ./main
hi
cfg == hi

ref: https://doc.rust-lang.org/rust-by-example/attribute/cfg.html

-L [KIND=]PATH

library search pathを追加する。

--crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]

crate typeを指定する。(bin、lib、proc-macro以外にもたくさんあるなー。)

--crate-name NAME

crateの名前を指定する。

--emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]

出力するファイルのtypeを指定する。

例えば、

$ rustc --emit asm,llvm-ir ./main.rs

とかやるとassemblyやLLVM IRが見れて面白い。

--extern NAME[=PATH]

外部libraryの場所を指定する。(直接の依存だけ指定できる。依存の依存といった、間接的な依存については-Lオプションを使う。)

具体的には列挙された外部libraryの名前はextern preludeに追加されるみたい。preludeについては以前まとめた記事がある。

Rustの名前解決の仕組み: Prelude

なおこのオプションについてはrustc --help -vの情報が少なかったので次のリンクを参照した。

The rustc book: -extern: specify where an external library is located

--sysroot PATH

sysrootのpathを指定する。

sysrootとは

cargo buildすると通常はtarget/debug/depsにビルドされたものが格納される。しかしここにはstd libなどは含まれない。それではstdproc_macroがどこからくるかというとsysrootである。

実行時にロードする必要があるあらゆるものがsysrootに含まれる。例えば:

  • libstd
  • libtest
  • libproc_macro
  • libLLVM.so

次のコマンドでsysrootディレクトリのpathが表示される。

$ rustc --print sysroot
/home/ohno/.rustup/toolchains/1.62.0-x86_64-unknown-linux-gnu

sysrootについては次が詳しいのではないかと思う。

rustc-dev-guide: What is a sysroot?

参照

Discussion