【初心者向け】CMake: 静的ライブラリとオブジェクトライブラリの依存関係を最適化する「CMAKE_OPTIMIZE_DEPENDENCIES」の解説


CMAKE_OPTIMIZE_DEPENDENCIES は、CMake バージョン 3.19 以降で導入された変数です。この変数は、静的ライブラリとオブジェクトライブラリの依存関係を最適化するための機能を有効化します。

静的ライブラリとオブジェクトライブラリは、実際にリンクされるわけではないため、依存関係の一部は不要となります。CMAKE_OPTIMIZE_DEPENDENCIES を有効化すると、CMake はこれらの不要な依存関係をビルド時に削除することで、ビルド時間を短縮し、ディスク領域の使用量を削減することができます。

使用方法

CMAKE_OPTIMIZE_DEPENDENCIES は、以下の2つの方法で使用できます。

  • プロジェクトレベルで設定
set(CMAKE_OPTIMIZE_DEPENDENCIES 1)
  • ターゲットレベルで設定
add_library(my_lib STATIC ...)

set_target_properties(my_lib PROPERTIES OPTIMIZE_DEPENDENCIES ON)

動作

CMAKE_OPTIMIZE_DEPENDENCIES が有効化されている場合、CMake は以下の処理を行います。

  1. 静的ライブラリとオブジェクトライブラリの依存関係を分析します。
  2. 分析結果に基づき、不要な依存関係を特定します。
  3. 特定された不要な依存関係をビルド時に削除します。

注意事項

  • CMAKE_OPTIMIZE_DEPENDENCIES を有効化すると、一部の依存関係が削除されるため、ライブラリの動作が変更される可能性があります。変更が発生する可能性がある場合は、事前に十分なテストを実施する必要があります。
  • CMAKE_OPTIMIZE_DEPENDENCIES は、静的ライブラリとオブジェクトライブラリにのみ適用されます。共有ライブラリには適用されません。

以下の例では、my_lib という静的ライブラリを作成し、CMAKE_OPTIMIZE_DEPENDENCIES を有効化して依存関係を最適化しています。

cmake_minimum_required(VERSION 3.19)

project(my_lib)

add_library(my_lib STATIC foo.c bar.c)

target_link_libraries(my_lib ext_lib)

set_target_properties(my_lib PROPERTIES OPTIMIZE_DEPENDENCIES ON)

この例では、my_libfoo.cbar.c というソースコードファイルから作成されます。また、ext_lib という外部ライブラリにもリンクされます。CMAKE_OPTIMIZE_DEPENDENCIES が有効化されているため、CMake は ext_lib の不要な依存関係をビルド時に削除します。



例1: プロジェクトレベルで設定

cmake_minimum_required(VERSION 3.19)

project(my_project)

set(CMAKE_OPTIMIZE_DEPENDENCIES 1)

add_executable(my_app main.c)

target_link_libraries(my_app ext_lib)

この例では、my_project というプロジェクトを作成し、CMAKE_OPTIMIZE_DEPENDENCIES1 に設定してプロジェクト全体で依存関係の最適化を有効化しています。その後、my_app という実行ファイルを作成し、ext_lib という外部ライブラリにリンクします。CMAKE_OPTIMIZE_DEPENDENCIES が有効化されているため、CMake は ext_lib の不要な依存関係をビルド時に削除します。

例2: ターゲットレベルで設定

cmake_minimum_required(VERSION 3.19)

project(my_project)

add_library(my_lib STATIC foo.c bar.c)

target_link_libraries(my_lib ext_lib)

set_target_properties(my_lib PROPERTIES OPTIMIZE_DEPENDENCIES ON)

add_executable(my_app main.c)

target_link_libraries(my_app my_lib)

この例では、my_project というプロジェクトを作成し、my_lib という静的ライブラリと my_app という実行ファイルを作成します。my_libfoo.cbar.c というソースコードファイルから作成され、ext_lib という外部ライブラリにリンクされます。my_appmain.c というソースコードファイルから作成され、my_lib にリンクされます。my_lib のターゲットプロパティで OPTIMIZE_DEPENDENCIESON に設定することで、my_lib の依存関係のみを最適化します。

例3: 特定のターゲットのみを最適化

cmake_minimum_required(VERSION 3.19)

project(my_project)

add_library(my_lib1 STATIC foo.c bar.c)

target_link_libraries(my_lib1 ext_lib1 ext_lib2)

set_target_properties(my_lib1 PROPERTIES OPTIMIZE_DEPENDENCIES ON)

add_library(my_lib2 STATIC baz.c qux.c)

target_link_libraries(my_lib2 ext_lib3)

add_executable(my_app main.c)

target_link_libraries(my_app my_lib1 my_lib2)

この例では、my_project というプロジェクトを作成し、my_lib1my_lib2 という2つの静的ライブラリと my_app という実行ファイルを作成します。my_lib1foo.cbar.c というソースコードファイルから作成され、ext_lib1ext_lib2 という外部ライブラリにリンクされます。my_lib2baz.cqux.c というソースコードファイルから作成され、ext_lib3 という外部ライブラリにリンクされます。my_appmain.c というソースコードファイルから作成され、my_lib1my_lib2 にリンクされます。my_lib1 のターゲットプロパティで OPTIMIZE_DEPENDENCIESON に設定することで、my_lib1 の依存関係のみを最適化します。



しかし、CMAKE_OPTIMIZE_DEPENDENCIES は以下の理由により、すべての状況で最適な解決策とは限りません。

  • 一部の依存関係を削除する可能性がある
    CMAKE_OPTIMIZE_DEPENDENCIES を有効化すると、一部の依存関係が削除されるため、ライブラリの動作が変更される可能性があります。変更が発生する可能性がある場合は、事前に十分なテストを実施する必要があります。
  • すべてのターゲットに適用されない
    CMAKE_OPTIMIZE_DEPENDENCIES は、静的ライブラリとオブジェクトライブラリにのみ適用されます。共有ライブラリには適用されません。
  • すべての CMake バージョンで使用できない
    CMAKE_OPTIMIZE_DEPENDENCIES は CMake バージョン 3.19 以降でのみ使用できます。古いバージョンの CMake を使用している場合は、この機能を使用できません。

これらの理由から、CMAKE_OPTIMIZE_DEPENDENCIES の代替方法を検討することがあります。以下に、いくつかの代替方法を紹介します。

代替方法

  1. 手動で依存関係を分析し、不要な依存関係を削除する

これは最も低レベルな方法ですが、最も柔軟性と制御性があります。CMake の target_link_libraries コマンドを使用して、各ターゲットに必要なライブラリを手動で指定します。その後、必要なライブラリのみがビルドされるように、依存関係を分析し、不要な依存関係を削除する必要があります。

  1. サードパーティ製のツールを使用する

ThinLTOLinkTimeOptimization などのサードパーティ製のツールを使用して、依存関係を最適化することができます。これらのツールは、CMake 固有の機能ではなく、より多くの制御と柔軟性を提供することができます。

  1. CMake の古いバージョンを使用する

CMAKE_OPTIMIZE_DEPENDENCIES が導入される前の CMake の古いバージョンを使用することもできます。ただし、古いバージョンには最新の機能が搭載されていない可能性があることに注意する必要があります。

最適な代替方法を選択

最適な代替方法は、プロジェクトの要件と CMake のバージョンによって異なります。

  • すべてのターゲットに適用したい、またはより多くの制御と柔軟性を必要とする場合
    手動で依存関係を分析するか、サードパーティ製のツールを使用する必要があります。
  • 複雑なプロジェクトで CMake の古いバージョンを使用している場合
    手動で依存関係を分析するか、サードパーティ製のツールを使用する必要があります。
  • シンプルなプロジェクトで CMake の最新バージョンを使用している場合
    CMAKE_OPTIMIZE_DEPENDENCIES は簡単な解決策となる可能性があります。