Fix: Move global variable definitions from headers to source files to prevent multiple definition errors#1098
Conversation
… prevent multiple definition errors Global variables in cms.h and ledstrip.h were defined directly in headers, causing multiple definition linker errors when included in multiple translation units (e.g., unit tests). This commit changes those to 'extern' declarations in the headers and adds the actual definitions to their respective .c files, following proper C linkage rules. Fixes emuflight#1096.
📝 WalkthroughWalkthroughHeader-only symbol definitions were converted to extern declarations and corresponding symbols were defined/initialized in implementation files: Changes
Sequence Diagram(s)sequenceDiagram
participant Caller
participant ledstrip.c as LedStrip
Note over LedStrip: Global pointers & flags now live in implementation
Caller->>LedStrip: ledStripInit()
alt populate config
LedStrip-->>LedStrip: colors = ledStripConfigMutable()->colors
LedStrip-->>LedStrip: modeColors = ledStripConfig()->modeColors
LedStrip-->>LedStrip: specialColors = ledStripConfig()->specialColors
LedStrip-->>LedStrip: ledStripInitialised = false
LedStrip-->>LedStrip: ledStripEnabled = true
end
Caller->>LedStrip: read color data (uses internal pointers)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
Comment |
|
@coderabbitai, re-verify that this is how Betaflight does it and that I may merge this PR as-is without further testing nor flight-testing. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 1200 🏁 Script executed: Length of output: 488 🏁 Script executed: Length of output: 869 🏁 Script executed: Length of output: 1414 🏁 Script executed: Length of output: 1848 🏁 Script executed: Length of output: 1859 🏁 Script executed: Length of output: 1524 @nerdCopter, I've thoroughly compared this PR with Betaflight's approach. Here's what I found: CMS Variables (cms.h / cms.c)✅ Matches Betaflight exactly:
LED Strip Variables (ledstrip.h / ledstrip.c)Betaflight:
EmuFlight PR:
Key Finding: In both EmuFlight and Betaflight, all external usage accesses these through Merge AssessmentCan you merge as-is? Yes, with caveats:
Recommendation: Safe to merge for fixing the immediate build issue. If you want to match Betaflight exactly in the future, you could consider making these LED strip variables |
…and improve encapsulation Remove extern declarations of colors, modeColors, and specialColors from ledstrip.h and make them static in ledstrip.c. These variables are only used internally within ledstrip.c and should not be exposed globally. This matches Betaflight's approach exactly and improves code encapsulation by reducing header pollution.
|
@coderabbitai, does commit f516506 fix your number 3 ? how important is number 4? This is an OLD Betaflight/Butterflight fork -- as far as i know LEDSTRIP has been working. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 2444 @nerdCopter, excellent follow-up! Let me address your questions: Does commit f516506 fix issue #3?✅ YES, completely! The commit perfectly addresses issue #3 by:
This now exactly matches Betaflight's pattern of keeping these as file-local variables that aren't exposed in the header. How important is issue #4 (const qualifier)?Not important for functionality. Issue #4 is purely a defensive programming detail:
Why it doesn't matter:
Final Recommendation✅ Safe to merge as-is. With commit f516506 included:
You can proceed with merging without additional testing or flight-testing for this linkage fix. |
|
@coderabbitai, , in the future use, for example, either "Number 3" or use Alphabet (e.g. |
|
Tip For best results, initiate chat on the files or code changes. @nerdCopter, understood! I'll use either spelled-out numbering (e.g., "Number 3") or alphabetic notation (e.g., "A.", "B.", "C.") in my recommendations to avoid accidental GitHub issue/PR references with the ✏️ Learnings added
|
Fix: Move global variable definitions from headers to source files to prevent multiple definition errors
Summary
This PR resolves a firmware bug where global variables were defined directly in header files (cms.h and ledstrip.h) instead of being declared as
extern. This caused multiple definition linker errors when the headers were included in multiple translation units, such as during unit testing.Details
externdeclarations.specialColorsinledstripremains a by-value struct, matching the pattern used in Betaflight and other professional firmware projects.Note on Betaflight
Betaflight, the upstream project, uses the same pattern: global variables are declared as
externin headers and defined in a single source file. Forledstrip, Betaflight also keepsspecialColorsas a by-value struct, not a pointer, for consistency and simplicity.Impact
Closes
Summary by CodeRabbit