2013-01-07 50 views
18

私は静的 libをcmakeに構築しています。これは多くの他の静的ライブラリに依存しています。私はそれらをすべて出力.lib/.aファイルに含めることを願っています。だから私は大きなlibファイルを顧客に送ることができます。 VS2010には、「リンクライブラリの依存関係」オプションがあり、これはまさにこれを行います。cmake:静的ライブラリのライブラリ依存関係を含む

しかし、私はcmakeでそれを行う方法を見つけることができません。 cmakeを使ってこのフラグを設定することができますか?同じ結果が得られますか?私はtarget_link_libraries(...)とadd_dependencies(...)を試みましたが、cmakeは静的ライブラリのためにこの行を単に無視するようです。

+0

リンクする必要のあるライブラリの静的バージョンはありますか?または、共有バージョンのみを持っていますか? – tpg2114

+0

私は静的なバージョン – Rolle

+0

を持っています。静的に静的なライブラリを含めていないと言うと、他の共有ライブラリとスタティックライブラリをリンクしようとしていますか? – tpg2114

答えて

12

さて、私は解決策を持っています。まず、静的ライブラリは他の静的ライブラリをコードにリンクしないことを認識することが重要です。結合されたライブラリが作成されなければなりません。これはLinux上ではarで行うことができます。詳細はLinking static libraries to other static librariesを参照してください。

は、2つのソースファイルを考えてみましょう:

Test1.cに:

int hi() 
{ 
    return 0; 
} 

がtest2.c:

int bye() 
{ 
    return 1; 
} 

CMakeLists.txt 2つのライブラリを作成し、組み合わせライブラリを作成するには、次のようになります。

project(test)

変数は、プラットフォームに依存しないものの
add_library(lib1 STATIC test1.c) 
add_library(lib2 STATIC test2.c) 

add_custom_target(combined ALL 
    COMMAND ${CMAKE_AR} rc libcombined.a $<TARGET_FILE:lib1> $<TARGET_FILE:lib2>) 
ar

コマンドのオプションは、この場合には、プラットフォームに依存しています。私はこれを行うもっと一般的な方法があるかどうかを見て回りますが、この方法はarを使用するシステムでは機能します。


編集:

add_custom_target(combined ALL 
    COMMAND ${CMAKE_CXX_ARCHIVE_CREATE} libcombined.a $<TARGET_FILE:lib1> $<TARGET_FILE:lib2>) 

これは使用されるコマンド構造であるため、これはプラットフォームに依存しないようになります。これを行うには良い方法は次のようになりますように見えるHow to set the options for CMAKE_ARに基づいて

CMakeによって内部的にアーカイブを作成する。もちろん、アーカイブコマンドに渡す唯一のオプションはrcです。これはarコマンドのCMakeに組み込まれているためです。

+3

ありがとう、対応する方法はWindows上でカスタムコマンド "lib.exe /OUT:combined.lib 1.lib 2.lib " – Rolle

+0

これを少し使った後、" ar "コマンドが非常にスケッチであり、gccの少なくともいくつかのバージョンでは動作しない結合されたlibsを生成していることに気付きました。私は、この方法で静的にリンクしようとしないほうがよいと思う。 – Rolle

+0

私にとっては、最初に説明したようなadd_custom_targetコマンドだけが機能しました。その真のプラットフォームに依存しないようにするに –

3

私はCMakeLists.txtファイルを実際に提供することで、他のソリューションを強化したいと考えています。このソリューションは、Visual Studioで、これまでに動作しますが、私はそれは、マルチプラットフォーム対応のなされることができますねというCMakeの

cmake_minimum_required(VERSION 2.8) 

add_library(lib1 test1.cpp) 
add_library(lib2 test2.cpp) 
include_directories(${CMAKE_CURRENT_DIR}) 
add_executable(mainexec main.cpp) 
target_link_libraries(mainexec combinedLib) # Important to place before add_custom_target 

set(LIBNAME "combinedLib.lib") 

add_custom_command(
    OUTPUT ${LIBNAME} 
    COMMAND lib.exe /OUT:${LIBNAME} $<TARGET_FILE:lib1> $<TARGET_FILE:lib2> 
    DEPENDS lib1 lib2 
    COMMENT "Combining libs..." 
) 

add_custom_target(combinedLib 
    DEPENDS ${LIBNAME} 
) 

注意を悪用

ソリューション。私は、次のバージョンでは、UNIXベースのプラットフォームのために働くかもしれないと想像することができます:あなたが置くならば、それは(代わりに静的または共有の)型UTILITYの対象に文句を言うと同じように、これらのソリューションは何とかCMakeのを誤用することを

set(LIBNAME "libCombinedLib.a") 

add_custom_command(
    OUTPUT ${LIBNAME} 
    COMMAND ar -rcT ${LIBNAME} $<TARGET_FILE:lib1> $<TARGET_FILE:lib2> 
    DEPENDS lib1 lib2 
    COMMENT "Combining libs..." 
) 

注意をtarget_link_librariesadd_custom_target宣言の後に呼び出します。

CMakeの目標宣言準拠のソリューション

それCMakeの準拠にするには、あなたが私の場合は

target_link_libraries(mainexec ${LIBNAME}) 
add_dependencies(mainexec combinedLib) 

によって `target_link_libraries'コールを置き換えることができmainexecを持っているので、それは完全に満足できるものではありませんすべての依存関係がtarget_link_libraries呼び出しによって処理されることを期待していますが、combinedLibについて知る必要があります。あなたは全体の後GLOBALを追加モジュール化する場合

cmake_minimum_required(VERSION 2.8) 

add_library(lib1 test1.cpp) 
add_library(lib2 test2.cpp) 
include_directories(${CMAKE_CURRENT_DIR}) 
add_executable(mainexec main.cpp) 

set(LIBNAME "combinedLib.lib") 

add_custom_command(
    OUTPUT ${LIBNAME} 
    COMMAND lib.exe /OUT:${LIBNAME} $<TARGET_FILE:lib1> $<TARGET_FILE:lib2> 
    DEPENDS lib1 lib2 
    COMMENT "Combining libs..." 
) 

add_custom_target(combinedLibGenerator 
    DEPENDS ${LIBNAME} 
) 

add_library(combinedLib STATIC IMPORTED) 
set_property(TARGET combinedLib PROPERTY IMPORTED_LOCATION ${LIBNAME}) 
add_dependencies(combinedLib combinedLibGenerator) 

target_link_libraries(mainexec combinedLib) 

少ないカップリングと代替ソリューション

輸入目標に向けて、さらにビットを見て、私は最終的に私の最後の問題を解決する解決策を見つけましたSTATIC IMPORTEDを使用すると、インポートされたターゲットをグローバルに表示できます。 CMakeのは推移的依存関係とインタフェースライブラリを完全にサポートを提供し、現在のCMakeのバージョンで

ポータブルCMakeのソリューション

。インタフェースライブラリは他のライブラリと「リンク」することができ、このインタフェースライブラリは「リンク」することができます。なぜ引用符ですか?これはうまくいきますが、実際には物理的に結合されたライブラリを作成するのではなく、一連のサブライブラリのエイリアスを作成します。それでも私たちが最終的に必要としていた解決策だったので、ここに追加したいのです。

add_library(combinedLib INTERFACE) 
target_link_libraries(combinedLib INTERFACE lib1 lib2) 

target_link_libraries(mainexec combinedLib) 

これだけです!

関連する問題