Skip to content

Commit

Permalink
Merge pull request #2314 from pupil-labs/develop
Browse files Browse the repository at this point in the history
Pupil Core 3.6 Release Candidate 1
  • Loading branch information
mikelgg93 committed Feb 16, 2023
2 parents a4e4306 + ebab635 commit 5e678b7
Show file tree
Hide file tree
Showing 291 changed files with 4,418 additions and 3,834 deletions.
95 changes: 95 additions & 0 deletions .github/workflows/bundle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Bundle Pupil Core

on:
push:
tags:
- "**"
workflow_dispatch:
inputs:
notarize_on_macos:
description: 'Notarize on macOS'
required: true
type: boolean

jobs:
Bundle:
name: Bundle ${{ matrix.platform }}
strategy:
fail-fast: False
matrix:
platform:
- windows-latest
- macOS-11
- ubuntu-18.04
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install Pupil Core dependencies
env:
ARCHFLAGS: "-arch x86_64"
run: |
python -m pip install -U pip wheel
python -m pip install -r requirements.txt -r requirements-bundle.txt
- name: Install Linux-specific dependencies
if: runner.os == 'Linux'
run: sudo apt-get install libportaudio2
- name: Bundle on Windows
if: runner.os == 'Windows'
run: .\reproducible_build.ps1
shell: powershell
working-directory: deployment
- name: Import macOS codesign certificates
if: runner.os == 'macOS'
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.MACOS_CERTIFICATE }}
p12-password: ${{ secrets.MACOS_CERTIFICATE_PWD }}
- name: Bundle on Unix
if: runner.os != 'Windows'
run: ./reproducible_build.sh
working-directory: deployment
env:
MACOS_SHOULD_SIGN_AND_NOTARIZE: >
${{
inputs.notarize_on_macos ||
(github.event_name == 'push' && contains(github.ref, 'refs/tags/'))
}}
MACOS_CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
MACOS_NOTARYTOOL_APPLE_ID: ${{ secrets.MACOS_NOTARYTOOL_APPLE_ID }}
MACOS_NOTARYTOOL_TEAM_ID: ${{ secrets.MACOS_NOTARYTOOL_TEAM_ID }}
MACOS_NOTARYTOOL_APPSPECIFIC_PASSWORD: ${{ secrets.MACOS_NOTARYTOOL_APPSPECIFIC_PASSWORD }}
- name: Upload build as artifact
uses: actions/upload-artifact@v3
if: always()
with:
name: bundle-${{ matrix.platform }}
path: |
deployment/*.rar
deployment/*.app
deployment/*.dmg
deployment/*.json
deployment/*.zip
draft_release:
name: Draft Github release
needs: Bundle
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- name: Download build artifacts
uses: actions/download-artifact@v3
- name: Create Github release draft
uses: softprops/action-gh-release@v1
with:
files: |
*.rar
*.dmg
*.zip
draft: true
name: Pupil Capture, Player, and Service release
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,14 @@ mprofile_*.dat
*.dmg
*.zip
deployment/pupil_v*
deployment/build/
deployment/dist/
*.pyd
*.dll
win_drv
.vs
.venv
.venv*

# pyenv local config
.python-version
*.exe
24 changes: 24 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,32 @@ repos:
- id: check-added-large-files
- id: check-ast
- id: check-toml
- id: check-case-conflict
- id: check-merge-conflict
- id: check-yaml
- id: debug-statements
- id: mixed-line-ending

- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black

- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
hooks:
- id: pyupgrade
name: PyUpgrade 3.6+
args: ["--py36-plus"]
exclude: ^bin/

- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
args: [--profile, black]

- repo: https://github.com/asottile/setup-cfg-fmt
rev: v2.2.0
hooks:
- id: setup-cfg-fmt
48 changes: 39 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,51 @@ There are a number of ways you can interact with Pupil Core software as a develo

All setup and dependency installation instructions are contained in this repo. All other developer documentation is [here](https://docs.pupil-labs.com/developer/core/overview/ "Pupil Core developer docs").

### Installing Dependencies
- [Ubuntu 18.04 LTS](./docs/dependencies-ubuntu18.md "Pupil dependency installation for Ubuntu 18.04") (recommended Linux distribution)
- [Ubuntu 17.10 or lower](./docs/dependencies-ubuntu17.md "Pupil dependency installation for Ubuntu 17.10 or lower")
- [macOS](./docs/dependencies-macos.md "Pupil dependency installation for macOS")
- [Windows 10](./docs/dependencies-windows.md "Pupil dependency installation for Windows 10")
### Installing Dependencies and Code

### Clone the repo
After you have installed all dependencies, clone this repo and start Pupil software.
To run the source code, you will need Python 3.7 or newer!

Note: It is recommended to install the requirements into a
[virtual environment](https://docs.python.org/3/tutorial/venv.html).

Note: On arm64 macs (e.g. M1 MacBook Air), use the `python3.*-intel64` binary to create
the virtual environment. We do not yet provide arm64-native wheels for the Pupil Core
dependencies.

```sh
git clone https://github.com/pupil-labs/pupil.git # or your fork
git clone https://github.com/pupil-labs/pupil.git
cd pupil
git checkout develop
python -m pip install -r requirements.txt
```

If you have trouble installing any of the dependencies, please see the corresponding
code repository for manual installation steps and troubleshooting.

#### Linux

##### USB Access

To grant Pupil Core applications access to the cameras, run

```sh
echo 'SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", GROUP="plugdev", MODE="0664"' | sudo tee /etc/udev/rules.d/10-libuvc.rules > /dev/null
sudo udevadm trigger
```

_Note_: If you are using Windows, you will have to complete a few more steps after cloning the repo. Please refer to the [Windows 10 dependencies setup guide](./docs/dependencies-windows.md "Pupil dependency installation for Windows 10").
and ensure that your user is part of the `plugdev` group:

```sh
sudo usermod -a -G plugdev $USER
```

##### Audio Playback

The [`sounddevice`](https://python-sounddevice.readthedocs.io/en/0.4.5/installation.html#installation) package depends on the `libportaudio2` library:

```sh
sudo apt install libportaudio2
```

### Run Pupil

Expand Down
5 changes: 5 additions & 0 deletions deployment/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
deploy_*/
bundle_*
find_opengl_bigsur.py
pupil_core_hooks.py
pupil_core_v*
13 changes: 8 additions & 5 deletions deployment/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
We use `deploy_capture`, `deploy_player`, and `deploy_service` to create application bundles for deployment.
We use `reproducible_build.*` to create application bundles for deployment.

Since pyinstaller does not cross compile the scripts need to work on mac/linux/windows.


This process in __NOT RECOMMENDED OR REQUIRED FOR USERS__! (Adding documented user support for bundling is hard to support and user problems almost impossible to debug.)
This process in __NOT RECOMMENDED OR REQUIRED FOR USERS__! (Adding documented user
support for bundling is hard to support and user problems almost impossible to debug.)

You have a few options:
- Use the runtime plugin-loader and a recent release bundle to customise your app. (the plugin loader will work in the bundle version just as it does when running from source.) <--RECOMMENDED
- If you just need a recent version of the main repo bundled, raise an issue and we will bundle and release ASAP.
- [Recommended] Use the runtime plugin-loader and a recent release bundle to customise
your app. The plugin loader will work in the bundle version just as it does when
running from source.)
- If you just need a recent version of the main repo bundled, raise an issue and we
will bundle and release ASAP.
- Figure out a setup that bundles by your own. (Expect a world of pain.)
35 changes: 35 additions & 0 deletions deployment/_packaging/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import enum

from version_utils import ParsedVersion, pupil_version, write_version_file

from . import linux, macos, windows


class SupportedPlatform(enum.Enum):
macos = "Darwin"
linux = "Linux"
windows = "Windows"


ICON_EXT = {
SupportedPlatform.macos: ".icns",
SupportedPlatform.linux: ".svg",
SupportedPlatform.windows: ".ico",
}
LIB_EXT = {
SupportedPlatform.macos: ".dylib",
SupportedPlatform.linux: ".so",
SupportedPlatform.windows: ".dll",
}

__all__ = [
"ParsedVersion",
"SupportedPlatform",
"ICON_EXT",
"LIB_EXT",
"linux",
"macos",
"pupil_version",
"windows",
"write_version_file",
]
115 changes: 115 additions & 0 deletions deployment/_packaging/linux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import pathlib
import shutil
import subprocess

from . import ParsedVersion


def create_zipped_deb_packages(dist_root: pathlib.Path, app_version: ParsedVersion):
deb_folder = dist_root / "debs"
deb_folder.mkdir(exist_ok=True)
for folder in dist_root.glob("Pupil */"):
deb_pkg = create_deb_package(dist_root, folder.name, app_version)
deb_pkg.rename(deb_folder / deb_pkg.name)

shutil.make_archive(str(dist_root), "zip", deb_folder)


def create_deb_package(
dist_root: pathlib.Path, app_name: str, app_version: ParsedVersion
) -> pathlib.Path:
# lets build the structure for our deb package_name.

package_name = app_name.lower().replace(" ", "_")
deb_folder = f"{package_name}_v{app_version}"
deb_root = (dist_root / deb_folder).resolve()
if deb_root.exists():
shutil.rmtree(str(deb_root))

control = deb_root / "DEBIAN" / "control"
desktop = deb_root / "usr" / "share" / "applications" / f"{package_name}.desktop"
starter = deb_root / "usr" / "local" / "bin" / package_name
opt_dir = deb_root / "opt"
ico_dir = deb_root / "usr" / "share" / "icons" / "hicolor" / "scalable" / "apps"

control.parent.mkdir(mode=0o755, exist_ok=True, parents=True)
starter.parent.mkdir(mode=0o755, exist_ok=True, parents=True)
desktop.parent.mkdir(mode=0o755, exist_ok=True, parents=True)
ico_dir.mkdir(mode=0o755, exist_ok=True, parents=True)

startup_WM_class = app_name
if startup_WM_class == "Pupil Capture":
startup_WM_class += " - World"

# DEB control file
with control.open("w") as f:
dist_size = sum(f.stat().st_size for f in dist_root.rglob("*"))
content = f"""\
Package: {package_name.replace("_", "-")}
Version: {app_version}
Architecture: amd64
Maintainer: Pupil Labs <info@pupil-labs.com>
Priority: optional
Description: {app_name} - Find more information on https://docs.pupil-labs.com/core/
Installed-Size: {round(dist_size / 1024)}
"""
# See this link regarding the calculation of the Installed-Size field
# https://www.debian.org/doc/debian-policy/ch-controlfields.html#installed-size
f.write(content)
control.chmod(0o644)

# bin_starter script

with starter.open("w") as f:
content = f'''\
#!/bin/sh
exec /opt/{package_name}/{package_name} "$@"'''
f.write(content)
starter.chmod(0o755)

# .desktop entry
# ATTENTION: In order for the bundle icon to display correctly
# two things are necessary:
# 1. Icon needs to be the icon's base name/stem
# 2. The window title must be equivalent to StartupWMClass
with desktop.open("w") as f:
content = f"""\
[Desktop Entry]
Version={app_version}
Type=Application
Name={app_name}
Comment=Preview Pupil Invisible data streams
Exec=/opt/{package_name}/{package_name}
Terminal=false
Icon={package_name.replace('_', '-')}
Categories=Application;
Name[en_US]={app_name}
Actions=Terminal;
StartupWMClass={startup_WM_class}
[Desktop Action Terminal]
Name=Open in Terminal
Exec=x-terminal-emulator -e {package_name}"""
f.write(content)
desktop.chmod(0o644)

svg_file_name = f"{package_name.replace('_', '-')}.svg"
src_path = pathlib.Path("icons", svg_file_name)
dst_path = ico_dir / svg_file_name
shutil.copy(str(src_path), str(dst_path))
dst_path.chmod(0o755)

# copy the actual application
shutil.copytree(str(dist_root / app_name), str(opt_dir / package_name))
for f in opt_dir.rglob("*"):
if f.is_file():
if f.name == package_name:
f.chmod(0o755)
else:
f.chmod(0o644)
elif f.is_dir():
f.chmod(0o755)
opt_dir.chmod(0o755)

subprocess.call(["fakeroot", "dpkg-deb", "--build", deb_root])
shutil.rmtree(str(deb_root))
return deb_root.with_name(deb_root.name + ".deb")
Loading

0 comments on commit 5e678b7

Please sign in to comment.