目录

编译构建常见问题

如何解决编译过程内存过高

问题现象

编译构建时,内存或CPU占用过高,导致出现DevEco Studio运行卡顿、延迟等现象。

解决措施

构建报错“Cannot read properties of undefined(reading 'XXX')”

请先根据XXX的值从以下场景排查,没解决问题再参考最终方案。

构建报错“Duplicated files found in module xxx. This may cause unexpected errors at runtime”

问题现象

编译构建时,出现报错“Duplicated files found in module xxx. This may cause unexpected errors at runtime”。

问题原因是构建时存在不同版本的同名so文件。比如将har模块产物里的so文件拷贝到entry模块的libs目录下,这时har模块里有一个libhar.so,entry模块里也有一个libhar.so,再配置entry依赖har,构建entry就会出现报错。

解决措施

使用select、pickFirsts、pickLasts等配置选中要使用的so文件,select提供native产物的精准选择能力,优先级高于excludes、pickFirsts等配置项。pickFirsts、pickLasts按照.so文件的优先级顺序,打包最高优先级的.so文件,优先级顺序是指依赖收集的顺序,越晚被收集优先级越高。

具体可参考:配置CPP。

基于上面的例子,可以在entry的build-profile.json5中添加配置select选中har模块中的so文件,package选中包名为“har”的模块, include选中“libhar.so”文件。

Linux环境下编译报错“JS heap out of memory”

问题现象

在Linux环境下,系统内存有64G,Hvigorw脚本中配置--max-old-space-size=40960,在编译构建时,实际在使用内存未达到配置的内存(例如使用到20G左右)就出现报错“JS heap out of memory”。

FATAL ERROR: NewSpace::Rebalance Allocation failed - JavaScript heap out of memory
Writing Node.js report to file: report.20200512.172528.47517.24.011.json
Node.js report completed
1: 0xa295e0 node::Abort() [node]
2: 0x9782df node::FatalError(char const*, char const*) [node]
3: 0xb99c2e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
4: 0xb99fa7 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
5: 0xd3a3b5 [node]
6: 0xd74f27 [node]
7: 0xd84707 v8::internal::MarkCompactCollector::CollectGarbage() [node]
8: 0xd481b9 v8::internal::Heap::MarkCompact() [node]
9: 0xd48f0b v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
10: 0xd499a5 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
11: 0xd4aebf v8::internal::Heap::HandleGCRequest() [node]
12: 0xcf5f97 v8::internal::StackGuard::HandleInterrupts() [node]
13: 0x104b803 v8::internal::Runtime_StackGuard(int, unsigned long*, v8::internal::Isolate*) [node]
14: 0x13a5a99 [node]
Aborted (core dumped)

问题原因

vm.max_map_count是一个与内核虚拟内存子系统相关的参数,用于控制进程可以拥有的内存映射区域的最大数量。它通常用于限制一个进程可以打开的文件数量,特别是在使用大量内存映射文件的情况下。

在Linux系统上,vm.max_map_count参数的默认值通常是较小的数值,例如65530。然而,对于一些需要大量内存映射的应用程序或者特定的使用场景,可能需要增加该参数的值,以便支持更多的内存映射区域。

解决措施

修改vm.max_map_count的值:

编译报错“Cannot find module XXX or its corresponding type declarations”

编译报错“Failed to get a resolved OhmUrl by filepath xx”

编译报错“Property xxx does not exist on type 'typeof BuildProfile'.”

问题现象1

使用了自定义参数BuildProfile,编译态无异常但编译构建失败,提示“Property xxx does not exist on type 'typeof BuildProfile'.”。

处理措施

检查在当前模块下build-profile.json5中的targets > buildProfileFields配置的自定义参数中key值是否相同,如果不同请将targets内所有buildProfileFields中的key值保持相同。

以下为导致编译报错的错误配置示例:

"targets": [
  {
    "name": "default",
    "config": {
      "buildOption": {
        "arkOptions": {
          "buildProfileFields": {
            "targetName": "default"
          }
        }
      }
    }
  },
  {
    "name": "default1",
    "config": {
      "buildOption": {
        "arkOptions": {
          "buildProfileFields": {
            "targetName1": "default1"
          }
        }
      }
    }
  },
]

请将targets内所有buildProfileFields中的key值修改一致,如以下示例:

"targets": [
  {
    "name": "default",
    "config": {
      "buildOption": {
        "arkOptions": {
          "buildProfileFields": {
            "targetName": "default"
          }
        }
      }
    }
  },
  {
    "name": "default1",
    "config": {
      "buildOption": {
        "arkOptions": {
          "buildProfileFields": {
            "targetName": "default1"
          }
        }
      }
    }
  },
]

问题现象2

使用了自定义参数BuildProfile并且编译器标红且构建失败,提示“Property xxx does not exist on type 'typeof BuildProfile'.”。

处理措施

请检查当前模块下build-profile.json5中buildProfileFields内是否添加了所使用的自定义参数,请确保该自定义参数已配置在buildProfileFields内。

CPP编译报错"A 'undefined symbol' error has occurred"

问题现象

在编译HarmonyOS C++ 项目时,报错提示"A 'undefined symbol' error has occurred"。

解决措施

"undefined symbol"错误通常表示链接器找不到特定符号的定义。这通常是因为源文件没有正确编译或链接,或者因为缺少必要的库文件。以下是如何定位和解决这个问题的步骤:

1. 确保所有源文件都已包含在 CMake 构建中。

首先,检查您的 CMakeLists.txt 文件,确保所有相关的源文件都已包含在项目中。

示例 CMakeLists.txt
cmake_minimum_required(VERSION 3.10) 
project(MyProject)  
set(CMAKE_CXX_STANDARD 17)  
include_directories(${CMAKE_CURRENT_SOURCE_DIR}                    
                    ${CMAKE_CURRENT_SOURCE_DIR}/include)  
# 添加所有源文件
add_library(myProgram SHARED main.cpp myLibrary.cpp) 

2. 确认源文件的符号定义。

确保在所有相关的源文件中正确定义了符号。例如,检查 myLibrary.cpp 是否包含 myFunction 的定义:

myLibrary.cpp

#include "myLibrary.h" 
void myFunction() {     
// Function implementation
}

myLibrary.h

#ifndef MY_LIBRARY_H
#define MY_LIBRARY_H 
void myFunction();  
#endif 

3. 检查编译和链接顺序。

确保所有源文件和库文件按照正确的顺序进行编译和链接。CMake 和 Ninja 通常会处理这个问题,但在手动编译时可能会出现问题。

4. 清理和重新生成构建文件。

有时,构建文件可能会损坏或丢失符号定义。尝试清理构建目录并重新生成构建文件:

hvigorw clean 1 

或手动删除模块下.cxx目录。

5. 检查库路径和链接器标志。

如果使用三方库,确保 CMakeLists.txt 中正确配置了库路径和链接器标志。例如:

cmake_minimum_required(VERSION 3.10) 
project(MyProject)  
set(CMAKE_CXX_STANDARD 17)  
# 确保添加三方库的头文件
include_directories(${PATH_TO_EXTERNAL_LIBRARY}
                    ${PATH_TO_EXTERNAL_LIBRARY}/include)  
# 添加源文件
add_library(myProgram SHARED main.cpp myLibrary.cpp)  
# 链接三方库
target_link_libraries(myProgram PUBLIC /path/to/external/library) 

6. 启用详细编译和链接输出。

为了解详细的编译和链接过程,可以启用更详细的输出。在 CMakeLists.txt 中添加以下内容:

set(CMAKE_VERBOSE_MAKEFILE ON)

7. 检查 Ninja 输出日志。

Ninja 默认生成 .ninja_log 文件,其中包含构建过程的详细信息。您可以检查这个日志文件以了解构建过程中的问题。

cat {module}/.cxx/default/default/arm64-v8a/.ninja_log 

检查编译日志中是否存在符号所在的源文件或头文件。

8. 使用 nm 工具检查符号。

使用 nm 工具检查目标文件和库文件中的符号,确保符号定义存在。

可使用sdk中内置的nm工具:sdk/default/openharmony/native/llvm/bin/llvm-nm。

检查目标文件

nm myLibrary.o | grep myFunction 

检查三方库文件

nm /path/to/external/library | grep myFunction

结论

通过上述步骤,您可以定位和解决 error: undefined symbol 问题。在使用 CMake、Ninja 和 LLVM 编译 C++ 项目时,确保所有源文件和库文件正确包含在项目中,并正确配置编译和链接选项是关键。如果问题依旧存在,详细的编译和链接输出日志通常能提供更多线索,帮助您找到具体的原因。

CPP编译报错"A 'unknown type name' error has occurred"

问题现象

在编译HarmonyOS C++ 项目时,报错提示"A 'unknown type name' error has occurred"。

解决措施

在编译HarmonyOS C++ 项目时,遇到"unknown type name"错误通常表示编译器无法识别某个类型。这可能是因为类型未定义、未包含相关的头文件,或者包含的头文件路径不正确。以下是定位和解决这个问题的步骤:

  1. 检查是否包含头文件。

    确保所有必要的头文件都已正确包含在源文件中。例如,如果您正在使用某个自定义类型或库提供的类型,请确保在使用该类型的文件中包含了相关的头文件。

    示例:

    // main.cpp
    #include "myLibrary.h" 
    int main() {
         MyType obj;
         // 使用自定义类型
         return 0;
    }
    
    // myLibrary.h
    #ifndef MY_LIBRARY_H
    #define MY_LIBRARY_H
    class MyType {
    public:
         MyType() {}
         void doSomething();
    };
    #endif
  2. 检查头文件路径。

    确保 CMakeLists.txt 中正确设置了头文件的搜索路径。可以通过 include_directories 添加头文件目录。

    示例 CMakeLists.txt:

    cmake_minimum_required(VERSION 3.10) 
    project(MyProject)  
    set(CMAKE_CXX_STANDARD 17)  
    # 添加头文件目录
    include_directories(${CMAKE_SOURCE_DIR}/include)  
    # 添加源文件
    add_library(myProgram SHARED src/main.cpp src/myLibrary.cpp) 
  3. 清理和重新生成构建文件。

    有时,构建文件可能会损坏或丢失符号定义。尝试清理构建目录并重新生成构建文件:

    hvigorw clean

    或手动删除模块下.cxx目录。

  4. 启用详细编译输出。

    为了解详细的编译过程,可以启用更详细的输出。在 CMakeLists.txt 中添加以下内容:

    set(CMAKE_VERBOSE_MAKEFILE ON) 
  5. 检查编译输出日志。

    Ninja 默认生成 .ninja_log 文件,其中包含构建过程的详细信息。你可以检查这个日志文件以了解构建过程中的问题。

    cat .cxx/default/default/arm64-v8a/.ninja_log
  6. 使用 CMake 的 message 函数调试。

    可以在 CMakeLists.txt 文件中添加 message 函数来打印一些调试信息,以确保路径和变量正确设置。

    示例:

    message(STATUS "Source directory: ${CMAKE_SOURCE_DIR}") 
    message(STATUS "Include directories: ${CMAKE_INCLUDE_PATH}") 
  7. 如果报错接口是系统API,请查阅对应API参考的起始版本,确认接口在当前版本是否可用。

结论

通过上述步骤,您可以定位和解决 unknown type name 问题。在使用 CMake、Ninja 和 LLVM 编译 C++ 项目时,确保所有头文件正确包含并设置正确的头文件路径是关键。如果问题依旧存在,详细的编译输出日志通常能提供更多线索,帮助您找到具体的原因。

编译报错“Init keystore failed: parseAlgParameters failed: ObjectIdentifier()”

问题现象

编译构建时,出现错误:Init keystore failed: parseAlgParameters failed: ObjectIdentifier()。

hap-sign-tool: error: ACCESS_ERROR, code: 109. Details:   Init keystore failed: parseAlgParameters failed: ObjectIdentifier() -- data isn't an object ID (tag = 48)   Detail: Please check the message from tools

错误原因

使用高版本JDK生成密钥对(p12),再使用低版本的JDK执行签名命令时,会因为不兼容导致解析p12失败,从而签名失败。

场景

  1. 使用DevEco Studio生成密钥对时,DevEco Studio默认会调用软件内预置的JDK,而用户使用本地的低版本JDK进行签名时则会报错。
  2. 用户本地使用高版本JDK生成密钥对时,又通过DevEco Studio进行签名,DevEco Studio中预置的JDK版本低于用户的JDK,导致报错。

解决方案

请检查当前使用的JDK版本和生成密钥对使用的JDK版本,使用版本匹配的JDK执行签名命令。

编译报错“generate SignerBlock failed”

问题现象

编译构建时,出现错误:message:generate SignerBlock failed。

hap-sign-tool: error: {errorcode:0,message:generate SignerBlock failed}

错误原因

签名用的公私钥对不匹配,使用私钥签名后,用公钥验签失败。需保证私钥(keyalias)和公钥(appCertPath)配对使用。

场景

  1. 本地生产签名材料时,未导出正确的keyalias对应的csr(证书请求文件),导致生成证书时,公钥与keyalias对应的私钥不匹配。
  2. 签名过程参数填写错误,使用了错误的keyalias或者appCertPath文件。

解决方案

请选择正确、配对的keyalias和appCertPath文件。

编译报错“java.io.IOException: DerValue.getOID, not an OID 49”

问题现象

编译构建时,出现错误:java.io.IOException: DerValue.getOID, not an OID 49。

hap-sign-tool: error: ACCESS_ERROR, code: 109. Details: java.io.IOException: DerValue.getOID, not an OID 49 Detail: Please check the message from tools

报错原因

证书文件解析失败,找不到证书的OID。

场景

  1. 证书被篡改。
  2. appCertPath参数中传入了非证书文件。

解决方案

请检查证书文件是否正确。

构建报错“input module releaseType is different”

问题现象

打包APP时,提示“input module releaseType is different”。

解决措施

根据报错日志的Warning信息所提示的模块名称,检查模块间的apiReleaseType字段是否一致。

该apiReleaseType字段由编译构建工具自动生成,保存在HAP/HSP包的module.json文件中。如下图所示,首先确认各模块间该字段是否一致,如果存在不一致的情况,需要将应用的各个模块,使用相同版本的SDK重新打包,然后打包APP。

构建报错“debug is different”

问题现象

打包APP时,提示“debug is different”。

解决措施

根据报错日志的Warning信息所提示的模块名称,检查模块间的debug字段是否一致,尤其需要关注本地模块和外部引用模块之间是否一致。

  1. 该debug字段由编译构建工具自动生成,保存在HAP/HSP包的module.json文件中,如下图所示,首先确认各模块间该字段是否一致。

  2. 编译工具根据设置的Build Mode选项生成debug标识,如图所示,可以通过此处进行设置。

编译报错 “Unknown resource name”

问题现象

工程中模块A引用了模块B,编译模块A时出现错误,提示 "Unknown resource name 'xxxx'",找不到模块B的资源。

解决措施

请确保符合以下条件:

  1. 资源需放置在目录resource/base路径下。
  2. 模块B已安装。
  3. 模块A中不能使用相对路径引用模块B的资源,应直接通过定义的模块名称来引用。

问题现象

引用模块的方式不对,如果引用的是一个其他模块的代码,也会报资源找不到。

解决措施

在oh_package.json5中引入该模块。通过定义的模块名称来引用。

如下图所示:

问题现象

HSP A 申请了某个权限,这个权限进行了资源的引用,在所有依赖A的组件进行构建时,报错 A 引用的资源找不到。

解决措施

手动在引用方配置对应资源可以解决此问题。

如何解决编译报错“Error: cJSON_Parse failed, please check the JSON file.”的问题

问题现象

编译报错“Error: cJSON_Parse failed, please check the JSON file”。

报错原因

module.json文件格式不正确。

常见场景

  1. json文件内末尾多了逗号。
  2. 根标签不是大括号{}。

解决措施

检查报错指向的json文件格式,比如是否末尾多了逗号,根标签是否为大括号{}。

编译报错“The useNormalizedOHMUrl settings of packages xxx and the project useNormalizedOHMUrl: xxx do not match”

问题现象

编译报错“The useNormalizedOHMUrl settings of packages xxx and the project useNormalizedOHMUrl: xxx do not match”。

解决措施

useNormalizedOHMUrl 为true的时候ohmurl使用的是新的拼接和解析方式,不能和旧的ohmurl混用,会导致运行时无法识别。

可采用以下两种方式解决该问题:

如果修改了useNormalizedOHMUrl仍无法解决,表明当前hsp包是本地包,需要以本地hsp包的形式引入,请在工程下的build-profile.json5中的modules中添加报错hsp模块,示例如下:

"modules": [
  {
    name: "hsp",   // 引用的hsp包依赖
    srcPath: "../MyApplication_stageB/hsp",   // 引用的hsp包的路径(绝对和相对都可以)
  }
]

如何解决编译报错“Could not resolve 'xxx' from”,但'xxx'目录存在的问题

问题现象

编译报错:“Could not resolve 'xxx' from”,但'xxx'目录存在,目录下存在Index文件。

问题原因

在引用目录时,编译时自动拼接小写的index文件,但目录中是大写的Index文件,在编译大小写敏感时,因找不到index文件而报错。

解决措施

在引用'xxx'目录时,明确写明引用到'xxx/Index'文件。

用户目录下没有npmrc文件

问题现象

新建项目报错 Error: The hvigor depends on the npmrc file. Configure the npmrc file first。

问题原因

在用户目录下没有 .npmrc 文件。

解决措施

在用户目录下创建.npmrc文件,配置如下信息:

registry=https://repo.huaweicloud.com/repository/npm/
@ohos:registry=https://repo.harmonyos.com/npm/

如何解决编译报错“Error: the name 'XXX' can only contain [a-zA-Z0-9_].”的问题

问题现象

编译报错“Error: the name 'XXX' can only contain [a-zA-Z0-9_]”。

解决措施

检查文件名是否合法,文件名只能包含大小写字母、数字、下划线。

如何解决编译报错“Cannot add xxxx items to index”的问题

问题现象

编译报错“Cannot add xxxx items to index”。

问题原因

被编译文件中某函数内部有大量object literal, array literal和string,导致item的数量超过了上限(65536)。

解决措施

排查相关文件,将存在上述原因的函数进行拆分。

如何解决编译卡死,提示“The modules directory at "xxx/workspace/node_modules" will be removed and reinstalled from scratch. Proceed? (Y/n) > true”的问题

问题现象

编译卡死,提示“The modules directory at "xxx/workspace/node_modules" will be removed and reinstalled from scratch. Proceed? (Y/n) > true”。

问题原因

安装构建插件使用的pnpm版本和当前DevEco Studio使用的pnpm版本不一致。

解决措施

  1. 使用DevEco Studio 26.0.0及以上版本。
  2. 如果还是使用当前DevEco Studio版本,删除报错中的路径(例如以上是删除“C:\Users\xxxx\.hvigor\project_caches\8e4ab2ae81c130fec666aeb0b81bd299”目录)和“C:\Users\xxxx\.hvigor\wrapper”目录。