65.9K
CodeProject 正在变化。 阅读更多。
Home

从零开始构建和运行嵌入式 Linux .NET 应用程序

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2014年5月23日

CPOL

11分钟阅读

viewsIcon

66247

.NET 应用程序在 Yocto/OpenEmbedded Linux 上运行

概述

本教程的目的是引导您从一个干净的系统开始,使用 meta-mono 层将 Mono 集成到构建镜像中,然后构建和打包一个示例 .NET 项目以包含在该镜像中。

您可能已经安装了 Yocto,并且第一次接触 Mono,那么您可以直接跳到您觉得最相关的内容,例如 构建示例项目并在主机上进行测试(可选)将 meta-mono 层添加到 Yocto 构建系统

以下是基本假设。您

获取主机系统支持 Yocto 所需的软件包

首先,我们将安装 Ubuntu 的必需主机软件包,如快速入门指南中所述。

  $ sudo apt-get install gawk wget git-core diffstat unzip texinfo 
  gcc-multilib build-essential chrpath socat libsdl1.2-dev xterm nano 

有关系统要求和安装的完整详细信息,请参阅 Yocto Quickstart

安装 Mono

另外,在您的主机系统上安装 Mono,因为我们将稍后使用它来构建和运行一些示例进行测试。

  $ sudo apt-get install mono-complete
  $ mono --version 

使用 Ubuntu 14.04.4 LTS,这将安装 Mono 版本 3.2.8,现在它已经相当老旧了。

如果您想在主机系统上安装新版本的 Mono,可以遵循这些 说明

  $ sudo add-apt-repository ppa:directhex/monoxide
  $ sudo apt-get update
  $ sudo apt-get install mono-complete
  $ mono --version

目前,这也会安装 Mono 3.2.8,但将来可能会提供更新的版本。

如果您想使用最新的 Mono,可以按照 此处的说明 从发布 tarball 构建,或者 此处 从 git 构建。请注意,此过程可能并不简单,并且可能存在问题,例如文件丢失。

此外,我撰写了一篇关于如何在 Windows 上构建 Mono(3.6.1 tarball / git)的详细教程,可以在 此处 找到。

下载并解压 Yocto 2.0 发行版

在撰写本文时,Yocto 的当前发行版 (2.0) 可以在 此处 找到。

  $ cd ~ 
  $ mkdir yocto
  $ wget http://downloads.yoctoproject.org/releases/yocto/yocto-2.0/poky-jethro-14.0.0.tar.bz2
  $ tar xjvf poky-jethro-14.0.0.tar.bz2 

这将为您提供 Yocto 2.0 的基础元数据和 bitbake 工具。您还可以添加额外的层,通常形式为“meta-foo”,以提供机器支持和附加功能。

配置构建环境以构建仿真器镜像

  $ cd ~/yocto/poky-jethro-14.0.0
  $ source oe-init-build-env build_qemux86 

这将创建一个名为 build_qemux86 的构建树,尽管您也可以使用其他名称,而不会产生任何负面影响。

完全有可能在不同的文件夹中并行拥有多个构建树,并使用 oe-init-build-env 在它们之间切换。

oe-init-build-env 将在 conf/local/conf 中创建一个默认配置文件,该文件将构建一个适合使用 qemu 执行的仿真器镜像。

构建一个基础镜像

配置环境后,您将停留在 build_qemux86 文件夹中。

然后,您应该构建一个基础镜像,这将花费一些时间(数小时)。

  $ bitbake core-image-minimal 

构建示例项目并在主机上进行测试(可选)

使用 autotools 构建

在 Yocto 中为不同目标编译非 .NET 项目的最直接方法是利用 autotools

支持 autotools 的项目提供了一组模板文件,然后由 autotools 使用这些文件生成适合为目标环境构建的 Makefiles 和相关配置文件。

同样,也可以使用 autotools 编译 Mono/.NET 项目。

一个非常简单的示例“Hello World”项目,名为 mono-helloworld,已提交到 GitHub 此处

如果您查看这两个源文件,helloworld.cshelloworldform.cs,您会发现第一个文件在控制台输出“Hello World”消息,第二个文件创建一个标题为“Hello World”的 Windows 窗体。

关于 Mono 的 <code><code><code>autotools 模板配置的讨论超出了本指南的范围,但 mono-helloworld 项目基于 mono-skel 示例,您可以在 Mono Application Deployment 指南的 Autotools 部分找到它。

该项目本身构建了两个 .NET 可执行文件:helloworldhelloworldform,第一个是控制台应用程序,第二个是简单的 Windows Forms 应用程序。

要在主机上独立于 Yocto 构建项目,请先克隆示例存储库

  $ mkdir ~/host 
  $ cd ~/host 
  $ git clone https://github.com/DynamicDevices/mono-helloworld 

然后运行 autotools,配置构建,并编译项目

  $ cd mono-helloworld
  $ ./autogen.sh
  $ ./configure --enable-winformdemo
  $ make 

成功编译后,您将在构建文件夹的根目录中找到许多新文件。

有两个新的 .NET 可执行文件:src/helloworld.exesrc/helloworldform.exe

您可以使用以下命令运行第一个:

  $ mono src/helloworld.exe 

它将输出:

HelloWorld 

您可以使用以下命令运行第二个:

  $ mono src/helloworldform.exe 

根据您的主机环境(例如,使用 SSH),您可能需要显式设置 DISPLAY 变量才能使其正常工作,使用:

  $ export DISPLAY=:0 
  $ mono src/helloworldform.exe 

这将为您提供一个基本的 Windows Forms 窗口标题:

所以您现在已经证明您可以在主机上成功获取、配置和构建项目。

接下来,我们将研究 Yocto 如何自动化此获取、配置和构建过程,然后安装和打包输出文件。

使用 xbuild 构建

许多人使用 Visual Studio、Mono Develop、Xamarin Studio 或其他类似的集成开发环境 (IDE) 进行开发。

Mono 提供了 xbuild,它是 Microsoft msbuild 的 Mono 实现,在此 进行了讨论。

本质上,这使得开发人员可以在他们选择的 IDE 中创建一个项目解决方案,然后使用 xbuild 在 Mono 环境中进行构建。

一个有用的工作流程可能是:在本地使用您选择的 IDE 进行开发,发布时提交到 git 存储库,然后使用 Yocto 配方将该发布版本构建到现有镜像中,或提供给包源以更新现场的现有目标。

上面讨论的 mono-helloworld 项目(构建与 autotools)也提供了解决方案和项目文件来支持使用 xbuild 进行构建,或者实际上支持像 Visual Studio 这样的 IDE。

如果您已经使用 autotools 构建了示例,请移动文件夹并重新开始。

  $ cd ~/host 
  $ rm -Rf mono-helloworld 

再次检出 mono-helloworld 项目。

  $ git clone https://github.com/DynamicDevices/mono-helloworld 

运行 xbuild。(正如您从 .sln 文件名中可能猜到的那样,您可以将此示例项目克隆到 Windows 主机并使用 Visual Studio 打开它,实际上它就是这样创建的。)

<code> </code> $ xbuild /p:Configuration=Debug mono-helloworld_vs2010.sln 

这将导致许多新文件,包括 bin/Debug 中的两个新的 Mono/.NET 可执行文件:helloworld.exehelloworldform.exe

您可以使用以下命令运行第一个:

  $ mono bin/Debug/helloworld.exe 

它将输出:

HelloWorld 

您可以使用以下命令运行第二个:

  $ mono bin/Debug/helloworldform.exe 

根据您的主机环境(例如,使用 SSH),您可能需要显式设置 DISPLAY 变量才能使其正常工作,使用:

  $ export DISPLAY=:0
  $ mono bin/Debug/helloworldform.exe 

这将为您提供一个基本的 Windows Forms 窗口标题。

所以您现在已经证明您可以在主机上成功获取、配置和构建项目。

接下来,我们将研究 Yocto 如何自动化此获取、配置和构建过程,然后安装和打包输出文件。

将 meta-mono 层添加到 Yocto 构建系统

将配方添加到构建环境的首选方法,也是本指南所示的方法,是将它们放在一个新的层中。

层根据机器、功能或类似项隔离特定于构建的元数据集,并有助于保持环境的清洁。

meta-mono 层包含 Mono 特定的配方,以支持在目标板上执行 .NET 应用程序。该层可以在 此处 找到。

要使用像这样的新层,您首先需要从其 git 存储库克隆该层,然后通过编辑 conf/bblayers.conf 将该层添加到您的 bitbake 配置中。

  $ cd ~/yocto/poky-jethro-14.0.0 
  $ git clone git://git.yoctoproject.org/meta-mono

您还需要 meta-openembedded 层的 jethro 分支,因为它提供了 libgdiplus 所需的 giflib 配方。

  $ cd ~/yocto/poky-jethro-14.0.0 
  $ git clone git://git.openembedded.org/meta-openembedded -b jethro
  $ cd ~/yocto/poky-jethro-14.0.0/build_qemux86
  $ nano conf/bblayers.conf

您的 bblayers.conf 应如下所示:

  # LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
  # changes incompatibly
  LCONF_VERSION = "6"
  
  BBPATH = "${TOPDIR}"
  BBFILES ?= ""
  
  BBLAYERS ?= " \
    /home/user/yocto/poky-jethro-14.0.0/meta \
    /home/user/yocto/poky-jethro-14.0.0/meta-yocto \
    /home/user/yocto/poky-jethro-14.0.0/meta-yocto-bsp \
    "
  BBLAYERS_NON_REMOVABLE ?= " \
    /home/user/yocto/poky-jethro-14.0.0/meta \
    /home/user/yocto/poky-jethro-14.0.0/meta-yocto \
    "

通过向 BBLAYERS 添加一行,使新层对 bitbake 可见。

  BBLAYERS ?= " \
    /home/user/yocto/poky-jethro-14.0.0/meta \
    /home/user/yocto/poky-jethro-14.0.0/meta-yocto \
    /home/user/yocto/poky-jethro-14.0.0/meta-yocto-bsp \
    /home/user/yocto/poky-jethro-14.0.0/meta-openembedded/meta-oe \  
    /home/user/yocto/poky-jethro-14.0.0/meta-mono \ 
    "

现在 bitbake 可以看到新层中的配方了。

您还将看到当 bitbake 运行时,并显示构建配置,您层的存储库分支和哈希会显示出来,这对于了解为什么构建失败很有用,例如:

Build Configuration:
BB_VERSION        = "1.28.0"
BUILD_SYS         = "x86_64-linux"
NATIVELSBSTRING   = "Ubuntu-14.04"
TARGET_SYS        = "i586-poky-linux"
MACHINE           = "qemux86"
DISTRO            = "poky"
DISTRO_VERSION    = "2.0"
TUNE_FEATURES     = "m32 i586"
TARGET_FPU        = ""
meta              
meta-yocto        
meta-yocto-bsp    = "<unknown>:<unknown>"
meta-mono         = "master:836115be90cac01cfbb677b24d6ad6d802a795e7"
meta-oe           = "jethro:dc5634968b270dde250690609f0015f881db81f2"

构建包含 Mono/.NET 支持的镜像

meta-mono 层包含一个构建 core-image-mono 镜像的配方,该镜像基于 Yocto 标准镜像 core-image-sato

要构建此镜像:

  $ bitbake core-image-mono 

这可能需要一段时间,即使您已经构建了 core-image-minimal,因为还需要构建额外的 GUI 支持包。

core-image-mono 配方可以在 此处 找到,并从中包含一个文件 此处

您可以在包含文件中看到,标准 core-image-sato 镜像中添加了额外的包。

  IMAGE_INSTALL += "mono mono-helloworld" 

这就是您如何在配方中或在 .bbappend 文件中为镜像添加 Mono 支持。事实上,只需要添加 mono 包,因为除非您出于测试目的需要示例,否则不需要这些示例。

包含的 mono-helloworld 配方演示了如何使用 autotools 构建示例项目。有关详细信息,请参阅配方本身 此处,更重要的是,它包含的文件 此处

您可以选择将 mono-helloworld 替换为 mono-helloworld-xbuild,顾名思义,它展示了如何使用 xbuild 构建示例项目。

在仿真目标上测试 .NET 可执行文件

构建完 core-image-mono 后,您就可以在 qemu 下运行它了。

要运行镜像,只需使用:

   $ runqemu qemux86

这将启动仿真器,加载镜像,您将看到内核加载,然后是一个基本的图形用户界面。

如果您发现键盘映射不正确,您可能希望显式设置它,例如:

 $ runqemu qemux86 qemuparams='-k en-gb' 

 $ runqemu qemux86 qemuparams='-k en-us'

使用相应的图标打开一个终端窗口,以“root”身份登录仿真器(无密码),然后运行示例。

您可以使用以下命令运行控制台可执行文件:

  $ mono helloworld.exe 

或者,该配方安装了一个脚本来包装 Mono 的使用,因此您可以使用以下形式:

  $ helloworld 

这将输出:

HelloWorld  

您可以使用以下命令运行 Windows Forms 可执行文件:

  $ mono /usr/lib/helloworldform.exe 

  $ helloworldform

根据您的主机环境(例如,使用 SSH),您可能需要显式设置 DISPLAY 变量才能使其正常工作,使用:

  $ export DISPLAY=:0 
  $ mono /usr/lib/helloworld/helloworldform.exe 

这将显示一个标题为“Hello World”的测试 Windows Forms 窗体。

您可以使用以下命令运行 GTK# 可执行文件:

  $ mono /usr/lib/helloworldgtk.exe 

  $ helloworldgtk

根据您的主机环境(例如,使用 SSH),您可能需要显式设置 DISPLAY 变量才能使其正常工作,使用:

  $ export DISPLAY=:0 
  $ mono /usr/lib/helloworld/helloworldgtk.exe 

这将显示一个标题为“Hello World”的测试 Windows Forms 窗体。

autotools 配方 breakdown

这是 mono-helloworld_1.2.bb 配方的内容。

require mono-helloworld.inc

SRC_URI[md5sum] = "ae22f282d36ae5cb82ae5a2e9bcbb8b5"
SRC_URI[sha256sum] = "365360d674bd63ab7ca1762e64e3d5d6c6d4841edf6e59f67ff8b40fafeb1137"

可以看到,我们提供了几个校验和,它们对应于将要下载的发行版 tarball。

同样,包含的 mono-helloworld.inc 文件可以在 此处 找到。

SUMMARY = "Mono Hello World"
DESCRIPTION = "Test applications for Mono console and windows forms"
AUTHOR = "Alex J Lennon <ajlennon@dynamicdevices.co.uk>"
HOMEPAGE = "http://www.dynamicdevices.co.uk"
SECTION = "mono/applications"
PRIORITY = "optional"
LICENSE = "GPLv3"
LIC_FILES_CHKSUM = "file://LICENSE;md5=783b7e40cdfb4a1344d15b1f7081af66"

SRC_URI = "https://github.com/DynamicDevices/mono-helloworld/releases/download/v${PV}/$

inherit autotools-brokensep
inherit mono

DEPENDS_${PN} = "mono"
RDEPENDS_${PN} = "mono"

EDEPENDS_X11 = "libgdiplus"
ERDEPENDS_X11 = "libgdiplus"
EDEPENDS_GTK = "gtk-sharp"
ERDEPENDS_GTK = "gtk-sharp"
EDEPENDS_WAYLAND = "wayland"
ERDEPENDS_WAYLAND = "wayland"

PACKAGECONFIG[x11] = "--enable-winformdemo=yes,,${EDEPENDS_X11},${ERDEPENDS_X11}"
PACKAGECONFIG[wayland] = ",,${EDEPENDS_WAYLAND},${ERDEPENDS_WAYLAND}"
PACKAGECONFIG[gtk] = "--enable-gtkdemo=yes,,${EDEPENDS_GTK},${ERDEPENDS_GTK}"

# Default configuration, distros might want to override
PACKAGECONFIG ??= "${@base_contains('DISTRO_FEATURES', 'x11', 'x11 gtk', '', d)} \
                   ${@base_contains('DISTRO_FEATURES', 'wayland', 'wayland gtk', '', d$
"

FILES_${PN} = "${libdir}/helloworld/helloworld.exe \
                ${bindir}/helloworld \
                ${libdir}/helloworld/helloworldform.exe \
                ${bindir}/helloworldform \
                ${libdir}/helloworld/helloworldgtk.exe \
                ${bindir}/helloworldgtk \
"  

有关校验和、许可证等的更多详细信息,请参阅 将第三方组件添加到 Yocto/OpenEmbedded LinuxYocto Recipe & Style Patch Guide

我们依赖于 mono 包,并且再次继承 autotools 类以利用 bitbakeautotools 功能。

最后,我们覆盖 FILES_${PN},它控制添加到主输出包的已安装文件。${libdir}${bindir} 是标准的 GNU 变量命名约定,用于安装路径。有关详细信息,请参阅 此处此处

在本例中,我们确保 helloworld 可执行文件以及 helloworldform.exe 都安装到 /usr/lib/helloworld/

将可执行程序集安装到 /usr/lib 位置可能看起来很奇怪,但这符合 Mono 应用程序部署建议

然后,我们将包装脚本安装到 /usr/bin,可以直接调用它们来运行各自的示例。这些脚本的形式如下:

  #!/bin/sh
  exec @MONO@ @prefix@/lib/helloworld/@APP@.exe $MONO_EXTRA_ARGS "$@" 

xbuild 配方 breakdown

xbuild 配方与上面的 autotools 配方类似,除了我们覆盖了几个方法以确保 xbuild 按我们期望的方式运行。

此配方可以在 此处 找到。

首先,我们包含包含文件中的定义,并设置要检索的存档的版本特定校验和。

require mono-helloworld.inc

SRC_URI[md5sum] = "ae22f282d36ae5cb82ae5a2e9bcbb8b5"
SRC_URI[sha256sum] = "365360d674bd63ab7ca1762e64e3d5d6c6d4841edf6e59f67ff8b40fafeb1137"

然后,我们设置源目录,该目录对于 bitbake 找到从检索到的存档中提取的文件必须是正确的。

 REALPN = "mono-helloworld"
 S = "${WORKDIR}/${REALPN}-${PV}" 

现在我们覆盖编译方法,调用 xbuild 以在存档中的 .SLN 文件上构建特定的 .NET 配置。

 CONFIGURATION = "Debug"
 do_compile() {
         xbuild /p:Configuration=${CONFIGURATION} ${REALPN}_vs2010.sln
 }

接下来,我们修改安装方法,以确保正确的文件被安装,并且可执行脚本被修改为运行输出程序集。

 do_install() {
        install -d "${D}${bindir}"
        install -d "${D}${libdir}/helloworld/.debug"
        install -m 0755 ${S}/bin/${CONFIGURATION}/*.mdb ${D}${libdir}/helloworld/.debug
        install -m 0755 ${S}/bin/${CONFIGURATION}/*.exe ${D}${libdir}/helloworld

        install -m 0755 ${S}/script.in ${D}${bindir}/helloworld
        sed -i "s|@MONO@|mono|g" ${D}${bindir}/helloworld
        sed -i "s|@prefix@|/usr|g" ${D}${bindir}/helloworld
        sed -i "s|@APP@|helloworld|g" ${D}${bindir}/helloworld
        install -m 0755 ${S}/script.in ${D}${bindir}/helloworldform
        sed -i "s|@MONO@|mono|g" ${D}${bindir}/helloworldform
        sed -i "s|@prefix@|/usr|g" ${D}${bindir}/helloworldform
        sed -i "s|@APP@|helloworld|g" ${D}${bindir}/helloworldform
}

最后,我们确保输出的 .MDB 调试文件在 -dbg 包中正确打包。${libdir}${bindir} 中的其他程序集将默认在主输出包中正确打包。

  FILES_${PN}-dbg += "${libdir}/helloworld/.debug/*" 

有关校验和、许可证等的更多详细信息,请参阅 将第三方组件添加到 Yocto/OpenEmbedded LinuxYocto Recipe & Style Patch Guide

反馈

这是一个活文档。请随时将评论、问题、更正发送给Alex Lennon

历史

  • 23/05/14 v1.0 - 首次发布
  • 22/02/16 v2.0 - 更新至 Yocto Jethro
© . All rights reserved.