web-dev-qa-db-ja.com

CMakeと静的リンク

プロジェクトでCMakeを使用していますが、いくつかのライブラリを静的にリンクしようとしています。設定しました:

set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
set_target_properties(icarus PROPERTIES LINK_SEARCH_END_STATIC 1)

そして、*。aバージョンを持っている実際のライブラリを探すときに確認しました。

現在、プロジェクトのインポート:

libPocoNet.a 
libPocoUtil.a 
libPocoXML.a 
libPocoFoundation.a 
libmysqlclient.a 
libmysqlpp.a 
libcrypto++.a 
CUDA

すべてのライブラリが検出され、動的/共有リンケージを実行するとき、それらは正常に機能します。また、コンパイルフラグを設定しようとしました:

set(GCC_CXX_FLAGS ${GCC_CXX_FLAGS} "-static-libgcc -static-libstdc++ -static")

しかし、無駄に。コンパイル中に問題は発生しませんが、リンケージは上記のライブラリで見つかった呼び出しに対してndefined referenceエラーを大量にスローします。

undefined reference to `mysql_thread_init'
undefined reference to `mysql_real_query'
undefined reference to `pthread_mutex_unlock'
undefined reference to `Poco::ErrorHandler::handle()'

特定の順序ではなく、各ライブラリに多数のエラーがあります。

GCCの最後の行を見ると:

/usr/bin/c++   -g -g  -static-libgcc -static-libstdc++ -static [list of *.cpp files]
-o icarus -rdynamic /usr/local/lib/libPocoFoundation.a /usr/local/lib/libPocoNet.a
/usr/local/lib/libPocoUtil.a /usr/local/lib/libPocoXML.a 
-Wl,-Bstatic -lmysqlclient -lmysqlpp -lcrypto++

私は不思議に思う:

  1. Pocoライブラリが-rdynamicとしてリンクされており、-Wl -Bstaticフラグがないのはなぜですか?静的リンケージからスキップ/除外されるかのように。
  2. mysqlclient、mysqlpp、crypto ++は静的リンケージ用に設定されているようですが、それでもエラーが発生します

だから、誰かが私に説明してください:

  1. CMakeを使用した部分的な静的リンケージの設定方法
  2. CMAKE_EXE_LINKER_FLAGSのみを設定する必要がありますか?
  3. プロジェクト全体ではなく、言及されたライブラリの静的リンクを強制する必要がありますか?

これらの質問が多すぎる、またはローカライズされすぎている場合はご容赦ください。これは以前に試したことがないので、ネットで多くの情報を見つけることができないようです。

26
Ælex

私は次を使用して問題を解決することができました:

#Dynamic/Shared Libs
...
#Static start
set_target_properties(icarus PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(icarus PROPERTIES LINK_SEARCH_END_STATIC 1)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
#Static Libs
...
#Set Linker flags
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")

これは、他の大きな問題を引き起こす-staticを渡さずに機能し、基本的に静的ライブラリと動的ライブラリを混在させることができます。

静的ライブラリの順序が正しい限り、静的ライブラリの依存関係が満たされている限り、動的なもの(つまり、mysqlclient、libmysql ++)と静的なすべて(crypto ++、PocoNet)をロードするELFを取得します。 、PocoUtil、PocoXML、PocoFoundation)。

静的リンクライブラリには独自の依存関係があることに注意してください。 readelf -d appを使用してデバッグアプリケーションを調べると、次のように表示されます。

Dynamic section at offset 0x508f88 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libmysqlpp.so.3]
 0x0000000000000001 (NEEDED)             Shared library: [libmysqlclient.so.18]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]

PthreadはPoco :: Runnableによってインポートされ、libmは数学演算などのためにインポートされることを知っています。これがCMakeを部分的な静的リンクに使用する正しい方法であるかどうかはまだわかりません。

Crypto ++、mysql ++、mysqlclientなどのDebianパッケージライブラリの場合、*。aライブラリを見つけるだけで機能しましたが、Pocoライブラリの場合は、ライブラリのフルパスと名前のみを取得し、フラグは取得しませんでした。 -Bdynamicは、上記の行を使用することによってのみオフにできます。

注:-static-libstdc++なしでは、Pocoを静的にリンクできませんでした

これが似たようなことで立ち往生している人を助けることを願っています。

28
Ælex

CMakeを使用した静的リンクの設定方法

まあ...あなたはしない:)それはCMakeの仕組みではありません:CMakeでは、最初にライブラリの絶対パスを見つけてから、target_link_librariesでリンクします。

したがって、静的ライブラリにリンクする場合は、その静的ライブラリを検索する必要があります。

find_library(SOMELIB libsomelib.a)

の代わりに:

find_library(SOMELIB somelib)
15
Guillaume