不如D:Dlang(D语言)下ARM嵌入式板子开发

最近自己开发一个板子上的数据处理与转发。无需UI,本来都是基于Qt/C++进行板子开发的。但是不同型号和板子基本都是靠厂商的虚拟机开发。于是想到之前用Dlang支持交叉编译的,于是测试了下Dlang下ARM嵌入式开发,结果让人惊喜。十分愉快。
Dlang进行ARM开发基于LDC,可以选择完全betterC或完整D语言。本次小项目考虑周边的库,就采用的完整D语言开发的方案。至于GC,作为一个安全的内存池使用。

开发依赖:

  • Linux 主机,因为基本ARM交叉编译GCC都是linux运行的,我是在 openSUSE-Tumbleweed下
  • LDC 编译器,dmd不支持arm,需要使用LDC
  • arm-gcc 交叉编译器(开发板厂家会提供,只需要C语言编译器就行。)

    开发步骤:

    1. 交叉编译 DRuntime 和 Phobos
    2. 配置LDC交叉编译的依赖库和链接器(GCC)
    3. 使用D语言编写程序(注意依赖,如果依赖需要C库,相应库也需要交叉编译)
    4. 进行交叉编译程序(dub build –compiler=ldc2 –arch=你的交叉编译配置)

我的环境

下面指令和命令都是基于我的环境构建,先把我的环境公布,剩下指令更改,根据环境不同自己变更。

主机环境

主机环境

LDC位置

LDC放在用户 bin 目录下。使用链接需要的dub与ldc2到~/bin下。在openSUSE下,~/bin也会添加到PATH中。省下设置PATH那一步了。
ldc设置

交叉编辑器

交叉编译器,按照开发板资料部署。本次是放到的目录中,并执行 设置脚本。
交叉编译器

1.交叉编译 DRuntime 和 Phobos

ldc交叉编译 DRuntime 和 Phobos 十分方便,提供了工具。如果下载代码中断,可以自己手动下载代码,放置到目录中。
需要安装CMAKE或ninja构建系统。在此我是使用了 ninja 构建系统。
编译命令:

CC=/home/duyu/bin/arm/arm-huiwei-linux-gnueabihf_sdk-buildroot/bin/arm-linux-gcc  ldc-build-runtime --ninja --dFlags="-mtriple=arm-linux-gnueabihf"
  • 其中 CC 是设置交叉编译器环境
  • ldc-build-runtime –ninja 使用ldc提供的 编译命令,此命令在 ldc的bin目录下,使用 ninja构建系统构建
  • –dFlags="-mtriple=arm-linux-gnueabihf" 设置交叉编译参数。arm 平台,linux系统,gnueabihf 是 arm下 float软解还是硬解参数,应该和交叉编译器后缀一样。

执行这个命令,会自动下载ldc的源码,并在执行的目录生成编译的临时目录。(自动下载比较慢,可以自己手动下载,然后按照下载名字命名)。
编译命令
执行完成后,会生成 lib 目录,就是我们交叉编译出来的目标平台(ARM-LINUX)下的 D 运行时与标准库了。
然后把库复制到 LDC 目录下,重命名自己标识的名字。例如我的重命名为了 “lib_huiweiArm”,是以开发板厂家命名的。
复制目录

2.配置LDC交叉编译环境

更改 ldc 目录下 etc/ldc2.conf ,添加我们目标平台的编译配置。
例如我的配置:
编译配置
上面是名字配置:格式是 "平台-平台备注-系统-系统备注"(后面两个备注都不是必须)
例如我的配置:arm-huiwei-linux-gnueabihf,其中 arm,linux,gnueabihf都是必须配置,huiwei可以使用 ".*" 用来所有的arm-linux平台使用,我加上huiwei是为了区别以后其他板子。
下面配置是JSON格式。其中:

  • switches 是传给编译器(LDC2)的参数。这里配置了 默认依赖的运行时库,以及使用的交叉编译gcc(这个必须配置,链接需要交叉编译的链接器)。
  • lib-dirs 库目录,也就是我们交叉编译出来 运行时的目录。这里也可以添加 板子环境中提供的库目录,或以来其他C的库(交叉编译后的)的目录。
  • rpath 默认defaultlib库的目录,也就是我们我们交叉编译出来 运行时的目录。
    我们根据实际情况填写我们交叉编译出来的库和信息。

3.编写我们的D程序

这里使用 dub 生成和更改我们的程序。这里生成一个http的tcp echo server。

  • dub.json 注意这里使用vibe.d设置不支持ssl,因为vibe.d的ssl需要openssl,板子环境里没有。
    {
    "authors": [
        "duyu"
    ],
    "copyright": "Copyright © 2023, duyu",
    "dependencies": {
        "serialport": "~>2.2.3",
        "vibe-d:http": "~>0.9.7",
        "vibe-d:tls": "~>0.9.7",
        "yu" :{
            "path" : "../yu"
        }
    },
    "description": "A simple vibe.d server application.",
    "license": "proprietary",
    "name": "webApi",
    "subConfigurations": {
        "vibe-d:tls": "notls"
    }
    }
  • app.d 主要程序,实现一个http的hello word以及 tcp echo server
    import vibe.http.server;
    import vibe.http.router;
    import vibe.core.net;
    import vibe.core.core;
    import vibe.core.stream;
    import vibe.core.log;
    import vibe.http.router;
    void main()
    {
    auto settings = new HTTPServerSettings;
    settings.port = 8080;
    auto router = new URLRouter();
    router.any("/",&hello);
    auto listener = listenHTTP(settings, router);
    auto tcps = listenTCP(2000, (conn) {
        try conn.pipe(conn);
        catch (Exception e) conn.close();
    });
    scope (exit)
    {
        listener.stopListening();
        foreach (ref k;tcps){
            k.stopListening();
        }
    }
    logInfo("Please open http://127.0.0.1:8080/ in your browser.");
    runApplication();
    }
    void hello(HTTPServerRequest req, HTTPServerResponse res)
    {
    res.writeBody("Hello, World!");
    }

    4. 交叉编译我们的程序

    使用dub交叉编译我们程序,命令:

    dub build --compiler=ldc2 --arch=arm-huiwei-linux-gnueabihf
  • –compiler=ldc2 使用 ldc2编译器,dmd不支持交叉编译
  • –arch=arm-huiwei-linux-gnueabihf 设置目标平台,配置就是我们ldc2.conf内设置的名字。
    如果需要 release 还需要在后面添加 “-b release”

    dub build --compiler=ldc2 --arch=arm-huiwei-linux-gnueabihf -b release

    编译命令

结尾

把 我们交叉编译的程序通过 sftp/ftp等传输到板子上,然后

chmod +x ./webApi”

添加可执行权限。然后就可以启动运行了。
这样编译,D 语言的所有依赖均是 静态编译,但是依赖 libc等库,如果需要完全静态编译,可以在了ldc2.conf中,我们的配置“switches”下,添加 “–static” 选项。


参考资料:
[1]Cross-compiling with LDC

[2]Building LDC runtime libraries


转载请注明:来自 “渡世白玉” https://www.dushibaiyu.com/

One thought on “不如D:Dlang(D语言)下ARM嵌入式板子开发”

  1. Dear author,

    Recently discovered your blog by searching for posts about Dlang.

    I liked your analyzes about D & ldc2 (mainly), and I don’t know if the tool offers any technical clarification on compiler-ABI usage.

    It is clear that it is possible to rule out the use of EH-ABI (nothrow) (use libgcc_s/libunwind?) and betterC. However, what about libgcc or libcompiler-rt support?

    Sorry, but I wonder about these internal topics because as a systems developer this subject is very obscure.

    I believe you will agree with me that the native integration of the development environment is aimed at the mainstream (gnu/msvc) specific to each platform. Rust, D,C/C++, etc… follow this line.
    However, languages like Zig (lang &toolchain) that propose to offer only their own solution (toolchain self-contained) can leave inexperienced users confused by leaving their comfort zone.

    e.g.: zig c++ build cpp code static-linking (libc++ + libunwind + compile-rt) on any (except, msvc yet) LLVM triple-targets. Non-GNU? Maybe choiced musl on Linux, but mingw/gnu (glibc [universal-headers] switching version) is allowed too.

    ldc2+zig cross-compile:
    https://gist.github.com/kassane/2a181fa4dfe66dbd283f3ad7a941ca2b

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.