From 722fd6eaf5b9748bccfab492d1ff2bb2e20baa51 Mon Sep 17 00:00:00 2001 From: youzi Date: Thu, 9 Apr 2026 21:54:44 +0800 Subject: [PATCH] fix(cmake): add -z nostart-stop-gc for LLVM/Clang toolchains When using LLVM-based toolchains (e.g. ST STM32CubeCLT arm-clang), ld.lld discards __start_/__stop_ encapsulation symbols under --gc-sections, causing undefined symbol errors for ctshell_cmd_section. Export CTSHELL_LINK_OPTIONS with -z nostart-stop-gc automatically when LLVM linker is detected. Also update porting docs (en/zh) to clarify GCC vs LLVM vs MDK-ARM linker script requirements. --- CMakeLists.txt | 10 ++++++++++ docs/en/quickstart/porting.rst | 12 ++++++++++-- docs/zh/quickstart/porting.rst | 12 ++++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a05c638..a1d6cbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,3 +112,13 @@ else() set(CTSHELL_DEFINITIONS ${CTSHELL_DEFINITIONS} CACHE INTERNAL "ctshell definitions") endif() + +# --- Linker options for section-based command registration --- +# GCC (ld.bfd) handles __start_/__stop_ symbols for orphan sections automatically. +# LLVM lld requires -z nostart-stop-gc to prevent these symbols from being +# discarded when --gc-sections is enabled. +set(CTSHELL_LINK_OPTIONS "") +if(CMAKE_LINKER MATCHES "lld" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + list(APPEND CTSHELL_LINK_OPTIONS "-z" "nostart-stop-gc") +endif() +set(CTSHELL_LINK_OPTIONS ${CTSHELL_LINK_OPTIONS} CACHE INTERNAL "ctshell linker options") diff --git a/docs/en/quickstart/porting.rst b/docs/en/quickstart/porting.rst index de311c2..08c1fc7 100644 --- a/docs/en/quickstart/porting.rst +++ b/docs/en/quickstart/porting.rst @@ -92,9 +92,17 @@ RTOS Environment: It is recommended to create a dedicated task to run the Shell. 6. Linker Script Modification - gcc: No need to modify. + **GCC (ld.bfd):** No need to modify the linker script. - MDK-ARM(v5 and v6): Add in scatter file, example: + **LLVM/Clang (ld.lld):** If you are using an LLVM-based toolchain (e.g., ST's STM32CubeCLT with arm-clang), the linker script does not need modification either. Simply append the following to the end of your ``CMakeLists.txt``: + + .. code-block:: cmake + + target_link_options(${CMAKE_PROJECT_NAME} PRIVATE ${CTSHELL_LINK_OPTIONS}) + + ``${CTSHELL_LINK_OPTIONS}`` is exported by ctshell and automatically adds ``-z nostart-stop-gc`` when an LLVM linker is detected, preventing ``__start_ctshell_cmd_section`` and ``__stop_ctshell_cmd_section`` symbols from being discarded under ``--gc-sections``. + + **MDK-ARM (v5 and v6):** Add in scatter file, example: .. code-block:: c diff --git a/docs/zh/quickstart/porting.rst b/docs/zh/quickstart/porting.rst index 05dd973..0a7367e 100644 --- a/docs/zh/quickstart/porting.rst +++ b/docs/zh/quickstart/porting.rst @@ -92,9 +92,17 @@ RTOS 环境: 建议创建一个独立的任务来运行 Shell。 6. 链接脚本修改 - gcc:无需修改。 + **GCC (ld.bfd):** 无需修改链接脚本。 - MDK-ARM(v5 and v6):在scatter file中添加示例如下: + **LLVM/Clang (ld.lld):** 如果你使用的是基于 LLVM 的工具链(如 ST 的 STM32CubeCLT arm-clang),则无需修改链接脚本,只需将以下内容追加到你的 ``CMakeLists.txt`` 末尾即可: + + .. code-block:: cmake + + target_link_options(${CMAKE_PROJECT_NAME} PRIVATE ${CTSHELL_LINK_OPTIONS}) + + ``${CTSHELL_LINK_OPTIONS}`` 由 ctshell 导出,会在检测到 LLVM 链接器时自动添加 ``-z nostart-stop-gc``,防止 ``__start_ctshell_cmd_section`` 和 ``__stop_ctshell_cmd_section`` 符号在 ``--gc-sections`` 下被回收。 + + **MDK-ARM(v5 and v6):** 在scatter file中添加示例如下: .. code-block:: c