どこから始めるか#
まず、このようなチュートリアルがあります。非常に「入門から入門」的です。👌
CMAKE のメカニズムと文法を完全に理解したい場合は、このチュートリアルに従って全過程を進めることができます。しかし、チュートリアルには以下の問題があります。
[!NOTE]
- 学習と理解のためだけであり、実稼働環境には使用できません。 チュートリアルは学習環境に基づいており、使用されるのは C++ とデフォルトの C コンパイラ(私の環境では clang)で、コンパイルされたものはデスクトップでのみ実行可能な exe です。私たちはもちろん arm_gcc を使用してコンパイルするか、少なくとも他の gcc ツールを指定できる必要があります。そうでなければ、プロジェクトを実稼働に使用することはできません。
- プロジェクト構造が過度に複雑で、初心者の理解に不利です。 そもそも実稼働には使用できず、全体のソフトウェアが非常に複雑で、cmakelist ファイルが多すぎて初心者には不親切です。
したがって、チュートリアルは Step1〜3 だけを見れば十分です。
その中で必要なソフトウェアツールは、自分でダウンロードし、実行可能ファイルのパスを環境変数に追加する必要があります。
- Cmake
- MinGW64
- arm-none-eabi-gcc
または、私のファイルサイトにあるパッケージ化されたポータブル vscode 環境を使用してください。
次に、stm32cubemxを使って適当に debuglink プロジェクトを生成し、プロジェクトのツールチェーンとして CMAKE を選択します。そして、生成されたプロジェクトを分析します。
ソフトウェアツールのダウンロード#
Cmake と MinGW64 は、MSYS2 の MINGW64 ブランチ環境でのインストールをお勧めします。手動インストールでは依存関係の問題が発生し、進行が困難になるか、依存関係が分散してモジュール化に不利です。
MSYS2をインストールした後、mingw64.exe を開き、以下の 2 つのコマンドを入力します。
pacman -S mingw-w64-x86_64-make
pacman -S mingw-w64-x86_64-cmake
インストールが完了したら、MSYS2 の mingw64/bin フォルダのパスをシステム環境変数の path に追加します。
arm-none-eabi-gcc は公式サイトからダウンロードする必要があります。MSYS2 でダウンロードしたものは不完全で、GDB ツールが欠けています。
Arm GNU Toolchain Downloads – Arm Developerの公式サイトからダウンロードするか、私のファイルミラーarm-gccを使用してください。
解凍またはインストール後、bin フォルダのパスをシステム環境変数の path に追加してください。
最もシンプルなプロジェクト#
stm32cubemx で適当にシンプルな cmake プロジェクトを生成すると、構造は大体以下のようになります。cmake に関連するものは以下の通りです。
実行可能な主ビルド#
生成された主ビルドファイルはルートディレクトリ下のCMakeLists.txt
で、これは私たちがcmake ../
のようなコマンドを使用して生成したネイティブビルドシステムが呼び出すCMakeLists.txt
です。
# CMakeの最低バージョン要件を3.22に指定
cmake_minimum_required(VERSION 3.22)
#
# このファイルはcmakeが呼び出す主ビルドファイルです
# ユーザーは必要に応じてこのファイルを自由に変更できます。
#
# コンパイラ設定部分を設定
set(CMAKE_C_STANDARD 11) # C標準をC11に設定
set(CMAKE_C_STANDARD_REQUIRED ON) # 指定されたC標準の使用を要求
set(CMAKE_C_EXTENSIONS ON) # コンパイラ拡張を有効にする
# ビルドタイプを定義
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug") # CMAKE_BUILD_TYPEが設定されていない場合、デフォルトで"Debug"に設定します。このパラメータは、"cmake ../"のようなコマンドを使用してネイティブビルドシステムを生成する際に-DCMAKE_BUILD_TYPE=Releaseを指定することができます。
endif()
# プロジェクト名を設定
set(CMAKE_PROJECT_NAME DebugBuild) # プロジェクト名をDebugBuildに設定
# ツールチェインファイルを含める
include("cmake/gcc-arm-none-eabi.cmake")
# コンパイルコマンド生成を有効にし、他のツールによるインデックス作成を容易にする
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) # compile_commands.jsonを生成し、IDEやツールで使用できるようにする
# CMakeによるASMとC言語のサポートを有効にする
enable_language(C ASM) # Cとアセンブリ(ASM)言語のサポートを有効にする
# コアプロジェクト設定
project(${CMAKE_PROJECT_NAME}) # プロジェクトを定義し、以前に設定したプロジェクト名を使用
message("Build type: " ${CMAKE_BUILD_TYPE}) # ビルドタイプをメッセージ出力
# 実行可能オブジェクトを作成
add_executable(${CMAKE_PROJECT_NAME}) # プロジェクト名を使用して実行可能ターゲットを定義
# サブディレクトリ部分を追加し、サブディレクトリ内のCMakeLists.txtファイルを自動的に処理します
add_subdirectory(cmake/stm32cubemx) # サブディレクトリを追加し、通常はSTM32CubeMX生成コードを含みます
# リンクディレクトリ設定
target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE
# ユーザー定義のライブラリ検索パスを追加
# 例: "/path/to/libs"
)
# 実行可能ターゲットにソースファイルを追加
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
# 追加のソースファイルを追加
# 例: "src/main.c"
)
# インクルードパスを追加
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
# ユーザー定義のインクルードパスを追加
# 例: "include"
)
# プロジェクトシンボル(マクロ)を追加
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
# ユーザー定義のシンボルを追加
# 例: "MY_MACRO=1"
)
# リンクライブラリを追加
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx # stm32cubemxライブラリをリンクします。実際にはproject()プロジェクトの形式で存在し、以前のadd_subdirectory(cmake/stm32cubemx)がこの名のstm32cubemxライブラリを引き入れました。このディレクトリ内のCMakeLists.txtファイルでこのライブラリが定義されています。
# ユーザー定義のライブラリを追加
# 例: "mylib"
)
注意すべき点は、この CMakeLists.txt は直接的にソースコードを引き入れていないことです。設定のいくつかを定義しているだけです。これは後で実行可能主ビルドの CMakeLists.txt を変更する際に保持する必要があります。
彼は
add_subdirectory(cmake/stm32cubemx)
......
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx
)
この 2 つの部分が間接的にすべてのソースファイルを引き入れます。cmake/stm32cubemx
には別のCMakeLists.txt
があり、そこではstm32cubemx
という名前のプロジェクトが定義され、すべてのインクルードパスとソースファイルが引き入れられ、target_link_librariesの方法で間接的に引き入れられます。このファイルについては後で詳しく説明します。
ツールチェインの指定#
実行可能主ビルドには次のような行があります。
include("cmake/gcc-arm-none-eabi.cmake")
この行は./cmake
フォルダ内のgcc-arm-none-eabi.cmake
ファイルを引き入れます。ここでの include は C 言語と同じで、テキスト置換を行います。つまり、gcc-arm-none-eabi.cmake ファイルのすべての内容がこの行に置き換えられ、ツールチェインを指定する目的を達成します。このファイルの内容は以下の通りです。
# システム名とプロセッサアーキテクチャを設定
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm) # プロセッサアーキテクチャをarmに設定
# コンパイラを強制的に指定
set(CMAKE_C_COMPILER_FORCED TRUE) # Cコンパイラを強制的に指定
set(CMAKE_CXX_COMPILER_FORCED TRUE) # C++コンパイラを強制的に指定
set(CMAKE_C_COMPILER_ID GNU) # CコンパイラIDをGNUに設定
set(CMAKE_CXX_COMPILER_ID GNU) # C++コンパイラIDをGNUに設定
# 一部のデフォルトGCC設定、arm-none-eabi-xxはPATH環境変数に存在する必要があります
set(TOOLCHAIN_PREFIX arm-none-eabi-) # ツールチェインプレフィックスをarm-none-eabi-に設定
# 各ツールのパスと名前を設定
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc) # Cコンパイラを設定
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) # アセンブリコンパイラを設定、Cコンパイラを使用
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++) # C++コンパイラを設定
set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}g++) # リンカを設定
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy) # オブジェクトコピー工具を設定
set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) # サイズ計算工具を設定
# 生成される実行ファイルのサフィックスを設定
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf") # アセンブリ実行ファイルのサフィックスを.elfに設定
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") # C実行ファイルのサフィックスを.elfに設定
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf") # C++実行ファイルのサフィックスを.elfに設定
# 試行コンパイルのターゲットタイプを静的ライブラリに設定
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # 試行コンパイルのターゲットタイプを静的ライブラリに設定
# MCU固有のコンパイルフラグ
set(TARGET_FLAGS "-mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard ") # ターゲットプラットフォームの特定コンパイルフラグを設定
# Cコンパイラフラグを設定
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}") # ターゲットプラットフォーム特有のコンパイルフラグをCコンパイラフラグに追加(元のフラグに基づいて追加)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -fdata-sections -ffunction-sections") # 追加のコンパイラフラグを追加
# ビルドタイプに応じて異なる最適化レベルを設定
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3") # Debugビルドタイプの場合、O0無最適化およびg3デバッグ情報生成に設定
endif()
if(CMAKE_BUILD_TYPE MATCHES Release)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -g0") # Releaseビルドタイプの場合、O3最適化およびg0デバッグ情報生成なしに設定
endif()
# アセンブリコンパイラフラグを設定
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP") # アセンブリコンパイラフラグを設定
# C++コンパイラフラグを設定
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics") # C++コンパイラフラグを追加し、RTTI、例外、およびスレッドセーフ静的変数を無効にする
# Cリンカフラグを設定
set(CMAKE_C_LINK_FLAGS "${TARGET_FLAGS}") # ターゲットプラットフォーム特有のコンパイルフラグをリンカフラグに追加
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -T \"${CMAKE_SOURCE_DIR}/STM32H743IITx_FLASH.ld\"") # リンクスクリプトを追加
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --specs=nano.specs") # nano.specs設定を使用
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections") # マッピングファイルを生成し、未使用の部分を削除
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lc -lm -Wl,--end-group") # Cライブラリと数学ライブラリをリンク
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--print-memory-usage") # メモリ使用状況を印刷
# C++リンカフラグを設定
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lstdc++ -lsupc++ -Wl,--end-group") # C++特有のリンクフラグを追加し、標準C++ライブラリをリンク
ここで、コンパイルツールチェインを指定し、いくつかのコンパイラパラメータをここで一つ一つ指定しています。たとえば、アセンブラにパラメータ「-masm=auto」を追加する場合は、次のようにします。
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP") # アセンブリコンパイラフラグを設定
この行の後に
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -masm=auto") # アセンブラに自動的にアセンブリ構文を認識させる
${CMAKE_ASM_FLAGS}
は、以前に設定したCMAKE_ASM_FLAGS
をすべて前に埋め込むことを意味し、追加の効果を実現します。
プロジェクトソースコードの引き入れ#
前の 2 つの関連ファイルでは、cmake 生成設定とツールチェインパラメータ設定を指定しました。次に、実際のソースコードファイルを引き入れます。
実行可能主ビルドには次のような行があります。
add_subdirectory(cmake/stm32cubemx)
これにより、./cmake/stm32cubemx
がすべて引き入れられます。実際に有効なのはCMakeLists.txt
だけで、他のファイルは実際には効果がありませんので、無視してください。このファイルの内容は以下の通りです。
# CMakeの最低バージョン要件を設定
cmake_minimum_required(VERSION 3.22)
# プロジェクト名をstm32cubemxに設定
project(stm32cubemx)
# INTERFACEライブラリを追加します。INTERFACEライブラリは実際のコンパイル成果物を生成せず、依存するターゲットにコンパイルオプションを提供します。
add_library(stm32cubemx INTERFACE)
# Cおよびアセンブリ言語のサポートを有効にします
enable_language(C ASM)
# stm32cubemxターゲットにコンパイル定義を追加します
target_compile_definitions(stm32cubemx INTERFACE
USE_HAL_DRIVER # USE_HAL_DRIVERマクロを定義
STM32H743xx # STM32H743xxマクロを定義
$<$<CONFIG:Debug>:DEBUG> # Debug構成の場合、DEBUGマクロを定義します。ここでの$<CONFIG:Debug>は実際にはCMAKE_BUILD_TYPE属性に対応します。
)
# stm32cubemxターゲットにインクルードディレクトリを追加します
target_include_directories(stm32cubemx INTERFACE
../../Core/Inc
../../Drivers/STM32H7xx_HAL_Driver/Inc
../../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy
../../Drivers/CMSIS/Device/ST/STM32H7xx/Include
../../Drivers/CMSIS/Include
)
# stm32cubemxターゲットにソースファイルを追加します
target_sources(stm32cubemx INTERFACE
../../Core/Src/main.c
../../Core/Src/gpio.c
../../Core/Src/stm32h7xx_it.c
../../Core/Src/stm32h7xx_hal_msp.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_hsem.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
../../Core/Src/system_stm32h7xx.c
../../Core/Src/sysmem.c
../../Core/Src/syscalls.c
../../startup_stm32h743xx.s
)
# stm32cubemxターゲットにリンクディレクトリを追加します
target_link_directories(stm32cubemx INTERFACE
)
# stm32cubemxターゲットにリンクライブラリを追加します
target_link_libraries(stm32cubemx INTERFACE
)
# STM32CubeMX生成のコードがC標準と互換性があるかを検証します。C11未満の場合はエラーを報告します。
if(CMAKE_C_STANDARD LESS 11)
message(ERROR "Generated code requires C11 or higher") # halライブラリには多くのオーバーライド可能な定義の関数があるため、C11標準のサポートが必要です。
endif()
ここで、実際のソースコードファイルとインクルードディレクトリを引き入れる場所です。stm32cubemx
を cmake プロジェクト名として使用します。主ビルドに以下の部分があったことを覚えていますか?
add_subdirectory(cmake/stm32cubemx)
......
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx
)
stm32cubemx
この cmake プロジェクトで、ソースコード関連の引き入れが実現されています。
vscode での cmake 設定#
1. 設定ファイル#
以下のサイトから cmake 設定ファイルをダウンロードし、vscode にインポートします。
2. ユーザー設定の変更#
設定ファイルをインポートすると、多くの必要なプラグインがダウンロードされます。ユーザー設定を変更し、各ツールチェインのパスを適切な設定項目に追加します。
前のステップでインポートした設定ファイルを有効にし、設定内で(ユーザー分野)arm toolchain path
を検索すると、以下のような項目が表示されます。
Cortex-debug: Arm Toolchain Path
GCC Arm Toolchain へのパス(標準プレフィックスは「arm-none-eabi」- armToolchainPrefix 設定を通じて設定可能)を使用します。設定されていない場合、ツールはシステムパスに存在する必要があります。このパスには実行可能ファイル名を含めないでください。
この項目の下にあるsettings.jsonで編集
をクリックし、このエントリを自分の arm-none-eabi-gcc の bin パスに変更します。
"cortex-debug.armToolchainPath": "C:\\111_APPS\\arm-gnu-toolchain-13.2.Rel1-mingw-w64-i686-arm-none-eabi\\bin",
設定内で(ユーザー分野)JLink GDBServer Path
を検索すると、以下のような項目が表示されます。
Cortex-debug: JLink GDBServer Path
JLink GDB サーバーへのパス。設定されていない場合、JLinkGDBServer(Windows では JLinkGDBServerCL.exe)はシステムパスに存在する必要があります。
この項目の下にあるsettings.jsonで編集
をクリックし、このエントリを自分の JLinkGDBServerCL.exe の bin パスに変更します。私が提供する例は通常 JLink デバッグタスクを記述し、JLink の RTT 印刷機能を利用するため、JLinkGDBServer を使用します。OpenGDBServer を使用する場合は、対応する GDBServerPath を自分で変更してください。ただし、デバッグタスクの記述が少し難しいかもしれません。
"cortex-debug.JLinkGDBServerPath": "C://111_APPS//SEGGER//JLink_V794f//JLinkGDBServerCL.exe",
3. vscode タスクの作成#
CMAKE スクリプトおよびプログラムのデバッグを行うために、デバッグタスクを自分で作成する必要があります。.workspace
ファイルの"launch"
部分に以下のように記述します。"launch"
部分がない場合は、最下部に記述できます。
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "CMake: Script debugging",
"type": "cmake",
"request": "launch",
"cmakeDebugType": "configure"
},
{
"cwd": "${workspaceRoot}",
"executable": "./build/H7_GCC_BASE.elf",
"name": "Debug with JLink",
"request": "launch",
"type": "cortex-debug",
"device": "STM32H743II",
// "runToEntryPoint": "Reset_Handler",
"runToEntryPoint": "main",
"showDevDebugOutput": "none",
"servertype": "jlink",
"interface": "swd",
"svdFile": "../../src/5_PhysicalChip/CPU/STM32H743.svd",
"liveWatch": {
"enabled": true,
"samplesPerSecond": 4
},
"rttConfig": {
"enabled": true,
"address": "auto",
"decoders": [
{
"label": "",
"port": 0,
"type": "console"
}
]
},
}
]
}
ここで、"executable"
部分には実際のコンパイル成果物を記入し、"device"
には実際のチップモデルを記入し、"svdFile"
部分には実際の svd ファイルの場所を記入します(もしない場合は、このエントリを削除してください)。
2 つのタスクを作成しました。1 つは CMAKE 生成スクリプトのデバッグ、もう 1 つはプログラムのデバッグです。vscode のデバッグウィンドウで対応するタスクを選択して開始できます。
まとめ#
stm32cubemx が生成した cmake プロジェクトは、非常に合理的で理解しやすいと思います。3 つの部分に分かれており、明確です。
- 実行可能主ビルド:cmake プロジェクトのさまざまな一般的設定を定義します。たとえば、C 標準、C++ の使用の有無など、ソースコードに関係ないことを定義し、他の 2 つの部分を引き入れます。
- コンパイルツールチェインの指定:どのコンパイラを使用するかを定義し、ターゲットプラットフォームによって異なります。
- ソースコードの引き入れ:この層は他の IDE を使用するのと似ており、ソースコード、インクルードディレクトリ、グローバル define を一つ一つ定義するだけです。
cmake に切り替えたい理由は、プロジェクトがますます大規模になり、各ソフトウェア機能をモジュール化して管理したいからです。IDE はソフトウェアパッケージの分割においてまだ不足しており、cmake は各機能モジュールが独自の CmakeList を持つことができ、ハードウェアドライバを除いてはプラットフォームに依存しないように抽象化できます。
拡張#
私の modbus プロトコルスタックは、機能モジュールの先進的な使用法を示しています。
機能ライブラリの CmakeList.txt は以下の通りです。
cmake_minimum_required(VERSION 3.22)
project(MODBUSX)
add_library(modbusx INTERFACE) # INTERFACEはこのライブラリ自体がコンパイルされず、他のターゲットによって使用される依存関係として提供されることを意味します。MBx_user.hは自分で定義し、ライブラリの動作を変更できます。
# すべてのソースファイルを再帰的に検索
file(GLOB_RECURSE SRC ${CMAKE_CURRENT_LIST_DIR}/source/*.c)
# 非再帰の例
# file(GLOB SRC ${CMAKE_CURRENT_LIST_DIR}/source/*.c)
target_include_directories(modbusx INTERFACE
${CMAKE_CURRENT_LIST_DIR}/include
${CMAKE_CURRENT_LIST_DIR}/../port/generic/inc
)
target_sources(modbusx INTERFACE
${SRC}
)
if(CMAKE_C_STANDARD LESS 11)
message(ERROR "Generated code requires C11 or higher")
endif()
主ビルドでは、このように呼び出します。
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/common) # サブディレクトリを追加
# 含めるべきパラメータを設定
set(MY_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/Example/win_test)
set(MY_DEFINITIONS MBX_INCLUDE_USER_DEFINE_FILE)
# ターゲットとリンク属性を設定
function(configure_target target_name source_file)
add_executable(${target_name} ${source_file})
target_compile_definitions(${target_name} INTERFACE ${MY_DEFINITIONS})
target_compile_definitions(${target_name} PRIVATE ${MY_DEFINITIONS})
target_include_directories(${target_name} INTERFACE ${MY_INCLUDE_DIR})
target_include_directories(${target_name} PRIVATE ${MY_INCLUDE_DIR})
target_link_libraries(${target_name} PRIVATE modbusx)
# リンカオプションを追加
target_link_options(${target_name} PRIVATE
-Wl,-Map=${target_name}.map
-Wl,--gc-sections
)
endfunction()
# 各実行可能ファイルを設定
configure_target(RTU_Mmain ${CMAKE_CURRENT_LIST_DIR}/Example/win_test/RTU_Mmain.c)
まず、サブビルドは INTERFACE ライブラリです。これは機能ライブラリであり、独立して実行することはできず、実際のアプリケーションソフトウェアがこの機能ライブラリを呼び出す必要があります。
例の主ビルドは、機能ライブラリの使用方法を示しています。ここでは、==INTERFACE== および ==PRIVATE== 属性を使用して、define と include パスを 2 回設定しています。
==INTERFACE== ラベルは、サブビルドで有効であることを示し、主ビルドでは無効です。
==PRIVATE== ラベルは、主ビルドでのみ有効であり、サブビルドでは無効です。
したがって、実際には 2 つの CmakeList.txt の両方で有効であり、==PUBLIC== というラベル属性を使用して、両方で有効にすることができます。例では、精密な制御が行われています。