代码工程及构建介绍
背景
ArkUI作为OpenHarmony的默认开发框架,在本项目(ArkUI-X)中需要做到一套代码同时支持多平台构建,所以会采取共仓开发的方式,部分仓直接指向OpenHarmony相关开源仓。
代码结构及仓库结构
代码工程的目录结构如下:
├── arkcompiler // 方舟编译器
├── base // 基础能力
├── build // 项目构建和配置脚本
├── build_plugins // 跨平台构建插件
├── commonlibrary // 公共基础库
├── community // 社区相关
├── developtools // 开发者工具
├── docs // 配套文档
├── foundation
│ ├── appframework // 应用框架兼容适配层
│ ├── arkui // ArkUI引擎
│ ├── communication // 通信能力
│ ├── distributeddatamgr // 分布式数据管理
│ ├── filemanagement // 文件管理
│ ├── graphic // 图形引擎
│ └── multimedia // 多媒体
├── interface // 接口声明
├── plugins // 插件管理与实现
├── prebuilts // 预编译目录
├── productdefine // 产品形态配置
├── samples // 示例代码
├── test // 测试框架与用例
└── third_party // 三方库
具体的代码结构及指向,见下表:
目录路径 | 描述 | 代码仓位置 |
---|---|---|
build | 项目构建和配置脚本 | [OpenHarmony/build] |
build_plugins | 跨平台构建插件 | [ArkUI-X/build_plugins] |
samples | 应用程序样例 | [ArkUI-X/samples] |
community | 社区运作管理 | [ArkUI-X/community] |
docs | 说明文档 | [ArkUI-X/docs] |
interface/sdk | ArkUI-X SDK配置 | [ArkUI-X/interface_sdk] |
plugins | API插件管理,OpenHarmony API插件实现 | [ArkUI-X/plugins] |
test/xts | ArkUI-X跨平台应用测试套件 | [ArkUI-X/xts] |
test/testfwk/arkxtest | ArkUI-X测试框架 | [ArkUI-X/arkxtest] |
developtools/ace_tools | 跨平台命令行工具 | [ArkUI-X/cli] |
foundation/appframework | 应用框架兼容适配层 | [ArkUI-X/app_framework] |
foundation/arkui/ace_engine/adapter/android | Android平台适配代码 | [ArkUI-X/arkui_for_android] |
foundation/arkui/ace_engine/adapter/ios | iOS平台适配代码 | [ArkUI-X/arkui_for_ios] |
foundation/arkui/ace_engine | ArkUI 引擎核心代码 | [OpenHarmony/arkui_ace_engine] |
foundation/arkui/napi | Native API扩展机制 | [OpenHarmony/arkui_napi] |
foundation/communication/netmanager_base | 网络管理模块 | [OpenHarmony/communication_netmanager_base] |
foundation/communication/netstack | 网络协议栈 | [OpenHarmony/communication_netstack] |
foundation/graphic/graphic_2d | 2D图形基础库 | [OpenHarmony/graphic_graphic_2d] |
foundation/filemanagement/file_api | 提供目录和文件的访问操作接口 | [OpenHarmony/filemanagement_file_api] |
foundation/multimedia/image_framework | 图片编解码功能实现 | [OpenHarmony/multimedia_image_framework] |
developtools/ace_ets2bundle | 基于ArkTS的声明式开发范式编译转换工具和跨平台应用构建工具 | [OpenHarmony/ace_ets2bundle] |
developtools/ace_js2bundle | 兼容JS的类Web开发范式编译转换工具和跨平台应用构建工具 | [OpenHarmony/ace_js2bundle] |
arkcompiler/ets_frontend | 方舟前端工具 | [OpenHarmony/arkcompiler_ets_frontend] |
arkcompiler/ets_runtime | 方舟ArkTS运行时 | [OpenHarmony/arkcompiler_ets_runtime] |
arkcompiler/runtime_core | 方舟编译器运行时 | [OpenHarmony/arkcompiler_runtime_core] |
arkcompiler/toolchain | 调试调优工具 | [OpenHarmony/arkcompiler_toolchain] |
prebuilts | 预编译目录,python,nodejs,clang和cmake等 | 通过脚本预下载 |
third_party | 开源第三方组件(统一复用OpenHarmony代码仓) | 引用开源三方库集合 |
commonlibrary/c_utils | 通用的C++功能函数和类 | [OpenHarmony/commonlibrary_c_utils] |
commonlibrary/ets_utils | 用于存放基础类库JSAPI,比如url、uri等 | [OpenHarmony/commonlibrary_ets_utils] |
base/hiviewdfx/hilog | 系统日志功能 | [OpenHarmony/hiviewdfx_hilog] |
base/web/webview | WebView组件的Native引擎 | [OpenHarmony/web_webview] |
base/global/resource_management | 全球化资源管理 | [OpenHarmony/global_resource_management] |
分支同步策略
OpenHarmony相关代码仓,指向OpenHarmony master分支的固定tag点,定期同步,默认按照OpenHarmony的Weekly分支频率进行同步。
ArkUI引擎核心代码仓目录结构
ArkUI引擎核心代码仓 ace_engine
的目录结构以及每个目录的内容如下:
foundation/arkui/ace_engine
├── ace_config.gni // 全局配置文件
├── adapter // 平台适配层
│ ├── android // Android平台适配,独立仓
│ │ ├── build
│ │ ├── capability
│ │ ├── entrance
│ │ ├── stage
│ │ └── osal
│ ├── ios // iOS平台适配,独立仓
│ │ ├── build
│ │ ├── capability
│ │ ├── entrance
│ │ ├── stage
│ │ └── osal
│ ├── ohos // OpenHarmony平台适配
│ └── preview // 预览器平台适配
├── build // 编译配置
│ ├── ace_gen_obj.gni
│ ├── ace_lib.gni
│ ├── BUILD.gn
│ ├── search.py
│ └── tools
├── BUILD.gn // 全局编译配置
├── frameworks // 引擎框架层
│ ├── base // base库
│ ├── bridge // 前端桥接
│ └── core // 引擎核心实现
├── interfaces // 通用对外接口
│ └── napi
│ └── kits
├── LICENSE
├── OAT.xml
├── README.md
├── README_zh.md
└── test // 测试相关
编译构建流程
为了支持一套代码在OpenHarmony和其它平台同时构建,需要根据代码结构动态对编译配置进行调整,因为对外依赖可能不同,并且不同环境下可能依赖的外部源码都有差异,所以必须对编译目标(targets)都进行动态的定义,否则无法保持一致。
- 编译入口: OpenHarmony的编译入口为bundle.json,这里定义了子系统的部件以及对外的接口,放在对应子系统根目录下,ArkUI的其它平台构建暂不需要,使用固定模块名“ace_packages”作为入口。
-
全局配置: 根目录下的BUILD.gn以及ace_config.gni为全局的配置,其中BUILD.gn下定义了全局使用的“ace_config”、“ace_test_config”,其中ace_config.gni分别定义了以下配置:
- 全局的变量配置,如“enable_ace_debug”,通过开关进行编译控制。
- 全局的路径定义,如“ace_napi“,配置路径的变量。
- 工具链相关的配置,如“windows_buildtool”。
- 在“ace_config”中使用的全局宏的定义,如“ace_common_defines”。
- 生成平台相关的配置项“ace_platforms”,这一步是动态定义目标的关键,见如下代码:
ace_platforms = [] # 通过搜索adapter下的目录,生成所有的adapter目录名 _ace_adapter_dir = rebase_path("$ace_root/adapter", root_build_dir) _adapters = exec_script("build/search.py", [ _ace_adapter_dir ], "list lines") # 导入每个adapter下的platform.gni,生成platform的定义配置,加入到ace_platforms中 foreach(item, _adapters) { import_var = {} import_var = { import("$ace_root/adapter/$item/build/platform.gni") } if (defined(import_var.platforms)) { foreach(platform, import_var.platforms) { if (defined(platform.name)) { ace_platforms += [ platform ] } } } }
-
平台配置: 每个adapter下的build目录存放平台相关的配置
├── BUILD.gn // 入口目标定义,如"ace_packages" ├── config.gni // 平台配置 ├── bundle.json // 部件配置,非OpenHarmony平台暂不需要 └── platform.gni // 平台定义
其中,单个config.gni的配置类似如下:
defines = [ "OHOS_PLATFORM", "OHOS_STANDARD_SYSTEM", ] js_engines = [] ark_engine = { engine_name = "ark" engine_path = "jsi" engine_defines = [ "USE_ARK_ENGINE" ] } js_engines += [ ark_engine ] disable_gpu = true use_external_icu = "shared" use_curl_download = true ohos_standard_fontmgr = true sk_use_hilog = true accessibility_support = false rich_components_support = true advance_components_support = false form_components_support = false if (disable_gpu) { defines += [ "GPU_DISABLED" ] } cflags_cc = [ "-Wno-thread-safety-attributes", "-Wno-thread-safety-analysis", ] platform_deps = [ "//foundation/arkui/ace_engine/adapter/ohos/entrance:ace_ohos_standard_entrance", "//foundation/arkui/ace_engine/adapter/ohos/osal:ace_osal_ohos", ]
这个文件定义了该平台的所有差异化配置,如宏、cflags、平台特有的依赖,以及一些功能性的开关。在具体的模块定义中,宏、cflags这一类编译配置直接从config引入,其它差异需要定义为功能性的开关,如上述的“use_curl_download”,使模块gn及特性的定义更清晰。
-
动态目标定义: 基于上述平台的配置,就可以实现动态的定义目标,以base模块为例:
import("//build/ohos.gni") import("//foundation/arkui/ace_engine/ace_config.gni") template("ace_base_source_set") { forward_variables_from(invoker, "*") ohos_source_set(target_name) { # 引入平台config中的define和cflags defines += invoker.defines cflags_cc = [] cflags_cc += invoker.cflags_cc deps = [ "$ace_root/build/third_party/cJSON:third_party_cjson", "i18n:ace_base_i18n_$platform", "resource:ace_resource", ] configs = [ "$ace_root:ace_config" ] # add base source file here sources = [ "geometry/animatable_dimension.cpp", "geometry/animatable_matrix4.cpp", "geometry/matrix4.cpp", "geometry/quaternion.cpp", "geometry/transform_util.cpp", "json/json_util.cpp", "log/ace_trace.cpp", "log/dump_log.cpp", "memory/memory_monitor.cpp", "thread/background_task_executor.cpp", "utils/base_id.cpp", "utils/date_util.cpp", "utils/resource_configuration.cpp", "utils/string_utils.cpp", "utils/time_util.cpp", ] # 通过platform变量来进行区别配置 if (platform != "windows") { # add secure c API include_dirs = [ "//utils/native/base/include" ] sources += [ "//utils/native/base/src/securec/memset_s.c", "//utils/native/base/src/securec/securecutil.c", "//utils/native/base/src/securec/secureprintoutput_a.c", "//utils/native/base/src/securec/snprintf_s.c", "//utils/native/base/src/securec/sprintf_s.c", "//utils/native/base/src/securec/strcat_s.c", "//utils/native/base/src/securec/strcpy_s.c", "//utils/native/base/src/securec/vsnprintf_s.c", "//utils/native/base/src/securec/vsprintf_s.c", ] } # 通过平台的config决定是否依赖和编译curl if (defined(config.use_curl_download) && config.use_curl_download) { configs += [ "//third_party/curl:curl_config" ] sources += [ "$ace_root/frameworks/base/network/download_manager.cpp" ] deps += [ "//third_party/curl:curl" ] } } } # 根据ace_platforms动态定义目标:假设里面包含三个平台"ohos"、"windows"、"mac",则会定义三个target, # 分别为:ace_base_ohos,ace_base_windows,ace_base_mac foreach(item, ace_platforms) { ace_base_source_set("ace_base_" + item.name) { # 从platform中导入变量 platform = item.name defines = [] cflags_cc = [] config = { } if (defined(item.config)) { config = item.config } if (defined(config.defines)) { defines = config.defines } if (defined(config.cflags_cc)) { cflags_cc = config.cflags_cc } } }
- 模块定义: 根据目录结构,尽量分成一个个小模块来定义,每个模块定义明确,如果涉及平台差异,使用上述方法定义,内部配置差异尽量使用特性来区分
- 依赖关系: 依赖关系尽量清楚,按层次依赖,不可反向依赖
- 开发前请熟悉鸿蒙开发指导文档:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。
开发原则
- 所有功能实现遵循分层设计
- frameworks目录下的所有模块都是平台无关的,不能依赖adapter目录下的模块,不能依赖除JS引擎相关的其它子系统
- 平台相关的代码都必须放到adapter目录对应的平台下,如果需要在frameworks中引用相关,需要进行适当的接口抽象
- 非OpenHarmony的adapter中不能依赖OpenHarmony其它子系统的模块(例外:该子系统有跨平台计划并且通用)
- frameworks/core不允许依赖frameworks/bridge下的模块
- 新增代码不可直接依赖skia接口,使用graphic_2d提供的drawing接口
- 修改OpenHarmony仓中的内容要保证各平台都能编译通过,功能正常
鸿蒙最值得程序员入行
为什么这么说?市场是决定人力需求的,数据说话最管用:
1、鸿蒙其全栈自研,头部大厂商都陆续加入合作开发鸿蒙原生应用——人才需求上涨。
2、鸿蒙作为新系统、新技术,而现在市面上技术人才少——高薪招聘开启。
3、鸿蒙1+8+N生态,不仅只有应用开发;还有车载、数码、智能家居、家电等——就业范围广。
4、纯血鸿蒙,目前没有多少人熟悉。都处于0基础同一起跑线——无行业内卷。
开发者最需要什么?岗位多、薪资高、不内卷、行业竞争低。而当下的鸿蒙恰恰符合要求。
那么这么好的鸿蒙岗位,应聘要求都很高吧?其实不然鸿蒙作为新出的独立系统,其源头上大家都处于同一水平线上,一开始的技术要求都不会很高,毕竟面试官也是刚起步学习。招聘要求示例:
从信息看出,几乎应职要求是对标有开发经验的人群。可以说鸿蒙对开发者非常友好,尽管上面没提鸿蒙要求,但是面试都会筛选具有鸿蒙开发技能的人。我们程序员都知道学习开发技术,最先是从语言学起,鸿蒙语言有TS、ArkTS等语法,那么除了这些基础知识之外,其核心技术点有那些呢?下面就用一张整理出的鸿蒙学习路线图表示:
从上面的OpenHarmony技术梳理来看,鸿蒙的学习内容也是很多的。现在全网的鸿蒙学习文档也是非常的少,下面推荐一些:完整内容可在头像页保存,或这qr23.cn/AKFP8k甲助力
内容包含:《鸿蒙NEXT星河版开发学习文档》
- ArkTS
- 声明式ArkUI
- 多媒体
- 通信问题
- 系统移植
- 系统裁剪
- FW层的原理
- 各种开发调试工具
- 智能设备开发
- 分布式开发等等。
这些就是对往后开发者的分享,希望大家多多点赞关注喔!