Make proprietary drivers optional (1/2): pmbootstrap changes (#1254)

Here are the changes necessary in pmbootstrap to make proprietary
software installed onto the device (firmware and userspace drivers)
optional (#756). To full close the issue, we need to apply this concept
to all device packages we already have in a follow-up PR.

Changes:
* New config file options nonfree_firmware and nonfree_userland, which
  we ask for during "pmbootstrap init" if there are non-free components
  for the selected device.
* We find that out by checking the APKBUILD's subpakages: The non-free
  packages are called $pkgname-nonfree-firmware and
  $pkgname-nonfree-userland.
* During "pmbootstrap init" we also show the pkgdesc of these
  subpackages. Parsing that is implemented in
  pmb.parse._apkbuild.subpkgdesc(). It was not implemented as part of
  the regular APKBUILD parsing, as this would need a change in the
  output format, and it is a lot *less* code if done like in this
  commit.
* pmb/parse/apkbuild.py was renamed to _apkbuild.py, and
  pmb/install/install.py to _install.py: needed to call the function in
  the usual way (e.g. pmb.parse.apkbuild()) but still being able to
  test the individual functions from these files in the test suite.
  We did the same thing for pmb/build/_package.py already.
* Install: New function get_nonfree_packages() returns the non-free
  packages that will be installed, based on the user's choice in
  "pmbootstrap init" and on the subpackages the device has.
* Added test cases and test data (APKBUILDs) for all new code,
  refactored test/test_questions.py to have multiple functions for
  testing the various questions / question types from
  "pmbootstrap init" instead of having it all in one big function.
  This allows to use another aport folder for testing the new
  non-free related questions in init.
This commit is contained in:
Oliver Smith 2018-02-24 21:49:10 +00:00 committed by GitHub
parent 2e30fa4281
commit ad5a0d4294
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 469 additions and 62 deletions

View File

@ -21,7 +21,7 @@ import os
import logging
import pmb.chroot.user
import pmb.helpers.cli
import pmb.parse.apkbuild
import pmb.parse
def newapkbuild(args, folder, args_passed):

View File

@ -46,6 +46,7 @@ work_version = "1"
# Only save keys to the config file, which we ask for in 'pmbootstrap init'.
config_keys = ["ccache_size", "device", "extra_packages", "jobs", "keymap",
"nonfree_firmware", "nonfree_userland",
"qemu_native_mesa_driver", "timezone", "ui", "user", "work"]
# Config file/commandline default values
@ -70,6 +71,8 @@ defaults = {
"log": "$WORK/log.txt",
"mirror_alpine": "http://dl-cdn.alpinelinux.org/alpine/",
"mirror_postmarketos": "http://postmarketos.brixit.nl",
"nonfree_firmware": True,
"nonfree_userland": False,
"port_distccd": "33632",
"qemu_native_mesa_driver": "dri-virtio",
"timezone": "GMT",

View File

@ -27,6 +27,7 @@ import pmb.helpers.run
import pmb.helpers.ui
import pmb.chroot.zap
import pmb.parse.deviceinfo
import pmb.parse._apkbuild
def ask_for_work_path(args):
@ -123,6 +124,51 @@ def ask_for_timezone(args):
return "GMT"
def ask_for_device_nonfree(args, device):
"""
Ask the user about enabling proprietary firmware (e.g. Wifi) and userland
(e.g. GPU drivers). All proprietary components are in subpackages
$pkgname-nonfree-firmware and $pkgname-nonfree-userland, and we show the
description of these subpackages (so they can indicate which peripherals
are affected).
:returns: answers as dict, e.g. {"firmware": True, "userland": False}
"""
# Parse existing APKBUILD or return defaults (when called from test case)
apkbuild_path = args.aports + "/device/device-" + device + "/APKBUILD"
ret = {"firmware": args.nonfree_firmware,
"userland": args.nonfree_userland}
if not os.path.exists(apkbuild_path):
return ret
apkbuild = pmb.parse.apkbuild(args, apkbuild_path)
# Only run when there is a "nonfree" subpackage
nonfree_found = False
for subpackage in apkbuild["subpackages"]:
if subpackage.startswith("device-" + device + "-nonfree"):
nonfree_found = True
if not nonfree_found:
return ret
# Short explanation
logging.info("This device has proprietary components, which trade some of"
" your freedom with making more peripherals work.")
logging.info("We would like to offer full functionality without hurting"
" your freedom, but this is currently not possible for your"
" device.")
# Ask for firmware and userland individually
for type in ["firmware", "userland"]:
subpkgname = "device-" + device + "-nonfree-" + type
if subpkgname in apkbuild["subpackages"]:
subpkgdesc = pmb.parse._apkbuild.subpkgdesc(apkbuild_path,
"nonfree_" + type)
logging.info(subpkgname + ": " + subpkgdesc)
ret[type] = pmb.helpers.cli.confirm(args, "Enable this package?",
default=ret[type])
return ret
def ask_for_device(args):
devices = sorted(pmb.helpers.devices.list(args))
logging.info("Target device (either an existing one, or a new one for"
@ -144,7 +190,8 @@ def ask_for_device(args):
pmb.aportgen.generate(args, "linux-" + device)
break
return (device, device_exists)
nonfree = ask_for_device_nonfree(args, device)
return (device, device_exists, nonfree)
def ask_for_qemu_native_mesa_driver(args, device, arch_native):
@ -200,8 +247,10 @@ def frontend(args):
cfg["pmbootstrap"]["work"] = args.work = ask_for_work_path(args)
# Device
device, device_exists = ask_for_device(args)
device, device_exists, nonfree = ask_for_device(args)
cfg["pmbootstrap"]["device"] = device
cfg["pmbootstrap"]["nonfree_firmware"] = str(nonfree["firmware"])
cfg["pmbootstrap"]["nonfree_userland"] = str(nonfree["userland"])
# Qemu mesa driver
if cfg["pmbootstrap"]["device"].startswith("qemu-"):

View File

@ -16,7 +16,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
"""
from pmb.install.install import install
from pmb.install._install import install
from pmb.install.partition import partition
from pmb.install.format import format
from pmb.install.partition import partitions_mount

View File

@ -67,6 +67,29 @@ def get_subpartitions_size(args):
return (full, boot)
def get_nonfree_packages(args, device):
"""
Get the non-free packages based on user's choice in "pmbootstrap init" and
based on whether there are non-free packages in the APKBUILD or not.
:returns: list of non-free packages to be installed. Example:
["device-nokia-n900-nonfree-firmware"]
"""
# Read subpackages
apkbuild_path = args.aports + "/device/device-" + device + "/APKBUILD"
apkbuild = pmb.parse.apkbuild(args, apkbuild_path)
subpackages = apkbuild["subpackages"]
# Check for firmware and userland
ret = []
prefix = "device-" + device + "-nonfree-"
if args.nonfree_firmware and prefix + "firmware" in subpackages:
ret += [prefix + "firmware"]
if args.nonfree_userland and prefix + "userland" in subpackages:
ret += [prefix + "userland"]
return ret
def copy_files_from_chroot(args):
"""
Copy all files from the rootfs chroot to /mnt/install, except
@ -316,7 +339,8 @@ def install(args):
logging.info('*** (2/{0}) CREATE DEVICE ROOTFS ("{1}") ***'.format(steps,
args.device))
install_packages = (pmb.config.install_device_packages +
["device-" + args.device])
["device-" + args.device] +
get_nonfree_packages(args, args.device))
if args.ui.lower() != "none":
install_packages += ["postmarketos-ui-" + args.ui]
suffix = "rootfs_" + args.device

View File

@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
"""
from pmb.parse.arguments import arguments
from pmb.parse.apkbuild import apkbuild
from pmb.parse._apkbuild import apkbuild
from pmb.parse.binfmt_info import binfmt_info
from pmb.parse.deviceinfo import deviceinfo
from pmb.parse.kconfig import check

View File

@ -173,3 +173,37 @@ def apkbuild(args, path, check_pkgver=True):
# Fill cache
args.cache["apkbuild"][path] = ret
return ret
def subpkgdesc(path, function):
"""
Get the pkgdesc of a subpackage in an APKBUILD.
:param path: to the APKBUILD file
:param function: name of the subpackage (e.g. "nonfree_userland")
:returns: the subpackage's pkgdesc
"""
# Read all lines
with open(path, encoding="utf-8") as handle:
lines = handle.readlines()
# Prefixes
prefix_function = function + "() {"
prefix_pkgdesc = "\tpkgdesc=\""
# Find the pkgdesc
in_function = False
for line in lines:
if in_function:
if line.startswith(prefix_pkgdesc):
return line[len(prefix_pkgdesc):-2]
elif line.startswith(prefix_function):
in_function = True
# Failure
if not in_function:
raise RuntimeError("Could not find subpackage function, no line starts"
" with '" + prefix_function + "' in " + path)
raise RuntimeError("Could not find pkgdesc of subpackage function '" +
function + "' (spaces used instead of tabs?) in " +
path)

View File

@ -25,7 +25,7 @@ import pytest
pmb_src = os.path.realpath(os.path.join(os.path.dirname(__file__) + "/.."))
sys.path.append(pmb_src)
import pmb.parse.apkindex
import pmb.parse.apkbuild
import pmb.parse
import pmb.helpers.logging

64
test/test_install.py Normal file
View File

@ -0,0 +1,64 @@
"""
Copyright 2018 Oliver Smith
This file is part of pmbootstrap.
pmbootstrap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pmbootstrap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
"""
import os
import pytest
import sys
# Import from parent directory
pmb_src = os.path.realpath(os.path.join(os.path.dirname(__file__) + "/.."))
sys.path.append(pmb_src)
import pmb.aportgen.device
import pmb.config
import pmb.config.init
import pmb.helpers.logging
import pmb.install._install
@pytest.fixture
def args(tmpdir, request):
import pmb.parse
sys.argv = ["pmbootstrap.py", "init"]
args = pmb.parse.arguments()
args.log = args.work + "/log_testsuite.txt"
pmb.helpers.logging.init(args)
request.addfinalizer(args.logfd.close)
return args
def test_get_nonfree_packages(args):
args.aports = pmb_src + "/test/testdata/init_questions_device/aports"
func = pmb.install._install.get_nonfree_packages
# Device without any non-free subpackages
args.nonfree_firmware = True
args.nonfree_userland = True
assert func(args, "lg-mako") == []
# Device with non-free firmware and userland
device = "nonfree-firmware-and-userland"
assert func(args, device) == ["device-" + device + "-nonfree-firmware",
"device-" + device + "-nonfree-userland"]
# Device with non-free userland
device = "nonfree-userland"
assert func(args, device) == ["device-" + device + "-nonfree-userland"]
# Device with non-free userland (but user disabled it init)
args.nonfree_userland = False
assert func(args, device) == []

View File

@ -0,0 +1,50 @@
"""
Copyright 2018 Oliver Smith
This file is part of pmbootstrap.
pmbootstrap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pmbootstrap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
"""
import os
import pytest
import sys
# Import from parent directory
pmb_src = os.path.realpath(os.path.join(os.path.dirname(__file__) + "/.."))
sys.path.append(pmb_src)
import pmb.parse._apkbuild
def test_subpkgdesc():
func = pmb.parse._apkbuild.subpkgdesc
testdata = pmb_src + "/test/testdata"
# Successful extraction
path = (testdata + "/init_questions_device/aports/device/"
"device-nonfree-firmware/APKBUILD")
pkgdesc = "firmware description"
assert func(path, "nonfree_firmware") == pkgdesc
# Can't find the function
with pytest.raises(RuntimeError) as e:
func(path, "invalid_function")
assert str(e.value).startswith("Could not find subpackage function")
# Can't find the pkgdesc in the function
path = testdata + "/apkbuild/APKBUILD.missing-pkgdesc-in-subpackage"
with pytest.raises(RuntimeError) as e:
func(path, "subpackage")
assert str(e.value).startswith("Could not find pkgdesc of subpackage")

View File

@ -41,64 +41,58 @@ def args(tmpdir, request):
return args
def test_questions(args, monkeypatch, tmpdir):
#
# PREPARATION
#
def fake_answers(monkeypatch, answers):
"""
Patch pmb.helpers.cli.ask() function to return defined answers instead of
asking the user for an answer.
# Use prepared answers
:param answers: list of answer strings, e.g. ["y", "n", "invalid-device"].
In this example, the first question is answered with "y",
the second question with "n" and so on.
"""
def fake_ask(args, question="Continue?", choices=["y", "n"], default="n",
lowercase_answer=True, validation_regex=None):
answer = answers.pop(0)
logging.info("pmb.helpers.cli.ask: fake answer: " + answer)
logging.info("pmb.helpers.cli.ask() fake answer: " + answer)
return answer
monkeypatch.setattr(pmb.helpers.cli, "ask", fake_ask)
# Do not generate aports
def fake_generate(args, pkgname):
return
monkeypatch.setattr(pmb.aportgen, "generate", fake_generate)
# Self-test
answers = ["first", "second"]
def test_fake_answers_selftest(monkeypatch):
fake_answers(monkeypatch, ["first", "second"])
assert pmb.helpers.cli.ask(args) == "first"
assert pmb.helpers.cli.ask(args) == "second"
assert len(answers) == 0
#
# SIMPLE QUESTIONS
#
# Booleans
def test_questions_booleans(args, monkeypatch):
functions = [pmb.aportgen.device.ask_for_keyboard,
pmb.aportgen.device.ask_for_external_storage]
for func in functions:
answers = ["y", "n"]
fake_answers(monkeypatch, ["y", "n"])
assert func(args) is True
assert func(args) is False
# Strings
def test_questions_strings(args, monkeypatch):
functions = [pmb.aportgen.device.ask_for_manufacturer,
pmb.aportgen.device.ask_for_name]
for func in functions:
answers = ["Simple string answer"]
fake_answers(monkeypatch, ["Simple string answer"])
assert func(args) == "Simple string answer"
#
# QUESTIONS WITH ANSWER VERIFICATION
#
# Architecture
answers = ["invalid_arch", "aarch64"]
def test_questions_arch(args, monkeypatch):
fake_answers(monkeypatch, ["invalid_arch", "aarch64"])
assert pmb.aportgen.device.ask_for_architecture(args) == "aarch64"
# Bootimg
def test_questions_bootimg(args, monkeypatch):
func = pmb.aportgen.device.ask_for_bootimg
answers = ["invalid_path", ""]
fake_answers(monkeypatch, ["invalid_path", ""])
assert func(args) is None
bootimg_path = pmb_src + "/test/testdata/bootimg/normal-boot.img"
answers = [bootimg_path]
fake_answers(monkeypatch, [bootimg_path])
output = {"base": "0x80000000",
"kernel_offset": "0x00008000",
"ramdisk_offset": "0x04000000",
@ -109,66 +103,119 @@ def test_questions(args, monkeypatch, tmpdir):
"qcdt": "false"}
assert func(args) == output
# Device
def test_questions_device(args, monkeypatch):
# Prepare args
args.aports = pmb_src + "/test/testdata/init_questions_device/aports"
args.device = "lg-mako"
args.nonfree_firmware = True
args.nonfree_userland = False
# Do not generate aports
def fake_generate(args, pkgname):
return
monkeypatch.setattr(pmb.aportgen, "generate", fake_generate)
# Existing device (without non-free components so we have defaults there)
func = pmb.config.init.ask_for_device
answers = ["lg-mako"]
assert func(args) == ("lg-mako", True)
nonfree = {"firmware": True, "userland": False}
fake_answers(monkeypatch, ["lg-mako"])
assert func(args) == ("lg-mako", True, nonfree)
answers = ["whoops-typo", "n", "lg-mako"]
assert func(args) == ("lg-mako", True)
# Non-existing device, go back, existing device
fake_answers(monkeypatch, ["whoops-typo", "n", "lg-mako"])
assert func(args) == ("lg-mako", True, nonfree)
answers = ["new-device", "y"]
assert func(args) == ("new-device", False)
# New device
fake_answers(monkeypatch, ["new-device", "y"])
assert func(args) == ("new-device", False, nonfree)
# Flash methods
def test_questions_device_nonfree(args, monkeypatch):
# Prepare args
args.aports = pmb_src + "/test/testdata/init_questions_device/aports"
args.nonfree_firmware = False
args.nonfree_userland = False
# APKBUILD with firmware and userland (all yes)
func = pmb.config.init.ask_for_device_nonfree
device = "nonfree-firmware-and-userland"
fake_answers(monkeypatch, ["y", "y"])
nonfree = {"firmware": True, "userland": True}
assert func(args, device) == nonfree
# APKBUILD with firmware and userland (all no)
fake_answers(monkeypatch, ["n", "n"])
nonfree = {"firmware": False, "userland": False}
assert func(args, device) == nonfree
# APKBUILD with firmware only
func = pmb.config.init.ask_for_device_nonfree
device = "nonfree-firmware"
fake_answers(monkeypatch, ["y"])
nonfree = {"firmware": True, "userland": False}
assert func(args, device) == nonfree
# APKBUILD with userland only
func = pmb.config.init.ask_for_device_nonfree
device = "nonfree-userland"
fake_answers(monkeypatch, ["y"])
nonfree = {"firmware": False, "userland": True}
assert func(args, device) == nonfree
def test_questions_flash_methods(args, monkeypatch):
func = pmb.aportgen.device.ask_for_flash_method
answers = ["invalid_flash_method", "fastboot"]
fake_answers(monkeypatch, ["invalid_flash_method", "fastboot"])
assert func(args) == "fastboot"
answers = ["0xffff"]
fake_answers(monkeypatch, ["0xffff"])
assert func(args) == "0xffff"
answers = ["heimdall", "invalid_type", "isorec"]
fake_answers(monkeypatch, ["heimdall", "invalid_type", "isorec"])
assert func(args) == "heimdall-isorec"
answers = ["heimdall", "bootimg"]
fake_answers(monkeypatch, ["heimdall", "bootimg"])
assert func(args) == "heimdall-bootimg"
# Keymaps
def test_questions_keymaps(args, monkeypatch):
func = pmb.config.init.ask_for_keymaps
answers = ["invalid_keymap", "us/rx51_us"]
fake_answers(monkeypatch, ["invalid_keymap", "us/rx51_us"])
assert func(args, "nokia-n900") == "us/rx51_us"
assert func(args, "lg-mako") == ""
# Qemu native mesa driver
def test_questions_qemu_native_mesa(args, monkeypatch):
func = pmb.config.init.ask_for_qemu_native_mesa_driver
answers = ["invalid_driver", "dri-swrast"]
fake_answers(monkeypatch, ["invalid_driver", "dri-swrast"])
assert func(args, "qemu-amd64", "x86_64") == "dri-swrast"
assert func(args, "qemu-aarch64", "x86_64") is None
# UI
answers = ["invalid_UI", "weston"]
def test_questions_ui(args, monkeypatch):
fake_answers(monkeypatch, ["invalid_UI", "weston"])
assert pmb.config.init.ask_for_ui(args) == "weston"
# Work path
def test_questions_work_path(args, monkeypatch, tmpdir):
tmpdir = str(tmpdir)
answers = ["/dev/null", os.path.dirname(__file__), pmb.config.pmb_src,
tmpdir]
fake_answers(monkeypatch, ["/dev/null", os.path.dirname(__file__),
pmb.config.pmb_src, tmpdir])
assert pmb.config.init.ask_for_work_path(args) == tmpdir
#
# BUILD OPTIONS
#
def test_questions_build_options(args, monkeypatch):
func = pmb.config.init.ask_for_build_options
cfg = {"pmbootstrap": {}}
# Skip changing anything
answers = ["n"]
fake_answers(monkeypatch, ["n"])
func(args, cfg)
assert cfg == {"pmbootstrap": {}}
# Answer everything
answers = ["y", "5", "2G", "n"]
fake_answers(monkeypatch, ["y", "5", "2G", "n"])
func(args, cfg)
assert cfg == {"pmbootstrap": {"jobs": "5",
"ccache_size": "2G"}}

View File

@ -25,7 +25,7 @@ import pytest
pmb_src = os.path.realpath(os.path.join(os.path.dirname(__file__) + "/.."))
sys.path.append(pmb_src)
import pmb.parse.apkindex
import pmb.parse.apkbuild
import pmb.parse
import pmb.helpers.logging

View File

@ -0,0 +1,8 @@
# Reference: <https://postmarketos.org/devicepkg>
pkgname="missing-pkgdesc-in-subpackage"
subpackages="$pkgname-subpackage"
subpackage() {
# this function does not have a pkgdesc
mkdir "$subpkgdir"
}

View File

@ -0,0 +1,16 @@
# This is not a real aport, it's for the "pmbootstrap init" questions test
pkgname=device-lg-mako
pkgver=2
pkgrel=16
pkgdesc="Google Nexus 4"
url="https://github.com/postmarketOS"
arch="noarch"
license="MIT"
depends="linux-lg-mako mkbootimg mesa-dri-swrast"
makedepends=""
install=""
subpackages="$pkgname-weston"
source=""
options="!check"

View File

@ -0,0 +1,31 @@
# Reference: <https://postmarketos.org/deviceinfo>
# Please use double quotes only. You can source this file in shell scripts.
deviceinfo_format_version="0"
deviceinfo_name="Google Nexus 4"
deviceinfo_manufacturer="LG"
deviceinfo_date=""
deviceinfo_nonfree="????"
deviceinfo_dtb=""
deviceinfo_modules_initfs=""
deviceinfo_external_disk="false"
deviceinfo_external_disk_install="false"
deviceinfo_flash_method="fastboot"
deviceinfo_arch="armhf"
# Device related
deviceinfo_keyboard="false"
deviceinfo_screen_width="768"
deviceinfo_screen_height="1280"
deviceinfo_dev_touchscreen="/dev/input/event2"
# Fastboot related
deviceinfo_generate_bootimg="true"
deviceinfo_flash_offset_kernel="0x80208000"
deviceinfo_flash_offset_ramdisk="0x81800000"
deviceinfo_flash_offset_second="0x81100000"
deviceinfo_flash_offset_tags="0x80200100"
deviceinfo_flash_pagesize="2048"
# Weston red screen workaround (see issue #54)
deviceinfo_weston_pixman_type="2"

View File

@ -0,0 +1,33 @@
# Reference: <https://postmarketos.org/devicepkg>
pkgname="device-nonfree-firmware-and-userland"
pkgdesc="Test device for nonfree questions"
pkgver=0.1
pkgrel=0
url="https://postmarketos.org"
license="MIT"
arch="noarch"
options="!check"
depends="mesa-dri-swrast"
makedepends="devicepkg-dev"
source="deviceinfo"
subpackages="$pkgname-nonfree-firmware:nonfree_firmware $pkgname-nonfree-userland:nonfree_userland"
build() {
devicepkg_build $startdir $pkgname
}
package() {
devicepkg_package $startdir $pkgname
}
nonfree_firmware() {
pkgdesc="firmware description"
mkdir "$subpkgdir"
}
nonfree_userland() {
pkgdesc="userland description"
mkdir "$subpkgdir"
}
sha512sums="71c640728d3ade4bea402523c1cdb30e0edac585948cfae987bac9f001a0eb572e5be9ea2babef4eb8f9f6437a3677ce3e7be398e00865a6d3f781a8d4b3bf5d deviceinfo"

View File

@ -0,0 +1,28 @@
# Reference: <https://postmarketos.org/devicepkg>
pkgname="device-nonfree-firmware"
pkgdesc="Test device for nonfree questions"
pkgver=0.1
pkgrel=0
url="https://postmarketos.org"
license="MIT"
arch="noarch"
options="!check"
depends="mesa-dri-swrast"
makedepends="devicepkg-dev"
source="deviceinfo"
subpackages="$pkgname-nonfree-firmware:nonfree_firmware"
build() {
devicepkg_build $startdir $pkgname
}
package() {
devicepkg_package $startdir $pkgname
}
nonfree_firmware() {
pkgdesc="firmware description"
mkdir "$subpkgdir"
}
sha512sums="71c640728d3ade4bea402523c1cdb30e0edac585948cfae987bac9f001a0eb572e5be9ea2babef4eb8f9f6437a3677ce3e7be398e00865a6d3f781a8d4b3bf5d deviceinfo"

View File

@ -0,0 +1,20 @@
# Reference: <https://postmarketos.org/devicepkg>
pkgname="device-nonfree-userland"
pkgdesc="Test device for nonfree questions"
pkgver=0.1
pkgrel=0
url="https://postmarketos.org"
license="MIT"
arch="noarch"
options="!check"
depends="mesa-dri-swrast"
makedepends="devicepkg-dev"
source="deviceinfo"
subpackages="$pkgname-nonfree-userland:nonfree_userland"
nonfree_userland() {
pkgdesc="userland description"
mkdir "$subpkgdir"
}
sha512sums="71c640728d3ade4bea402523c1cdb30e0edac585948cfae987bac9f001a0eb572e5be9ea2babef4eb8f9f6437a3677ce3e7be398e00865a6d3f781a8d4b3bf5d deviceinfo"