利用snapcraft为我们的Snappy Ubuntu应用打包

我们知道在现在的Ubuntu桌面中,我们几乎都使用的是debian包.有的Linux系统上是使用rpm包.在Snappy Ubuntu上,我们使用的包叫做snap包.它的包的扩展名叫做.snap.这是一种崭新的包,和我们以前使用的不一样哦.我们知道debian包的打包非常难懂.相比较而言,snap包的语法就简单得多.今天在我们的教程中,我们来以一个简单的例程来介绍.在以后的教程中,我们用更加详细的方式来介绍snapcraft.snapcraft的功能是:

  • 它是一个编译工具
  • 让我们很方便地把不同资源的component集成起来,并编译它们
  • 它是一个snap的打包工具
  • Mark Shuttleworth的话简单地说snapcraft就是"apt-get for github"(24分37秒)

snap包具有如下的特性:

  • 包含应用所需运行的所有dependence
  • 你可以100%确定你的应用不会因为任何在应用之外的变化的改变而导致你的应用不能正常运行,比如卸载一个Java应用不会导致其它Java应用的运行.安装一个使用不同版本的Java JDK/OpenJDK的Java应用,不会干扰现有的任何一个运行在不同JDK/OpenJDK版本的Java应用
  • 通常snap的包比正常应用的包要大,因为它包含了所有它需要运行的环境

snapcraft的安装如下.如果大家已经按照"Snappy Ubuntu 入门"文章中介绍的那样就已经安装好了.

$ sudo add-apt-repository ppa:snappy-dev/tools
$ sudo apt-get update
$ sudo apt-get install snappy-tools bzr snapcraft

在安装完上面的包以后 ,我们将得到如下的工具

snappy build		- make snap packages out of a file hierarchy
snappy-remote 		- run snappy operations on remote snappy target by IP
snapcraft 		- the snap build tool for all snaps
ubuntu-device-flash	- image creation tool for snappy ubuntu

我们可以在地址找到snapcraft的源码.里面也有许多的例程供我们来参考.综合下来,一个snap工程有一下几个部分 (icon图片snapcraft.yaml应用代码):


1)应用图片


我们可以为我们的Snappy应用找到一个独特的图标.就像在snapcraft例程中给出的 图标一样.如果你还没有一个图标,你可以用如下的命令来创建一个:

$ touch icon.png
如果我们想把我们的snap最终发布到snap商店上,我们必须设计自己的图标.

2)snapcraft.yaml



这个文件是如何生成我们Snappy应用的最重要的文件.关于yaml的格式定义,我们可以参阅 链接.利用它,我们可以生成我们的snap包.在Ubuntu官方的开发者网站上,我们有一篇介绍snapcraft的文章" snapSnapcraft: Advanced features".有兴趣的开发者可以仔细阅读一下那里的教程.用一个最简单的图来描述snapcraft是怎么工作的:




从上面的图上可以看出来,snapcraft整个的工作分为4个部分: Pull, Build, StageSnap.snapcraft可以更加我们定义在snapcraft.yaml中的dependency来自动抓包(pull),并编译它们(build),并把每个dependency所编译的包集中到一个文件目录(stage)来,最终通过snap来生成一个最终的.snap文件(Snap).

我们也可以通过命令snapcraft --help来得到更多的信息:






pull阶段,snapcraft会下载或克隆在网上的源码,并存于本地的电脑中.snapcraft将生产" parts"目录,并根据定义在snapcraft.yaml文件中的parts部分生产相应的子目录.源码将存于目录parts/part-name/src中.





build阶段,编译已经下载过的源码.每个part都分别在其下面的"build"目录中存放编译的文件,并把最终的安装文件存于"install"目录中.




stage阶段,把每个part的"install"目录下的文件都拷入到用户可以看见的一个"stage"目录里.所有的part都分享同样的一个文件布局."stage"目录对于编译一些不定义在snapcraft.yaml文件中的内容非常有用.你可以在该目录下利用"snapcraft shell make"来编译一个本地的项目.



snap阶段,把在stage阶段生产的文件,除去过滤掉的/不包含的文件到一个用户可以看见的文件目录"snap"中.在这个阶段,它也同时生产额外的metadata文件,比如在 meta文件目录下的文件.所有在snap目录下的文件将最终被打包入.snap文件中.这和在stage阶段中的文件是不同的.stage中可能包含用于编译其它part的中间文件.


assemble阶段,把在snap目录中的所有文件,根据snap的包格式打包到一个.snap文件中.最终的.snap包可以发布到商店中或是安装到目标上进行测试.

一个典型的编译后的文件目录如下:




使用的snapcraft.yaml文件如下:

snapcraft.yaml


name: mqtttestclient
version: 1
vendor: Thibaut Rouffineau <thibaut.rouffineau@canonical.com>
summary: MQTT client on Eclipse Foundation sandbox
description: This app is a small client using Eclipse Foundation MQTT client and using the Eclipse Foundation sandbox
icon: ./icons/Paho.png

binaries:
 mqttpublish: 
  exec: python3 bin/mqttpublish

parts:
 mqtt:
  plugin: python3
  source: git://git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.python
 publish:
  plugin: copy
  files:
    ./bin/mqttpublish.py: bin/mqttpublish

处在snapcraft中最核心的是 parts.parts是一些软件或数据被用来构造snap包的,或是用来编译其它软件的.每个part是由一个plugin(比如上面的 python3copy)来管理的,并且通常是互相独立的.

我们可以通过如下的方法来得到目前所支持的所有的plugin:
liuxg@liuxg:~$ snapcraft list-plugins
ant
autotools
catkin
cmake
copy
go
jdk
make
maven
nil
nodejs
python2
python3
qml
roscore
scons
tar-content

从上面我们可以看出,我们有几个重要的目录: parts, snapstage.这几个目录是在我们使用snapcraft工具进行编译时所生成的.根据定义在snapcraft.yaml文件中的parts,自动下载python3的源码到指定的parts中的目录,并进行编译.在我们上面的例程中,我们也使用了copy,并把我们需要的文件考入到我们所需要的parts目录中.stage目录中将各个parts中所编译生成的文件集中到一个目录中stage.在stage中,我们也可以加入一些不在snapcraft中定义的项目,这样可以使得我们最终的项目中包含我们所需要的库.snap目录中将只包含最终打包到.snap文件包中的文件.


3)应用代码



根据不同的应用场景,应用代码可以放在和snapcraft.yaml相同的目录或处于另外一个不同的目录.在今天的例程中,我们将使用一个"hello-world"的例程来介绍如何来创建一个最基本的snap项目,从而让我们对snapcraft的例程有所了解.

在上面我们已经对snapcraft的流程有一些了解.下面我们用一个实际的例程来展示如何创建一个snap包.

首先,我们在电脑上创建一个我们所需要的文件目录,比如"hello-world".在该目录下生成如下的几个文件:




我们可以看出,我们已经有一个hello.png的图标文件,在我们的bin目录下,我们有我们几个需要的script文件.最重要的一个文件snapcraft.yaml也在根目录中.整个项目的源码可以在如下的地址找到:


对于一个崭新的项目来说,我们可以使用如下的命令来生产一个简单的snapcraft.yaml文件:

$ snapcraft init

利用我们刚生产的snapcraft.yaml文件,我们做如下的修改:

snapcraft.yaml


name: hello-xiaoguo
version: 1.0.18
vendor: Snappy Developers <snappy-devel@lists.ubuntu.com>
icon: hello.png
binaries:
  echo:
    exec: bin/echo
  env:
    exec: bin/env
  evil:
    exec: bin/evil
  showdev:
    exec: bin/showdev
  usehw:
    exec: bin/usehw
  sh:
    exec: bin/sh    
    
summary: Hello xiaoguo
description: This is a simple hello world example

parts:
 hello:
  plugin: copy
  files:
    ./bin/echo: bin/echo
    ./bin/env: bin/env
    ./bin/evil: bin/evil
    ./bin/showdev: bin/showdev
    ./bin/usehw: bin/usehw
    ./bin/sh: bin/sh

在我们建立这个文件时, 注意我们不要使用tab键.summary的长度不要超过78个字符.首先,我们看到的是"hello-xiaoguo".这个名字决定了最终的snap包的名称"hello-xiaoguo_1.0.18_amd64.snap".关于snapcraft里的这些项的定义,我们也可以参考文章" packaging-format-apps".我们可以使用如下的命令来编译我们的snap包:

liuxg@liuxg:~/snappy/examples/hello-world$ snapcraft

如果你想clean的话,可以使用如下的命令:

liuxg@liuxg:~/snappy/examples/hello-world$ snapcraft clean

编译后的整个文件目录就像:

liuxg@liuxg:~/snappy/examples/hello-world$ tree
.
├── bin
│   ├── echo
│   ├── env
│   ├── evil
│   ├── sh
│   ├── showdev
│   └── usehw
├── hello.png
├── hello-xiaoguo_1.0.18_amd64.snap
├── parts
│   └── hello
│       ├── build
│       ├── install
│       │   └── bin
│       │       ├── echo
│       │       ├── env
│       │       ├── evil
│       │       ├── sh
│       │       ├── showdev
│       │       └── usehw
│       ├── src
│       ├── state
│       └── ubuntu
├── snap
│   ├── bin
│   │   ├── echo
│   │   ├── echo.wrapper
│   │   ├── env
│   │   ├── env.wrapper
│   │   ├── evil
│   │   ├── evil.wrapper
│   │   ├── sh
│   │   ├── showdev
│   │   ├── showdev.wrapper
│   │   ├── sh.wrapper
│   │   ├── usehw
│   │   └── usehw.wrapper
│   └── meta
│       ├── hello.png
│       ├── package.yaml
│       └── readme.md
├── snapcraft.yaml
└── stage
    └── bin
        ├── echo
        ├── env
        ├── evil
        ├── sh
        ├── showdev
        └── usehw

在上面我们可以看到,我们已经成功生产了我们梦寐以求的"hello-xiaoguo_1.0.18_amd64.snap"文件.如果仔细的开发者,你可以打开在snap目录下的 meta文件目录,你可以发现有三个中要的文件:

  1. hello.png
  2. package.yaml
  3. readme.md
这三个文件的内容都是基于我们先前的hello.png文件及snapcraft.yaml文件而生产的.

package.yaml


architectures:
- amd64
binaries:
- exec: bin/echo.wrapper
  name: echo
- exec: bin/evil.wrapper
  name: evil
- exec: bin/usehw.wrapper
  name: usehw
- exec: bin/env.wrapper
  name: env
- exec: bin/showdev.wrapper
  name: showdev
- exec: bin/sh.wrapper
  name: sh
icon: meta/hello.png
name: hello-xiaoguo
vendor: Snappy Developers <snappy-devel@lists.ubuntu.com>
version: 1.0.18

readme.md

Hello xiaoguo
This is a simple hello world example

我们可以通过在文章" Snappy Ubuntu 入门"介绍的方式部署到我们不同的target上来测试我们的应用.为了运行我们的snappy应用,我们可以采用如下的方式:



注意这里的"hello-xiaoguo"是我们在我们的snapcraft.yaml中定义的name项,"echo"是我们在binaries中定义的项.

虽然这是一个简单的应用,但是,我们还是可以学习很多的知识,比如运行我们的hello-xiaoguo.env就可以得到我们当前应用可以得到的所有的环境变量:





我们以后可以在我们的应用中应用这些变量,并使用它们.我们不必要硬编码这些路径.

比如我们也可以使用hello-xiaoguo.evil:




我们从上面可以看出来,当我们的应用尝试创建并向/var/tmp/myevil.txt写入一个文字时,我们看到错误信息" Permission denied".很显然,我们应用的confinement是起作用的.这是因为"/var/tmp/"不是我们应用可以访问的目录.

接下来,我们如法炮制,我们重新创建一个新的叫做createfile的script:

createfile

#!/bin/sh

set -e
echo "Hello a nice World!"

echo "This example demonstrates the app confinement"
echo "This app tries to write to its own user directory"

echo "Haha" > $HOME/test.txt

echo "Succeeded! Please find a file created at $HOME/test.txt"
echo "If do not see this, please file a bug"

这里,我们使用了$HOME变量来得到我们应用的使用空间.在编程中,这个是我们唯一可以操控的空间.这个目录是可以让我们来读写属于我们应用的目录:




如果有兴趣的开发者可以试一试路径$SNAP_APP_DATA_PATH看一看能否正确写入我们所期望的数据.


4)如何得到snapcraft的帮助信息


我们可以通过如下的方法来得到snapcraft的帮助信息:

liuxg@liuxg:~$ snapcraft --help
usage: snapcraft [-h] [-v]
                 {init,shell,run,list-plugins,clean,pull,build,stage,snap,assemble,all,version,help}
                 ...

positional arguments:
  {init,shell,run,list-plugins,clean,pull,build,stage,snap,assemble,all,version,help}
    init                start a project
    shell               enter staging environment
    run                 run snap in kvm
    list-plugins        list the available plugins that handle different types
                        of a part
    clean               clean up the environment (to start from scratch)
    pull                get sources
    build               build parts
    stage               put parts into staging area
    snap                put parts into snap area
    assemble (all)      make snap package
    version             show the program's version number and exit
    help                obtain help for plugins and specific topics

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         show the program's version number and exit

我们也可以通过如下的方式来得到帮助的信息:

liuxg@liuxg:~$ snapcraft help
usage: Get help on additional topics or plugin usage.
    snapcraft help topics    To get the list of topics
    snapcraft help <plugin>  To get help for a specific plugin
    snapcraft help <topic>   To get help on a speficic topic

To see the list of available plugins run

    snapcraft list-plugins
snapcraft help: error: the following arguments are required: topic

比如我们想得到python3的帮助信息,我们可以通过如下的方式来做到:

liuxg@liuxg:~$ snapcraft help python3
The python3 plugin can be used for python 3 based parts.

The python3 plugin can be used for python 3 projects where you would
want to do:

    - import python modules with a requirements.txt
    - build a python project that has a setup.py
    - install sources straight from pip

This plugin uses the common plugin keywords as well as those for "sources".
For more information check the 'plugins' topic for the former and the
'sources' topic for the latter.

Additionally, this plugin uses the following plugin-specific keywords:

    - requirements:
      (string)
      path to a requirements.txt file
    - python-packages:
      (list)
      A list of dependencies to get from PyPi


5)如何查看snap包里的文件内容



我们可以通过如下的命令来查看一个snap包里的内容:

$ dpkg -c webcam-webui_1_amd64.snap 
$ dpkg -x webcam_1.0_amd64.snap unpacked




关于Snapcraft,我们也有一个英文的教程 Snappy Ubuntu Core clinic 视频 .如果你的英文不错的话,可以仔细听一听哦!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值