#冲刺创作新星# #跟着小白一起学鸿蒙#[五]开源鸿蒙的4种编译方法

时间:2022-10-08 11:59:10

作者:王石,胡瑞涛

简介

在#跟着小白一起学鸿蒙# [二]第一个OpenHarmony程序章节我们学习了如何开发一个OpenHarmony的终端程序,采用的方法就是使用BUILD.gn脚本文件,通过./build.sh脚本进行编译,这也是OpenHarmony官方推荐的编译程序的方法。但是这样的方法牵扯方便广,速度慢,接下来我们来熟悉下OpenHarmony的另外两种编译方法。

GCC编译方法

  1. 工具链位置:

    [源码路径]/prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin/
    
  2. 编译命令:

    arm-linux-gnueabi-gcc -static helloworld.c -o gcchelloworld
    
  3. 方法解析:

    使用gcc工具链的编译方法是嵌入式开发的通用方法。但是这里有个特殊的地方-static。 gcc 加上 -static,会在链接阶段, 查找对应模块的静态库, 而非动态库, 并把需要的东西,都带进目标文件),编译好后,文件会非常大,但是,运行时就不需要依赖。这个原因则是在OpenHarmony的镜像文件里放的是musl的lib库,没有glibc的lib库,所以如果不用-static标志则有可能在运行时找其他运行库,找不到则运行不成功。

CLang编译方法

  1. 工具链位置:[源码路径]/prebuilts/clang/ohos/linux-x86_64/llvm/bin

  2. 编译命令:

    • clang --sysroot=[ohos代码路径]/out/rk3568/obj/third_party/musl/ --target=arm-linux-ohosmusl -D__clang__ -march=armv7-a -mfloat-abi=softfp -mfpu=neon-vfpv4 -w -o helloworld.c.o -c helloworld.c

    • clang --sysroot=[ohos代码路径]/out/rk3568/obj/third_party/musl/ --target=arm-linux-ohosmusl -D__clang__ -march=armv7-a -mfloat-abi=softfp -mfpu=neon-vfpv4 -w -Wl,--dynamic-linker,/lib/ld-musl-arm.so.1 -rdynamic helloworld.c.o -o muslhelloworld

  3. 方法解析:

    clang编译器是APPLE公司的编译器大牛Chris Lattner主导下编写的,其目标是替换大名鼎鼎的GCC编译器。一般编译器的流程如下:

    graph LR
    源代码 --> 预处理 --> 前端 --> 优化 --> 后端 --> 链接 --> 生成文件
    

    通过上面的命令分析分了两部,第一步编译生成中间文件:helloworld.c.o,也就是从预处理一直到后端的过程;第二步链接helloworld.c.o和/lib/ld-musl-arm.so.1生成目标文件muslhelloworld也就是链接和生成文件。这部分和上部分的区别就是手动引用musl库。那么musl库和glibc的库的区别是什么呢?

    1. 开源版本:glibc(LGPLv2.1),musl(MIT)
    2. 运行速度:glibc优于musl,同时稳定性也是glibc更好
    3. 代码可读性:musl优于glibc

总结

OpenHarmony的官方编译方法就是使用./build.sh脚本文件,调用顺序大致如下:

graph LR
build.sh --> entry.py --> vendor和product --> hb --> ninja --> clang

所以如果要缩减编译时间还有一些特殊方法:

  • ./build.sh --product-name 【产品名称如:rk3568】--ccache --build-target 【编译对象模块,如:moduleb_lib】

    此方法也是官方的一种编译方法,虽说只编译一个模块,但是流程是完整的,即:

    • 用BUILD.gn生成ninja文件,然后通过上面的流程编译最总的模块二进制文件
  • ninja -C /out/rk3568(根据编译的productname来填) moduleb_lib(编译对象模块,如:moduleb_lib)

    此方法的前提是首先用./build.sh编译过一遍,然后因为out目录里提前生成了build.ninja,所以可以直接用ninja命令直接编译对应模块

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com/#bkwz