【CMake】ターゲットのリンカ起動を自由自在に操る!LANG_LINKER_LAUNCHER徹底解説


"LANG_LINKER_LAUNCHER" プロパティは、CMake の "Properties: Targets" カテゴリに属し、ターゲットのリンカ起動時に実行されるコマンドを指定するために使用されます。これは、特定のコンパイラやリンカオプションをグローバル設定ではなく、個々のターゲットに対して設定したい場合に役立ちます。

構文

set_target_properties(target_name LANG_LINKER_LAUNCHER "<command>")

ここで、

  • <command> は、リンカ起動時に実行されるコマンドを表す文字列です。
  • <target_name> は、プロパティを設定するターゲットの名前です。

set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")

set(MY_TARGET_C_LINKER_LAUNCHER "gdb --args <linker> -ex 'bt'")
set(MY_TARGET_CXX_LINKER_LAUNCHER "gdb --args <linker> -ex 'bt'")

set_target_properties(my_c_target PROPERTIES
  LANG_LINKER_LAUNCHER "${MY_TARGET_C_LINKER_LAUNCHER}")

set_target_properties(my_cpp_target PROPERTIES
  LANG_LINKER_LAUNCHER "${MY_TARGET_CXX_LINKER_LAUNCHER}")

この例では、my_c_targetmy_cpp_target ターゲットに対して、リンカ起動時に GDB デバッガを実行するコマンドが設定されています。

  • リンカ起動時に渡される引数は、<command> 文字列内の <linker> プレースホルダを使用して参照できます。
  • リンカ起動時に実行されるコマンドは、シェルスクリプト形式で記述できます。
  • このプロパティは、ターゲットのソースコードディレクトリにある CMakeLists.txt ファイル内で設定する必要があります。
  • "LANG_LINKER_LAUNCHER" プロパティは、リンカの種類ごとに個別に設定できます。例えば、C 言語ターゲットと C++ 言語ターゲットで異なるコマンドを設定することも可能です。


例 1: 単純なコマンド

この例では、my_target ターゲットに対して、リンカ起動時に gdb デバッガを実行するコマンドを設定します。

set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")

set_target_properties(my_target PROPERTIES
  LANG_LINKER_LAUNCHER "gdb --args <linker> -ex 'bt'")

例 2: 複数のターゲットと異なるコマンド

この例では、my_c_targetmy_cpp_target ターゲットに対して、それぞれ異なるコマンドを設定します。

set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")

set(MY_TARGET_C_LINKER_LAUNCHER "valgrind --tool=memcheck <linker>")
set(MY_TARGET_CXX_LINKER_LAUNCHER "gdb --args <linker> -ex 'bt'")

set_target_properties(my_c_target PROPERTIES
  LANG_LINKER_LAUNCHER "${MY_TARGET_C_LINKER_LAUNCHER}")

set_target_properties(my_cpp_target PROPERTIES
  LANG_LINKER_LAUNCHER "${MY_TARGET_CXX_LINKER_LAUNCHER}")

例 3: 環境変数を使用したコマンド

この例では、CMAKE_C_LINKER_LAUNCHER 環境変数を使用して、my_c_target ターゲットのリンカ起動時に実行されるコマンドを設定します。

set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")

set(CMAKE_C_LINKER_LAUNCHER "gdb --args <linker> -ex 'bt'")

set_target_properties(my_c_target PROPERTIES
  LANG_LINKER_LAUNCHER "${CMAKE_C_LINKER_LAUNCHER}")

例 4: シェルスクリプトを使用したコマンド

この例では、シェルスクリプトを使用して、my_target ターゲットのリンカ起動時に実行されるコマンドを定義します。

set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")

set(MY_TARGET_LINKER_LAUNCHER_SCRIPT "${CMAKE_BINARY_DIR}/my_linker_launcher.sh")

file(WRITE "${MY_TARGET_LINKER_LAUNCHER_SCRIPT}"
  "# This script is executed when the linker is launched for my_target.\n"
  "gdb --args <linker> -ex 'bt'")

set_target_properties(my_target PROPERTIES
  LANG_LINKER_LAUNCHER "${MY_TARGET_LINKER_LAUNCHER_SCRIPT}")

これらの例は、"LANG_LINKER_LAUNCHER" プロパティをさまざまな方法で使用する方法を示すほんの一例です。詳細については、CMake ドキュメントを参照してください。

上記の例に加えて、"LANG_LINKER_LAUNCHER" プロパティを使用して、次のようなことを実現することもできます。

  • リンカの出力情報をカスタマイズする
  • 静的分析ツールを実行する
  • 特定のコンパイラオプションをリンカに渡す

注意事項

"LANG_LINKER_LAUNCHER" プロパティを使用する際には、以下の点に注意する必要があります。

  • 設定が CMake バージョン間で互換性があるように注意する
  • 設定が他のターゲットと競合しないように注意する
  • 設定が複雑になりすぎないように注意する


環境変数

"LANG_LINKER_LAUNCHER" プロパティと同様に、環境変数を使用してリンカ起動時に実行されるコマンドを設定することができます。この方法は、複数のターゲットで同じコマンドを使用する場合に有効です。


set(CMAKE_C_LINKER_LAUNCHER "gdb --args <linker> -ex 'bt'")

カスタムターゲット

カスタムターゲットを使用して、リンカ起動前に実行される一連のコマンドを定義することができます。この方法は、より複雑な処理が必要な場合に有効です。


add_custom_target(my_linker_launcher
  COMMAND gdb --args <linker> -ex 'bt'
  VERBATIM)

set_target_properties(my_target PROPERTIES
  LINK_DEPENDS my_linker_launcher)

外部ビルドシステム

CMake とは別に、Make や Ninja などの外部ビルドシステムを使用してリンカ起動を制御することもできます。この方法は、より高度なビルドシステムが必要な場合に有効です。


set(CMAKE_BUILD_TYPE Release)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/build/toolchain.cmake")

set(MY_TARGET_LINKER_LAUNCHER "gdb --args <linker> -ex 'bt'")

include(CMakeLists.txt)

手動スクリプト

CMake を使用せずに、手動でスクリプトを作成してリンカ起動を制御することもできます。この方法は、最も柔軟性がありますが、最も複雑な方法でもあります。


#!/bin/bash

set -e

# Build the target.
cmake --build .

# Launch the linker with the desired command.
gdb --args <linker> -ex 'bt'

選択の指針

どの代替方法を選択するかは、以下の要素によって決まります。

  • スキル
    手動スクリプトを作成するには、スクリプト言語の知識が必要です。
  • 複雑性
    より複雑な処理が必要な場合は、カスタムターゲットや外部ビルドシステムなどの方法が必要になります。
  • 必要な機能
    必要な機能によって、適切な方法が決まります。