Newer
Older
{
description = "The PrivateStorage Mobile application";
inputs = {
nixpkgs = {
url = "github:NixOS/nixpkgs?ref=nixos-22.05";
};
flake-utils.url = "github:numtide/flake-utils";
pypi-deps-db = {
flake = false;
url = "github:DavHau/pypi-deps-db";
};
mach-nix-flake = {
flake = true;
url = "github:DavHau/mach-nix";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils";
pypi-deps-db.follows = "pypi-deps-db";
};
};
buildozerSrc = {
flake = false;
url = "github:PrivateStorageio/buildozer?ref=build-without-installing";
};
pythonForAndroidSrc = {
flake = false;
url = "github:PrivateStorageio/python-for-android?ref=work-on-nixos";
};
};
outputs = { self, nixpkgs, flake-utils, mach-nix-flake, buildozerSrc, pythonForAndroidSrc, ... }:
flake-utils.lib.eachSystem [
"x86_64-linux"
] (system: let
mach-nix = mach-nix-flake.lib.${system};
config = {
allowUnfree = true;
android_sdk.accept_license = true;
};
lib = pkgs.lib;
python-for-android = mach-nix.buildPythonPackage {
src = pythonForAndroidSrc;
requirementsExtra = ''
sh>=1.10
'';
};
buildozer = mach-nix.buildPythonPackage {
src = buildozerSrc;
packagesExtra = [ ];
};
kivy-env = mach-nix.mkPython {
python = "python39";
requirements = ''
kivy
Pillow
cython
'';
packagesExtra = [ python-for-android buildozer ];
};
# THESE MUST AGREE WITH app/app/build.gradle
#
# If they do not you will get failures that look something like:
# FAILURE: Build failed with an exception.
#
# * What went wrong:
# Could not determine the dependencies of task ':app:compileReleaseJavaWithJavac'.
# > Failed to install the following SDK components:
# platforms;android-32 Android SDK Platform 32
# The SDK directory is not writable (/nix/store/46214a16f22rd7q8vkrhsa907ra0405l-androidsdk/libexec/android-sdk)
cmakeVersion = "3.10.2";
# Check out pkgs/development/mobile/androidenv/repo.json for
# nixpkgs-supported versions.
ndkVersion = "23.0.7123448-rc1";
# Also includes ndk
androidComposition = pkgs.callPackage ./android.nix {
inherit cmakeVersion buildToolsVersion platformVersion ndkVersion;
getBuildInputs = getInputs: xs: builtins.foldl' (accum: drv: (getInputs drv) ++ accum) [] xs;
# Make sure gradle uses the aapt2 from our Android SDK. Otherwise it
# downloads one from the internet that doesn't work because it
# specifies an interpreter (ld.so) that nothing has ensured will
# exist.
#
# Without this you get a stack of build errors that look a bit like:
#
# Execution failed for task ':app:processDebugResources'.
# > Could not resolve all files for configuration ':app:debugRuntimeClasspath'.
# > Failed to transform appcompat-1.3.0.aar (androidx.appcompat:appcompat:1.3.0) to match attributes {artifactType=android-compiled-dependencies-resources, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.libraryelements=aar, org.gradle.status=release, org.gradle.usage=java-runtime}.
# > Execution failed for AarResourcesCompilerTransform: /home/exarkun/.gradle/caches/transforms-3/f5908003b5fc10a9cf0fd543db10ae32/transformed/appcompat-1.3.0.
# > AAPT2 aapt2-7.2.1-7984345-linux Daemon #1: Daemon startup failed
# This should not happen under normal circumstances, please file an issue if it does.
ANDROIDSDK = "${androidComposition.androidsdk}/libexec/android-sdk";
gradle-wrapper = pkgs.writeShellApplication {
name = "gradle";
text = ''
${pkgs.gradle}/bin/gradle -Pandroid.aapt2FromMavenOverride=${ANDROIDSDK}/build-tools/${buildToolsVersion}/aapt2 "$@"
in {
# packages.host-python = (import nixpkgs { system = "aarch64-linux-android"; }).python3Minimal.override { self = self.packages.host-python; };
packages.apk = pkgs.androidenv.buildApp {
name = "PrivateStorage Mobile";
src = ./app;
release = false;
platformVersions = [ platformVersion ];
includeNDK = false;
};
type = "app";
program = let
emulator = pkgs.androidenv.emulateApp {
name = "PrivateStorage Mobile";
inherit platformVersion;
abiVersion = "x86_64";
systemImageType = "default";
Jean-Paul Calderone
committed
app = self.packages.${system}.apk;
package = "MyApp";
activity = "MainActivity";
};
in
"${emulator}/bin/run-test-emulator";
};
devShells.gradle = pkgs.mkShell rec {
name = "nix-native";
version = "2022.11.09";
ANDROIDNDK = "${ANDROIDSDK}/ndk-bundle";
ANDROID_SDK_ROOT = ANDROIDSDK;
ANDROID_NDK_ROOT = ANDROIDNDK;
# Deprecated but ... :shrug:
ANDROID_HOME = ANDROIDSDK;
ANDROID_PLATFORM_VERSION = "${platformVersion}";
# https://nix.dev/tutorials/cross-compilation
buildInputs = with pkgs; [
ant
android-studio
android-tools
(python310.withPackages (ps: with ps; [ build ]))
shellHook = ''
# Tell the tools a third time where the SDK and NDK are to be found.
cat >app/local.properties <<EOF
# THIS FILE IS AUTOMATICALLY GENERATED
# DO NOT EDIT
# YOUR CHANGES WILL BE DESTROYED
sdk.dir=${ANDROIDSDK}
};
devShells.default = self.devShells.${system}.gradle;
# https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/android.section.md
# is a good reference for this stuff.
devShells.kivy = pkgs.mkShell rec {
name = "ps-mobile";
version = "2022.10.21";
# The docs talk about ANDROID_SDK_ROOT but apparently it has been
# renamed yet again.
ANDROIDSDK = "${androidComposition.androidsdk}/libexec/android-sdk";
ANDROIDNDK = "${ANDROIDSDK}/ndk-bundle";
shellHook = ''
export PATH="$(echo "$ANDROIDSDK/cmake/${cmakeVersion}".*/bin):$PATH"
'';
buildInputs = with pkgs; [
android-studio
kivy-env
# https://github.com/kivy/python-for-android/blob/v2020.04.29/doc/source/troubleshooting.rst#errors-related-to-java-version
openjdk8
Jean-Paul Calderone
committed
# python-for-android recipes all want to download and unpack their
# own sources! aaaaaa
unzip
] ++
# Also we need build dependencies for all of the things it is going to
# build!
(getBuildInputs (drv: drv.buildInputs) [ openssl libffi python39 ]);
nativeBuildInputs =
with pkgs; getBuildInputs (drv: drv.nativeBuildInputs) [ openssl libffi python39 ];
};
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
}) // {
# Python cross-compilation notes.
#
# You can get a lot of cross-compiled stuff out of nixpkgs beneath
# `pkgsCross`. For example,
#
# pkgsCross.aarch64-android.python3Minimal
#
# is just what the name says. This builds fine with only one small
# change against current nixpkgs. However, its extension modules have a
# harder time. For example,
#
# pkgsCross.aarch64-android.python3Minimal.pkgs.zfec
#
# fails to build because:
#
# running bdist_wheel
# Traceback (most recent call last):
# File "/build/wheel-0.37.1-source/nix_run_setup", line 8, in <module>
# exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
# File "setup.py", line 4, in <module>
# setup(maintainer=u'Alex Grönholm')
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/__init__.py", line 87, in setup
# return distutils.core.setup(**attrs)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/core.py", line 185, in setup
# return run_commands(dist)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/core.py", line 201, in run_commands
# dist.run_commands()
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/dist.py", line 973, in run_commands
# self.run_command(cmd)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/dist.py", line 1217, in run_command
# super().run_command(command)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/dist.py", line 992, in run_command
# cmd_obj.run()
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/wheel/bdist_wheel.py", line 295, in run
# build_ext = self.reinitialize_command('build_ext')
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/__init__.py", line 200, in reinitialize_command
# cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/cmd.py", line 312, in reinitialize_command
# return self.distribution.reinitialize_command(command, reinit_subcommands)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/dist.py", line 945, in reinitialize_command
# command = self.get_command_obj(command_name)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/dist.py", line 864, in get_command_obj
# klass = self.get_command_class(command)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/dist.py", line 954, in get_command_class
# self.cmdclass[command] = cmdclass = ep.load()
# File "/nix/store/537cvh8mqdaglc0an8ndmzszllh1lwac-python3-minimal-3.10.8/lib/python3.10/importlib/metadata/__init__.py", line 171, in load
# module = import_module(match.group('module'))
# File "/nix/store/537cvh8mqdaglc0an8ndmzszllh1lwac-python3-minimal-3.10.8/lib/python3.10/importlib/__init__.py", line 126, in import_module
# return _bootstrap._gcd_import(name[level:], package, level)
# File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
# File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
# File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
# File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
# File "<frozen importlib._bootstrap_external>", line 883, in exec_module
# File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/command/build_ext.py", line 26, in <module>
# get_config_var("LDSHARED")
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/sysconfig.py", line 574, in get_config_var
# return get_config_vars().get(name)
# File "/nix/store/azdg3l16q2d03g8drgr94bg1069mfzpq-python3.10-bootstrapped-pip-22.2.2/lib/python3.10/site-packages/setuptools/_distutils/sysconfig.py", line 553, in get_config_vars
# _config_vars = sysconfig.get_config_vars().copy()
# File "/nix/store/537cvh8mqdaglc0an8ndmzszllh1lwac-python3-minimal-3.10.8/lib/python3.10/sysconfig.py", line 615, in get_config_vars
# _init_posix(_CONFIG_VARS)
# File "/nix/store/537cvh8mqdaglc0an8ndmzszllh1lwac-python3-minimal-3.10.8/lib/python3.10/sysconfig.py", line 477, in _init_posix
# _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
# ModuleNotFoundError: No module named '_sysconfigdata__linux_aarch64-linux-android'
#
# Notice that the *build* Python
# (537cvh8mqdaglc0an8ndmzszllh1lwac-python3-minimal-3.10.8) is trying to
# load sysconfigdata for the *host* Python - presumably so it can
# compile the extension correctly. However, the host Python
# sysconfigdata module appears to be unavailable to the build Python.
#
# Why? The nixpkgs CPython expression writes the sysconfigdata module
# for both Pythons (build and host). It has ``sysconfigdataHook`` that
# goes to a lot of trouble to compute the right parameters for the host
# Python and write the data to a properly named source file.
#
# However, the build Python and host Pythons each only get one of these
# modules. For the build Python it is:
#
# _sysconfigdata__linux_x86_64-linux-gnu.py
#
# and the host Python gets:
#
# _sysconfigdata__linux_.py
#
# Each of these contains information which is apparently correct for
# their respective runtime systems. Then, the nixpkgs CPython
# expression for building the extension module uses "bootstrap pip"
# which will respect PYTHONPATH for module search.
#
# (Q) Does something put the host Python's _sysconfigdata__linux_.py on
# the build Python's PYTHONPATH? What? How?
#
# (Q)
#
# And now for something completely different.
#
# https://crossenv.readthedocs.io/en/latest/ is a tool specifically for
# this. It assumes you can cross-compile CPython on your own, though,
# and then helps you use it to cross-compile extension modules. Maybe
# our nixpkgs-cross-compiled CPython would be a good complement?
#
# packages.host-python = pkgsCross.aarch64-android.python3Minimal.withPackages (ps: [
# # The nixpkgs zfec has some extra dependencies that we might not
# # really care about. This one is leaner. Mostly only relevant
# # because we have to cross-compile anything here.
# (ps.callPackage ./zfec.nix {})
# ]);
# packages.aarch64-android.host-python310 =
# let
# pkgs = import nixpkgs {
# system = "x86_64-linux";
# config = {
# allowUnfree = true;
# android_sdk.accept_license = true;
# };
# };
# in
# (pkgs.pkgsCross.aarch64-android.python310.override {
# # Turn off all the things. Each one might be broken for
# # cross-compilation and even if not we don't need them for this build
# # Python. We just need it to report the right platform info.
# mimetypesSupport = false;
# x11Support = false;
# bluezSupport = false;
# sqlite = null;
# openssl = null;
# tzdata = null;
# readline = null;
# }).overrideAttrs (old: {
# # Turn off even more things which aren't parameters to the Python
# # expressionThey .
# # These drag in an aarch64-android bash which fails to build.
# preFixup = null;
# postPatch = null;
# # This drags in a -lcrypt dependency which isn't satisfied by Google
# # Android Bionic.
# LIBS = null;
# });
};