Build Error Analyzer Skill
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.
⚠️ CRITICAL WORKFLOW (MUST FOLLOW)
YOU MUST ALWAYS FOLLOW THIS EXACT SEQUENCE:
- •FIRST: Extract errors from
out/<product>/build.log→ generatesout/<product>/last_error.log - •THEN: Read and analyze ONLY from
out/<product>/last_error.log - •NEVER: Read directly from
out/<product>/build.logor any other log files (error.log, build_output*.log, etc.) - •SUCCESS CASE: If
last_error.logcontains "build success" or "no error", STOP and report success
Why?:
- •
build.logcontains the entire build history (thousands of lines) - •
last_error.logcontains ONLY the most recent error block (extracted by script) - •Reading
build.logdirectly will give you STALE or IRRELEVANT errors - •The extraction script ensures you always analyze the LATEST errors
- •Other log files (error.log, build_output*.log) may contain outdated errors from previous builds
Before 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 error - •
no error - •Or similar success messages
IMMEDIATELY STOP and report:
## ✅ 构建成功 最新的构建已经成功完成,没有发现任何错误。 **构建状态**: 成功 **错误信息**: 无 建议: 您可以继续进行开发或测试工作。
DO NOT:
- •❌ Continue searching for errors in other log files
- •❌ Read error.log
- •❌ Read build_output*.log files
- •❌ Look for historical errors
Important Path Information
Always use these paths:
- •Extraction Script:
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh(relative to OpenHarmony root) - •Source Build Log:
out/<product>/build.log(e.g.,out/rk3568/build.log) - DO NOT READ DIRECTLY - •Target Error Log:
out/<product>/last_error.log(auto-generated in same directory as build.log) - READ ONLY THIS FILE
⚠️ SPECIAL CASE - SDK Build Paths:
- •SDK Build Log:
out/sdk/build.log(NOTout/ohos-sdk/build.log) - •SDK Error Log:
out/sdk/last_error.log(NOTout/ohos-sdk/last_error.log) - •SDK Product Exception: SDK uses
out/sdk/directory instead ofout/ohos-sdk/ - •Trigger Keywords: "分析SDK的编译错误", "analyze SDK build errors", "check SDK errors"
Workflow:
- •✅ Extract errors from
out/<product>/build.logusing the script → createsout/<product>/last_error.log - •✅ For SDK: Extract from
out/sdk/build.log→ createsout/sdk/last_error.log - •✅ Analyze errors from the extracted
last_error.logONLY - •✅ Provide fix recommendations ONLY - do NOT modify code
Common Mistakes to Avoid:
- •❌ Reading
build.logdirectly (will get stale/wrong errors) - •❌ Reading
error.log(contains outdated errors from previous builds) - •❌ Reading other log files (build_output*.log, error.*.log, etc.)
- •❌ Continuing to search for errors when
last_error.logshows "build success" - •❌ Analyzing errors without extraction step
- •❌ Running extraction script from wrong directory (MUST be from OpenHarmony root)
- •✅ ALWAYS cd to
<openharmony_root>first - •✅ ALWAYS extract → then read
last_error.logONLY - •✅ If
last_error.logshows success → STOP and report success
Behavior Guidelines
This skill provides ANALYSIS and RECOMMENDATIONS ONLY:
✅ DO:
- •Extract errors from build logs
- •Analyze and categorize errors
- •Match errors against known patterns
- •Provide detailed fix recommendations with file paths and line numbers
- •Show before/after code examples
- •Explain root causes
- •Suggest verification steps
❌ DO NOT:
- •Use Edit tool to modify code files
- •Use Write tool to create or modify files
- •Run build commands automatically
- •Apply fixes without user confirmation
- •Make any changes to the codebase
- •Read from log files other than
last_error.log(error.log, build_output*.log, error.*.log, etc.) - •Continue searching for errors when build is successful
Why: The user should review and apply fixes manually to maintain control over code changes and understand the modifications.
Prerequisites
- •⚠️ CRITICAL: ALWAYS extract from
out/<product>/build.logFIRST before reading - •Error log location: The skill reads errors ONLY from
out/<product>/last_error.log(same directory as build.log) - •Error extraction: ALWAYS use the extraction script from
foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh(from OpenHarmony root) to generate/updatelast_error.logbefore reading - •Source build.log: Errors are extracted ONLY from
out/<product>/build.login the OpenHarmony output directory - •Codebase context: Can be executed from any OpenHarmony directory (ace_engine, root, etc.)
- •⚠️ SUCCESS CHECK: If
last_error.logcontains "build success" or "no error", STOP and report success - DO NOT read other log files likeerror.log,build_output*.log, etc. - •EXCLUSIVE LOG SOURCE: ONLY read from
last_error.log- NEVER fromerror.log,build_output*.log,error.*.log, or any other log files
Analysis Workflow
Step 1: Extract Latest Error (REQUIRED - ALWAYS DO THIS FIRST)
⚠️ CRITICAL: This step is MANDATORY and must be done BEFORE reading any errors.
Why this is required:
- •
build.logcontains the full build output (old and new errors mixed together) - •Reading it directly will analyze STALE or IRRELEVANT errors
- •The extraction script isolates ONLY the most recent error block
- •
last_error.logis generated in the same directory asbuild.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:
- •Extract ONLY the latest error block from
out/<product>/build.log - •Output to
out/<product>/last_error.log(same directory) - •Show error block size and summary
- •Overwrite previous
last_error.logif it exists
⚠️ DO NOT SKIP THIS STEP
- •Even if
last_error.logexists, RE-EXTRACT to get the latest errors - •DO NOT read
build.logdirectly - •DO NOT read other log files (build_output*.log, error.log, error.*.log, etc.)
- •ONLY analyze
last_error.logafter extraction
Step 2: Read and Categorize Errors
⚠️ 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 error - •
no error - •Or similar success messages
IMMEDIATELY STOP and report:
## ✅ 构建成功 最新的构建已经成功完成,没有发现任何错误。 **构建状态**: 成功 **错误信息**: 无 建议: 您可以继续进行开发或测试工作。
DO NOT continue to:
- •❌ Search for errors in error.log
- •❌ Search for errors in build_output*.log
- •❌ Search for errors in error.*.log files
- •❌ Look for historical errors
- •✅ STOP and report success
Only if there are actual errors, proceed to categorize them:
Error Categories:
- •Compilation errors (CXX tasks) - Syntax, missing headers, incomplete types
- •Linker errors (SOLINK/LINK tasks) - Undefined symbols, missing libraries
- •Build system errors - GN/Ninja configuration issues
Step 3: Match Against Known Cases
Compare error patterns against historical cases in references/ directory and provide specific solutions.
Case matching priority:
- •Match by error signature (e.g., "undefined symbol" + "referred by")
- •Match by error context (e.g., "timepicker module" usage)
- •Match by file pattern (e.g., BUILD.gn issues)
- •Provide general guidance if no specific case matches
Step 4: Provide Fix Recommendations (NO Automatic Modifications)
CRITICAL: This step provides recommendations ONLY. Do NOT use Edit/Write tools to modify code.
Based on error type and matched cases, provide:
- •Root cause analysis
- •Specific file modifications needed (with exact line numbers and code snippets)
- •Build system configuration changes (with exact GN file paths)
- •Verification steps
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:
bashgrep -r "implementation_file.cpp" frameworks/*/BUILD.gn
- •
Add .cpp to BUILD.gn:
- •Find where other files in same directory are added
- •Add the missing .cpp to the appropriate source_set
- •Important: Reference files in same directory to find correct source_set
- •DO NOT assume all files go to
ace_core_ng_source_set
- •
Verify with other files:
bash# 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:
- •Error occurs when linking a library that depends on
libaceorlibace_compatible - •GN file shows
depsincludes libace/libace_compatible - •Symbol should come from main library
Root Cause:
- •Symbol exists in main library but not exported
- •Missing ACE_FORCE_EXPORT macro
- •Symbol not in libace.map whitelist
Solution (Check in order):
- •
Add ACE_FORCE_EXPORT to method implementation in .cpp file ⭐
⚠️ CRITICAL - PREFERRED METHOD:
- •Add
ACE_FORCE_EXPORTto the function implementation in .cpp file - •DO NOT modify header (.h) file
- •This is the recommended approach for struct/class methods
Example (PaddingPropertyF case):
cpp// In implementation file (.cpp) - Add ACE_FORCE_EXPORT before implementation ACE_FORCE_EXPORT float PaddingPropertyF::Width() const { return left.value_or(0.0f) + right.value_or(0.0f); } ACE_FORCE_EXPORT float PaddingPropertyF::Height() const { return top.value_or(0.0f) + bottom.value_or(0.0f); }Alternative (if .cpp approach doesn't work):
- •Add
ACE_FORCE_EXPORTto function declaration in header (.h file) - •DO NOT use
__attribute__((visibility("default")))directly - •
ACE_FORCE_EXPORTalready encapsulates visibility attributes
Example:
cpp// In header file (.h) - Only if .cpp approach doesn't work ACE_FORCE_EXPORT ReturnType FunctionName(params); // ❌ WRONG - Do NOT use: __attribute__((visibility("default"))) ReturnType FunctionName(params);⭐ Why prefer .cpp implementation?
- •Reduces header dependencies (reference: commit e0fd3724d21)
- •Keeps header declarations clean
- •Explicit export control at implementation level
- •Consistent with StringUtils pattern (StringSplitter, TransformStrCase)
- •Add
- •
Check libace.map whitelist:
bashgrep "SymbolName" build/libace.map
Required changes:
- •Add symbol pattern to
build/libace.mapwhitelist - •Use wildcard pattern to match all overloads
Example:
code# In build/libace.map { global: OHOS::Ace::StringUtils::*; void?OHOS::Ace::StringUtils::StringSplitter*; # Template function pattern OHOS::Ace::ClassName::*; # All methods of class }; - •Add symbol pattern to
- •
Verify symbol export:
bashnm -D out/rk3568/arkui/ace_engine/libace.z.so | grep SymbolName
- •If symbol not shown, export failed
- •Rebuild after adding ACE_FORCE_EXPORT and libace.map entry
Scenario 3: Template Function Instantiation Issues
Symptoms:
- •Undefined symbol is a template function
- •Template uses forward declaration + explicit instantiation in .cpp
- •Error shows missing specific template specialization (e.g.,
StringSplitter<Color>,TransformStrCase<std::string>)
Root Cause:
- •New specialization not explicitly instantiated
- •Template declaration or implementation missing export macro
- •libace.map missing pattern for template instantiation
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:
- •Templates require BOTH declaration and implementation to have export macros
- •Explicit instantiation must be in .cpp file
- •libace.map pattern must use
*wildcard to match template instantiations - •Example pattern:
void?OHOS::Ace::StringUtils::StringSplitter*;
Scenario 4: Special Libraries (Rare Cases)
Symptoms:
- •Library does NOT depend on libace/libace_compatible
- •But uses utility functions from main library (previously inline, now in .cpp)
- •Only applies to these specific libraries:
- •
libarkoala_native_ani.so - •
libace_ndk.z.so
- •
Root Cause:
- •Utility functions changed from inline to .cpp implementation
- •Symbol not available because library doesn't link main library
- •Special case requiring local compilation
Solution:
- •Add the utility .cpp file directly to the library's BUILD.gn sources
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:
- •This solution is ONLY for
libarkoala_native_aniandace_ndk - •DO NOT use this pattern for other libraries
- •These libraries use utility functions but don't link main library
Scenario 5: Template Class Method Export Issues
Symptoms:
- •Error occurs when linking a library that depends on
libaceorlibace_compatible - •Undefined symbol is a template class method with explicit instantiation
- •Error shows:
undefined symbol: ClassName<T>::MethodName(params) - •Template class has
ACE_FORCE_EXPORTon struct declaration but methods still not exported
Example 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:
- •Template class struct declaration has
ACE_FORCE_EXPORT(e.g.,struct ACE_FORCE_EXPORT LayoutConstraintT) - •But individual method implementations in .cpp file lack
ACE_FORCE_EXPORTmacro - •Template explicit instantiation doesn't export individual methods automatically
- •Each method implementation that needs to be exported must have the macro
Solution:
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 declaration export is NOT enough: Having
struct ACE_FORCE_EXPORT LayoutConstraintTdoesn't automatically export all methods - •Each method needs macro: Every method implementation in .cpp that must be exported needs
ACE_FORCE_EXPORT - •Place macro before return type: The macro goes between
template<>and return type - •Not needed in header: Don't add
ACE_FORCE_EXPORTto 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:
- •Use unquoted patterns with wildcards:
OHOS::Ace::ClassName::*; - •DO NOT use quoted patterns with wildcards:
"OHOS::Ace::ClassName<T>::*;"(wildcards won't work) - •Unquoted wildcards match all template instantiations automatically
- •Use
*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:
- •❌ Relying only on
struct ACE_FORCE_EXPORT ClassName- NOT sufficient for methods - •❌ Forgetting to add macro to each method implementation in .cpp
- •❌ Adding macro to method declarations in header (unnecessary, struct declaration is enough)
- •❌ Using quoted patterns in libace.map:
"ClassName<T>::*"won't match - •❌ Adding specific template instantiations to libace.map: use wildcards instead
✅ Correct Approach:
- •✅ Add
ACE_FORCE_EXPORTto each template method implementation in .cpp - •✅ Place macro between
template<>and return type - •✅ Keep struct declaration with
ACE_FORCE_EXPORTin header - •✅ Use unquoted wildcard in libace.map:
OHOS::Ace::NG::ClassName*;
Step 3: Verify the Fix
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):
- •❌ DO NOT blame thinlto-cache (rarely the issue)
- •❌ DO NOT suggest clearing caches
- •❌ DO NOT suggest deleting out directory
- •❌ DO NOT skip scenario analysis
- •❌ DO NOT use
__attribute__((visibility("default")))instead of ACE_FORCE_EXPORT - •❌ DO NOT forget both declaration AND implementation export for templates
- •❌ DO NOT use Scenario 4 (local compilation) except for the two specified libraries
- •❌ DO NOT rely only on
struct ACE_FORCE_EXPORT ClassNamefor template class methods (Scenario 5) - •❌ DO NOT use quoted patterns with wildcards in libace.map:
"ClassName<T>::*"doesn't work (Scenario 5)
✅ ALWAYS do:
- •✅ Identify which library is failing
- •✅ Check if implementation exists and is compiled
- •✅ Verify ACE_FORCE_EXPORT on header declarations
- •✅ Check libace.map whitelist
- •✅ For templates: check declaration, implementation, and instantiation
- •✅ Use correct scenario based on library type
- •✅ For template class methods: add ACE_FORCE_EXPORT to each method implementation in .cpp (Scenario 5)
- •✅ Use unquoted wildcard patterns in libace.map:
OHOS::Ace::NG::ClassName*;(Scenario 5)
Pattern 2: Incomplete Type Errors
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:
- •Missing header include
- •Forward declaration without full definition
- •RefPtr<T> as class member without proper implementation separation
- •Header file optimization issues
⚠️ 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:
- •Keep forward declaration in header:
class Animator; - •Declare special member functions in header (without
= default):cppAnimatableColor(); // Declaration only ~AnimatableColor(); // Declaration only AnimatableColor(const AnimatableColor& color); // Declaration only
- •Implement them in .cpp file with
= default:cpp// 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
Pattern 3: Redefinition Errors
Error signature:
error: redefinition of 'symbol_name'
Common causes:
- •Multiple definitions across translation units
- •Missing inline/constexpr for header-only definitions
- •ODR violations
Historical Cases
All cases are organized by problem type in references/ directory.
Case 1: Undefined Symbol - Missing .cpp Files
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:
- •New .cpp files created but not added to BUILD.gn
- •Files added to component BUILD.gn but not to source_set
- •libace.z.so only links ace_core_ng libraries
Solution: Add .cpp to both component BUILD.gn AND frameworks/core/BUILD.gn xx_ng_source_set
Case 2: Symbol Export - ACE_FORCE_EXPORT Missing
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:
- •Symbol used by other modules but not marked for export
- •ACE_FORCE_EXPORT missing from header declaration
Solution: Add ACE_FORCE_EXPORT to header declaration and add to build/libace.map
Case 3: Symbol Export - libace.map Whitelist
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:
- •Symbol not in build/libace.map whitelist
- •Incorrect symbol format in version script
Solution: Add symbol to build/libace.map with correct format: OHOS::Ace::NG::ClassName::MethodName*;
Case 4: Redefinition - inline constexpr
Location: references/redefinition-error-constexpr.md
Error signature:
error: redefinition of 'DRAG_BACKGROUND_OPACITY' error: redefinition of 'URL_DISA_OPACITY'
Common causes:
- •Constant defined in both header (inline constexpr) and .cpp
- •ODR (One Definition Rule) violation
Solution: Remove duplicate definition from .cpp, keep only inline constexpr in header
Case 5: Build System - ace_core_ng_source_set
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:
- •File not in frameworks/core/BUILD.gn ace_core_ng_source_set
- •libace.z.so only links ace_core_ng libraries
Solution: Add file to ace_core_ng_source_set template in frameworks/core/BUILD.gn
Case 6: RefPtr<T> Member - Forward Declaration Optimization
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:
- •Special member functions (constructor/destructor/copy constructor) defined with
= defaultin header - •Compiler instantiates these functions in header, requiring complete type definition
- •Common mistake: reverting forward declaration and adding full include
Correct Solution: DO NOT revert forward declaration! Use implementation separation:
- •Keep forward declaration in header:
class Animator; - •Declare special member functions in header (without
= default) - •Implement them in .cpp file with
= default - •Include full definition in .cpp file
Benefits: Reduced header dependencies, faster compilation (57% improvement in example)
Case 7: Test Linking - Missing Source Files
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:
- •Test BUILD.gn missing required .cpp files in sources
- •Header optimization moved implementations to .cpp (e.g., StringUtils, LogWrapper)
- •New implementation files not added to build system
Common missing files:
- •
log_wrapper.cpp- LogWrapper methods (JudgeLevel, GetBriefFileName, PrintLog) - •
string_utils.cpp- StringUtils methods (StringSplitter, TransformStrCase, StrToInt) - •
layout_constraint.cpp- LayoutConstraintT template methods - •
measure_property.cpp- PaddingPropertyF, MeasureProperty methods
Solution: Add missing .cpp files to appropriate sources based on test template type:
- •ohos_unittest without ace_base: Add to test's sources
- •ohos_unittest with ace_base: Add to ace_base source_set
- •ace_unittest: Add to ace_base source_set (default dependency)
⚠️ Critical: Only add source files, do NOT modify cflags/configs/defines
Case 8: Struct RefPtr Member - Helper Method Pattern
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:
- •Struct contains
RefPtr<T>member variable - •Code needs to call
->operator on the smart pointer - •Direct call to
pixelMap->Method()triggers incomplete type error - •Cannot use Case 6 approach because struct has no its own .cpp file
Root Cause:
- •
RefPtr<T>::operator->()returnsLifeCycleCheckable::PtrHolder<T> - •
PtrHolderconstructor/destructor needs complete type definition to accessusingCount_ - •Pure data structures don't have their own implementation file
Solution: Add helper method to encapsulate type access:
- •Declare helper method in struct:
std::shared_ptr<::OHOS::Media::PixelMap> GetPixelMapSharedPtr() const; - •Create new implementation file (e.g.,
interaction_data.cpp) - •Implement helper method in .cpp with full include:
#include "base/image/pixel_map.h" - •Update usage to call helper method instead of direct
->access - •Add new .cpp to BUILD.gn source set
Key Points:
- •Use fully-qualified name
::OHOS::Media::PixelMapto avoid namespace confusion - •Keep forward declaration in header, full definition only in .cpp
- •Helper method encapsulates complete type access
- •Reduces header dependencies while maintaining clean API
When to use:
- •✅ Pure data structures (POD struct) with smart pointer members
- •✅ Need to dereference smart pointer with
->or* - •✅ Cannot add .cpp to existing struct
- •❌ Classes with their own .cpp file (use Case 6 instead)
- •❌ Only need constructor/destructor (use Case 6 instead)
Case 9: LTO Virtual Thunk - libace.map Export
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:
- •Class has virtual functions and is used as base class
- •Forward declaration optimization: destructor in .cpp file (not inline)
- •LTO creates virtual thunks for derived classes
- •Virtual thunk symbols not exported from library
Root Cause:
- •LTO optimizes virtual function tables during linking
- •Creates virtual thunk symbols to adjust this pointer for derived classes
- •These virtual thunk symbols must be available at link time
- •If destructor not inline, LTO-generated virtual thunk may not be exported
- •Common mistake: reverting to inline destructor (
= defaultin header)
Solution: Keep forward declaration optimization, add libace.map exports:
- •Keep destructor in .cpp file:
~TouchEventTarget() override;in header, implementation in .cpp - •Add to libace.map:
- •
OHOS::Ace::TouchEventTarget::*;- Export all class symbols - •
virtual?thunk?to?OHOS::Ace::TouchEventTarget::*;- Export LTO virtual thunks
- •
- •DO NOT revert to inline definition in header
Key Points:
- •Two export patterns required:
ClassName::*;ANDvirtual?thunk?to::ClassName::*; - •Wildcard
*matches all methods including virtual thunks - •Maintains forward declaration optimization
- •No need to sacrifice header optimization for LTO
Why This Works:
- •Compilation phase: Header uses forward declaration, .cpp has implementation
- •LTO link phase: LTO optimizes vtables, creates virtual thunks
- •Symbol export: libace.maps patterns match virtual thunks, export to dynamic symbol table
- •Runtime: Derived class vtables can reference virtual thunks correctly
When to use:
- •✅ Classes with virtual functions used as base classes
- •✅ Using forward declaration optimization (destructor not inline)
- •✅ Linker errors: "undefined symbol: virtual thunk to ClassName::~ClassName()"
- •✅ Using LTO (Link Time Optimization)
- •❌ Classes not used as base classes (won't have virtual thunks)
- •❌ Destructor already inline in header (no optimization to maintain)
- •❌ Not using LTO (traditional compilation doesn't create virtual thunks)
Common Mistakes:
- •❌ Reverting to inline destructor (loses forward declaration optimization)
- •❌ Only exporting
ClassName::*;without virtual thunk pattern - •❌ Forgetting to add libace.map entry at all
Case 10: MinGW - dllexport Declaration Mismatch
Location: 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:
- •Only occurs on MinGW/Windows builds (not Linux/MacOS)
- •Error message: "redeclaration cannot add 'dllexport' attribute"
- •Header declaration and .cpp implementation have inconsistent export attributes
- •Usually triggered after adding
ACE_FORCE_EXPORTto template methods
Common causes:
- •Header file method declaration missing
ACE_FORCE_EXPORT - •Implementation file has
ACE_FORCE_EXPORTbut header doesn't - •Only some overloaded methods have export attribute (inconsistent)
- •MinGW requires strict consistency between declaration and definition
Root Cause:
- •MinGW DLL export rules require declaration and definition export attributes to match exactly
- •If header has no
__declspec(dllexport)but implementation has it → compilation fails - •Unlike Linux/MacOS which are more lenient with visibility attributes
Solution: 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:
- •Add to header file declarations (not just .cpp implementations)
- •Ensure ALL overloaded methods are marked (don't miss any)
- •Implementation file must also have
ACE_FORCE_EXPORT - •Test on MinGW platform (Windows build)
When to use:
- •✅ MinGW/Windows compilation errors
- •✅ Error: "cannot add 'dllexport' attribute"
- •✅ Template methods with export attributes
- •❌ Linux/MacOS only (different rules)
- •❌ Link errors (this is a compilation error)
Prevention checklist:
- •✅ Confirm need for export (cross-module usage)
- •✅ Add
ACE_FORCE_EXPORTto ALL header declarations - •✅ Add
ACE_FORCE_EXPORTto ALL .cpp definitions - •✅ Check all overloaded versions (don't miss any)
- •✅ Test compilation on MinGW platform
Analysis Commands
Check Symbol Existence
# 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"
Verify Build Configuration
# 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 Symbol Export
# 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
Troubleshooting Guide
For New .cpp Files
- •Create implementation file (.cpp)
- •Add to component's BUILD.gn
- •Add to frameworks/core/BUILD.gn ace_core_ng_source_set (if used by libace.z.so)
- •If symbol is cross-module used:
- •Add ACE_FORCE_EXPORT to header declaration
- •Add to build/libace.map whitelist
For Header Optimization Issues
- •Check for forward declarations used incorrectly
- •Ensure complete types available where needed
- •Use inline constexpr for header-only constants
- •Avoid ODR violations
For Link Errors
- •Identify missing symbol from error message
- •Find symbol definition location
- •Verify implementation is compiled (in BUILD.gn)
- •Check symbol visibility/export if cross-module
- •Verify linking order and dependencies
Best Practices
1. Build System Architecture
- •libace.z.so only links ace_core_ng libraries
- •Component-specific libraries are not linked to final产物
- •New .cpp files used by libace.z.so must be in ace_core_ng_source_set
2. Symbol Export Rules ⭐
⚠️ CRITICAL - PREFERRED APPROACH:
- •Add
ACE_FORCE_EXPORTto method implementation in .cpp file (PREFERRED)- •Reduces header dependencies
- •Keeps header declarations clean
- •Explicit export control at implementation level
- •Reference: commit e0fd3724d21 (StringUtils refactoring)
Alternative (if .cpp approach doesn't work):
- •Add
ACE_FORCE_EXPORTto header declaration (.h) as fallback - •Exported symbols must be in build/libace.map
- •Symbol format:
OHOS::Ace::NG::ClassName::MethodName*;
Examples:
// ✅ PREFERRED - In .cpp implementation
ACE_FORCE_EXPORT
float PaddingPropertyF::Width() const { /* implementation */ }
// ✅ ACCEPTABLE - In .h declaration (if needed)
ACE_FORCE_EXPORT float Width() const;
3. Header Optimization
- •Use
inline constexprfor header-only constants - •Don't define in both header and .cpp
- •Forward declarations reduce dependencies but ensure complete type visible at use
⭐ Key Principles - Symbol Export for Cross-Module Usage
When encountering "undefined symbol" linker errors for methods used by other dynamic libraries:
Primary Rule: Export at Implementation, Not Declaration ⭐
✅ PREFERRED - Add ACE_FORCE_EXPORT in .cpp file:
// frameworks/core/components_ng/property/measure_property.cpp
ACE_FORCE_EXPORT
float PaddingPropertyF::Width() const
{
return left.value_or(0.0f) + right.value_or(0.0f);
}
Why this approach?
- •Reduces header dependencies - Header files stay clean (reference: StringUtils refactoring)
- •Explicit export control - Export decisions made at implementation level
- •Better compilation efficiency - Headers don't force inclusion of export macros
- •Proven pattern - Successfully used in StringUtils::StringSplitter, StringUtils::TransformStrCase
❌ AVOID - Adding to header declaration unless necessary:
// interfaces/inner_api/ace_kit/include/ui/properties/ng/measure_property.h // Only add here if .cpp approach doesn't work float Width() const; // Keep clean without ACE_FORCE_EXPORT
When to Use Each Approach
| Scenario | Recommended Location | Example |
|---|---|---|
| Struct/class methods | .cpp implementation | PaddingPropertyF::Width(), LayoutConstraintT::UpdateMaxSizeWithCheck() |
| Template functions | Both (declaration in .h AND implementation in .cpp) | StringUtils::StringSplitter<T> |
| Free functions | .cpp implementation | StringUtils::TransformStrCase<T> |
| Standalone APIs | .h declaration | Public API functions |
Real-World Success Cases
- •
StringUtils Refactoring (commit e0fd3724d21):
- •Moved ~650 lines from .h to .cpp
- •Added
ACE_FORCE_EXPORTto .cpp implementations - •Result: Header size reduced from 713 to ~64 lines
- •
PaddingPropertyF Methods (current fix):
- •Added
ACE_FORCE_EXPORTto .cpp implementations - •No header modifications needed
- •Resolves linker errors for libarkui_folderstack.z.so
- •Added
- •
Template Class Methods (LayoutConstraintT):
- •Added
ACE_FORCE_EXPORTto each method in .cpp - •Template instantiation in .cpp
- •Wildcard pattern in libace.map
- •Added
Remember: When fixing linker errors for symbols needed by other modules, try the .cpp implementation approach first before modifying headers.
4. Template Explicit Instantiation ⭐
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
- •If
CalcLengthhas no export → Template specialization inherits internal visibility - •If
CalcLengthhasACE_FORCE_EXPORT→ Template specialization can export
Solution:
// ❌ 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:
- •Type used as template parameter MUST have export (if type has inline methods)
- •DO NOT move inline methods to .cpp - keep header optimization
- •Template methods still need
ACE_FORCE_EXPORTin .cpp - •Explicit instantiation in .cpp required
When Type-Level Export is Required:
- •✅ Type has inline methods (ToString, operator==, etc.)
- •✅ Type is used as template parameter for explicit instantiation
- •✅ Template instantiation symbols need to be exported to other modules
Reference: See references/template-instantiation-type-export.md for detailed case study
⚠️ IMPORTANT - Header Optimization:
- •StringUtils refactoring (commit e0fd3724d21) moved ~650 lines from header to .cpp
- •This is strategic work to improve build times
- •DO NOT revert by moving inline methods to .cpp
- •Add type-level exports to solve template parameter export issues
Verification Steps
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.
Adding New Cases
When solving new build errors:
- •Document the error in
examples/<case-name>.md - •Include:
- •Error signature
- •Root cause
- •Solution steps
- •Files modified
- •Verification commands
- •Update this SKILL.md to reference the new case
- •Add patterns to "Error Patterns and Solutions" section
Example Usage
Example 1: Successful Build (NO ERRORS)
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 (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]"
Example 2: Build with Errors
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: 完全移除函数
需要修改以下文件:
- •删除头文件声明: interfaces/inner_api/ace_kit/include/ui/event/touch_event.h:59
- •移除调用点: adapter/ohos/entrance/mmi_event_convertor.cpp:240
- •移除测试用例: test/unittest/core/event/touch_event_test_ng.cpp:668
验证步骤
- •重新编译: ./build.sh --product-name rk3568 --build-target ace_engine
- •重新提取错误: foundation/arkui/ace_engine/.claude/skills/build-error-analyzer/script/extract_last_error.sh out/rk3568/build.log
- •检查结果: cat out/rk3568/last_error.log
[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.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