CMake外部ライブラリへのリンク


126

CMakeに、同じCMakeプロジェクト内でビルドされていない外部共有ライブラリに実行可能ファイルをリンクさせる方法は?

行うだけでtarget_link_libraries(GLBall ${CMAKE_BINARY_DIR}/res/mylib.so)エラーが発生します

make[2]: *** No rule to make target `res/mylib.so', needed by `GLBall'.  Stop.
make[1]: *** [CMakeFiles/GLBall.dir/all] Error 2
make: *** [all] Error 2
(GLBall is the executable)

ライブラリをバイナリdirにコピーした後bin/res

使ってみた find_library(RESULT mylib.so PATHS ${CMAKE_BINARY_DIR}/res)

これはで失敗しRESULT-NOTFOUNDます。

回答:


101

最初にライブラリ検索パスを設定します。

LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)

そして、ただ

TARGET_LINK_LIBRARIES(GLBall mylib)

43
link_directories独自のドキュメントでも、の使用はお勧めしません。ここfind_libraryでは、元の質問で失敗した呼び出しを解決するか、@ Andreのソリューションを使用する方が良いと思います。
フレーザー

4
「インポートされた」ライブラリターゲットは、特定のライブラリの場所をターゲットにするので、代わりにグローバル検索パスを提供するだけなので、より堅牢であることがわかります。アンドレの答えを見てください。
Mark Lakata 2016年

1
find_libraryこのパスは、ハードコーディングするのではなく、常に使用して使用する必要があります。私の答え
usr1234567

121

arrowdodgerの答えは正しく、多くの場合に好まれます。私は単に彼の答えに代替案を追加したいと思います:

リンクディレクトリの代わりに、「インポートされた」ライブラリターゲットを追加できます。何かのようなもの:

# Your-external "mylib", add GLOBAL if the imported library is located in directories above the current.
add_library( mylib SHARED IMPORTED )
# You can define two import-locations: one for debug and one for release.
set_target_properties( mylib PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/res/mylib.so )

そして、このライブラリがプロジェクトによってビルドされたかのようにリンクします。

TARGET_LINK_LIBRARIES(GLBall mylib)

このようなアプローチにより、もう少し柔軟性が高まります。 。add_library()コマンドと、インポートされたライブラリに関連する多くのターゲットプロパティを

これが「libsの更新されたバージョン」に関する問題を解決するかどうかはわかりません。


2
おそらくそれがエラーになるadd_library( mylib SHARED IMPORTED )か、add_library called with IMPORTED argument but no library typeエラーが発生します
Marvin

4
@Andre:IMPORTED_LOCATION開始ブラケットが間違っていると思います
Ela782 14年

5
あなたが追加する必要がありますGLOBALIMPORTED、あなたが現在上記のディレクトリにインポートされたライブラリにアクセスする場合:add_library(breakpad STATIC IMPORTED GLOBAL)
ローマクルグロフ

@Andre IMPORTED_LOCATIONは、ファイルを含むディレクトリではなく、ファイルへのパスを必要とするようです
SOUser

1
@SOUser:はい、IMPORTED_LOCATIONはディレクトリではなくファイルを指す必要があります。私はそれを修正しました、作者は文句を言わないでしょうね。
Tsyvarev

64

私はあなたがfooと呼ばれるライブラリにリンクしたいと思います、そのファイル名は通常何かリンクfoo.dllまたはlibfoo.soです。

1.図書館を探す図書館
を探す必要があります。ライブラリへのパスを知っている場合でも、これは良い考えです。ライブラリが消えたか、新しい名前が付けられた場合、CMakeはエラーになります。これは、エラーを早期に発見し、何が問題の原因であるかをユーザー(自分でもよい)に明らかにするのに役立ちます。
ライブラリfooを見つけて、FOO_LIB使用中のパスを保存するには

    find_library(FOO_LIB foo)

CMakeは、実際のファイル名がどのようになっているのかを理解します。それはのような通常の場所をチェック/usr/lib/usr/lib64およびのパスをPATH

あなたはすでにあなたの図書館の場所を知っています。CMAKE_PREFIX_PATHCMakeを呼び出すときにそれをに追加すると、CMakeは渡されたパスでライブラリも検索します。

ヒントまたはパスのサフィックスを追加する必要がある場合があります。詳細については、ドキュメントを参照してください:https : //cmake.org/cmake/help/latest/command/find_library.html

2.ライブラリをリンクする 1.から、完全なライブラリ名を取得しFOO_LIBます。あなたのターゲットにライブラリをリンクするためにこれを使用してGLBallのように

  target_link_libraries(GLBall PRIVATE "${FOO_LIB}")

あなたは追加する必要がありPRIVATEPUBLICまたはINTERFACEターゲットの後に、参照 ドキュメント:https : //cmake.org/cmake/help/latest/command/target_link_libraries.html

これらの可視性指定子の1つを追加しない場合、CMakeのバージョンと設定されたポリシーに応じて、PRIVATEまたはのように動作しますPUBLIC

3.インクルードを追加します (この手順は必須ではない
場合があります)。ヘッダーファイルもインクルードする場合は、ヘッダーファイルとfind_path同様のものを使用しfind_libraryて検索します。次に、とtarget_include_directories同様のincludeディレクトリを追加しますtarget_link_libraries

ドキュメント:https : //cmake.org/cmake/help/latest/command/find_path.html および https://cmake.org/cmake/help/latest/command/target_include_directories.html

外部ソフトウェアで利用可能な場合は、置き換えることができますfind_libraryおよびfind_pathによってfind_package


4
私見これが最良の答えです。しかし、「プロジェクト」の後に「find_library」を、「add_executable」の後に「target_link_libraries」を呼び出さなかったため、問題が発生しました。
スムースウェア

1
find_packageこれらの手順を実行するよりもはるかに簡単です
activedecay 2018年

2
ステップ2は理解できません。共有ライブラリの場合、$ {FOO_LIB}は/full/path/to/libfoo.dylibのようになります。それはどのように役立ちますか?target_link_librariesは「-L / full / path / to -lfoo」を作成しないので、find_libraryは、ライブラリがすでにある場所にあることを確認する以外に、有用なものを返しません。何が欠けていますか?
guymac

target_link_libraries(mylib "${FOO_LIB}")?ターゲットはmylib彼の実際のターゲットではありGLBallませんか?私にはあまり意味がありません
Bersan

5

さらにもう1つ、Appstoreで作業している場合は、「資格」が必要であり、Appleフレームワークとリンクする必要があります。

エンタイトルメントを機能させるには(例:GameCenter)、「バイナリをライブラリにリンクする」-buildstepを作成し、「GameKit.framework」にリンクする必要があります。CMakeはライブラリを「低レベル」でコマンドラインに「挿入」します。したがって、Xcodeはそれを実際に認識しないため、機能画面でGameKitを有効にできません

CMakeを使用して「Link with Binaries」ビルドステップを作成する1つの方法は、CMakeでxcodeprojを生成し、次に「sed」を使用して「検索と置換」を行い、XCodeが好む方法でGameKitを追加することです...

スクリプトは次のようになります(Xcode 6.3.1の場合)。

s#\/\* Begin PBXBuildFile section \*\/#\/\* Begin PBXBuildFile section \*\/\
    26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks \*\/ = {isa = PBXBuildFile; fileRef = 26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/; };#g

s#\/\* Begin PBXFileReference section \*\/#\/\* Begin PBXFileReference section \*\/\
    26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System\/Library\/Frameworks\/GameKit.framework; sourceTree = SDKROOT; };#g

s#\/\* End PBXFileReference section \*\/#\/\* End PBXFileReference section \*\/\
\
\/\* Begin PBXFrameworksBuildPhase section \*\/\
    26B12A9F1C10543B00A9A2BA \/\* Frameworks \*\/ = {\
        isa = PBXFrameworksBuildPhase;\
        buildActionMask = 2147483647;\
        files = (\
            26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks xxx\*\/,\
        );\
        runOnlyForDeploymentPostprocessing = 0;\
    };\
\/\* End PBXFrameworksBuildPhase section \*\/\
#g

s#\/\* CMake PostBuild Rules \*\/,#\/\* CMake PostBuild Rules \*\/,\
            26B12A9F1C10543B00A9A2BA \/\* Frameworks xxx\*\/,#g
s#\/\* Products \*\/,#\/\* Products \*\/,\
            26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/,#g

これを "gamecenter.sed"に保存し、次にこのように "適用"します(xcodeprojが変更されます!)

sed -i.pbxprojbak -f gamecenter.sed myproject.xcodeproj/project.pbxproj

必要に応じてスクリプトコマンドを変更する必要がある場合があります。

警告:プロジェクト形式が変わる可能性があるため、Xcodeのバージョンが異なると壊れる可能性があります。(ハードコードされた)一意の番号は実際には一意ではない可能性があります。通常、他の人によるソリューションの方が優れているため、Appstoreをサポートする必要がない場合+資格(および自動ビルド)は、これを行わないでください。

これはCMakeのバグです。http: //cmake.org/Bug/view.php?id = 14185 およびhttp://gitlab.kitware.com/cmake/cmake/issues/14185を参照してください


特に、cmakeを外部ライブラリとリンクさせることは問題ではありません(上記の解決策はいくつかあります)。これを自動化された方法で機能させ、Apple Appstore およびエンタイトルメントで機能させることは困難です。その特定のケースでは、XCodeがそのようにリンクされたライブラリを「認識」せず、資格が機能しないため、上記のソリューションは機能しません。Afaik cmakeは、xcodeが「appstore互換の方法」で必要とする方法でライブラリを追加できません。もう一度教えてください。
kalmiya 2017年

1
ああ、それは悲しいことです。完全を期すために、現在commnetを含まない新しい課題追跡へのリンク:gitlab.kitware.com/cmake/cmake/issues/14185
usr1234567

この問題は5か月前に解決されたため、CMakeの最近のバージョンでは存在しないはずです。gitlab.kitware.com/cmake/cmake/issues/14185を
usr1234567
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.