どこから始めるか
まず、こんなチュートリアルがあります。まさに「入門から入門へ」という感じです。👌
CMake の仕組みと文法をしっかり理解したいなら、このチュートリアルを最後まで進めてみてください。ただし、次のような問題があります。
- 学習用としてしか使えず、本番環境には使えません。 このチュートリアルは学習環境を前提にしており、C++ とデフォルトの C コンパイラ(私の環境では clang)を使い、生成されるのもデスクトップでしか動かない exe です。本番で使えるようにするには、当然 arm_gcc でコンパイルするか、少なくとも他の gcc ツールを指定できる必要があります。
- プロジェクト構成が複雑すぎて、初心者が理解しにくいです。 もともと本番には使えないうえに、ソフトウェア全体が複雑で、CMakeLists ファイルが多すぎて初心者には不親切です。
というわけで、このチュートリアルは 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 に関係する部分は図のとおりです。

ルートフォルダー
./cmake
./cmake/stm32cubemx
実行可能なメインビルド
生成されるメインビルドファイルは ルートディレクトリの 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
# 添加用户定义的库搜索路径
# e.g., "/path/to/libs"
)
# 向可执行目标添加源文件
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
# 添加额外的源文件
# e.g., "src/main.c"
)
# 添加包含路径
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
# 添加用户定义的包含路径
# e.g., "include"
)
# 添加项目符号(宏)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
# 添加用户定义的符号
# e.g., "MY_MACRO=1"
)
# 添加链接库
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx # 链接stm32cubemx库 实际上也是以project()项目的形式存在,此前的add_subdirectory(cmake/stm32cubemx)引入了这名为stm32cubemx的库,该目录下的CMakeLists.txt文件中定义了这个库
# 添加用户定义的库
# e.g., "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-specific 编译标志
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") # 打印内存使用情况s's
# 设置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()
というわけで、ここがプロジェクトの実際のソースコードファイルとインクルードディレクトリを取り込む場所です。CMake プロジェクト名は stm32cubemx です。メインビルドの中に次のような部分があったのを覚えていますか?
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 ツールチェーンへのパス(標準のプレフィックスは「arm-none-eabi」で、armToolchainPrefix 設定で変更できます)。未設定の場合は、ツールがシステムの PATH に存在している必要があります。このパスに実行ファイル名は含めないでください。
この項目の下にある 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)がシステムの PATH に存在している必要があります。
この項目の下にある settings.json で編集 をクリックし、次のようにエントリを編集して、パスを自分の JLinkGDBServerCL.exe のパスに変更します。ここで紹介する例はたいてい JLink のデバッグタスクを想定しており、JLink の RTT プリント機能を使うため JLinkGDBServer を使用しています。OpenGDBServer を使う場合は、対応する GDBServerPath を自分で変更してください。ただし、デバッグタスクの作成は少し難しいかもしれません。
"cortex-debug.JLinkGDBServerPath": "C://111_APPS//SEGGER//JLink_V794f//JLinkGDBServerCL.exe",
3. vscode タスクを作成する
CMake スクリプトとプログラムのデバッグを行うには、debug タスクを自分で作成する必要があります。.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 のデバッグウィンドウで対応するタスクを選択して開始すれば OK です。
まとめ
STM32CubeMX が生成する CMake プロジェクトは、個人的にはとても合理的で分かりやすいと思います。次の3つの部分にきれいに分かれています。
- 実行可能なメインビルド: CMake プロジェクトの各種共通設定(C 標準や C++(C艹)などのコンパイラを使うかどうかなど、ソースコードに関係しないこと)を定義し、残りの2つの部分を取り込みます。
- コンパイルツールチェーンの指定: 使うコンパイラを定義します。ターゲットプラットフォームによって異なります。
- ソースコードの取り込み: この層は他の IDE を使うのと似ていて、ソースコード、インクルードディレクトリ、グローバル define を一つずつ定義するだけです。
なぜ CMake に乗り換えたいのかというと、プロジェクトがどんどん大きくなり、各ソフトウェア機能をモジュール化して切り離して管理したいからです。IDE はソフトウェアパッケージの分割という点ではやや不十分で、CMake なら機能モジュールごとに独立した CMakeLists.txt を持てばよいからです。ハードウェアドライバ以外は抽象化してプラットフォーム非依存にできます。
発展
私の modbus プロトコルスタック は、機能モジュールの高度な使い方の例です。
機能ライブラリの CMakeLists.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 path をそれぞれ2回設定しています。
==INTERFACE== は、ここではサブビルドで有効になり、このメインビルドでは有効になりません。
==PRIVATE== は、ここではメインビルドでのみ有効で、サブビルドでは有効になりません。
つまり、実際には2つの CMakeLists.txt の両方で有効にしたい場合は、==PUBLIC== という属性を使えば両方で有効になります。サンプルでは細かく制御されています。