どこから始めるか#
まず、このようなチュートリアルがあります。非常に「入門から入門」しています。👌
Cmake tutorial in Chinese, CMake教程中文翻译
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")
# コンパイルコマンド生成を有効にし、他のツールがインデックスを作成できるようにする(例:clangd)
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>は少し混乱を招くが、実際にはCONFIGは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 Server へのパス。設定されていない場合、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
属性を使用して定義とインクルードパスを 2 回設定しています。
INTERFACE
タグは、サブビルドで有効であり、主ビルドでは無効であることを示します。
PRIVATE
タグは、主ビルドでのみ有効であり、サブビルドでは無効であることを示します。
したがって、実際には 2 つの CmakeList.txt の両方で有効になり、PUBLIC
というタグ属性を使用すると、両方で有効になることを示すことができます。例では、精密な制御が行われています。