共有の代わりに静的ライブラリに対してリンクするようにcmakeに指示することは可能ですか?
CMakeLists.txt
以下を構成しました:
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
後で、バイナリを追加し、リリースモードでtcmalloc
に対してリンクするように指示します。
target_link_libraries(${BIN_NAME} optimized tcmalloc_minimal)
結果のメイクファイルは、共有バージョンのtcmalloc
をリンクします。
$ make VERBOSE=1 | grep tcmalloc
/usr/bin/c++ ... -Wl,-Bdynamic ltcmalloc_minimal
さらに証明:
$ ldd app
...
libtcmalloc_minimal.so.4 => /usr/local/lib/libtcmalloc_minimal.so.4 (0x00007eff89733000)
...
Tcmallocの静的バージョンと共有バージョンの両方が存在します。
$ ls -1 /usr/local/lib/libtcmalloc_minimal*
/usr/local/lib/libtcmalloc_minimal.a
/usr/local/lib/libtcmalloc_minimal_debug.a
/usr/local/lib/libtcmalloc_minimal_debug.la
/usr/local/lib/libtcmalloc_minimal_debug.so
/usr/local/lib/libtcmalloc_minimal_debug.so.4
/usr/local/lib/libtcmalloc_minimal_debug.so.4.2.6
/usr/local/lib/libtcmalloc_minimal.la
/usr/local/lib/libtcmalloc_minimal.so
/usr/local/lib/libtcmalloc_minimal.so.4
/usr/local/lib/libtcmalloc_minimal.so.4.2.6
質問:
tcmalloc
の静的バージョンに対してリンクするようにcmakeを構成するにはどうすればよいですか?
問題のライブラリを検索し、結果を出力変数に設定する関数スコープでCMAKE_FIND_LIBRARY_SUFFIXES
を設定するヘルパー関数を作成できます( したがって、親スコープには影響しません )。
function(find_static_library LIB_NAME OUT)
if (WIN32 OR MSVC)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
elseif (UNIX)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
endif()
find_library(
FOUND_${LIB_NAME}_STATIC
${LIB_NAME}
)
if (FOUND_${LIB_NAME}_STATIC)
get_filename_component(ABS_FILE ${FOUND_${LIB_NAME}_STATIC} ABSOLUTE)
else()
message(SEND_ERROR "Unable to find library ${LIB_NAME}")
endif()
set(${OUT} ${ABS_FILE} PARENT_SCOPE)
endfunction()
次に、CMakeLists.txt
のどこかからこの関数を呼び出して、ライブラリの場所を変数に設定できます。
それを見つけるのに失敗すると、ハード障害が発生します
find_static_library(tcmalloc_minimal TCMALLOC)
次に、この変数をtarget_link_libraries
への呼び出しで使用し、静的バージョンにリンクしていることを確認します
target_link_libraries(${BIN_NAME} optimized ${TCMALLOC})
ここで結果を見ることができます:
$ make VERBOSE=1 | grep tcmalloc
/usr/bin/c++ ... /usr/local/lib/libtcmalloc_minimal.a ...
Windows以外のプラットフォームのみをサポートする必要がある場合は、キットウェア開発者の1人によるCMakeメーリングリストの this old email が最も簡単な方法です。本質的には、find_library()
を使用して実際のライブラリの場所を見つけ、共有ライブラリよりも静的ライブラリを優先して、検索する名前の最初にリストします。つまり.
find_library(TCMALLOC_LIB NAMES libtcmalloc_minimal.a tcmalloc_minimal)
次に、通常の方法で見つかったライブラリにリンクします。
target_link_libraries(${BIN_NAME} ${TCMALLOC_LIB})
静的ライブラリにlib???.a
以外の名前が付けられているプラットフォームをサポートする必要がある場合は、静的ライブラリ名の定義方法を賢くすることができます。そのためには、CMAKE_STATIC_LIBRARY_PREFIXおよびCMAKE_STATIC_LIBRARY_SUFFIX変数を使用します。
Windowsでは、キットウェアバグトラッカーの this old issue で説明されているように、DLLの静的ライブラリとインポートライブラリを区別できないという問題があります。どちらにもファイル拡張子.lib
があるため、Unixベースのプラットフォームとは異なり、特定のファイルが静的ライブラリであるかどうかにかかわらず、拡張子を使用して問題を解決することはできません。