web-dev-qa-db-ja.com

cmake:target_link_librariesは共有されていない静的ライブラリを使用します

共有の代わりに静的ライブラリに対してリンクするように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を構成するにはどうすればよいですか?

17
Steve Lorimer

問題のライブラリを検索し、結果を出力変数に設定する関数スコープで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 ...
3
Steve Lorimer

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ベースのプラットフォームとは異なり、特定のファイルが静的ライブラリであるかどうかにかかわらず、拡張子を使用して問題を解決することはできません。

2
Craig Scott