Rust: LLDとのリンク

作成日 2017年02月17日  ·  94コメント  ·  ソース: rust-lang/rust

LLVM 4.0はLLDを有効にして出荷されますが、AFAIKはまだすべてのプラットフォームで本番環境に対応しているわけではありません。 とにかくAVR / emscriptenの問題を解決するためにLLVMのアップグレードが間もなく計画されていると思います。それをサポートするために何をする必要があるか、コンパイラのパフォーマンス/バイナリサイズ/ランタイムのパフォーマンスにどのように影響するかを判断するときが来ました。通常のリンカー、およびデフォルトでそれを有効にする可能性のあるプラットフォーム。

https://github.com/rust-lang/rust/issues/39915#issuecomment -618726211に要約されている現在のステータス(2020-04-24)

A-linkage C-feature-request I-compiletime T-compiler

最も参考になるコメント

このバグは少し混乱しているので、これを前進させたい人々のために、現在の状況の簡単な要約で私のベストショットを示します。

lldとは

llvmプロジェクトの一部であるリンカー。これは、次の2つの理由で望ましいものです。

  • クロスコンパイルは非常にフレンドリーです(したがって、埋め込みターゲットに重点が置かれています)
  • 非常に高速で(Goldの半分の時間で実行されることがよくあります。大きなプロジェクト(rustc、servoなど)ではリンクに数分かかる場合があります。リンクは、増分ビルドを使用したコンパイルの大部分を占める可能性があるため、このランタイムを半分にすることは大したことです。)

Rustが今日lldで行うこと

  • Rustは現在、ほとんどのプラットフォームで独自のlldのコピーをrust-lldと呼ばれるバイナリとして出荷しています。
  • rust-lldは、多くのベアメタルターゲットでデフォルトで使用されます
  • rust-lldはデフォルトでwasmに使用されます
  • (?)「-Clinker-flavor」を使用して、rust-lldの使用を明示的に要求できます(ベアメタル以外のプラットフォームでこれが正確に何をするかについてはあいまいです。以下を参照してください)

より多くの場所(つまり、デスクトップlinux / mac / windows)でrust-lldを使用する際の問題

  • lldのmacOS(Mach-O)バックエンドが壊れて放棄された

    • ゼロからの書き直しが始まりましたが、まだ初期の段階です

  • linux / unixプラットフォームでは、ld / lldを直接呼び出すことは想定されていません。 システムcコンパイラ(つまりgcc)を介してリンカを呼び出すことになっています。このコンパイラの責任は、crt1.oなどのシステムシンボルを検出し、それらをldに提供することです。 これは、rust-lldを「ただ」使用することはできないことを意味します。 gcc / clang / whateverにフィードする必要があります。 (このシステムシンボルロジックを自分で実装したくありません)

    • 一般に、リンカをパスとして指定することはできません。リンカを「ld」としてCコンパイラの検索パスに挿入する必要があります。

    • または、同じことを実行できますが、「ld.lld」として挿入し、「-fuse-ld = lld」を渡します。



      • これは重要かもしれません、どうやらlldはそれが「ld」または「ld.lld」として実行されているかどうかのclangスタイルのバイナリ名検出を行います(調査が必要です)


      • 残念ながら、-fuse-ld = lldはGCC9の一部にすぎないため、使用するには機能/バージョンの検出が必要になる場合があります(clangには長い間使用されてきました)



  • windows-msvcは明らかに良好な状態であり、バックエンドでrust-lldを使用するためのサポートが制限されているようですが、ここで何をする必要があるのか​​わかりません。
  • windows-mingwはlinux / unixとほぼ同じ場所にあるようですが、古いGCCを入手する傾向があり、pseudo-windows-linuxは十分にテストされた構成ではないため、状況は少し不安定ですか?

また、一般的に、lldは新しいものであり、ほとんどのOSのデフォルトではありません。これをより多くの場所で使用し始めると、ランダムな互換性のあるバグがほぼ確実に発生します。

2つのプラットフォームでデフォルトで(rust-)lldを使用することに焦点を当てた取り組みのために、2つのメタバグを提出しました。

  • #71515-x64 Ubuntu 20.04 LTS(およびより広くすべてのx64 ELFプラットフォーム)
  • #71520-x64msvcウィンドウ

全てのコメント94件

#36120のPoCも参照してください。

LLDはMinGWターゲットの非常に良い候補である可能性があります。これは、現在リンカーをバンドルしており、MinGWのリンカーにはASLRの欠如からbigobjサポートの欠如までさまざまな問題があるためです。 ネイティブターゲティング(rustupのmingwパッケージが現在制限されている)だけでなく、クロスコンパイル時に必要なmingwライブラリも何とか持っていくことができれば、Linuxからのrustクロスコンパイルがすぐに可能になります。これは大きな改善になります。ディストリビューションはほとんどの場合互換性のないMinGWを使用するため、人々がディストリビューションからMinGWを取得し、問題が発生するという既存の状況を超えています。

LLDは、いくつかの理由により、MSVCターゲットをネイティブにターゲットにするのに適した候補ではありません。主な理由は、debuginfoのサポートがないことです。 MSVCターゲットへのクロスコンパイルには、再配布できないライブラリが必要であるため、そのままではサポートできません。

LLVM 4.0にアップグレードする際の追跡の問題は、 https://github.com/rust-lang/rust/issues/37609です。

記録のために、lldはSolarisターゲットに対して確実に準備ができていません。 しかし、Solarisでは、ネイティブのldの代わりにlldを使用することに気付いている理由はありません。 リンクにgccを使用する代わりに、SolarisでSolarisldを錆びさせるには何が必要かをすでに検討しました。

Solarisではなく、Solaris上で構築する際に使用LLDに@binarycrusader一つの理由です。

PR rust-lang / rust#40018は、 -Z linker-flavorフラグをrustcに追加して、LLDをリンカーとして使用できるようにします。 そのPRは、LLDをrustcに埋め込んでいませんが、ツリー外での実験を可能にします。

@binarycrusader ^これは、gccの代わりにSolarisのldを直接使用する実験に役立つ可能性があります。

これで、LLVM4.0で実行されているように見えます。 @japaric 、これは、リンカーフレーバーフラグを使用して、LLDをシステムリンカーと比較および対比できるようになったことを意味しますか?

@ bstrie #40018は数週間前に着陸しました。 その着陸以来、 -Z linker-flavor=ld -C linker=ld.lldを使用して外部LLDバイナリをリンカーとして使用できるようになりました。 gccとは異なり、LLDはシステムライブラリがどこにあるかを認識しないため、システムライブラリにリンクする場合は、 -C link-args='-L ...'を使用してライブラリ検索パスをリンカーに渡す必要があることに注意してください。

LLVM 4.0が役立つのは、LLDをrustcにマージすることです。 この変更により、MUSLバイナリやベアメタルプログラムのリンクなど、一部のシナリオでは外部リンカーが不要になります。 ほとんどのターゲットは、前述のライブラリ検索パスの問題に遭遇するシステムライブラリへのリンクを必要とするため、いくつかのシナリオを言います。 これらのターゲットの場合、LLDはそのままでは機能しません。 その問題をどこでどのように解決するかは明確ではなく、その解決策がなければ、最も重要な(ティア1)ターゲットをLLDに切り替えることはできません。これにより、そもそもLLDをrustcに埋め込む魅力が低下します。

@japaric (sysroot-relativeライブラリ)検索パスや-lc -lpthread crt0.oなどを直接rustcに埋め込むことに反対する議論は何ですか? 結局のところ、ツールチェーンの一部のコンポーネントは、従うべきプラットフォームの標準がないため、それらを埋め込む必要があり、binutilsはこの知識の優れた黄金の情報源ではありません。

私が考えることができる唯一の欠点は、同じトリプルが異なるフレーバーのシステムで異なる検索パスを持つという状況です(これは、Linux / glibcトリプル専用であり、multilibを備えたプラットフォームでは特に悪いでしょう)。 その場合、clangはOS名をスヌープし、OS固有の規則をハードコードすると思います。これは悪いように見えますが、Linuxで実行される(システムリンカーを必要としない)単一のバイナリを配布する場合はおそらく避けられません。

@ retep998数ヶ月前にlldを簡単に調べました。 Linuxから.exeをクロスコンパイル(クロスリンク?)できませんでした。 lldはプラットフォームのネイティブフォーマットのみをサポートしているようです。

うまくいけば、私は間違っています。

これをパフォーマンスバグとしてタグ付けします。LLDのベンチマークによると、GNU ldよりも10倍優れているようであり、リンクパフォーマンスは現在コンパイラ速度の大きな要素です。

えー、ベンチマークをリンクするのを忘れました: https

(LLVM 5.0がリリースされたばかりなので、今日関連しています。)

LLDとのリンクは、bfdやgoldよりもはるかに高速ですが、LLDを使用すると全体的なパフォーマンスが大幅に向上するとは思えません。 それでも、この問題は重要であり、優先すべきだと思います。

@tpimh I-slowタグが実行時のパフォーマンスのバグを表すのか、コンパイル時のパフォーマンスのバグを表すのか、実際には完全には

@bstrie I-slowは実行時のパフォーマンスが悪いため、I-compiletimeは前回チェックしたときのコンパイラパフォーマンス用です

LinuxからWindowsへのクロスリンクというあいまいなトピックに関心のある人には朗報です。 lldでは不可能だと前に言いましたが、それはlldのldフレーバーにのみ当てはまります。 lldのlink.exeフレーバー(lld-link)が可能です。

特にRustの場合、コードをいくつか変更するだけで、今日これを行うことができます。

  1. mingw-w64のCRTの非常に小さなサブセットを.oオブジェクトファイルにコンパイルする必要があります。 つまり、いくつかのスレッドローカルストレージの初期化。 chkstkも必要です。

  2. lldはMinGWの通常のインポートライブラリが好きではありません。 代わりに、lld-linkまたはllvm-dlltoolを使用して、.defファイルを自分で.libファイルにビルドする必要があります。

  3. lldを変更して、IMPORT_NAME_NOPREFIXを次のように扱います。
    IMPORT_NAME_UNDECORATE、ステップ2でも.libsは完全ではないため

  4. Rustのseh.rsを変更して、TYPE_INFO_VTABLEをptr :: null()に置き換えます。 シンボル??_7type_info@@6B@がMinGWで定義されていないため、必須です。 次に、Rustをビルドしてインストールします。

  5. .cargo / configを使用して、リンカーとしてカスタムラッパースクリプトを指定します。

  6. ラッパーリンカスクリプトは、主に渡されたパラメータを使用してlld-linkを呼び出す必要があります。 ただし、いくつかの調整を行う必要があります。

    a)ファイル名の大文字と小文字を修正します。たとえばAdvAPI32.Libをadvapi32.libに変更します。

    b)Rustが生成する.defファイルを変更して、シンボルの前に追加のアンダースコアを付けます

    c)エントリポイント(/ entry)をオーバーライドします。 名前マングリングの問題が原因である可能性があります。

    d)ステップ1でコンパイルしたmingw-crtオブジェクトファイルを追加します

  7. xargo --target = i686-pc-windows-msvcを使用してRustプロジェクトをビルドします

上記の手順を実行すると、Rustコードをクロスコンパイルできます。 RustのSEHベースの巻き戻しを使用して、パニックを起こしたり、パニックをキャッチしたりすることもできます。

@iainnicol msvcターゲットをMinGWビットと混合しているため、これらの奇妙な変更をすべて行う必要があります。 既存のVC ++インストールからライブラリをコピーするだけの場合は、これらすべての変更やMinGWビットを使用せずに、通常はlld-linkを使用できます。

しかし、既存のVC ++インストールを使用したくありませ

スタンドアロンのビルドツールは、それがすでに言及しているものでない限り、はるかに軽量です。その場合、MinGWが実際にMSVCと互換性があるように、改善または再作成するためにいくつかの作業を行う必要があります。

スタンドアロンのビルドツールははるかに軽量です

マイクロソフトがそれらを配布していることに気づいていません。 それらにリンクしてもらえますか? 実際に実行せずにインストールアーカイブを抽出する合理的な方法はありますか?つまり、msiまたは同様のものですか?

ここにあります: http

2015バージョンと2017バージョンはどちらもexeですが、2017 exeを説得して、次の方法で必要なものを提供できる場合があります: https

本当にWindowsでこれを正しく実行したい場合は、まずhttps://github.com/rust-lang/rust/issues/30027を使用して、WindowsSDKまたはMinGWのインポートライブラリの必要性を排除する必要があります。 次に、CRTビットを独自の純粋なRustバージョン(数学/メモリ関数、エントリポイント、Rustが必要とする他のいくつかのランタイムビット)に置き換えるだけで、完全に自己完結型のRustツールチェーンを使用できます。 Windowsバイナリを作成してください! これの欠点は、MinGWまたはVC ++からの適切なCRTでのリンクに非常に大きく依存しているため、C / C ++コードを静的にリンクできないことです。 もちろん、Rustの要点は、Rustのすべてを書き直すことなので、これはそれほど問題にはなりません。

LinuxからWindowsへのクロスリンクというあいまいなトピックに関心のある人には朗報です。 lldでは不可能だと前に言いましたが、それはlldのldフレーバーにのみ当てはまります。 lldのlink.exeフレーバー(lld-link)が可能です。

ldフレーバーでも可能になるはずです: https

新しいlldのMinGW互換ドライバーは、lld-linkリンカーのラッパーです。 Unix風のオプションをWindows風のオプションに内部的に変換してから、lld-linkのエントリポイントを呼び出します。 MinGW用のMakefileがない限り、(ラッパードライバーが不完全で、使用する準備ができていないことを除いて)それを使用したいかどうかはわかりません。

クロスコンパイルについて、(おそらくばかげた)質問があります。 Windowsでは、すべてのdllimportされたシンボルには、インポート元のDLL名があります。 MSVCライブラリファイルがない場合、dllimportされたシンボルがどのファイルからインポートされたかをどのようにして知ることができますか?

クロスコンパイルについて、(おそらくばかげた)質問があります。 Windowsでは、すべてのdllimportされたシンボルには、インポート元のDLL名があります。 MSVCライブラリファイルがない場合、dllimportされたシンボルがどのファイルからインポートされたかをどのようにして知ることができますか?

インポートライブラリがない場合は、インポートライブラリを作成するか、 https://github.com/rust-lang/rust/issues/30027を実装して、 winapiがすべてのハードを実行できるようにする必要があります。各シンボルがどのDLLからのものであるかを指定する作業と、通常のようなざわめき。 何かが、それはあなたのコード内でインポートライブラリや注釈あるかどうか、のDLL内のシンボル/序へのリンク時のシンボルのマッピングを指定する必要があります。

https://reviews.llvm.org/rL311734をプルした後、macOSでlldを使用してrustcをブートストラップすることがほぼ可能になりました。 dylibメタデータに問題があるようですが、まだ調査する必要があります。

https://github.com/rust-lang/rust/pull/36120を復活させるブランチがありhttps://github.com/rust-lang/rust/issues/43370でブロックされてい

@tamird :#43370は終了しました。

LLDはhttps://github.com/rust-lang/rust/pull/48125に追加され、現在、ティア1プラットフォーム(mac、linux、windows)で出荷されてい-Z linker-flavorを使用してテストできますが、デフォルトではほとんどのプラットフォームで機能する可能性はほとんどありません。 ただし、MSVCではデフォルトで機能します。 例えば:

$ RUSTFLAGS='-Z linker-flavor=lld-link' cargo build

Cargo自身のリンク時間を2.5秒から1.5秒に短縮しました。これは素晴らしい改善です。

@alexcrichton 、次のステップは何ですか? 理想的には、すべてのプラットフォームでデフォルトでLLDが機能するようにし(これにかかる作業量についてはわかりません)、コンパイル時/実行時ベンチマークを実行して、LLDをデフォルトにすることが理にかなっているかどうかを確認します。任意のプラットフォーム。 特にインクリメンタルコンパイルでは、リンクのパフォーマンスがこれまで以上に重要になります。

特にインクリメンタルコンパイルでは、リンクのパフォーマンスがこれまで以上に重要になります。

残念なことに、リンクのパフォーマンスは、それをサポートするプラットフォームでインクリメンタルリンクを有効にするなどのことを行うにはまだ十分に重要ではありません。 https://github.com/rust-lang/rust/issues/37543

@bstrieこれらが次のステップであり、他のプラットフォームで機能するようになると思います:)

それが何を伴うのかはわかりませんが、すでにMSVCで動作しているので、MinGW / Linuxで動作することにはほど遠いと思います。また、OSXにもかなり近づいています。 クロスアーキテクチャのサポートについても、よくわかりません。 近い将来、wasmプラットフォーム以外で「安定化」することはないと思います。

@alexcrichton 「安定化」をどのように指定しますか? 錆がサポートする他の主要なプラットフォームのlldとのリンクを「安定化」できないのはなぜですか? (例:Linux for macOSから実行可能ファイルをクロスコンパイルする)。

現時点では、クロスコンパイルするのは非常に面倒です。たとえば、LinuxからmacOS(x86_64-apple-darwin)の実行可能ファイルをクロスコンパイルするために必要な作業には、xcodeSDKの取得やツールチェーン全体の構築などの簡単な手順が必要です。

@cynecx良い質問です! あまり考えていないもの。 ただし、LLDを別のプラットフォームに追加したからといって、事実上安定化させたくないと思います。LLDを正しく公開するには、時間と労力が必要です。

たとえば、LinuxからmacOS(x86_64-apple-darwin)の実行可能ファイルをクロスコンパイルするために必要な作業には、xcodeSDKの取得やツールチェーン全体の構築などの重要な手順が必要です。

LLDはここではあまり役に立ちません。再配布できないヘッダーがあるため、Xcode SDKが必要です(構築するものによっては、他のSDKツールも必要になります)。

LLDが毎晩組み込まれていることの本当に素晴らしい点は、純粋なRustプロジェクトをWindowsからLinuxにRUSTFLAGS='-Z linker-flavor=ld.lld' cargo build --target x86_64-unknown-linux-musl簡単にクロスコンパイルできることです。 Rustを単純にインストールできないLinuxマシン用の小さなツールを作成するのに最適です。

近い将来、wasmプラットフォーム以外で「安定化」することはないと思います。

@rkarpが言ったように、非常に一般的なユースケースは、コンテナ化されたLinuxワークロードをサポートするためにx86_64-unknown-linux-musl(そして最終的にはsteed)をターゲットにすることです。 これは、Goが非常にうまく機能していることの1つであり、Rustが同様に実行できることに非常に近いように思われます。 実際の使用法に関しては、x86_64-unknown-linux-muslのLLDは、実際にはwasmよりもはるかに広く使用されると思います。

より一般的には、クロスビルディングに関しては、「すべてのホストおよび/またはすべてのターゲットで機能する必要がある」というアプローチは意味がないと思います。 ターゲットが機能し始めたら、ターゲットごとにこれを安定させることは理にかなっていると思います。

特に、x86_64-unknown-linux-muslターゲットのLLDをできるだけ早く安定させるための取り組みを支援したいと思います。

私のプロジェクトには37個のクレートがあり、ビルドは約70個のバイナリ(多くのテスト)にリンクしています。 非科学的に( top )、ビルド時間の少なくとも半分はldのみを実行しています。 lldを使用すると、ビルドが大幅に高速化されると思います。 私たちは安定したRustを使用しており、lld6.0をまだ動作させることができていません。

@briansmithは、muslとユースケースについてLLDをテストしましたか? 理論的には、テストするために必要なのは-Z linker-flavor=ld.lldに合格することだけです。それがうまくいくと思われる場合は、デフォルトを切り替えることができます。

@rocallahan確認のために、現在、すべての人がゴールドリンカーを使用していますよね? (afaikとして、標準のbinutilsリンカーよりも高速です)。 -Z linker-flavor=ld.lld機能する(そしてより高速である)場合、おそらくそれを安定させることができます! それはどのプラットフォームにありましたか?

非科学的に(目を見張るようなトップ)、ビルド時間の少なくとも半分はldのみを実行しています。

ところで、これはデバッグビルド用です。

現在、全員がゴールドリンカーを使用していますよね? (afaikとして、標準のbinutilsリンカーよりも高速です)

いいえ、それは標準のGNUリンカーであるFedoraシステムリンカーです。

それはどのプラットフォームにありましたか?

Fedora 27、SSDを搭載したクアッドコアSkylakeラップトップ。 いくつかのパフォーマンス数値を取得します。

知ってよかった! デバッグビルドは、リンカーの改善ではなく、スプリットドワーフ(https://github.com/rust-lang/rust/issues/34651)からリンク時間で最大の利益を得る可能性があります。

ただし、タイミング情報については、 ld.goldld.lld使用してテストする機会があれば、 @ rocallahan

もちろん。 また、問題#48762は、Linuxのデバッグリンク時間を高速化するための非常に簡単な方法であることを忘れないでください。 (実行可能ファイルから.debug_pubnames / .debug_pubtypesを削除するハッキングされたリンカースクリプトをすでに使用しています。)

分割DWARFは良いかもしれませんが、ユーザーに問題を引き起こす可能性もあります。 その号でコメントします。

@briansmithは、muslとユースケースについてLLDをテストしましたか? 理論的には、テストするために必要なのは-Zリンカー-flavor = ld.lldを渡すことだけです。それがうまくいくと思われる場合は、デフォルトを切り替えることができます。

OK、テストします。 おそらく最初は、「デフォルト」と「毎晩のみ」の中間にあるはずです。 -Zでできるように、LLDを使用することを選択する方法がありますが、 -Z使用しないで機能します。安定したビルドで。

ただし、-Zを使用しないため、安定したビルドで機能します。

RUSTC_BOOTSTRAP=1 RUSTFLAGS="-Z linker-flavor=foo" cargo build試すことができます

ブートストラップフラグをお勧めしませんか? 十分な数のプロジェクトがそれに依存している場合、物事は事実上安定し、安定メカニズム全体のポイントを打ち負かすのではないかと心配しています。

申し訳ありません= /

データポイントとして、Rustリポジトリ内のrustc_transクレートをリンクすること自体が、ローカルマシンの78秒のリンク時間から1秒のリンク時間に急落しました。

私のパフォーマンスは、クレート階層の最下部近くにあるクレートに空白を変更した結果です。 クアッドコアSkylakeラップトップ、16GB RAM、rustc 1.24.0、LLD 7.0.0、GNU ld2.29-13。 .debug_pubnames.debug_pubtypesを破棄するカスタムリンカースクリプトを使用します。 リンカスクリプトが存在する場合、LLDはまったく異なるコードパスを使用するため、状況に影響を与える可能性があります。

GNU ld:

real    2m39.138s
user    8m18.992s
sys 1m37.513s

LLD:

real    2m19.164s
user    6m4.477s
sys 0m56.858s

ゴールドは機能しませんでした。リンカースクリプトでバーフされました。 結果はかなり安定しています。 LLDはエンドツーエンドの時間にはそれほど影響しませんが、CPU使用率を大幅に削減します。 これは、ビルドがldの終了を待つのに多くの時間を費やさないことを意味していると思いますが、実行には多くのCPU時間が費やされます。

GNU ldからlldに切り替えると、一般的な「マイナーな変更と再構築」ワークロードの実行が2.5倍以上速くなる実際の例については、#50584を参照してください。

Er https://github.com/rust-lang/rust/issues/50584#issuecomment -400918647は、ここでより適切です。


LLDを安定させるための次のステップは、すべてのターゲット(Windows + Mac + Linux)で機能する-Zリンカー-flavor = lldのようなフラグを取得することです。 さまざまなプラットフォーム間で機能するために必要なことは何でもします。

それが完了したら、フィードバックを求めて、コミュニティに宣伝することができます。 ここでは、タイミング情報とバグレポートの両方を取得してLLDに送信できます。 すべてがスムーズに進む場合(まったく新しいリンカーでは疑わしいですが、わかりません!)、デフォルトでオンにすることができます。それ以外の場合は、LLDの選択を安定させてから、Cargoにオプションを追加できます。 tomlなので、プロジェクトは少なくともオプトインできます。

一部のターゲットではlldに切り替えました: https

私もwasmを信じますか?

この問題は、外部lldバイナリとのリンクとrustc自体に組み込まれている内部lldサポートとのリンクの両方をカバーしていますか? それとも前者だけ?

この問題は、外部lldバイナリとのリンクとrustc自体に組み込まれている内部lldサポートとのリンクの両方をカバーしていますか? それとも前者だけ?

外部のlldバイナリIIUCだけです。

@nnethercote内部リンカーの使用を追跡するための別の問題がありますか、それとも別の問題を提出する必要がありますか?

内部リンカーのアイデアについては、これまで聞いたことがありません。 私はそれのPRを知りません。

https://github.com/rust-lang/rust/pull/57514LLDを使用してLLVMをリンクするための準備されたグラウンド。

おそらく最初は、「デフォルト」と「夜間のみ」の中間にあるはずです。-Zを使用する場合と同様に、安定したビルドで機能するように-Zを使用せずに、LLDの使用を選択する方法があります。

https://github.com/rust-lang/rust/pull/56351-C linker-flavor追加しました。

この問題が何を追跡することを意図しているのかは明確ではありません。 「Microsoftのツールチェーンが利用できない場合は、-msvcターゲットのLLDとリンクする」などの特定の問題を抱えるために、これを閉じる方がよいようです。

私にとって、この問題は、すべてのターゲットのデフォルトリンカーとしてLLDを有効にすることに関するものです。 LLDは非常に高速であり、リンク時間はコンパイル時間の重要な要素であることが多く、コンパイル速度は永続的な問題であるため、私はそれを望んでいます。

@briansmithに同意し、さまざまなターゲットのステータスを追跡するための専用の問題を勧めしますが、これを閉じるのではなく、メタバグに変えることができます。 問題を開く価値のあるターゲットについて詳しく知っている人がいる場合は、LLDサポートステータスのループから外れているので、遠慮なくお問い合わせください。

LLDとのリンクはどこかに文書化されていますか? 私は(Linuxでは) rustc -C linker-flavor=ld.lld hello.rsを持っていますが、運がありません。 LLDはLLVMのコピーと一緒に配布されていると思いましたが、間違っていますか? apt経由でLLDをインストールしようとしましたが、rustcはまだ謎に包まれています。 今日RustコードでLLDを試すために取らなければならないステップは何ですか?

@bstrieさらに-C linker=rust-lld引数を渡す必要があります。

貨物で動作するはずですか? さびと貨物の最新のナイトリービルドで空白のプロジェクトをビルドしようとすると、現在次のエラーが発生します。

$ RUSTFLAGS='-C linker=rust-lld' cargo build
   Compiling rust3 v0.1.0 (/home/carado/tmp/rust3)
error: linking with `rust-lld` failed: exit code: 1
  |
  = note: "rust-lld" "-flavor" "gnu" "-L" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.2ualxzb8lqn4ho3y.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.32vfyq64cfbzv618.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.4rbt3m5y8o8cl09t.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.ben0932xzwyt64v.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.fzsdnygvstiwzxo.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.x0rq6ifodcf11zi.rcgu.o" "-o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.1m259ox4uzrzk583.rcgu.o" "--gc-sections" "-pie" "-zrelro" "-znow" "-L" "/home/carado/tmp/rust3/target/debug/deps" "-L" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--start-group" "-Bstatic" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-44988553032616b2.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-607feef6be9150b2.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace-a8dbf6d92401e34a.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-9a4716f5e8a3e722.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-988a64d96b043c6d.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-cadd6177b8c6d586.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-8f1d8efc92b45369.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-1e76014677816767.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-cc28bce38cb195d9.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-4123e9e89add689a.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4d259c17788c1fb5.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-9495dbda85bb8f16.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-793d0026c575805f.rlib" "--end-group" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-33c3162edae6574e.rlib" "-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: rust-lld: error: unable to find library -ldl
          rust-lld: error: unable to find library -lrt
          rust-lld: error: unable to find library -lpthread
          rust-lld: error: unable to find library -lgcc_s
          rust-lld: error: unable to find library -lc
          rust-lld: error: unable to find library -lm
          rust-lld: error: unable to find library -lrt
          rust-lld: error: unable to find library -lpthread
          rust-lld: error: unable to find library -lutil
          rust-lld: error: unable to find library -lutil


error: aborting due to previous error

error: Could not compile `rust3`.

To learn more, run the command again with --verbose.

カラドと同じエラーが発生します。 -L / usr / libをリンカー呼び出しに「靴べら」することができましたが、これにより、欠落したライブラリのリストが-lgcc短縮され、システムのどこにもlibgccとして存在しません( libgcc_s.a )これはいくつかのgnu-ismの結果だと思いますが、修正方法がわかりません。

@almindorはRUSTFLAGS='-C linker=rust-lld -L /usr/lib -L /usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0'または同様のものを試してください。 パスは、ディストリビューションとコンパイラのバージョンによって異なります。

私のコメントはLLDを使用する正しい方法の上にありますか? すべてのプログラムがSIGSEGVクラッシュするため、動作させることができません。

Reading symbols from target/debug/hello...
(gdb) show directories
Source directories searched: ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/etc:$cdir:$cwd
(gdb) r
Starting program: target/debug/hello 

Program received signal SIGSEGV, Segmentation fault.
core::ops::function::FnOnce::call_once{{vtable-shim}} () at /rustc/a7f28678bbf4e16893bb6a718e427504167a9494/src/libcore/ops/function.rs:231
(gdb) l
226     #[stable(feature = "fn_once_output", since = "1.12.0")]
227     type Output;
228 
229     /// Performs the call operation.
230     #[unstable(feature = "fn_traits", issue = "29625")]
231     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
232 }
233 
234 mod impls {
235     #[stable(feature = "rust1", since = "1.0.0")] 
(gdb) info reg
rax            0x0                 0
rbx            0x0                 0
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x0                 0
rbp            0x0                 0x0
rsp            0x7fffffffddb0      0x7fffffffddb0
r8             0x0                 0
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x0                 0
r13            0x0                 0
r14            0x0                 0
r15            0x0                 0
rip            0x7ffff7ffc000      0x7ffff7ffc000 <core::ops::function::FnOnce::call_once{{vtable-shim}}>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) disassemble 
Dump of assembler code for function core::ops::function::FnOnce::call_once{{vtable-shim}}:
=> 0x00007ffff7ffc000 <+0>: mov    (%rdi),%rax
   0x00007ffff7ffc003 <+3>: mov    (%rax),%rdi
   0x00007ffff7ffc006 <+6>: jmpq   *0x11d4(%rip)        # 0x7ffff7ffd1e0
End of assembler dump.

GCC 9またはClangをコンパイラーとして使用している場合、ここで終わる人にとって、魔法の呪文はRUSTFLAGS="-C link-arg=-fuse-ld=lld" cargo buildです。 あるいは、 -C linker=clangはGCCのバージョンに関係なく機能するはずなので、それが好まれるかもしれません。

これを永続的にするには、特定のプロジェクトの~/.cargo/configまたは.cargo/configに追加します。

[build]
rustflags = ["-C", "linker=clang"]
# rustflags = ["-C", "link-arg=-fuse-ld=lld"]

@lnicolaは、GCC9またはClangをCCとして使用する場合にのみ

@bstrieこれの現在の状況を知っていますか? それを前進させるための阻害要因は何ですか?

@ mati865古いGCCを持つ人々のための代替呼び出しをたまたま知っていますか?

@lnicolaすべてのプラットフォームにClang + GCC 9があり、互換性のないコンパイラーでの使用方法については調査していません。

@jonhoo私はこの分野の仕事に遅れをとっていません。コンパイラチームに聞いてみたいと思います。

チームにタグを付けることはできないと思いますし、チームに過度のノイズを発生させたくもありません。 そこから誰かにあなたの考えをざっと見てもらうための最良の方法は何ですか?

トリアージ; @ rust-lang / compiler誰かがこの問題の現在の状況を知っていますか?

LLDをRustで動作させることに成功した人のために、プラットフォームと使用されているすべてのコンパイラの特定のバージョンに関する詳細を追加で含めることができますか? ここにリストされているアドバイスがあっても、野生の人々がそれを機能させるのに苦労しているのを見ています。

上記で投稿したコマンドは、GCC9.2.0およびLLD9.0.0を使用するLinuxで機能します。 Windowsでも動作することがあると思いますが、-fuse = lldをサポートしていないWindows用のGCC9を使用している人を見かけました。 ここに投稿されたいくつかのリンクによると、MacOSでは試す価値はありません。

LLDをRustで動作させることに成功した人のために、プラットフォームと使用されているすべてのコンパイラの特定のバージョンに関する詳細を追加で含めることができますか? ここにリストされているアドバイスがあっても、野生の人々がそれを機能させるのに苦労しているのを見ています。

cat / etc / system-release
Fedoraリリース30(30)

cc --version
cc(GCC)9.2.1 20190827(Red Hat 9.2.1-1)

ld.lld --version
LLD 8.0.0(GNUリンカーと互換性があります)

うまくいけば、これが役立つ

しかし、-fuse = lldをサポートしていないGCC9 forWindowsを使用している人を見たことがあります。

@lnicola
Windows GCC 9ビルドは-fuse-ld=lldをサポートします(サポートしないようにパッチが適用されている場合を除きますが、なぜ誰かがそれを行うのでしょうか?)。
rust-mingwコンポーネントがインストールされ、リンカーが.cargo/configオーバーライドされなかったと思います。 そのようにして、rustcはシステム1の代わりに出荷するGCC6を選択しました。

Windowsのもう1つの問題は、LLD 9以前ではサポートされていないハードコードされたリンカーフラグ--enable-long-section-namesです(将来的にサポートする予定です)。 これを回避するには、次のことができます。

  • このフラグを取り除くラッパーを作成します
  • このフラグをno-opとして受け入れるようにLLDにパッチを適用します
  • このフラグを使用しない、パッチが適用されたローカルのRustビルドを使用する

Windowsのもう1つの問題は、LLD 9以前ではサポートされていないハードコードされたリンカーフラグ--enable-long-section-namesです(将来的にサポートする予定です)。

この部分は次の方法で修正されています: https
ただし、Windows-gnuユーザーは、 -fuse-ld=lldをサポートするCコンパイラを使用するために手作業を行う必要があります。

@bstrie :これはWindows-MSVCのStable and Nightlyで動作します。詳細は、このgamedev-wg問題の最初の投稿にあります//github.com/rust-gamedev/wg/issues/50

別のデータポイント: rustc自体を構築するときにRUSTFLAGS="-C link-arg=-fuse-ld=lld"を使用すると、高速の14コアLinuxボックスでリンク時間が93秒から41秒に短縮されます。

@nnethercote :それは(たとえば) config.toml[target.x86_64-unknown-linux-gnu]セクションでlinker=lldを設定することとは異なりますか?

@ Aaron1011 :2つのアプローチは同じ効果があると思いますが、私はこれを自分でチェックしていません。

@ Aaron1011それはclangである必要があります。https: //github.com/rust-lang/rust/issues/39915#issuecomment-538049306を参照して

@ mati865
LLDをリンカーとしてx86_64-pc-windows-gnu rustcを構築しようとしましたか?

今日試してみましたが、LLDがビルドの途中でハングして作業を停止するか、 unknown argument: --version-script=...について文句を言います。
ハングは、LLDがLLVMのリンクにのみ使用されている場合にも発生します。

[llvm]
use-linker = "lld"

ツールバージョン:

$ ld.lld --version
LLD 9.0.1 (https://github.com/msys2/MINGW-packages.git 5e3b8820ed9f04221affee4197e458aca2612e87) (compatible with GNU linkers)

$ gcc --version
gcc.exe (Rev2, Built by MSYS2 project) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

@petrochenkovはい私はいくつかのハックでそれを構築することができました:

  • LLD COFFバックエンドはリンカースクリプトをサポートしていませんが、LDとLLDの両方がMSVCスタイルの.defファイルで問題ありません。 簡単に解決できます
  • LLDは、ライブラリがlib始まることを期待しています(これはUNIXの世界では標準です)が、どういうわけかRustはすべてのwindows-*ターゲットに対してそれを行わないことになりました: https
    LDはどちらの方法でもかまいませんし、LLDを押すかRust側を押して修正するかわかりません。

私はここにいくつかの将来の可能性を書き留めています。 いくつかの実装作業が必要ですが、これらはRust開発における長年の問題点の解決に役立つと思います。

  • 外部から提供されたlldを使用する代わりに、それをrustc内の静的ライブラリとしてビルドして使用します。 これにより、rustc自体との緊密な統合が可能になり、すぐに使用できるエクスペリエンスが向上し、将来の可能性が広がります。
  • リンカコマンドとして多くのパス名をlldに渡す代わりに、仮想ファイルシステムを使用し、十分なメモリスペースがある場合は常に、ディスクIOを使用する代わりに、それらのデータをメモリからメモリに渡します。 大規模なプロジェクトの場合、これにより数百または数千メガバイトのディスクIOが節約され、コンパイル時間が改善される可能性があります。

リンカコマンドとして多くのパス名をlldに渡す代わりに、仮想ファイルシステムを使用し、十分なメモリスペースがある場合は常に、ディスクIOを使用する代わりに、それらのデータをメモリからメモリに渡します。 大規模なプロジェクトの場合、これにより数百または数千メガバイトのディスクIOが節約され、コンパイル時間が改善される可能性があります。

IO帯域幅の問題だけではありません。 Windowsのようなプラットフォームでは、特にWindows Defenderが有効になっている場合、操作するファイルごとにかなりの時間ペナルティが追加されます。Rustのcodegenユニットモデルは、クレートが数百の小さなオブジェクトファイルに分割され、大量のコンパイルをすばやく処理できることを意味します。時間。

このバグは少し混乱しているので、これを前進させたい人々のために、現在の状況の簡単な要約で私のベストショットを示します。

lldとは

llvmプロジェクトの一部であるリンカー。これは、次の2つの理由で望ましいものです。

  • クロスコンパイルは非常にフレンドリーです(したがって、埋め込みターゲットに重点が置かれています)
  • 非常に高速で(Goldの半分の時間で実行されることがよくあります。大きなプロジェクト(rustc、servoなど)ではリンクに数分かかる場合があります。リンクは、増分ビルドを使用したコンパイルの大部分を占める可能性があるため、このランタイムを半分にすることは大したことです。)

Rustが今日lldで行うこと

  • Rustは現在、ほとんどのプラットフォームで独自のlldのコピーをrust-lldと呼ばれるバイナリとして出荷しています。
  • rust-lldは、多くのベアメタルターゲットでデフォルトで使用されます
  • rust-lldはデフォルトでwasmに使用されます
  • (?)「-Clinker-flavor」を使用して、rust-lldの使用を明示的に要求できます(ベアメタル以外のプラットフォームでこれが正確に何をするかについてはあいまいです。以下を参照してください)

より多くの場所(つまり、デスクトップlinux / mac / windows)でrust-lldを使用する際の問題

  • lldのmacOS(Mach-O)バックエンドが壊れて放棄された

    • ゼロからの書き直しが始まりましたが、まだ初期の段階です

  • linux / unixプラットフォームでは、ld / lldを直接呼び出すことは想定されていません。 システムcコンパイラ(つまりgcc)を介してリンカを呼び出すことになっています。このコンパイラの責任は、crt1.oなどのシステムシンボルを検出し、それらをldに提供することです。 これは、rust-lldを「ただ」使用することはできないことを意味します。 gcc / clang / whateverにフィードする必要があります。 (このシステムシンボルロジックを自分で実装したくありません)

    • 一般に、リンカをパスとして指定することはできません。リンカを「ld」としてCコンパイラの検索パスに挿入する必要があります。

    • または、同じことを実行できますが、「ld.lld」として挿入し、「-fuse-ld = lld」を渡します。



      • これは重要かもしれません、どうやらlldはそれが「ld」または「ld.lld」として実行されているかどうかのclangスタイルのバイナリ名検出を行います(調査が必要です)


      • 残念ながら、-fuse-ld = lldはGCC9の一部にすぎないため、使用するには機能/バージョンの検出が必要になる場合があります(clangには長い間使用されてきました)



  • windows-msvcは明らかに良好な状態であり、バックエンドでrust-lldを使用するためのサポートが制限されているようですが、ここで何をする必要があるのか​​わかりません。
  • windows-mingwはlinux / unixとほぼ同じ場所にあるようですが、古いGCCを入手する傾向があり、pseudo-windows-linuxは十分にテストされた構成ではないため、状況は少し不安定ですか?

また、一般的に、lldは新しいものであり、ほとんどのOSのデフォルトではありません。これをより多くの場所で使用し始めると、ランダムな互換性のあるバグがほぼ確実に発生します。

2つのプラットフォームでデフォルトで(rust-)lldを使用することに焦点を当てた取り組みのために、2つのメタバグを提出しました。

  • #71515-x64 Ubuntu 20.04 LTS(およびより広くすべてのx64 ELFプラットフォーム)
  • #71520-x64msvcウィンドウ

windows-msvcは明らかに良好な状態であり、バックエンドでrust-lldを使用するためのサポートが制限されているようですが、ここで何をする必要があるのか​​わかりません。

LLD + windows-msvcはかなり良好な状態です。現在、このセットアップをrustc開発に使用しています。

lld-link必要なすべてのサポートは、 rustcバックエンドで実施されていますが、 https://github.com/rust-lang/rust/issues/68647のようなバグがあり

  • これは重要かもしれません、どうやらlldはそれが「ld」または「ld.lld」として実行されているかどうかのclangスタイルのバイナリ名検出を行います(調査が必要です)

ありますが、ldとld.lldは同じモードです: https

  • 残念ながら、-fuse-ld = lldはGCC9の一部にすぎないため、使用するには機能/バージョンの検出が必要になる場合があります(clangには長い間使用されてきました)

ld.lldはldと同じであり、 https: //patches-gcc.linaro.org/patch/11148/によると、-fuse-ld = lldでの唯一の変更は、ldの代わりにld.lldを実行することです。 PATHインジェクションを使用します。問題ないはずです。 しかし、これをgcc 9+にロックアウトするのは良くないと思います。debianstableは8.3しかなく、ブルズアイはおそらく2021年までリリースされないでしょう。

  • windows-mingwはlinux / unixとほぼ同じ場所にあるようですが、古いGCCを入手する傾向があり、pseudo-windows-linuxは十分にテストされた構成ではないため、状況は少し不安定ですか?

2018-09-16にリリースされたmingw-w646.0.0にはgcc8.3.0があり、-fuse-ld = lldはありませんが、それでもかなり新しいものです。 2019-11-11にリリースされたmingw-w647.0.0にはgcc9.3.0があり、-fuse-ld = lldがあります。 Debianバスター(安定版)は6.0.0、ブルズアイ(テスト)は7.0.0です。 Debianストレッチ(oldstable)には5.0.1とgcc 6.3.0しかありませんが、gcc 6.3に重大な問題がある場合は、lldサポート用に最新のdebian安定版を要求するのが妥当だと思います。

2つのプラットフォームでデフォルトで(rust-)lldを使用することに焦点を当てた取り組みのために、2つのメタバグを提出しました。

  • #71515-x64 Ubuntu 20.04 LTS(およびより広くすべてのx64 ELFプラットフォーム)
  • #71520-x64msvcウィンドウ

lldのmacOS(Mach-O)ポートについて: https: //github.com/rust-lang/rust/issues/39915#issuecomment -618726211以降、動作するか、少なくとも大幅に改善されているようです。書かれた!

このLLVMコミットを使用しlldビルドしnightly-x86_64-apple-darwinに対してトレースを作成し、すべてのテストを正常に実行しました。 私は(デバッグ)ビルド時間について特に満足しています:

  • ld場合、クリーンなcargo buildは35秒かかりました。
  • lld場合、クリーンなcargo buildは20秒かかりました。

ご了承ください:

  • これらのパフォーマンスの数値は、32GBのRAMと8コアi9を搭載した最近のMacBookProからのものです。
  • lldとMach-Oにはいくつかの未解決の問題があります。

@davidbarskyかっこいい! 好奇心から、そのパフォーマンスはzldとどのように比較されますか? (https://github.com/michaeleisel/zld)

また、サーマルについて説明しましたか? MBPは、特にデフォルトのファン速度プロファイルを使用すると、非常に迅速に熱スロットリングに入ります。 実行を実行する前に、ヒンジの近くのマシンの下部が触ると冷えるまで待つだけで、一貫性が保たれます。

私はUbuntu16i686でちょうどそのようなバグです

このページは役に立ちましたか?
0 / 5 - 0 評価