560
社区成员




目前OpenHarmony使用的是GN作为编译构建工具。
BUILD.gn大部分人都没接触过,会感觉比较困难,但是实际上懂了,还是会发现很简单的。
这里录制了一个视频课程,大致讲解了BUILD.gn相关的。
视频链接: OpenHarmony编译构建系统解读——BUILD.gn分析
通过本节视频,将会了解到:
(1)如何新建自己的应用并导入到编译中
(2)解决头文件找不到的问题
(3)如何引用第三方组件
(4)如何自己添加第三方组件
编写一个hello world程序比较简单,可以参考官网:
本文在这里做下总结:
(1)确定目录结构。
开发者编写业务时,务必先在./applications/sample/wifi-iot/app路径下新建一个目录(或一套目录结构),用于存放业务源码文件。
例如:在app下新增业务my_first_app,其中hello_world.c为业务代码,BUILD.gn为编译脚本,具体规划目录结构如下:
└── applications
└── sample
└── wifi-iot
└── app
│── my_first_app
│ │── hello_world.c
│ └── BUILD.gn
└── BUILD.gn
(2)编写业务代码。
在hello_world.c中新建业务入口函数HelloWorld,并实现业务逻辑。并在代码最下方,使用 HarmonyOS启动恢复模块接口SYS_RUN()启动业务。(SYS_RUN定义在ohos_init.h文件中)
#include <stdio.h>
#include "ohos_init.h"
#include "ohos_types.h"
void HelloWorld(void)
{
printf("[DEMO] Hello world.\n");
}
SYS_RUN(HelloWorld);
(3)编写用于将业务构建成静态库的BUILD.gn文件。
如步骤1所述,BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,需由开发者完成填写。以my_first_app为例,需要创建./applications/sample/wifi-iot/app/my_first_app/BUILD.gn,并完如下配置。
static_library("myapp") {
sources = [
"hello_world.c"
]
include_dirs = [
"//utils/native/liteos/include"
]
}
static_library中指定业务模块的编译结果,为静态库文件libmyapp.a,开发者根据实际情况完成填写。
sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。
include_dirs中指定source所需要依赖的.h文件路径。
(4)编写模块BUILD.gn文件,指定需参与构建的特性模块。
配置./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目标模块参与编译。features字段指定业务模块的路径和目标,以my_first_app举例,features字段配置如下。
my_first_app是相对路径,指向./applications/sample/wifi-iot/app/my_first_app/BUILD.gn。
myapp是目标,指向./applications/sample/wifi-iot/app/my_first_app/BUILD.gn中的static_library("myapp")。
打开鸿蒙系统的源码,可以看到有这么一个文件夹:third_party。里面存放的是第三方的代码。
点开我们可以看到有很多第三方代码:
后续我们如果需要往系统中添加、移植任何开源代码,都可以添加到这个文件夹中。接下来,教大家如何添加一个自己的软件包,名字为a_myparty。
1. 新建一个文件夹a_myparty
2. 往文件中放置软件包源码
这里我放在的是 myparty.c和myparty.h文件
3. 新建BUILD.gn文件
整个代码目录如下:
4. myparty.c文件内容如下:
其实,我这个只是为了演示的,所以里面代码没什么作用
#include <stdio.h>
void myparty_test(void)
{
printf("first myparty \r\n");
}
5. BUILD.gn文件内容如下:
BUILD.gn文件主要是描述了软件包的相关信息,包括编译哪些源文件,头文件路径、编译方式(目前Hi3861 只支持静态加载)
import("//build/lite/config/component/lite_component.gni")
import("//build/lite/ndk/ndk.gni")
#这里是配置头文件路径
config("a_myparty_config") {
include_dirs = [
".",
]
}
#这里是配置要编译哪些源码
a_myparty_sources = [
"myparty.c",
]
#这里是静态链接,类似于Linux系统的 .a文件
lite_library("a_myparty_static") {
target_type = "static_library"
sources = a_myparty_sources
public_configs = [ ":a_myparty_config" ]
}
#这里是动态加载,类似于Linux系统的 .so文件
lite_library("a_myparty_shared") {
target_type = "shared_library"
sources = a_myparty_sources
public_configs = [ ":a_myparty_config" ]
}
#这里是入口,选择是静态还是动态
ndk_lib("a_myparty_ndk") {
if (kernel_type != "liteos_m") {
lib_extension = ".so"
deps = [
":a_myparty_shared"
]
} else {
deps = [
":a_myparty_static"
]
}
head_files = [
"//third_party/a_myparty"
]
}
到了这里我们基本上就写完了。
最后我们要让这个第3放软件包编译到我们固件中。
我们在app里面新建一个 myparty_demo的文件夹,目录如下:
其中BUILD.gn内容如下:
static_library("myparty_demo") {
sources = [
"myparty_demo.c"
]
#注意需要把a_myparty的头文件路径加进来
include_dirs = [
"//utils/native/lite/include",
"//third_party/a_myparty",
]
#表示需要a_myparty 软件包
deps = [
"//third_party/a_myparty:a_myparty_static",
]
}
myparty_demo.c里面内容如下
#include <stdio.h>
#include "ohos_init.h"
#include "ohos_types.h"
#include "myparty.h"
void myparty_demo(void)
{
myparty_test();
printf("___________>>>>>>>>>>>>>>>>>>>> [DEMO] Hello world.\n");
}
SYS_RUN(myparty_demo);
一样是第三方组件没编译。单独编就报没这个编译选项。
./build.sh --product-name rk3568 --build-target a_myparty_static
[OHOS ERROR] ninja: error: unknown target 'a_myparty_static'
[OHOS ERROR] /usr/lib/gcc/arm-none-eabi/9.2.1/../../../arm-none-eabi/bin/ld: obj/device/qemu/arm_mps2_an386/liteos_m/board/myparty_demo/bsp_config.myparty_demo.o: in function myparty_demo': [OHOS ERROR] myparty_demo.c:(.text.myparty_demo+0x4): undefined reference to
myparty_test'
[OHOS ERROR] collect2: error: ld returned 1 exit status
请教下,为什么三方组件没有编译,链接出错呢?