1. ホーム
  2. c++

[解決済み] cmakeで共有ライブラリを作成する方法は?

2022-04-20 14:12:32

質問

今まで自作のMakefileを使ってコンパイルしていたライブラリを、cmakeに切り替えたいと考えています。ツリーは以下のような感じです(無関係なファイルはすべて削除しました)。

.
├── include
│   ├── animation.h
│   ├── buffers.h
│   ├── ...
│   ├── vertex.h
│   └── world.h
└── src
    ├── animation.cpp
    ├── buffers.cpp
    ├── ...
    ├── vertex.cpp
    └── world.cpp

つまり、私がやろうとしていることは、ソースを共有ライブラリにコンパイルして、ヘッダーファイルと一緒にインストールするだけなのです。

私が見つけたほとんどの例は、いくつかの共有ライブラリを含む実行ファイルをコンパイルしますが、単なる共有ライブラリをコンパイルすることはありません。 また、誰かがcmakeを使用する非常に単純なライブラリを教えてくれれば、私はこれを例として使用することができます。

どのように解決するのですか?

の必要最小限のバージョンを常に指定します。 cmake

cmake_minimum_required(VERSION 3.9)

プロジェクトを宣言する必要があります。 cmake は必須であり、便利な変数を定義することになります。 PROJECT_NAME , PROJECT_VERSIONPROJECT_DESCRIPTION (後者の変数はcmake 3.9が必要です)。

project(mylib VERSION 1.0.1 DESCRIPTION "mylib description")

新しいライブラリターゲットを宣言します。の使用は避けてください。 file(GLOB ...) . この機能では、コンパイル処理のマスタリングに参加することはできません。もし、あなたが怠け者なら、コピーペーストで ls -1 sources/*.cpp :

add_library(mylib SHARED
    sources/animation.cpp
    sources/buffers.cpp
    [...]
)

設定 VERSION プロパティを設定します(オプションですが、良い習慣です)。

set_target_properties(mylib PROPERTIES VERSION ${PROJECT_VERSION})

を設定することもできます。 SOVERSION をメジャーナンバーに VERSION . そこで libmylib.so.1 へのシンボリックリンクになります。 libmylib.so.1.0.0 .

set_target_properties(mylib PROPERTIES SOVERSION 1)

ライブラリの公開APIを宣言します。このAPIは、サードパーティアプリケーションのためにインストールされることになります。プロジェクトツリーの中で分離しておくとよいでしょう。 include/ ディレクトリに移動します)。なお、プライベートヘッダはインストールしてはいけませんので、ソースファイルと一緒に配置することを強くお勧めします。

set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h)

サブディレクトリを扱う場合 "../include/mylib.h" . そこで、インクルードディレクトリにトップディレクトリを渡します。

target_include_directories(mylib PRIVATE .)

または

target_include_directories(mylib PRIVATE include)
target_include_directories(mylib PRIVATE src)

ライブラリのインストールルールを作成します。変数 CMAKE_INSTALL_*DIR で定義された GNUInstallDirs :

include(GNUInstallDirs)

そして、インストールするファイルを宣言します。

install(TARGETS mylib
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

をエクスポートすることもできます。 pkg-config ファイルを作成します。このファイルによって、サードパーティのアプリケーションは簡単にあなたのライブラリをインポートすることができます。

という名前のテンプレートファイルを作成します。 mylib.pc.in (参照 pc(5) マンページ をご覧ください)。

prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: @PROJECT_NAME@
Description: @PROJECT_DESCRIPTION@
Version: @PROJECT_VERSION@

Requires:
Libs: -L${libdir} -lmylib
Cflags: -I${includedir}

あなたの CMakeLists.txt を展開するルールを追加します。 @ マクロ ( @ONLY という形式の変数を展開しないように cmake に依頼します。 ${VAR} ):

configure_file(mylib.pc.in mylib.pc @ONLY)

そして最後に、生成されたファイルをインストールします。

install(FILES ${CMAKE_BINARY_DIR}/mylib.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)

を使用することもできます。 cmake EXPORT 特徴 . ただし、この機能が対応するのは cmake と、使いにくさを感じています。

最後に、全体の CMakeLists.txt は、次のようになります。

cmake_minimum_required(VERSION 3.9)
project(mylib VERSION 1.0.1 DESCRIPTION "mylib description")
include(GNUInstallDirs)
add_library(mylib SHARED src/mylib.c)
set_target_properties(mylib PROPERTIES
    VERSION ${PROJECT_VERSION}
    SOVERSION 1
    PUBLIC_HEADER api/mylib.h)
configure_file(mylib.pc.in mylib.pc @ONLY)
target_include_directories(mylib PRIVATE .)
install(TARGETS mylib
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${CMAKE_BINARY_DIR}/mylib.pc
    DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)

EDIT

コメントにあるように、標準に準拠するためには、共有ライブラリだけでなく、静的ライブラリも生成できるようにする必要があります。このプロセスはもう少し複雑で、最初の質問とは一致しません。しかし、それは非常に説明されていることを言及する価値がある こちら .