skills/build-error-analyzer/SKILL.md
This skill should be used when the user asks to "分析构建错误", "analyze build errors", "查看编译错误", "检查构建日志", "诊断链接错误", "fix build errors", "resolve compilation errors", "分析 last_error.log", "extract build error", "分析SDK的编译错误", "分析 SDK 编译错误", "analyze SDK build errors", "check SDK errors", "诊断 sdk 编译错误", or mentions analyzing build failures, compilation errors, linker errors, undefined symbols, SDK compilation errors, or needs to fix build issues. Focuses on reading last_error.log from out/<product>/ directory (or out/sdk/ for SDK builds) and providing specific fix recommendations based on error patterns and historical cases.
npx skillsauth add openharmonyinsight/openharmony-skills build-error-analyzerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill specializes in analyzing OpenHarmony build errors from last_error.log and providing fix recommendations only (no automatic code modifications) based on error patterns and historical case studies.
IMPORTANT: This skill provides analysis and recommendations ONLY. It does NOT automatically modify code files.
YOU MUST ALWAYS FOLLOW THIS EXACT SEQUENCE:
out/<product>/build.log → generates out/<product>/last_error.logout/<product>/last_error.logout/<product>/build.log or any other log files (error.log, build_output*.log, etc.)last_error.log contains "build success" or "no error", STOP and report successWhy?:
build.log contains the entire build history (thousands of lines)last_error.log contains ONLY the most recent error block (extracted by script)build.log directly will give you STALE or IRRELEVANT errorsBefore reading ANY errors, ALWAYS run:
# ⚠️ CRITICAL: First cd to OpenHarmony root directory, then run the script
cd <openharmony_root>
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/<product>/build.log
⚠️ CRITICAL - CHECK FOR SUCCESS FIRST:
After reading last_error.log, if you see:
build success, no errorno errorIMMEDIATELY STOP and report:
## ✅ 构建成功
最新的构建已经成功完成,没有发现任何错误。
**构建状态**: 成功
**错误信息**: 无
建议: 您可以继续进行开发或测试工作。
DO NOT:
Always use these paths:
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh (relative to OpenHarmony root)out/<product>/build.log (e.g., out/rk3568/build.log) - DO NOT READ DIRECTLYout/<product>/last_error.log (auto-generated in same directory as build.log) - READ ONLY THIS FILE⚠️ SPECIAL CASE - SDK Build Paths:
out/sdk/build.log (NOT out/ohos-sdk/build.log)out/sdk/last_error.log (NOT out/ohos-sdk/last_error.log)out/sdk/ directory instead of out/ohos-sdk/Workflow:
out/<product>/build.log using the script → creates out/<product>/last_error.logout/sdk/build.log → creates out/sdk/last_error.loglast_error.log ONLYCommon Mistakes to Avoid:
build.log directly (will get stale/wrong errors)error.log (contains outdated errors from previous builds)last_error.log shows "build success"<openharmony_root> firstlast_error.log ONLYlast_error.log shows success → STOP and report successThis skill provides ANALYSIS and RECOMMENDATIONS ONLY:
✅ DO:
❌ DO NOT:
last_error.log (error.log, build_output*.log, error.*.log, etc.)⚠️ CRITICAL - NEVER SUGGEST CLEARING LTO CACHE:
thinlto-cache directoryllvmcache-* directoriesout/obj directoryout/ directoryWhy: The user should review and apply fixes manually to maintain control over code changes and understand the modifications. LTO cache issues are extremely rare and clearing caches as first resort masks real problems, wastes rebuild time, and disrupts incremental compilation benefits.
out/<product>/build.log FIRST before readingout/<product>/last_error.log (same directory as build.log)foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh (from OpenHarmony root) to generate/update last_error.log before readingout/<product>/build.log in the OpenHarmony output directorylast_error.log contains "build success" or "no error", STOP and report success - DO NOT read other log files like error.log, build_output*.log, etc.last_error.log - NEVER from error.log, build_output*.log, error.*.log, or any other log files⚠️ CRITICAL: This step is MANDATORY and must be done BEFORE reading any errors.
Why this is required:
build.log contains the full build output (old and new errors mixed together)last_error.log is generated in the same directory as build.log⚠️ IMPORTANT: Always navigate to OpenHarmony root first, then run the script:
# Step 1: Navigate to OpenHarmony root directory
cd <openharmony_root>
# Step 2: Run the extraction script (relative path from root)
# Example for rk3568 product - extract errors from out/rk3568/build.log
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/rk3568/build.log
# Example for SDK product - extract errors from out/sdk/build.log (⚠️ SPECIAL CASE: out/sdk/ NOT out/ohos-sdk/)
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/sdk/build.log
# Example for other products:
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/rk3588/build.log
The script will:
out/<product>/build.logout/<product>/last_error.log (same directory)last_error.log if it exists⚠️ DO NOT SKIP THIS STEP
last_error.log exists, RE-EXTRACT to get the latest errorsbuild.log directlylast_error.log after extraction⚠️ CRITICAL: Only read last_error.log from out/<product>/ directory in the OpenHarmony output tree.
After extraction, the error log is located at:
out/<product>/last_error.log (same directory as build.log)Read the extracted error log:
# Check for last_error.log in common product directories
cat out/rk3568/last_error.log
# or for SDK (⚠️ SPECIAL CASE: out/sdk/ NOT out/ohos-sdk/)
cat out/sdk/last_error.log
# or for other products
cat out/rk3588/last_error.log
⚠️ CRITICAL - CHECK FOR SUCCESS FIRST:
Before any analysis, CHECK if the build succeeded:
If last_error.log contains:
build success, no errorno errorIMMEDIATELY STOP and report:
## ✅ 构建成功
最新的构建已经成功完成,没有发现任何错误。
**构建状态**: 成功
**错误信息**: 无
建议: 您可以继续进行开发或测试工作。
DO NOT continue to:
Only if there are actual errors, proceed to categorize them:
Error Categories:
Compare error patterns against historical cases in references/ directory and provide specific solutions.
Case matching priority:
CRITICAL: This step provides recommendations ONLY. Do NOT use Edit/Write tools to modify code.
Based on error type and matched cases, provide:
Recommended Output Format:
## 构建错误分析
### 错误类型
[编译错误/链接错误/构建系统错误]
### 错误位置
[文件路径:行号]
### 错误信息
[完整的错误消息]
### 根本原因
[详细解释为什么会出现这个错误]
### 修复建议
**文件**: [完整文件路径:行号]
**当前代码**:
```cpp
[错误代码片段]
应修改为:
[正确代码片段]
修改说明: [解释为什么要这样修改]
[相关的历史案例或文档链接]
**DO NOT**:
- ❌ Use Edit tool to make changes
- ❌ Use Write tool to create/modify files
- ❌ Run build commands automatically
**DO**:
- ✅ Provide clear recommendations with file paths and line numbers
- ✅ Show before/after code snippets
- ✅ Explain why the fix works
- ✅ Suggest verification commands
## Error Patterns and Solutions
### Pattern 1: Undefined Symbol Errors
**Error signature:**
ld.lld: error: undefined symbol: <symbol_name>
referenced by <file>:<line>
**⚠️ CRITICAL ANALYSIS WORKFLOW (MUST FOLLOW IN ORDER):**
When encountering `ld.lld: error: undefined symbol:` linker errors, you MUST follow this sequence:
#### Step 1: Identify Which Library is Failing to Link
Check the error message to determine which library has the undefined symbol:
- Look for the target being built (e.g., `libace.z.so`, `libace_compatible.z.so`, `libarkoala_native_ani.so`, `libace_ndk.z.so`)
- Check which library is referencing the symbol (`>>> referenced by`)
#### Step 2: Apply the Correct Scenario Based on Library Type
**Scenario 1: libace/libace_compatible Main Library Cannot Find Symbol**
**Symptoms:**
- Error occurs when linking `libace.z.so` or `libace_compatible.z.so`
- Symbol is undefined in the main library itself
**Root Cause:**
- Symbol implementation is missing or not compiled
- Method exists but .cpp file not in BUILD.gn
**Solution:**
1. **Check if implementation exists:**
```bash
grep -r "SymbolName" --include="*.cpp" frameworks/
If implementation exists, check BUILD.gn:
grep -r "implementation_file.cpp" frameworks/*/BUILD.gn
Add .cpp to BUILD.gn:
ace_core_ng_source_setVerify with other files:
# Find where similar files in same directory are compiled
find frameworks/core/components_ng/pattern/<pattern_name>/ -name "*.cpp"
grep "similar_file.cpp" frameworks/core/BUILD.gn
Scenario 2: Other Library Links with libace/libace_compatible Dependency
Symptoms:
libace or libace_compatibledeps includes libace/libace_compatibleRoot Cause:
⚠️ CRITICAL: Distinguish Non-Template vs Template FIRST
Before applying any solution, determine the type:
undefined symbol error
↓
Is it a non-template class method?
→ YES: Use Non-Template Solution (Step 1A)
→ NO: Use Template Solution (Step 1B, see Scenario 3)
Solution (Step-by-Step):
Step 1A: For NON-TEMPLATE class methods ⭐
⚠️ CHECK 1: Does the class have ACE_FORCE_EXPORT?
// Case A: Class WITHOUT ACE_FORCE_EXPORT
class PaddingPropertyF {
float Width() const;
};
// Case B: Class WITH ACE_FORCE_EXPORT
class ACE_FORCE_EXPORT PaddingPropertyF {
float Width() const;
};
For Case A (Class WITHOUT export) - PREFERRED METHOD:
ACE_FORCE_EXPORT to method declaration in header (.h file)Example (PaddingPropertyF case):
// In header file (.h) - Add ACE_FORCE_EXPORT to method declarations
class PaddingPropertyF {
ACE_FORCE_EXPORT float Width() const; // ← Add here
ACE_FORCE_EXPORT float Height() const; // ← Add here
};
// In implementation file (.cpp) - NO ACE_FORCE_EXPORT here
float PaddingPropertyF::Width() const
{
return left.value_or(0.0f) + right.value_or(0.0f);
}
float PaddingPropertyF::Height() const
{
return top.value_or(0.0f) + bottom.value_or(0.0f);
}
For Case B (Class WITH export):
ACE_FORCE_EXPORT to individual methodsExample:
// In header file (.h) - Class already exported
class ACE_FORCE_EXPORT PaddingPropertyF { // ← Entire class exported
float Width() const; // Automatically exported
float Height() const; // Automatically exported
};
// In implementation file (.cpp) - No individual exports needed
float PaddingPropertyF::Width() const { /* implementation */ }
Step 1B: For TEMPLATE class methods/functions (see Scenario 3)
Template-specific rules apply - refer to Scenario 3 for detailed steps.
Step 2: Add to libace.map with fine-grained symbol names ⭐
After adding exports, add the symbol to build/libace.map:
# Check if symbol already in libace.map
grep "ClassName" build/libace.map
Required changes:
build/libace.map whitelistExample - Regular Methods:
# In build/libace.map
{
global:
# ✅ FINE-GRAINED - Export specific methods (PREFERRED for non-template)
OHOS::Ace::PaddingPropertyF::Width*;
OHOS::Ace::PaddingPropertyF::Height*;
# ⚠️ ACCEPTABLE - Export entire class (if class has ACE_FORCE_EXPORT)
OHOS::Ace::PaddingPropertyF::*;
# ⚠️ DIFFERENT - Template patterns (use wildcards)
void?OHOS::Ace::StringUtils::StringSplitter*; # Template function
OHOS::Ace::NG::LayoutConstraintT*; # Template class
};
}
Why fine-grained for non-templates?
Common Mistakes (DO NOT do):
ClassName::*; when only specific methods are neededStep 3: Verify symbol export:
nm -D out/rk3568/arkui/ace_engine/libace.z.so | grep SymbolName
Common mistakes (DO NOT do):
ClassName::*; when only specific methods are needed (⚠️ COMMON MISTAKE)ACE_FORCE_EXPORT__attribute__((visibility("default"))) directly⚠️ Example of Common Mistake - Over-Exporting:
// ❌ WRONG - Exports entire class when only constructors needed
OHOS::Ace::VelocityTracker::*; // Exports ALL members unnecessarily
// ✅ CORRECT - Fine-grained constructor export
OHOS::Ace::VelocityTracker::VelocityTracker*; // Only constructors
When to use each pattern:
ClassName::MethodName*; for specific methodsClassName::ClassName*; for all constructor overloadsClassName::*; ONLY when most/all members are exported (rare)Scenario 3: Template Function Instantiation Issues
Symptoms:
StringSplitter<Color>, TransformStrCase<std::string>)Root Cause:
Solution (3 steps required):
Step 1: Add extern template declaration in header (.h)
Add explicit template declaration for new specialization:
// In header file (.h)
extern template void StringSplitter<Color>(const std::string& source, char delimiter,
Color (*)(const std::string&), std::vector<Color>& out);
Step 2: Add ACE_FORCE_EXPORT to template function declaration
// In header file (.h) - Template function declaration
template<class T>
ACE_FORCE_EXPORT
void StringSplitter(
const std::string& source, char delimiter, T (*func)(const std::string&), std::vector<T>& out);
Step 3: Add explicit instantiation in .cpp
// In implementation file (.cpp)
template void StringSplitter<Color>(const std::string& source, char delimiter,
Color (*)(const std::string&), std::vector<Color>& out);
Step 4: Add ACE_FORCE_EXPORT to template implementation
// In implementation file (.cpp) - Template function implementation
template<class T>
ACE_FORCE_EXPORT
void StringSplitter(
const std::string& source, char delimiter, T (*func)(const std::string&), std::vector<T>& out)
{
// implementation
}
Step 5: Add to libace.map whitelist
# In build/libace.map
{
global:
OHOS::Ace::StringUtils::*;
void?OHOS::Ace::StringUtils::StringSplitter*; # Match template instantiations
void?OHOS::Ace::StringUtils::TransformStrCase*; # Match template instantiations
};
⚠️ Template Special Notes:
* wildcard to match template instantiationsvoid?OHOS::Ace::StringUtils::StringSplitter*;Scenario 4: Special Libraries (Rare Cases)
Symptoms:
libarkoala_native_ani.solibace_ndk.z.soRoot Cause:
Solution:
Example for libarkoala_native_ani:
# In: frameworks/bridge/arkts_frontend/koala_projects/arkoala-arkts/arkui-ohos/src/ani/native/BUILD.gn
ohos_shared_library("arkoala_native_ani") {
sources = [
"//foundation/arkui/ace_engine/frameworks/base/utils/string_utils.cpp",
"UINode/uinode_module_methods.cpp",
# ... other sources
]
}
Example for ace_ndk:
# In: interfaces/native/BUILD.gn
ohos_shared_library("ace_ndk") {
sources = [
"//foundation/arkui/ace_engine/frameworks/base/utils/string_utils.cpp",
"//foundation/arkui/ace_engine/frameworks/core/accessibility/native_interface_accessibility_impl.cpp",
# ... other sources
]
}
⚠️ IMPORTANT:
libarkoala_native_ani and ace_ndkScenario 5: Template Class Method Export Issues
Symptoms:
libace or libace_compatibleundefined symbol: ClassName<T>::MethodName(params)ACE_FORCE_EXPORT on struct declaration but methods still not exportedExample Error:
ld.lld: error: undefined symbol: OHOS::Ace::NG::LayoutConstraintT<float>::UpdateSelfMarginSizeWithCheck(OHOS::Ace::NG::OptionalSize<float> const&)
>>> referenced by slider_layout_algorithm.cpp:212
Root Cause:
ACE_FORCE_EXPORT (e.g., struct ACE_FORCE_EXPORT LayoutConstraintT)ACE_FORCE_EXPORT macroSolution:
Step 1: Add ACE_FORCE_EXPORT to method implementation in .cpp
Add ACE_FORCE_EXPORT to each template method implementation that needs to be exported:
// In implementation file (.cpp)
template<typename T>
ACE_FORCE_EXPORT // ← Add this macro before return type
bool LayoutConstraintT<T>::UpdateSelfMarginSizeWithCheck(const OptionalSize<T>& size)
{
if (selfIdealSize == size) {
return false;
}
return selfIdealSize.UpdateSizeWithCheck(size);
}
template<typename T>
ACE_FORCE_EXPORT // ← Add this macro before return type
bool LayoutConstraintT<T>::UpdateMaxSizeWithCheck(const SizeT<T>& size)
{
if (maxSize == size) {
return false;
}
return maxSize.UpdateSizeWhenSmaller(size);
}
⚠️ Template Method Export Notes:
struct ACE_FORCE_EXPORT LayoutConstraintT doesn't automatically export all methodsACE_FORCE_EXPORTtemplate<> and return typeACE_FORCE_EXPORT to method declarations in header file (struct declaration is sufficient)Step 2: Verify libace.map has wildcard pattern
Check that libace.map includes the template class with wildcard:
# Check libace.map for template class pattern
grep "LayoutConstraintT" build/libace.map
Expected output:
OHOS::Ace::NG::LayoutConstraintT*;
⚠️ libace.map Wildcard Rules:
OHOS::Ace::ClassName::*;"OHOS::Ace::ClassName<T>::*;" (wildcards won't work)* at end to match all methods: OHOS::Ace::NG::LayoutConstraintT*;Step 3: Verify symbol export
# Check if symbol is exported in shared library
nm -D out/rk3568/arkui/ace_engine/libace.z.so | grep LayoutConstraintT
Expected output (should show exported symbols):
0000000000000000 T _ZN2OHOS3Ace2NG14LayoutConstraintTIfE25UpdateSelfMarginSizeWithCheckERKNS0_11OptionalSizeIfEE
⚠️ Common Mistakes:
struct ACE_FORCE_EXPORT ClassName - NOT sufficient for methods"ClassName<T>::*" won't match✅ Correct Approach:
ACE_FORCE_EXPORT to each template method implementation in .cpptemplate<> and return typeACE_FORCE_EXPORT in headerOHOS::Ace::NG::ClassName*;After applying the appropriate solution:
# 1. Navigate to OpenHarmony root and rebuild
cd <openharmony_root>
./build.sh --product-name rk3568 --build-target ace_engine
# 2. Check if symbol is now exported (for scenarios 2-3)
nm -D out/rk3568/arkui/ace_engine/libace.z.so | grep SymbolName
# 3. Extract new errors
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/rk3568/build.log
# 4. Check result
cat out/rk3568/last_error.log
# For SDK builds (⚠️ use out/sdk/ directory):
# 1. Build SDK: ./build.sh --product-name ohos-sdk --ccache
# 2. Extract errors: foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/sdk/build.log
# 3. Check result: cat out/sdk/last_error.log
Common mistakes (DO NOT do):
⚠️ CRITICAL - CACHE CLEARING IS FORBIDDEN:
Other common mistakes:
__attribute__((visibility("default"))) instead of ACE_FORCE_EXPORTstruct ACE_FORCE_EXPORT ClassName for template class methods (Scenario 5)"ClassName<T>::*" doesn't work (Scenario 5)✅ ALWAYS do:
OHOS::Ace::NG::ClassName*; (Scenario 5)Error signature:
error: member access into incomplete type 'const ClassName'
error: invalid use of incomplete type 'class ClassName'
error: member access into incomplete type 'OHOS::Ace::Animator'
rawPtr_->IncRefCount();
Common causes:
⚠️ SPECIAL CASE: RefPtr<T> as Class Member
When encountering incomplete type errors with RefPtr<T> or WeakPtr<T> as class members:
DO NOT simply add the full include to the header file. Instead:
class Animator;= default):
AnimatableColor(); // Declaration only
~AnimatableColor(); // Declaration only
AnimatableColor(const AnimatableColor& color); // Declaration only
= default:
// animatable_color.cpp
#include "core/animation/animator.h" // Full definition here
AnimatableColor::AnimatableColor() = default;
AnimatableColor::~AnimatableColor() = default;
AnimatableColor::AnimatableColor(const AnimatableColor& color) = default;
See: references/forward-declaration-refptr-member.md for detailed solution
Error signature:
error: redefinition of 'symbol_name'
Common causes:
All cases are organized by problem type in references/ directory.
Location: references/undefined-symbol-missing-cpp.md
Error signature:
ld.lld: error: undefined symbol: OHOS::Ace::TextTheme::Builder::Build
ld.lld: error: undefined symbol: OHOS::Ace::AdvancedTextStyle::GetGradient
Common causes:
Solution: Add .cpp to both component BUILD.gn AND frameworks/core/BUILD.gn xx_ng_source_set
Location: references/symbol-export-ace-force-export.md
Error signature:
ld.lld: error: undefined symbol: OHOS::Ace::NG::DialogTypeMargin::UpdateDialogMargin
>>> referenced by dialog_button.cpp (timepicker module)
Common causes:
Solution: Add ACE_FORCE_EXPORT to header declaration and add to build/libace.map
Location: references/symbol-export-libace-map.md
Error signature:
ld.lld: error: undefined symbol: OHOS::Ace::NG::ClassName::MethodName
Context: Symbol has ACE_FORCE_EXPORT but still not exported
Common causes:
Solution: Add symbol to build/libace.map with correct format: OHOS::Ace::NG::ClassName::MethodName*;
Location: references/redefinition-error-constexpr.md
Error signature:
error: redefinition of 'DRAG_BACKGROUND_OPACITY'
error: redefinition of 'URL_DISA_OPACITY'
Common causes:
Solution: Remove duplicate definition from .cpp, keep only inline constexpr in header
Location: references/build-system-ace-core-ng-source-set.md
Error signature:
ld.lld: error: undefined symbol
Context: File exists in component BUILD.gn but symbol still undefined
Common causes:
Solution: Add file to ace_core_ng_source_set template in frameworks/core/BUILD.gn
Location: references/forward-declaration-refptr-member.md
Error signature:
error: member access into incomplete type 'OHOS::Ace::Animator'
rawPtr_->IncRefCount();
note: in instantiation of member function 'OHOS::Ace::RefPtr<OHOS::Ace::Animator>::RefPtr'
Context: RefPtr<Animator> or WeakPtr<T> used as class member variable
Common causes:
= default in headerCorrect Solution: DO NOT revert forward declaration! Use implementation separation:
class Animator;= default)= defaultBenefits: Reduced header dependencies, faster compilation (57% improvement in example)
Location: references/test-missing-source-files.md
Error signature:
ld.lld: error: undefined symbol: OHOS::Ace::ClassName::MethodName(...)
>>> referenced by test_file.cpp:123
Context: Linking test executable (e.g., xxx_unittest)
Common causes:
Common missing files:
log_wrapper.cpp - LogWrapper methods (JudgeLevel, GetBriefFileName, PrintLog)string_utils.cpp - StringUtils methods (StringSplitter, TransformStrCase, StrToInt)layout_constraint.cpp - LayoutConstraintT template methodsmeasure_property.cpp - PaddingPropertyF, MeasureProperty methodsSolution: Add missing .cpp files to appropriate sources based on test template type:
⚠️ Critical: Only add source files, do NOT modify cflags/configs/defines
Location: references/forward-declaration-struct-helper-method.md
Error signature:
error: member access into incomplete type 'OHOS::Ace::PixelMap'
shadowInfo.pixelMap->GetPixelMapSharedPtr()
^
note: forward declaration of 'OHOS::Ace::PixelMap'
class PixelMap;
Context: Pure data structure (POD struct) contains RefPtr<T> member and needs -> access
Common causes:
RefPtr<T> member variable-> operator on the smart pointerpixelMap->Method() triggers incomplete type errorRoot Cause:
RefPtr<T>::operator->() returns LifeCycleCheckable::PtrHolder<T>PtrHolder constructor/destructor needs complete type definition to access usingCount_Solution: Add helper method to encapsulate type access:
std::shared_ptr<::OHOS::Media::PixelMap> GetPixelMapSharedPtr() const;interaction_data.cpp)#include "base/image/pixel_map.h"-> accessAdvanced Scenario (when helper method is not enough):
std::vectorstd::vector::operator= triggers copy, needs complete typeforward-declaration-struct-helper-method.md - "Advanced Scenario" sectionKey Points:
::OHOS::Media::PixelMap to avoid namespace confusionLocation: references/namespace-ambiguous-type-resolution.md
Error signature:
error: no member named 'DragEvent' in namespace 'OHOS::Ace'
using OnDragStartFunc = std::function<DragDropBaseInfo(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)>;
~~~~~~~~~~~~~^
Context: Type defined in parent namespace, used in child namespace
Common causes:
DragEvent defined in OHOS::Ace namespaceOHOS::Ace::NG child namespace- OHOS::Ace::DragEvent)Root Cause:
OHOS::Ace::DragEvent)OHOS::Ace::NG)Correct Solutions (in priority order):
Preserve full namespace qualifier (RECOMMENDED):
// In OHOS::Ace::NG namespace
using OnDragStartFunc = std::function<DragDropBaseInfo(
const RefPtr<OHOS::Ace::DragEvent>&, // ✅ Keep full namespace
const std::string&)>;
Add forward declaration in correct namespace:
// In header, before OHOS::Ace::NG namespace
namespace OHOS::Ace {
class DragEvent; // ✅ Forward declare in correct namespace
}
// In OHOS::Ace::NG namespace
using OnDragStartFunc = std::function<DragDropBaseInfo(
const RefPtr<OHOS::Ace::DragEvent>&, // Still need full namespace
const std::string&)>;
Add header dependency (when complete type needed):
#include "core/components_ng/event/drag_event.h"
// In OHOS::Ace::NG namespace
using OnDragStartFunc = std::function<DragDropBaseInfo(
const RefPtr<OHOS::Ace::DragEvent>&, // Still use full namespace
const std::string&)>;
⚠️ Critical:
OHOS::Ace, forward declaration must also be in OHOS::AceKey Points:
When to use:
-> or *Location: references/lto-virtual-thunk-libace-map-export.md
Error signature:
ld.lld: error: undefined symbol: virtual thunk to OHOS::Ace::TouchEventTarget::~TouchEventTarget()
>>> referenced by ld-temp.o
>>> lto.tmp:(construction vtable for OHOS::Ace::TouchEventTarget-in-OHOS::Ace::V2::ListScrollBarController)
>>> referenced by ld-temp.o
>>> lto.tmp:(construction vtable for OHOS::Ace::TouchEventTarget-in-OHOS::Ace::VerticalDragRecognizer)
Context: Class with virtual functions used as base class, destructor declared in header and implemented in .cpp (forward declaration optimization), LTO (Link Time Optimization) enabled
Common causes:
Root Cause:
= default in header)Solution: Keep forward declaration optimization, add libace.map exports:
~TouchEventTarget() override; in header, implementation in .cppOHOS::Ace::TouchEventTarget::*; - Export all class symbolsvirtual?thunk?to?OHOS::Ace::TouchEventTarget::*; - Export LTO virtual thunksKey Points:
ClassName::*; AND virtual?thunk?to::ClassName::*;* matches all methods including virtual thunksWhy This Works:
When to use:
Common Mistakes:
ClassName::*; without virtual thunk patternLocation: references/mingw-dllexport-declaration-mismatch.md
Error signature:
error: redeclaration of 'OHOS::Ace::NG::PaddingPropertyT::SetEdges' cannot add 'dllexport' attribute
void PaddingPropertyT<T>::SetEdges(const T& leftValue, const T& rightValue, const T& topValue, const T& bottomValue)
^
note: previous declaration is here
void SetEdges(const T& leftValue, const T& rightValue, const T& topValue, const T& bottomValue);
^
Context: MinGW/Windows platform compilation only
Key features:
ACE_FORCE_EXPORT to template methodsCommon causes:
ACE_FORCE_EXPORTACE_FORCE_EXPORT but header doesn'tRoot Cause:
__declspec(dllexport) but implementation has it → compilation failsSolution: Add ACE_FORCE_EXPORT to ALL overloaded method declarations in header:
// Header file - add to ALL declarations
ACE_FORCE_EXPORT void SetEdges(const T& padding);
ACE_FORCE_EXPORT void SetEdges(const T&, const T&, const T&, const T&); // ✅ Don't forget
ACE_FORCE_EXPORT bool operator==(const PaddingPropertyT& value) const;
ACE_FORCE_EXPORT bool operator!=(const PaddingPropertyT& value) const; // ✅ Don't forget
Key Points:
ACE_FORCE_EXPORTWhen to use:
Prevention checklist:
ACE_FORCE_EXPORT to ALL header declarationsACE_FORCE_EXPORT to ALL .cpp definitionsLocation: references/case-std-function-refptr-forward-declaration.md
Error signature:
error: no member named 'DragEvent' in namespace 'OHOS::Ace'
using OnDragStartFunc = std::function<DragDropBaseInfo(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)>;
~~~~~~~~~~~^
Context: std::function template using RefPtr<T> as parameter type
Key features:
RefPtr<T> is a pointer wrapper with fixed sizeusing alias does NOT immediately instantiate templateCommon causes:
std::function requires complete type definitionRoot Cause:
RefPtr<T> has fixed size (pointer size), so forward declaration worksusing OnDragStartFunc = ... is just a type alias, not instantiationSolution: Use forward declaration in header, full definition in .cpp:
// Header file (gesture_event_hub.h)
namespace OHOS::Ace {
class DragEvent; // ✅ Forward declaration only
}
namespace OHOS::Ace::NG {
// Type alias - NO template instantiation here
using OnDragStartFunc = std::function<DragDropBaseInfo(
const RefPtr<OHOS::Ace::DragEvent>&, // ✅ Works with forward decl
const std::string&)>;
}
// Implementation file (gesture_event_hub.cpp)
#include "core/gestures/drag_event.h" // ✅ Full definition here
// Actual usage - template instantiation happens here
OnDragStartFunc callback = ...;
Key Principles:
When to use:
std::function<RefPtr<T>> in header (type alias)std::vector<RefPtr<T>> in header (no instantiation)Comparison with Related Cases:
Benefits:
Real-World Example: OpenHarmony ACE Engine - gesture_event_hub.h optimization successfully uses forward declaration with std::function<RefPtr<OHOS::Ace::DragEvent>>
# Search for symbol definition in codebase
grep -r "SymbolName" --include="*.h" --include="*.cpp" frameworks/
# Check if .cpp file exists
find frameworks/ -name "implementation_file.cpp"
# Check if file in BUILD.gn
grep -r "implementation_file.cpp" frameworks/*/BUILD.gn
# Check ace_core_ng source set
grep -A 100 "ace_core_ng_source_set" frameworks/core/BUILD.gn | grep "implementation_file.cpp"
# Check if symbol exported in shared library
nm -D out/rk3568/arkui/ace_engine/libace.z.so | grep SymbolName
# Check libace.map
grep "SymbolName" build/libace.map
⚠️ ABSOLUTE PROHIBITION - When encountering ANY build errors:
Rule Description: NEVER, UNDER ANY CIRCUMSTANCES, suggest clearing LTO cache, deleting build directories, or performing a "clean build" as the first or primary solution.
What is STRICTLY FORBIDDEN:
thinlto-cache directoryllvmcache-* directoriesout/obj directoryout/ directoryrm -rf out/Why this is FORBIDDEN:
Remember: Real build errors have real causes. Find them, fix them. Don't blame the cache.
⚠️ CRITICAL RULE - When encountering "file not found" or "no such file or directory" header errors:
Rule Description: When compilation fails due to missing header files, ALWAYS follow this priority order:
Why this rule?:
How to Detect Optimized Headers:
Before suggesting any header modifications, CHECK if the header file is in an optimization state:
# Check 1: Staged changes (暂存状态)
git status --porcelain | grep "^M.*\.h$"
# Check 2: Modified but not staged (修改状态)
git status --porcelain | grep "^ M.*\.h$"
# Check 3: Recent commit (最近一笔提交)
git log -1 --name-only --pretty=format:"" | grep "\.h$"
# Combined check - all three states:
git status --porcelain | grep "\.h$" # Staged or modified
git diff HEAD~1 --name-only | grep "\.h$" # Changed in last commit
If the header is in ANY of these states:
When to add to .cpp file (PREFERRED):
// ✅ CORRECT - Add to the .cpp file with the compilation error
// frameworks/core/components_ng/pattern/search/search_gesture_event_hub.cpp
#include "core/events/click_event.h" // Add missing header here
// ❌ WRONG - Do NOT add back to optimized headers
// frameworks/core/components_ng/event/click_event.h
// #include "core/pipeline/base/element.h" // Don't restore deleted dependencies
User Confirmation Template (when header modification might be necessary):
⚠️ 检测到 [header_name.h] 可能正在被优化(状态:暂存/修改/最近提交)
编译错误:[error_message]
缺失头文件:[missing_header.h]
错误位置:[error_file.cpp:line]
建议方案:
✅ 方案1(推荐):在 [error_file.cpp] 中添加 #include "[missing_header.h]"
- 保持头文件优化成果
- 不增加头文件依赖
- 符合最佳实践
⚠️ 方案2(需确认):在 [header_name.h] 中添加回 #include "[missing_header.h]"
- 可能影响编译性能优化
- 需要用户确认必要性
请确认是否使用方案1,或说明为何需要方案2?
Examples of optimized headers (do NOT modify without confirmation):
animation_utils.h - Animation utility functionsclick_event.h - Click event handlingDetection Workflow:
Step 1: When encountering "file not found" error
# Extract the missing header path from error
# Example: error: 'core/pipeline/base/element.h' file not found
Step 2: Check if the referencing file is an optimized header
# Find where this error occurs
grep -r "#include.*element.h" frameworks/core/components_ng/event/click_event.h
# Check if click_event.h is being optimized
git status --porcelain | grep "click_event.h"
git log -1 --name-only | grep "click_event.h"
Step 3: Apply the appropriate solution
Verification steps:
Key Principles:
Related Skills:
Related Cases:
⚠️ CRITICAL RULE - When encountering type mismatch errors with common class names:
Rule Description: When error messages show type mismatches for common class names (like PixelMap), ALWAYS verify you're using the correct namespace variant for the code location.
Common Pitfall - PixelMap Namespace Confusion:
In ACE Engine frameworks (frameworks/core/components_ng/, etc.):
OHOS::Ace::PixelMap (wrapper class in base/image/pixel_map.h)OHOS::Media::PixelMap (underlying media class)Why this happens:
Ace::PixelMap is a wrapper around Media::PixelMapbase/image/pixel_map.hMedia::PixelMapSolution Pattern:
Identify the error location:
frameworks/ directoryUse correct type:
// ✅ CORRECT for frameworks/
#include "base/image/pixel_map.h"
RefPtr<PixelMap> pixelMap_; // OHOS::Ace::PixelMap
// ❌ WRONG in frameworks/
#include "native_image/imageinfo.h" // Don't include media headers
RefPtr<Media::PixelMap> pixelMap_; // Wrong namespace
Fix all occurrences:
# Find wrong usage
grep -rn "Media::PixelMap" frameworks/core/components_ng/
# Replace with correct type
# Media::PixelMap → PixelMap (or OHOS::Ace::PixelMap)
When to apply this rule:
frameworks/ (not interfaces/)DO NOT:
Media::PixelMap is correct just because IDE suggests itusing Media::PixelMap; to fix namespace issuesVerification:
#include "base/image/pixel_map.h" presentRefPtr<PixelMap> or RefPtr<OHOS::Ace::PixelMap>Media::PixelMap references in framework codeRelated Patterns:
⚠️ CRITICAL - RULES FOR NON-TEMPLATE CLASSES AND NON-TEMPLATE METHODS:
When encountering "undefined symbol" linker errors for non-template classes and non-template methods, follow these rules in order:
Rule 1: Check if class has ACE_FORCE_EXPORT
First, check if the class definition has ACE_FORCE_EXPORT:
// Case A: Class WITHOUT ACE_FORCE_EXPORT
class PaddingPropertyF { // ← No export on class
float Width() const;
};
// Case B: Class WITH ACE_FORCE_EXPORT
class ACE_FORCE_EXPORT PaddingPropertyF { // ← Export on entire class
float Width() const;
};
Rule 2: Apply export based on class export status
Case A - Class WITHOUT ACE_FORCE_EXPORT:
ACE_FORCE_EXPORT to method declaration in header (PREFERRED)// ✅ CORRECT - Add to header declaration
// interfaces/inner_api/ace_kit/include/ui/properties/ng/measure_property.h
class PaddingPropertyF {
ACE_FORCE_EXPORT float Width() const; // ← Add here
ACE_FORCE_EXPORT float Height() const; // ← Add here
};
// frameworks/core/components_ng/property/measure_property.cpp
// NO ACE_FORCE_EXPORT here
float PaddingPropertyF::Width() const { /* implementation */ }
Case B - Class WITH ACE_FORCE_EXPORT:
ACE_FORCE_EXPORT to individual methods// ✅ CORRECT - No individual method exports needed
class ACE_FORCE_EXPORT PaddingPropertyF { // ← Entire class exported
float Width() const; // Automatically exported
float Height() const; // Automatically exported
};
Rule 3: Add to libace.map with fine-grained symbol names ⭐
⚠️ CRITICAL: ALWAYS prefer fine-grained symbol export as the FIRST choice
After applying Rule 1 and Rule 2, add the symbol to build/libace.map:
// build/libace.map
{
global:
// ✅ FINE-GRAINED - Export specific methods (PREFERRED - ALWAYS TRY THIS FIRST)
OHOS::Ace::PaddingPropertyF::Width*;
OHOS::Ace::PaddingPropertyF::Height*;
// ✅ FINE-GRAINED CONSTRUCTORS - Match all constructor overloads
OHOS::Ace::VelocityTracker::VelocityTracker*; // Matches both constructors
// ⚠️ ACCEPTABLE - Export entire class (ONLY if fine-grained not feasible)
OHOS::Ace::PaddingPropertyF::*;
};
Fine-Grained Export Pattern Priority (in order of preference):
Method-level (MOST PREFERRED):
OHOS::Ace::ClassName::MethodName*; # Single method
Constructor-level (CONSTRUCTORS):
OHOS::Ace::ClassName::ClassName*; # All constructor overloads
Class-level (LAST RESORT):
OHOS::Ace::ClassName::*; # All class members (use sparingly)
Why fine-grained export? ⭐
Decision Tree:
Linker Error: undefined symbol ClassName::MethodName
↓
Is ClassName a non-template class?
YES → Is class declaration has ACE_FORCE_EXPORT?
YES → ✅ Class already exported
→ Add ClassName::* to libace.map
→ DONE (no individual method exports needed)
NO → ✅ Add ACE_FORCE_EXPORT to method declaration in .h
→ Add ClassName::MethodName* to libace.map
→ DONE
NO → Use template export rules (see below)
Comparison: Non-Template vs Template
| Aspect | Non-Template Class/Method | Template Class/Method |
|--------|--------------------------|----------------------|
| Export location | Method declaration in .h (Rule 2) | Both declaration in .h AND definition in .cpp |
| Class export | Covers all methods if present | Individual methods still need export |
| libace.map | Fine-grained: ClassName::MethodName*; | Wildcard: ClassName*; or TemplateFunction*; |
| Reference | This section (Rule 2) | Pattern 1, Scenario 3 & 5 |
⚠️ TEMPLATE-ONLY RULES (NOT for non-template):
For template classes and template functions ONLY, use different rules:
Template functions (Pattern 1, Scenario 3):
ACE_FORCE_EXPORT to BOTH declaration in .h AND implementation in .cppvoid?ClassName::FunctionName*;Template class methods (Pattern 1, Scenario 5):
ACE_FORCE_EXPORT to EACH method implementation in .cppClassName*;DO NOT mix rules:
inline constexpr for header-only constantsWhen encountering "undefined symbol" linker errors for methods used by other dynamic libraries:
Before applying any export rules, FIRST determine the type:
Linker Error: undefined symbol
↓
Is it a non-template class method?
→ YES: Use Non-Template Rules (below)
→ NO: Use Template Rules (Pattern 1, Scenario 3 & 5)
✅ PREFERRED for Non-Template - Add ACE_FORCE_EXPORT to method declaration in header (.h):
// interfaces/inner_api/ace_kit/include/ui/properties/ng/measure_property.h
class PaddingPropertyF {
ACE_FORCE_EXPORT float Width() const; // ← Add here (PREFERRED)
ACE_FORCE_EXPORT float Height() const; // ← Add here (PREFERRED)
};
// frameworks/core/components_ng/property/measure_property.cpp
// NO ACE_FORCE_EXPORT here for non-template methods
float PaddingPropertyF::Width() const
{
return left.value_or(0.0f) + right.value_or(0.0f);
}
Why this approach for non-templates?
⚠️ CRITICAL: Check Class Export Status First
// Case A: Class WITHOUT export → Add to individual method declarations
class PaddingPropertyF {
ACE_FORCE_EXPORT float Width() const; // ← Required
};
// Case B: Class WITH export → No individual exports needed
class ACE_FORCE_EXPORT PaddingPropertyF { // ← Entire class exported
float Width() const; // Automatically exported, no ACE_FORCE_EXPORT needed
};
❌ DO NOT for Non-Template:
ACE_FORCE_EXPORT to method definition in .cpp (unless template)ACE_FORCE_EXPORTFor template classes and template functions, use DIFFERENT rules (see Pattern 1, Scenarios 3 & 5):
| Rule Type | Non-Template | Template |
|-----------|--------------|----------|
| Export location | Method declaration in .h | BOTH declaration in .h AND definition in .cpp |
| Class export sufficient? | YES (covers all methods) | NO (individual methods need export) |
| libace.map pattern | Fine-grained: ClassName::MethodName*; | Wildcard: ClassName*; |
| Reference | This section | Pattern 1, Scenarios 3 & 5 |
| Scenario | Recommended Location | Example |
|----------|---------------------|---------|
| Non-template class method | Method declaration in .h | PaddingPropertyF::Width() |
| Template class method | Both declaration in .h AND implementation in .cpp | LayoutConstraintT<T>::UpdateMaxSizeWithCheck() |
| Template function | Both declaration in .h AND implementation in .cpp | StringUtils::StringSplitter<T> |
| Free function (non-template) | Method declaration in .h | StringUtils::TransformStrCase<std::string> |
| Class with export already | None needed | All methods auto-exported |
Non-Template Methods (PaddingPropertyF):
ACE_FORCE_EXPORT to method declarations in .hOHOS::Ace::PaddingPropertyF::Width*;Template Class Methods (LayoutConstraintT):
ACE_FORCE_EXPORT to each method implementation in .cppOHOS::Ace::NG::LayoutConstraintT*;Template Functions (StringUtils):
ACE_FORCE_EXPORT to both declaration in .h AND implementation in .cppvoid?OHOS::Ace::StringUtils::StringSplitter*;Remember: When fixing linker errors for symbols needed by other modules, try the .cpp implementation approach first before modifying headers.
For template classes with explicit instantiation:
Issue: PaddingPropertyT<CalcLength> symbols not exported, but PaddingPropertyT<Dimension> works
Root Cause: When a type is used as template parameter for explicit instantiation, the type itself must have export attribute
Key Principle:
Template Type Visibility (CalcLength)
↓
Template Specialization (PaddingPropertyT<CalcLength>)
↓
Symbol Export Success/Failure
CalcLength has no export → Template specialization inherits internal visibilityCalcLength has ACE_FORCE_EXPORT → Template specialization can exportSolution:
// ❌ BEFORE - Type missing export (fails when used as template parameter)
class CalcLength {
std::string ToString() const { /* inline */ }
};
// ✅ AFTER - Add type-level export (required for template parameters)
class ACE_FORCE_EXPORT CalcLength { // ← Required when used as template type
std::string ToString() const { /* inline - keep in header */ }
};
Critical Rules:
ACE_FORCE_EXPORT in .cppWhen Type-Level Export is Required:
Reference: See references/template-instantiation-type-export.md for detailed case study
⚠️ IMPORTANT - Header Optimization:
After user applies the recommended fixes, suggest these verification commands:
# 1. Navigate to OpenHarmony root directory and rebuild
cd <openharmony_root>
./build.sh --product-name rk3568 --build-target ace_engine --ccache
# 2. Check for link errors in out/<product>/build.log
grep "ld.lld: error:" out/rk3568/build.log | wc -l
# 3. Verify symbol export (if applicable)
nm -D out/rk3568/arkui/ace_engine/libace.z.so | grep SymbolName
# 4. Extract and check new errors from out/<product>/build.log
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/rk3568/build.log
# 5. Read the extracted errors:
cat out/rk3568/last_error.log
# For SDK builds (⚠️ use out/sdk/ directory):
# 1. Build SDK: ./build.sh --product-name ohos-sdk --ccache
# 2. Check errors: grep "error:" out/sdk/build.log | tail -50
# 3. Extract errors: foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/sdk/build.log
# 4. Read errors: cat out/sdk/last_error.log
Note: These are suggestions for the user to run manually. Do not execute build commands automatically.
When solving new build errors:
examples/<case-name>.mdUser: "帮我分析一下构建错误"
Assistant: "I'll analyze the build errors from the OpenHarmony output directory.
⚠️ FIRST, I'll extract the latest errors from build.log:
[STEP 1 - NAVIGATE TO ROOT]
cd <openharmony_root>
[STEP 2 - EXTRACTION - MANDATORY]
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/rk3568/build.log
Output:
Extracted latest error block (24 bytes) from out/rk3568/build.log
→ Saved to out/rk3568/last_error.log
[STEP 3 - READ EXTRACTED ERRORS]
Reading out/rk3568/last_error.log...
Content:
build success, no error
[STEP 4 - CHECK FOR SUCCESS]
✅ Build is successful! No errors found.
## ✅ 构建成功
最新的构建已经成功完成,没有发现任何错误。
**构建状态**: 成功
**错误信息**: 无
建议: 您可以继续进行开发或测试工作。
[STOP - DO NOT read other log files like error.log]"
User: "帮我分析一下构建错误"
Assistant: "I'll analyze the build errors from the OpenHarmony output directory.
⚠️ FIRST, I'll extract the latest errors from build.log:
[STEP 1 - NAVIGATE TO ROOT]
cd <openharmony_root>
[STEP 2 - EXTRACTION - MANDATORY]
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/rk3568/build.log
Output:
Extracted latest error block (12345 bytes) from out/rk3568/build.log
→ Saved to out/rk3568/last_error.log
[STEP 3 - READ EXTRACTED ERRORS]
Reading out/rk3568/last_error.log...
[STEP 4 - CATEGORIZE]
Identified as: compilation error - undeclared identifier
[STEP 5 - MATCH PATTERNS]
Checking references/ directory for similar patterns...
Found match: references/undefined-symbol-missing-cpp.md
[STEP 6 - PROVIDE RECOMMENDATIONS]
Providing detailed fix recommendations (NOT modifying files)
## 构建错误分析
### 错误类型
编译错误 - 未声明的标识符
### 错误位置
frameworks/core/event/touch_event.cpp:25
### 根本原因
函数被删除但调用点未移除:TouchPoint::CovertId() 已删除,但头文件中仍有声明且多处调用
### 修复建议
**选项1: 恢复函数实现** (推荐)
在 frameworks/core/event/touch_event.cpp 中恢复函数:
**当前代码**: (函数已删除)
**应添加**:
```cpp
void TouchPoint::CovertId()
{
if (sourceTool == SourceTool::PEN) {
originalId = TOUCH_TOOL_BASE_ID + static_cast<int32_t>(sourceTool);
id = id + originalId;
}
}
选项2: 完全移除函数
需要修改以下文件:
[NOTE: Only providing recommendations, NOT modifying files]"
**Key Points**:
- ⚠️ **ALWAYS navigate to root first** → `cd <openharmony_root>` before running extraction script
- ⚠️ **ALWAYS extract first** → use script on `out/<product>/build.log` with correct relative path from root
- ✅ **THEN read** → analyze only from `out/<product>/last_error.log`
- ❌ **NEVER read** → `build.log` directly or other log files
- ✅ **Check for success** → if `last_error.log` shows "build success", STOP and report
- ❌ **NEVER read other logs** → DO NOT read `error.log`, `build_output*.log`, `error.*.log`, etc.
- ✅ **Use correct script path** → `foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/` (from OpenHarmony root)
- ✅ **Provide recommendations ONLY** → do NOT automatically modify code
## Version History
- **0.14.0** (2026-02-10): Non-Template Symbol Export Rules
- ⚠️ **重要修改**:区分非模板类和模板类的符号导出规则
- 📋 **非模板类规则**:优先在方法声明处(.h 文件)增加 ACE_FORCE_EXPORT
- 🔍 **类导出检查**:如果 class 已有 ACE_FORCE_EXPORT,则无需额外导出方法
- 🎯 **精细化导出**:libace.map 中优先使用细粒度符号名(ClassName::MethodName*)
- 📊 **决策树**:添加非模板 vs 模板的决策流程图
- 🔧 **对比表格**:非模板与模板导出规则的清晰对比
- ✅ **更新位置**:
- Best Practices 部分:"### 2. Symbol Export Rules ⭐"
- Key Principles 部分:"## ⭐ Key Principles - Symbol Export for Cross-Module Usage"
- Pattern 1 Scenario 2:更新为基于类导出状态的决策流程
- 🚫 **禁止事项**:非模板方法不要在 .cpp 中添加 ACE_FORCE_EXPORT
- 💡 **核心理念**:非模板支持精细化导出控制,模板需要宽泛通配符
- **0.13.0** (2026-02-10): CRITICAL RULE - Never Clear LTO Cache
- ⚠️ **关键修改**:绝对禁止建议清理 LTO cache 或删除构建目录
- 📋 在 Behavior Guidelines 部分添加 "CRITICAL - NEVER SUGGEST CLEARING LTO CACHE" 子部分
- 🚨 在 Best Practices 部分添加全新的 "CRITICAL RULE - NEVER Clear LTO Cache" 高优先级规则
- 💡 强调 LTO cache 问题极其罕见(99.9% 的情况都不是缓存问题)
- ⏱️ 说明清理缓存会浪费大量时间(完整重建需要数小时,增量编译只需数分钟)
- 🎯 明确要求必须分析真实错误并修复根本原因,而不是怪罪缓存
- 📝 加强 Pattern 1 Common mistakes 部分的相关说明
- ⛔ 仅在极端罕见情况下(用户明确修改了编译器标志等)才考虑缓存问题
- ✅ 即使在那些情况下,也必须先询问用户并记录具体原因
- **0.12.0** (2026-02-10): Case 11 - std::function<RefPtr<T>> Forward Declaration
- ✨ 新增 Case 11:std::function<RefPtr<T>> 前向声明成功案例
- 📝 新增案例分析文档:`case-std-function-refptr-forward-declaration.md`
- 🎯 核心观点:using 别名不立即实例化模板,RefPtr<T> 大小固定
- 💡 关键发现:模板实例化延迟到 .cpp 实际使用时
- 📊 对比表格:Case 6/8/11 的 RefPtr<T> 前向声明使用场景
- 🔧 纠正错误理解:std::function 不需要完整类型定义
- ✅ 实战案例:OpenHarmony gesture_event_hub.h 优化成功应用
- 🛡️ 验证原则:RefPtr<> 本质是指针包装器,前向声明可行
- **0.11.0** (2026-02-09): High Priority Rule - Header Optimization Protection
- ⭐ 新增高优先级规则:处理头文件缺失错误时的优先级顺序
- 🔍 新增优化检测方法:通过 git status 检测暂存/修改/最近提交状态
- ✅ 优先方案:在出错的 .cpp 文件中添加缺失头文件(推荐)
- ⚠️ 最后手段:仅在用户确认后才修改已优化的头文件
- 📝 新增用户确认模板:清晰展示两个方案供用户选择
- 🔧 新增检测工作流:三步检测并应用正确的解决方案
- 🛡️ 保护头文件优化成果:避免盲目回退已删除的依赖
- 🔗 关联 header-optimization 和 compile-analysis skills
- **0.10.0** (2026-02-06): Case 8 Advanced Scenario - Struct with Own .cpp File
- ✨ 新增 Case 8 进阶场景:当辅助方法模式不够时的完整解决方案
- 📝 在 `forward-declaration-struct-helper-method.md` 中添加 Advanced Scenario
- 🎯 应用场景:结构体有 .cpp 文件,被 std::vector 使用,需要保持聚合初始化
- 💡 关键技术:升级为完整的前向声明优化(类似 Case 6),同时保留辅助方法
- 🔧 决策树:指导何时使用标准方案 vs 完整方案
- 📊 对比表格:标准方案(无 .cpp)vs Advanced Scenario(有 .cpp)
- ⚠️ 渐进式升级:从辅助方法模式开始,遇到 vector 拷贝问题时升级
- 🔗 关联 Case 6 和 Case 7:完整的 RefPtr 成员优化知识体系
- **0.9.0** (2026-02-04): LTO Virtual Thunk Export Solution
- ✨ 新增 LTO Virtual Thunk 导出案例分析:`lto-virtual-thunk-libace-map-export.md`
- 📝 新增 Case 9:基类虚函数 + LTO 的 libace.map 导出解决方案
- 🎯 核心观点:保持前向声明优化,不要回退到 inline 定义
- 💡 关键技术:在 libace.map 中同时导出 `ClassName::*;` 和 `virtual?thunk?to::ClassName::*;`
- 🔧 LTO 工作原理:链接时创建 virtual thunk 调整 this 指针
- 📊 符号导出模式:通配符 `*` 匹配所有方法和 virtual thunk
- ⚠️ 常见错误:只导出类符号而忘记导出 virtual thunk
- **0.8.0** (2026-02-04): Struct RefPtr Member Optimization
- ✨ 新增结构体智能指针成员优化案例分析:`forward-declaration-struct-helper-method.md`
- 📝 新增 Case 8:纯数据结构中 RefPtr 成员的辅助方法模式
- 🎯 与 Case 6 的区别:Case 6 适用于有自己 .cpp 的类,Case 8 适用于纯数据结构
- 💡 关键技术:使用辅助方法封装完整类型访问,保持头文件前向声明优化
- 🔧 完全限定名 `::OHOS::Media::PixelMap` 避免命名空间混淆
- 📊 编译性能优化:减少头文件依赖,降低重编译范围
- **0.7.0** (2026-02-02): Test Linking Error Support
- ✨ 新增测试链接错误案例分析:`test-missing-source-files.md`
- 📝 新增 Case 7:测试中缺失源文件的通用解决方案
- 🎯 泛化案例场景,不仅限于 LogWrapper,涵盖所有缺失源文件情况
- 📋 列出常见缺失源文件:log_wrapper.cpp、string_utils.cpp、layout_constraint.cpp 等
- ⚠️ 强调只添加源文件,不修改 cflags/configs/defines
- 🌳 添加决策树帮助判断正确的解决方案
- **0.6.0** (2025-02-02): 新增 SDK 编译错误分析支持
- ✨ 添加 SDK 错误触发关键词:"分析SDK的编译错误"、"analyze SDK build errors"、"check SDK errors"
- ⚠️ 特别说明:SDK 日志路径为 `out/sdk/build.log` 和 `out/sdk/last_error.log`(特殊目录)
- 📝 更新所有路径示例,标注 SDK 的特殊目录结构
- 🔧 优化错误提取命令,支持 SDK 路径
- **0.5.0** (2026-01-27): 模板类方法导出支持
- **0.4.0** (2026-01-27): 模板实例化类型导出支持
- **0.3.0** (2026-01-27): 符号导出最佳实践
- **0.2.0** (2026-01-27): 添加重定义错误案例
- **0.1.0** (2026-01-27): 初始版本,包含未定义符号案例研究
## Related Skills
- **openharmony-build**: For building OpenHarmony codebase
- **compile-analysis**: For analyzing compilation performance and dependencies
development
Run local code quality checks covering a subset of OpenHarmony gate CI (copyright, CodeArts C/C++) plus additional local checks (pylint/flake8, shellcheck/bashate, gn format). Use before committing to reduce gate failures. Triggers on: /oh-precommit-codecheck, "门禁检查", "门禁预检", "检查代码", "run codecheck", "check code quality", "lint my code", "代码检查", or after completing code implementation. WHEN to use: before git commit, before creating PR, after modifying C/C++/Python/Shell/GN files, when gate CI fails with codecheck defects, or when you want to preview what gate will flag.
development
OpenHarmony PR full lifecycle workflow. Five modes: - Commit: standardized commit with DCO sign-off and Issue linking - Create PR: commit + push to fork + create Issue + create PR on upstream - Fix Codecheck: fetch gate CI codecheck defects from a PR and auto-fix them - Review PR: fetch a PR's changes to local for code review - Fix Review: fetch unresolved review comments from a PR and auto-fix them Triggers on: /oh-pr-workflow, "提交代码", "创建PR", "提个PR", "commit", "修复告警", "修复门禁", "修复codecheck", "fix codecheck", "review pr", "review这个pr", "看下这个pr", "检视pr", "修复review", "修复检视意见", "fix review", or a GitCode PR URL with fix/review intent.
testing
分析 HM Desktop PRD 文档,提取需求信息、验证完整性、检查章节顺序(需求来源→需求背景→需求价值分析→竞品分析→需求描述)、检查 KEP 定义、检测需求冲突并生成结构化分析报告。适用于用户请求:(1) 分析或审查 PRD 文档, (2) 从需求中提取 KEP 列表, (3) 检查 PRD 完整性或一致性, (4) 将需求映射到模块架构, (5) 验证 PRD 格式合规性, (6) 验证竞品分析章节完整性。关键词:PRD分析, requirement extraction, KEP验证, completeness check, chapter order validation, 竞品分析检查, analyze PRD, 需求提取, 完整性检查, 章节顺序验证
development
基于 PRD 文档自动生成鸿蒙系统设计文档,包括架构设计文档和功能设计文档。生成前会分析 OpenHarmony 存量代码结构,确保与现有架构兼容。架构设计文档第2章必须为竞品方案分析,位于需求背景之后。适用于用户请求:(1) 生成架构设计文档, (2) 生成功能设计文档, (3) 从 PRD 生成设计文档, (4) 创建系统架构设计, (5) 编写功能规格说明, (6) 分析 OH 代码结构。关键词:architecture design, functional design, design doc, 竞品方案分析, OpenHarmony code analysis, 架构设计, 功能设计, 设计文档生成, OH代码分析, analyze codebase, competitor analysis