├── README.md ├── Vagrantfile └── bootstrap.sh /README.md: -------------------------------------------------------------------------------- 1 | Setting up a development environment for development and packaging of Linux desktop 2 | applications using Kivy is not straightforward. 3 | 4 | This example demonstrates creating a debian package of a kivy application on Ubuntu 12.04. 5 | The Vagrantfile provisions an Ubuntu instance using the included `bookstrap.sh`. 6 | 7 | `bootstrap.sh` does the following: 8 | - Sets up the Ubuntu Desktop 9 | - Installs `python`, `kivy`, and `pyinstaller` 10 | - Packages a kivy demo application as a single-file binary 11 | - Creates a `.deb` contains the kivy app and an Unity Launcher (.desktop file) 12 | - Installs the .deb package using `dpkg` 13 | - Creates a shortcut on the Desktop that the user can double-click to launch the app 14 | 15 | 16 | Instructions: 17 | 18 | - Install [VirtualBox](https://www.virtualbox.org/) and [Vagrant](http://www.vagrantup.com) 19 | - `git clone https://github.com/rajbot/kivy_pyinstaller_linux_example.git` 20 | - `cd kivy_pyinstaller_linux_example` 21 | - `vagrant up` (this will take a while) 22 | - After the provisioning script is finished, type `vagrant reload` to boot into the desktop environment you just installed 23 | - In the VirtualBox GUI window, log in as user "vagrant", pw "vagrant" 24 | - Double-click on the `Kivy Pong` icon on the Desktop to launch the app 25 | 26 | 27 | The setup script will install Kivy and PyInstaller in a virtualenv. We need to install 28 | Kivy in a virtualenv instead of using the PPA because we need the `kivy.tools` 29 | package in order to use the PyInstaller helper functions supplied by Kivy. The PPA does 30 | not install the `kivy.tools` package. 31 | 32 | In our PyInstaller .spec file, we install hooks using this code: 33 | ```python 34 | from kivy.tools.packaging.pyinstaller_hooks import install_hooks 35 | install_hooks(globals()) 36 | ``` 37 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! 5 | VAGRANTFILE_API_VERSION = "2" 6 | 7 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 8 | # All Vagrant configuration is done here. The most common configuration 9 | # options are documented and commented below. For a complete reference, 10 | # please see the online documentation at vagrantup.com. 11 | 12 | # Every Vagrant virtual environment requires a box to build off of. 13 | config.vm.box = "precise32" 14 | 15 | config.vm.provision "shell", path: "bootstrap.sh" 16 | 17 | 18 | # The url from where the 'config.vm.box' box will be fetched if it 19 | # doesn't already exist on the user's system. 20 | config.vm.box_url = "http://files.vagrantup.com/precise32.box" 21 | 22 | # Create a forwarded port mapping which allows access to a specific port 23 | # within the machine from a port on the host machine. In the example below, 24 | # accessing "localhost:8080" will access port 80 on the guest machine. 25 | # config.vm.network :forwarded_port, guest: 80, host: 8080 26 | 27 | # Create a private network, which allows host-only access to the machine 28 | # using a specific IP. 29 | # config.vm.network :private_network, ip: "192.168.33.10" 30 | 31 | # Create a public network, which generally matched to bridged network. 32 | # Bridged networks make the machine appear as another physical device on 33 | # your network. 34 | # config.vm.network :public_network 35 | 36 | # If true, then any SSH connections made will enable agent forwarding. 37 | # Default value: false 38 | # config.ssh.forward_agent = true 39 | 40 | # Share an additional folder to the guest VM. The first argument is 41 | # the path on the host to the actual folder. The second argument is 42 | # the path on the guest to mount the folder. And the optional third 43 | # argument is a set of non-required options. 44 | # config.vm.synced_folder "../data", "/vagrant_data" 45 | 46 | # Provider-specific configuration so you can fine-tune various 47 | # backing providers for Vagrant. These expose provider-specific options. 48 | # Example for VirtualBox: 49 | # 50 | config.vm.provider :virtualbox do |vb| 51 | # Don't boot with headless mode 52 | vb.gui = true 53 | 54 | # Use VBoxManage to customize the VM. For example to change memory: 55 | # vb.customize ["modifyvm", :id, "--memory", "1024"] 56 | 57 | # Add nikon j3 camera 58 | vb.customize ['modifyvm', :id, '--usb', 'on'] 59 | vb.customize ['usbfilter', 'add', '0', '--target', :id, '--name', 'NikonJ3', '--vendorid', '0x04b0', '--productid', '0x0605'] 60 | 61 | # Add nikon j4 camera 62 | vb.customize ['usbfilter', 'add', '0', '--target', :id, '--name', 'NikonJ4', '--vendorid', '0x04b0', '--productid', '0x0609'] 63 | 64 | # Add nikon j5 camera 65 | vb.customize ['usbfilter', 'add', '0', '--target', :id, '--name', 'NikonJ5', '--vendorid', '0x04b0', '--productid', '0x060b'] 66 | 67 | end 68 | # 69 | # View the documentation for the provider you're using for more 70 | # information on available options. 71 | 72 | # Enable provisioning with Puppet stand alone. Puppet manifests 73 | # are contained in a directory path relative to this Vagrantfile. 74 | # You will need to create the manifests directory and a manifest in 75 | # the file precise32.pp in the manifests_path directory. 76 | # 77 | # An example Puppet manifest to provision the message of the day: 78 | # 79 | # # group { "puppet": 80 | # # ensure => "present", 81 | # # } 82 | # # 83 | # # File { owner => 0, group => 0, mode => 0644 } 84 | # # 85 | # # file { '/etc/motd': 86 | # # content => "Welcome to your Vagrant-built virtual machine! 87 | # # Managed by Puppet.\n" 88 | # # } 89 | # 90 | # config.vm.provision :puppet do |puppet| 91 | # puppet.manifests_path = "manifests" 92 | # puppet.manifest_file = "site.pp" 93 | # end 94 | 95 | # Enable provisioning with chef solo, specifying a cookbooks path, roles 96 | # path, and data_bags path (all relative to this Vagrantfile), and adding 97 | # some recipes and/or roles. 98 | # 99 | # config.vm.provision :chef_solo do |chef| 100 | # chef.cookbooks_path = "../my-recipes/cookbooks" 101 | # chef.roles_path = "../my-recipes/roles" 102 | # chef.data_bags_path = "../my-recipes/data_bags" 103 | # chef.add_recipe "mysql" 104 | # chef.add_role "web" 105 | # 106 | # # You may also specify custom JSON attributes: 107 | # chef.json = { :mysql_password => "foo" } 108 | # end 109 | 110 | # Enable provisioning with chef server, specifying the chef server URL, 111 | # and the path to the validation key (relative to this Vagrantfile). 112 | # 113 | # The Opscode Platform uses HTTPS. Substitute your organization for 114 | # ORGNAME in the URL and validation key. 115 | # 116 | # If you have your own Chef Server, use the appropriate URL, which may be 117 | # HTTP instead of HTTPS depending on your configuration. Also change the 118 | # validation key to validation.pem. 119 | # 120 | # config.vm.provision :chef_client do |chef| 121 | # chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME" 122 | # chef.validation_key_path = "ORGNAME-validator.pem" 123 | # end 124 | # 125 | # If you're using the Opscode platform, your validator client is 126 | # ORGNAME-validator, replacing ORGNAME with your organization name. 127 | # 128 | # If you have your own Chef Server, the default validation client name is 129 | # chef-validator, unless you changed the configuration. 130 | # 131 | # chef.validation_client_name = "ORGNAME-validator" 132 | end 133 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | echo "Provisioning ubuntu desktop" 5 | apt-get update 6 | DEBIAN_FRONTEND=noninteractive apt-get install -y ubuntu-desktop 7 | 8 | echo "Setting up kivy" 9 | 10 | #from http://kivy.org/docs/installation/installation-linux.html#ubuntu-12-04-with-python-2-7 11 | # Install necessary system packages 12 | sudo apt-get install -y build-essential mercurial git python2.7 \ 13 | python-setuptools python-dev ffmpeg libsdl-image1.2-dev \ 14 | libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsmpeg-dev libsdl1.2-dev \ 15 | libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev zlib1g-dev 16 | 17 | #from http://developer.ubuntu.com/2012/02/how-to-prepare-a-compiled-application-for-ubuntu-software-center/ 18 | # Install packages necessary for creating .debs 19 | sudo apt-get install -y devscripts lintian dh-make 20 | 21 | 22 | # Bootstrap a current Python environment 23 | sudo apt-get remove --purge -y python-virtualenv python-pip 24 | sudo easy_install-2.7 -U pip 25 | sudo pip2.7 install -U virtualenv 26 | 27 | # Install current version of Cython 28 | sudo apt-get remove --purge -y cython 29 | sudo pip2.7 install -U cython 30 | 31 | # Install other PyGame dependencies 32 | sudo apt-get remove --purge -y python-numpy 33 | sudo pip2.7 install -U numpy 34 | 35 | # Install PyGame 36 | sudo apt-get remove --purge python-pygame 37 | hg clone https://bitbucket.org/pygame/pygame 38 | cd pygame 39 | python2.7 setup.py build 40 | sudo python2.7 setup.py install 41 | cd .. 42 | sudo rm -rf pygame 43 | 44 | 45 | 46 | # Create a vitualenv 47 | rm -rf venv 48 | sudo -u vagrant virtualenv -p python2.7 --system-site-packages venv 49 | 50 | # Install stable version of Kivy into the virtualenv 51 | sudo -u vagrant venv/bin/pip install kivy 52 | # For the development version of Kivy, use the following command instead 53 | # venv/bin/pip install git+https://github.com/kivy/kivy.git@master 54 | 55 | # Install development version of buildozer into the virtualenv 56 | # venv/bin/pip install git+https://github.com/kivy/buildozer.git@master 57 | 58 | # Install development version of plyer into the virtualenv 59 | # venv/bin/pip install git+https://github.com/kivy/plyer.git@master 60 | 61 | # Install a couple of dependencies for KivyCatalog 62 | sudo -u vagrant venv/bin/pip install -U pygments docutils 63 | 64 | 65 | echo "Setting up pyinstaller" 66 | sudo -u vagrant venv/bin/pip install pyinstaller 67 | 68 | 69 | echo "Setting up demo pong app" 70 | sudo -u vagrant cp -r venv/share/kivy-examples/tutorials/pong . 71 | 72 | spec="# -*- mode: python -*- 73 | from kivy.tools.packaging.pyinstaller_hooks import install_hooks 74 | install_hooks(globals()) 75 | 76 | a = Analysis(['main.py'], 77 | pathex=['/home/scribe/pong'], 78 | hiddenimports=[], 79 | ) 80 | pyz = PYZ(a.pure) 81 | exe = EXE(pyz, 82 | [('pong.kv', 'pong.kv', 'DATA')], 83 | a.scripts, 84 | a.binaries, 85 | a.zipfiles, 86 | a.datas, 87 | name='pong', 88 | debug=False, 89 | strip=None, 90 | upx=True, 91 | console=False ) 92 | " 93 | 94 | sudo -u vagrant echo "$spec" > pong/pong.spec 95 | chown vagrant pong/pong.spec 96 | 97 | cd pong 98 | sudo -u vagrant HOME=/home/vagrant /home/vagrant/venv/bin/pyinstaller pong.spec --clean 99 | cd .. 100 | 101 | echo "Creating and Installing kivypong_1.0-1.deb" 102 | 103 | #Create a .deb 104 | sudo -u vagrant mkdir -p kivypong_1.0-1/usr/local/bin 105 | sudo -u vagrant mkdir -p kivypong_1.0-1/usr/share/applications 106 | sudo -u vagrant mkdir -p kivypong_1.0-1/DEBIAN 107 | 108 | deb_control="Source: kivypong 109 | Priority: extra 110 | Maintainer: vagrant 111 | Build-Depends: debhelper (>= 8.0.0) 112 | Standards-Version: 3.9.2 113 | Package: kivypong 114 | Version: 1.0-1 115 | Architecture: i386 116 | Description: Kivy Pong example 117 | This is an example of creating a single-binary .deb with a kivy app 118 | " 119 | 120 | echo "$deb_control" > kivypong_1.0-1/DEBIAN/control 121 | chown vagrant kivypong_1.0-1/DEBIAN/control 122 | 123 | desktop="[Desktop Entry] 124 | Version=1.0 125 | Name=Kivy Pong 126 | Comment=Kivy Pong Example 127 | Exec=/usr/local/bin/kivypong 128 | Icon=/usr/share/icons/Humanity/apps/32/application-community.svg 129 | Type=Application 130 | Categories=Games; 131 | " 132 | 133 | echo "$desktop" > kivypong_1.0-1/usr/share/applications/kivypong.desktop 134 | chmod a+x kivypong_1.0-1/usr/share/applications/kivypong.desktop 135 | chown vagrant kivypong_1.0-1/usr/share/applications/kivypong.desktop 136 | 137 | 138 | sudo -u vagrant cp pong/dist/pong kivypong_1.0-1/usr/local/bin/kivypong 139 | 140 | sudo -u vagrant dpkg-deb --build kivypong_1.0-1 141 | 142 | #install .deb 143 | dpkg -i kivypong_1.0-1.deb 144 | 145 | #create link on desktop 146 | sudo -u vagrant rm -f /home/vagrant/Desktop/kivypong.desktop 147 | sudo -u vagrant ln -s /usr/share/applications/kivypong.desktop /home/vagrant/Desktop 148 | 149 | 150 | echo "You will now need to run 'vagrant reload' to start with the Ubuntu Desktop. A shortcut to the Kivy Pong application has been placed on the Desktop, which you can now run." 151 | --------------------------------------------------------------------------------