web-dev-qa-db-ja.com

CMake:「可能な限り静的」にバイナリを生成する方法

CMakeでバイナリと検出/リンクされるライブラリのタイプを制御したいのですが。最後の目標は、バイナリを生成することです"可能な限り静的"これは、静的バージョンが利用可能なすべてのライブラリに対して静的にリンクすることです。これは、テスト中に異なるシステム間でバイナリの移植性を有効にするために重要です。

ATMこれは、FindXXX.cmakeパッケージとして実現するのは非常に難しいようです。正確には、find_libraryコマンドは、静的ライブラリと動的ライブラリの両方が利用可能な場合は常に動的ライブラリを取得します。

この機能を(できればエレガントな方法で)実装するためのヒントは大歓迎です。

47
pszilard

私はいくつかの調査を行い、問題に対する満足のいく解決策を見つけることができませんでしたが、半分の解決策を見つけました。

静的ビルドの問題は、3つのことに要約されます。

  1. プロジェクトの内部ライブラリの構築とリンク。

    非常に単純です。BUILD_SHARED_LIBSスイッチOFFを反転するだけです。

  2. 外部ライブラリの静的バージョンを見つける。

    唯一の方法は、必要なファイルサフィックスを含むようにCMAKE_FIND_LIBRARY_SUFFIXESを設定することです(これは優先リストです)。

    この解決策はかなり「汚い」ものであり、CMakeのクロスプラットフォームの願望に非常に反しています。私見これはCMakeによって裏で処理されるべきですが、私が理解している限り、Windowsでの「.lib」の混乱のため、CMake開発者は現在の実装を好むようです。

  3. システムライブラリに対して静的にリンクする。

CMakeはオプション LINK_SEARCH_END_STATIC を提供します。これはドキュメントに基づいています:「静的システムライブラリが使用されるようにリンク行を終了します。」これで問題は解決したと思います。しかし、現在の実装はその仕事に任されていないようです。オプションがオンになっている場合、CMakeは、-Wl,-Bstaticを含め、リンカーに渡されたオプションで終了する引数リストを含む暗黙的なリンカー呼び出しを生成します。ただし、これだけでは不十分です。静的にリンクするようにリンカに指示するだけでエラーが発生します。私の場合は/usr/bin/ld: cannot find -lgcc_sです。不足しているのは、CMakeによるリンカー呼び出しに対してnotである-static引数を介した静的リンクが必要であることをgccに伝えていることです。これはバグだと思いますが、まだ開発者からの確認が取れていません。

最後に、これはすべて裏でCMakeによって可能であり、実行する必要があると思います。結局、それほど複雑ではありませんが、Windowsでは不可能ですが、それが複雑であると見なされれば...

28
pszilard

適切に作成されたFindXXX.cmakeファイルには、このためのものが含まれます。 FindBoost.cmakeを確認すると、Boost_USE_STATIC_LIBS変数を設定して、静的ライブラリまたは共有ライブラリを検出するかどうかを制御できます。残念ながら、大多数のパッケージはこれを実装していません。

モジュールがfind_libraryコマンドを使用する場合(ほとんどの場合)、 CMAKE_FIND_LIBRARY_SUFFIXES 変数を使用してCMakeの動作を変更できます。これを使用するためのFindBoost.cmakeからの関連するCMakeコードは次のとおりです。

IF(WIN32)
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
ELSE(WIN32)
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
ENDIF(WIN32)

これをfind_packageを呼び出す前に置くことも、.cmakeファイル自体を変更してコミュニティに貢献することもできます。

プロジェクトで使用する.cmakeファイルについては、すべてをソース管理内の独自のフォルダーに保存します。一部のライブラリの正しい.cmakeファイルを保持することに一貫性がなく、自分のコピーを保持することで変更を加え、コードをチェックアウトしたすべてのユーザーが同じビルドシステムファイルを使用できるようにしたため、これを行いました。

15