Skip to content

fix(cmake): add -z nostart-stop-gc for LLVM/Clang toolchains#5

Merged
MDLZCOOL merged 1 commit intoMDLZCOOL:mainfrom
youziLab:fix/lld-nostart-stop-gc
Apr 13, 2026
Merged

fix(cmake): add -z nostart-stop-gc for LLVM/Clang toolchains#5
MDLZCOOL merged 1 commit intoMDLZCOOL:mainfrom
youziLab:fix/lld-nostart-stop-gc

Conversation

@youziLab
Copy link
Copy Markdown
Contributor

@youziLab youziLab commented Apr 9, 2026

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.

Summary by CodeRabbit

  • New Features

    • Introduced linker configuration support for LLVM/Clang toolchains with automatic flag management.
  • Documentation

    • Updated porting guides (English and Chinese) to clarify toolchain-specific linker setup instructions and how to use the new configuration option.

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.
@youziLab youziLab force-pushed the fix/lld-nostart-stop-gc branch from 7479749 to 722fd6e Compare April 9, 2026 14:01
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d6b6fe99-340b-44f4-bd33-88c3dc1124ec

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CMakeLists.txt`:
- Around line 121-122: The current conditional uses compiler IDs and causes the
ELF-only flag "-z nostart-stop-gc" to be appended whenever Clang is used; change
the check to detect the actual linker binary (CMAKE_LINKER) and only append to
CTSHELL_LINK_OPTIONS when CMAKE_LINKER resolves to the LLVM lld binary (e.g.,
matches "ld.lld" or ends with "ld.lld"); update the if(...) that references
CMAKE_LINKER so it no longer tests CMAKE_C_COMPILER_ID or CMAKE_CXX_COMPILER_ID
but instead tests CMAKE_LINKER MATCHES ".*ld.lld$" (or equivalent exact-path
check) before appending "-z" "nostart-stop-gc" to CTSHELL_LINK_OPTIONS.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6cffc1b6-bb5c-414c-a455-3429a397c774

📥 Commits

Reviewing files that changed from the base of the PR and between 9b5cf1c and 722fd6e.

📒 Files selected for processing (3)
  • CMakeLists.txt
  • docs/en/quickstart/porting.rst
  • docs/zh/quickstart/porting.rst

Comment on lines +121 to +122
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")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

cache_file="$(fd -HI '^CMakeCache.txt$' | head -n1 || true)"
if [[ -z "${cache_file}" ]]; then
  echo "No CMakeCache.txt found. Run CMake configure first."
  exit 1
fi

linker="$(rg -n '^CMAKE_LINKER:FILEPATH=' "$cache_file" | sed 's/^[^=]*=//' | head -n1)"
echo "Resolved linker: $linker"

if [[ ! -x "$linker" ]]; then
  echo "Linker binary is not executable: $linker"
  exit 1
fi

"$linker" --help 2>&1 | rg -n 'nostart-stop-gc|start-stop-gc'

Repository: MDLZCOOL/ctshell

Length of output: 111


🏁 Script executed:

cat -n CMakeLists.txt | sed -n '110,135p'

Repository: MDLZCOOL/ctshell

Length of output: 857


🏁 Script executed:

rg -n "CMAKE_LINKER|CMAKE_C_COMPILER_ID|CMAKE_CXX_COMPILER_ID|lld|nostart-stop-gc" CMakeLists.txt

Repository: MDLZCOOL/ctshell

Length of output: 371


Narrow linker detection to prevent passing -z nostart-stop-gc to unsupported linkers.

The condition on line 121 uses OR with Clang compiler checks, which means the flag is appended whenever Clang is used as the compiler, regardless of the actual linker. This causes -z nostart-stop-gc (an ELF-specific flag for LLVM lld) to be passed to incompatible linkers like Apple's ld64 or GNU ld, resulting in link failures.

The fix should check only if CMAKE_LINKER actually resolves to the ld.lld binary:

🔧 Proposed fix
 set(CTSHELL_LINK_OPTIONS "")
-if(CMAKE_LINKER MATCHES "lld" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+if(CMAKE_LINKER MATCHES [[(^|.*/)ld\.lld(\.exe)?$]])
     list(APPEND CTSHELL_LINK_OPTIONS "-z" "nostart-stop-gc")
 endif()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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")
if(CMAKE_LINKER MATCHES [[(^|.*/)ld\.lld(\.exe)?$]])
list(APPEND CTSHELL_LINK_OPTIONS "-z" "nostart-stop-gc")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CMakeLists.txt` around lines 121 - 122, The current conditional uses compiler
IDs and causes the ELF-only flag "-z nostart-stop-gc" to be appended whenever
Clang is used; change the check to detect the actual linker binary
(CMAKE_LINKER) and only append to CTSHELL_LINK_OPTIONS when CMAKE_LINKER
resolves to the LLVM lld binary (e.g., matches "ld.lld" or ends with "ld.lld");
update the if(...) that references CMAKE_LINKER so it no longer tests
CMAKE_C_COMPILER_ID or CMAKE_CXX_COMPILER_ID but instead tests CMAKE_LINKER
MATCHES ".*ld.lld$" (or equivalent exact-path check) before appending "-z"
"nostart-stop-gc" to CTSHELL_LINK_OPTIONS.

@MDLZCOOL
Copy link
Copy Markdown
Owner

LGTM, Thanks!

@MDLZCOOL MDLZCOOL merged commit 6a30f50 into MDLZCOOL:main Apr 13, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants