├── kivy_ios
├── __init__.py
├── recipes
│ ├── __init__.py
│ ├── hostpython3
│ │ ├── ModulesSetup
│ │ ├── allow-cflags-override.patch
│ │ ├── disable_sysconfig_cflags.patch
│ │ └── __init__.py
│ ├── python3
│ │ ├── ModulesSetup.mobile
│ │ ├── posixmodule.patch
│ │ ├── ctypes_duplicate.patch
│ │ ├── dynload_shlib.patch
│ │ ├── configure.patch
│ │ ├── ModulesSetup
│ │ └── __init__.py
│ ├── zbarlight
│ │ ├── zbarlight_1_2.patch
│ │ └── __init__.py
│ ├── plyer
│ │ └── __init__.py
│ ├── pykka
│ │ └── __init__.py
│ ├── pyobjus
│ │ └── __init__.py
│ ├── curly
│ │ └── __init__.py
│ ├── audiostream
│ │ └── __init__.py
│ ├── ios
│ │ ├── src
│ │ │ ├── setup.py
│ │ │ ├── ios_wrapper.h
│ │ │ ├── ios_browser.m
│ │ │ ├── ios_filechooser.m
│ │ │ ├── ios_mail.m
│ │ │ ├── ios_utils.m
│ │ │ └── ios.pyx
│ │ └── __init__.py
│ ├── photolibrary
│ │ └── __init__.py
│ ├── pycrypto
│ │ ├── hash_SHA2_template.c.patch
│ │ └── __init__.py
│ ├── libzbar
│ │ ├── werror.patch
│ │ └── __init__.py
│ ├── py3dns
│ │ ├── __init__.py
│ │ └── ios.patch
│ ├── sdl2
│ │ ├── uikit-transparent.patch
│ │ ├── disable-hidapi.patch
│ │ └── __init__.py
│ ├── cymunk
│ │ └── __init__.py
│ ├── python.py
│ ├── pillow
│ │ ├── bypass-find-library.patch
│ │ └── __init__.py
│ ├── click
│ │ └── __init__.py
│ ├── jinja2
│ │ └── __init__.py
│ ├── werkzeug
│ │ └── __init__.py
│ ├── pyyaml
│ │ └── __init__.py
│ ├── flask
│ │ └── __init__.py
│ ├── itsdangerous
│ │ └── __init__.py
│ ├── libpng
│ │ └── __init__.py
│ ├── sdl2_ttf
│ │ └── __init__.py
│ ├── libcurl
│ │ └── __init__.py
│ ├── hostpython.py
│ ├── libjpeg
│ │ └── __init__.py
│ ├── sdl2_image
│ │ ├── fix-ios-xcodebuild.patch
│ │ └── __init__.py
│ ├── openssl
│ │ └── __init__.py
│ ├── numpy
│ │ ├── duplicated_symbols.patch
│ │ ├── __init__.py
│ │ └── skip-math-test.patch
│ ├── markupsafe
│ │ └── __init__.py
│ ├── sdl2_mixer
│ │ └── __init__.py
│ ├── netifaces
│ │ └── __init__.py
│ ├── ffpyplayer
│ │ ├── __init__.py
│ │ └── misc-visibility.patch
│ ├── freetype
│ │ └── __init__.py
│ ├── hostopenssl
│ │ └── __init__.py
│ ├── kivy
│ │ └── __init__.py
│ ├── libffi
│ │ ├── __init__.py
│ │ └── enable-tramp-build.patch
│ ├── ffmpeg
│ │ └── __init__.py
│ └── kivent_core
│ │ └── __init__.py
├── tools
│ ├── __init__.py
│ ├── external
│ │ └── __init__.py
│ ├── templates
│ │ ├── {{ cookiecutter.project_name }}-ios
│ │ │ ├── YourApp
│ │ │ │ ├── images
│ │ │ │ │ ├── .empty
│ │ │ │ │ ├── faust_github.jpg
│ │ │ │ │ ├── 5509213687_ffd18df0b9_b.jpg
│ │ │ │ │ └── 5552597274_de8b3fb5d2_b.jpg
│ │ │ │ ├── android.txt
│ │ │ │ ├── shadow32.png
│ │ │ │ ├── README.txt
│ │ │ │ └── pictures.kv
│ │ │ ├── icon.png
│ │ │ ├── {{ cookiecutter.project_name }}.xcodeproj
│ │ │ │ └── project.xcworkspace
│ │ │ │ │ └── contents.xcworkspacedata
│ │ │ ├── {{ cookiecutter.project_name }}
│ │ │ │ └── Images.xcassets
│ │ │ │ │ └── AppIcon.appiconset
│ │ │ │ │ └── Contents.json
│ │ │ ├── bridge.h
│ │ │ ├── {{ cookiecutter.project_name }}-Info.plist
│ │ │ ├── Storyboards
│ │ │ │ └── Launch Screen.storyboard
│ │ │ ├── bridge.m
│ │ │ └── main.m
│ │ └── cookiecutter.json
│ ├── biglink
│ ├── cythonize.py
│ └── liblink
└── context_managers.py
├── Sources
└── kivy-ios
│ └── kivy_ios.swift
├── kivy_ios.egg-info
├── dependency_links.txt
├── top_level.txt
├── entry_points.txt
├── requires.txt
├── SOURCES.txt
└── PKG-INFO
├── setup.py
├── toolchain.py
├── pyproject.toml
├── requirements.txt
├── .ci
├── constants.py
├── test_project.sh
├── utils.sh
└── rebuild_updated_recipes.py
├── MANIFEST.in
├── .gitignore
├── Package.swift
├── tox.ini
├── .github
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
└── workflows
│ ├── pypi-release.yml
│ ├── setup.yml
│ ├── support.yml
│ └── kivy_ios.yml
├── setup.cfg
├── LICENSE
├── tests
├── test_python3
│ ├── main.py
│ └── main.m
└── test_libs
│ └── main.py
└── README.md
/kivy_ios/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kivy_ios/tools/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sources/kivy-ios/kivy_ios.swift:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/kivy_ios/tools/external/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kivy_ios.egg-info/dependency_links.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/kivy_ios.egg-info/top_level.txt:
--------------------------------------------------------------------------------
1 | kivy_ios
2 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 | setup()
4 |
--------------------------------------------------------------------------------
/toolchain.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import main
2 |
3 | main()
4 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/.empty:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/hostpython3/ModulesSetup:
--------------------------------------------------------------------------------
1 | zlib zlibmodule.c -I$(prefix)/include -lz
2 |
--------------------------------------------------------------------------------
/kivy_ios.egg-info/entry_points.txt:
--------------------------------------------------------------------------------
1 | [console_scripts]
2 | toolchain = kivy_ios.toolchain:main
3 |
4 |
--------------------------------------------------------------------------------
/kivy_ios.egg-info/requires.txt:
--------------------------------------------------------------------------------
1 | Cython
2 | cookiecutter
3 | pbxproj
4 | Pillow
5 | requests
6 | sh
7 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.0"]
3 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pbxproj==3.5.0
2 | Pillow>=6.1.0
3 | requests>=2.13
4 | cookiecutter==2.1.1
5 | sh==1.12.14
6 | Cython==0.29.17
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/android.txt:
--------------------------------------------------------------------------------
1 | title=Pictures
2 | author=Kivy team
3 | orientation=landscape
4 |
--------------------------------------------------------------------------------
/.ci/constants.py:
--------------------------------------------------------------------------------
1 | BROKEN_RECIPES = set(["netifaces"])
2 |
3 | # recipes that were already built will be skipped
4 | CORE_RECIPES = set(["kivy", "hostpython3", "python3"])
5 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kewlbear/kivy-ios/HEAD/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/icon.png
--------------------------------------------------------------------------------
/kivy_ios/recipes/python3/ModulesSetup.mobile:
--------------------------------------------------------------------------------
1 | # Ctypes
2 | _ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c -I$(srcdir)/../../build/include/ffi
3 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/cookiecutter.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "",
3 | "project_name": "",
4 | "domain_name": "",
5 | "project_dir": "",
6 | "version": "1.0.0",
7 | "dist_dir": ""
8 | }
9 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/shadow32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kewlbear/kivy-ios/HEAD/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/shadow32.png
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/faust_github.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kewlbear/kivy-ios/HEAD/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/faust_github.jpg
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/5509213687_ffd18df0b9_b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kewlbear/kivy-ios/HEAD/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/5509213687_ffd18df0b9_b.jpg
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/5552597274_de8b3fb5d2_b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kewlbear/kivy-ios/HEAD/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/5552597274_de8b3fb5d2_b.jpg
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include kivy_ios *.py
2 | recursive-include kivy_ios/recipes *.py *.patch *.diff *.rst ModulesSetup ModulesSetup.mobile *.m *.h *.pyx *.so
3 | recursive-include kivy_ios/tools *.py biglink liblink
4 | recursive-include kivy_ios/tools/templates *
5 |
6 | prune .git
--------------------------------------------------------------------------------
/kivy_ios/recipes/zbarlight/zbarlight_1_2.patch:
--------------------------------------------------------------------------------
1 | --- zbarlight-1.2/build/lib.macosx-10.13-x86_64-2.7/zbarlight/__init__.py
2 | +++ zbarlight-1.2/build/lib.macosx-10.13-x86_64-2.7/zbarlight/__init__.py
3 | @@ -10,1 +10,1 @@
4 | -__version__ = pkg_resources.get_distribution('zbarlight').version
5 | +__version__ = '1.2'
6 |
7 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/plyer/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import PythonRecipe
2 |
3 |
4 | class PlyerRecipe(PythonRecipe):
5 | version = "master"
6 | url = "https://github.com/kivy/plyer/archive/{version}.zip"
7 | depends = ["python", "pyobjus"]
8 | archs = ["x86_64"]
9 |
10 |
11 | recipe = PlyerRecipe()
12 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/pykka/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import PythonRecipe
2 |
3 |
4 | class PykkaRecipe(PythonRecipe):
5 | version = '1.2.1'
6 | url = 'https://github.com/jodal/pykka/archive/v{version}.zip'
7 |
8 | depends = ['python3']
9 |
10 | site_packages_name = 'pykka'
11 |
12 |
13 | recipe = PykkaRecipe()
14 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.ci/test_project.sh:
--------------------------------------------------------------------------------
1 |
2 | #!/bin/bash
3 |
4 | set -eo pipefail
5 |
6 | toolchain create Touchtracer kivy-ci-clone/examples/demo/touchtracer
7 |
8 | xcodebuild -project touchtracer-ios/touchtracer.xcodeproj \
9 | -scheme touchtracer \
10 | -destination generic/platform=iOS\
11 | clean build CODE_SIGNING_ALLOWED=NO | xcpretty
--------------------------------------------------------------------------------
/kivy_ios/recipes/pyobjus/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe
2 |
3 |
4 | class PyobjusRecipe(CythonRecipe):
5 | version = "master"
6 | url = "https://github.com/kivy/pyobjus/archive/{version}.zip"
7 | library = "libpyobjus.a"
8 | depends = ["python"]
9 | pre_build_ext = True
10 |
11 |
12 | recipe = PyobjusRecipe()
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swo
2 | *.pyc
3 | *.pyo
4 | *.swp
5 | freetype-*
6 | build/*
7 | dist/*
8 | src/SDL/Xcode-iPhoneOS/SDL/build/
9 | src/SDL/Xcode-iOS/SDL/build/
10 | tmp/*
11 | kivy/*
12 | libtremor/*
13 | libogg/*
14 | app-*
15 | .cache
16 | src/ios/build/
17 | src/ios/iosbuild/
18 | src/ios/ios.c
19 | *.DS_Store*
20 | #*-ios/
21 | __pycache__
22 | .tox
23 | venv
24 | *.egg-info
--------------------------------------------------------------------------------
/kivy_ios/recipes/curly/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe
2 |
3 |
4 | class CurlyRecipe(CythonRecipe):
5 | version = "master"
6 | url = "https://github.com/tito/curly/archive/{version}.zip"
7 | library = "libcurly.a"
8 | depends = ["python", "libcurl", "sdl2", "sdl2_image"]
9 | pre_build_ext = True
10 |
11 |
12 | recipe = CurlyRecipe()
13 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "kivy-ios",
7 | products: [
8 | .library(
9 | name: "kivy-ios",
10 | targets: ["kivy-ios"]),
11 | ],
12 | targets: [
13 | .target(
14 | name: "kivy-ios",
15 | dependencies: []),
16 | ]
17 | )
18 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/audiostream/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe
2 |
3 |
4 | class AudiostreamRecipe(CythonRecipe):
5 | version = "master"
6 | url = "https://github.com/kivy/audiostream/archive/{version}.zip"
7 | library = "libaudiostream.a"
8 | depends = ["python", "sdl2", "sdl2_mixer"]
9 | pre_build_ext = True
10 |
11 |
12 | recipe = AudiostreamRecipe()
13 |
--------------------------------------------------------------------------------
/.ci/utils.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | arm64_set_path_and_python_version(){
4 | python_version="$1"
5 | if [[ $(/usr/bin/arch) = arm64 ]]; then
6 | echo $PATH
7 | export PATH=/usr/local/bin:$PATH
8 | export PATH=/opt/homebrew/bin:$PATH
9 | eval "$(pyenv init --path)"
10 | pyenv install $python_version -s
11 | pyenv global $python_version
12 | export PATH=$(pyenv prefix)/bin:$PATH
13 | fi
14 | }
15 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ios/src/setup.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup, Extension
2 |
3 |
4 | setup(name='ios',
5 | version='1.1',
6 | ext_modules=[
7 | Extension('ios',
8 | ['ios.c', 'ios_utils.m', 'ios_mail.m', 'ios_browser.m',
9 | 'ios_filechooser.m'],
10 | libraries=[],
11 | library_dirs=[],
12 | )
13 | ]
14 | )
15 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ios/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe
2 |
3 |
4 | class IosRecipe(CythonRecipe):
5 | version = "master"
6 | url = "src"
7 | library = "libios.a"
8 | depends = ["python"]
9 | pbx_frameworks = ["MessageUI", "CoreMotion", "UIKit", "WebKit", "Photos"]
10 |
11 | def install(self):
12 | self.install_python_package(
13 | name=self.so_filename("ios"), is_dir=False)
14 |
15 |
16 | recipe = IosRecipe()
17 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/photolibrary/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe
2 |
3 |
4 | class PhotoRecipe(CythonRecipe):
5 | version = "master"
6 | url = "https://github.com/akshayaurora/photolibrary/archive/master.zip"
7 | library = "libphotolibrary.a"
8 | depends = ["python"]
9 | pbx_frameworks = ["UIKit", "Photos", "MobileCoreServices"]
10 |
11 | def install(self):
12 | self.install_python_package(name="photolibrary.so", is_dir=False)
13 |
14 |
15 | recipe = PhotoRecipe()
16 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/pycrypto/hash_SHA2_template.c.patch:
--------------------------------------------------------------------------------
1 | --- ../src/src/hash_SHA2_template.c 2015-07-15 15:25:59.000000000 +0530
2 | +++ src/hash_SHA2_template.c 2015-07-17 15:35:13.000000000 +0530
3 | @@ -87,7 +87,7 @@
4 | * return 1 on success
5 | * return 0 if the length overflows
6 | */
7 | -static int add_length(hash_state *hs, sha2_word_t inc) {
8 | +int add_length(hash_state *hs, sha2_word_t inc) {
9 | sha2_word_t overflow_detector;
10 | overflow_detector = hs->length_lower;
11 | hs->length_lower += inc;
12 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/python3/posixmodule.patch:
--------------------------------------------------------------------------------
1 | diff -Naur Python-3.9.2.orig/Modules/posixmodule.c Python-3.9.2/Modules/posixmodule.c
2 | --- Python-3.9.2.orig/Modules/posixmodule.c 2021-03-20 12:28:02.000000000 +0100
3 | +++ Python-3.9.2/Modules/posixmodule.c 2021-03-20 12:29:00.000000000 +0100
4 | @@ -326,7 +326,7 @@
5 | # define HAVE_KILL 1
6 | # define HAVE_OPENDIR 1
7 | # define HAVE_PIPE 1
8 | -# define HAVE_SYSTEM 1
9 | +# undef HAVE_SYSTEM
10 | # define HAVE_WAIT 1
11 | # define HAVE_TTYNAME 1
12 | # endif /* _MSC_VER */
13 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/libzbar/werror.patch:
--------------------------------------------------------------------------------
1 | diff --git a/configure.ac b/configure.ac
2 | index 256aedb..727caba 100644
3 | --- a/configure.ac
4 | +++ b/configure.ac
5 | @@ -3,7 +3,7 @@ AC_PREREQ([2.61])
6 | AC_INIT([zbar], [0.10], [spadix@users.sourceforge.net])
7 | AC_CONFIG_AUX_DIR(config)
8 | AC_CONFIG_MACRO_DIR(config)
9 | -AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects std-options dist-bzip2])
10 | +AM_INIT_AUTOMAKE([1.10 -Wall foreign subdir-objects std-options dist-bzip2])
11 | AC_CONFIG_HEADERS([include/config.h])
12 | AC_CONFIG_SRCDIR(zbar/scanner.c)
13 | LT_PREREQ([2.2])
--------------------------------------------------------------------------------
/kivy_ios/recipes/py3dns/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import PythonRecipe
2 |
3 |
4 | class Py3DNSRecipe(PythonRecipe):
5 | site_packages_name = 'DNS'
6 | version = '3.2.1'
7 | url = 'https://launchpad.net/py3dns/trunk/{version}/' \
8 | '+download/py3dns-{version}.tar.gz'
9 | depends = ['python3']
10 |
11 | def prebuild_arch(self, arch):
12 | if self.has_marker("patched"):
13 | return
14 |
15 | self.apply_patch("ios.patch")
16 | self.set_marker("patched")
17 |
18 |
19 | recipe = Py3DNSRecipe()
20 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ios/src/ios_wrapper.h:
--------------------------------------------------------------------------------
1 | #ifndef __IOS_WRAPPER
2 | #define __IOS_WRAPPER
3 |
4 | typedef struct {
5 | float top;
6 | float bottom;
7 | float right;
8 | float left;
9 | } padding;
10 |
11 | float ios_uiscreen_get_scale(void);
12 | int ios_uiscreen_get_dpi(void);
13 | padding ios_get_safe_area(void);
14 | void ios_open_url(char *url);
15 | void load_url_webview(char *url, int x, int y, int width, int height);
16 |
17 | typedef void (*ios_send_email_cb)(char *, void *);
18 |
19 | int ios_send_email(char *subject, char *text, char *mimetype, char *filename,
20 | char *filename_alias, ios_send_email_cb callback, void *userdata);
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/sdl2/uikit-transparent.patch:
--------------------------------------------------------------------------------
1 | --- slime73-sdl-experiments-618662dc9e82/src/video/uikit/SDL_uikitopenglview.m.orig 2015-08-20 16:09:59.000000000 +0200
2 | +++ slime73-sdl-experiments-618662dc9e82/src/video/uikit/SDL_uikitopenglview.m 2015-08-20 16:11:25.000000000 +0200
3 | @@ -99,7 +99,7 @@
4 |
5 | CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
6 |
7 | - eaglLayer.opaque = YES;
8 | + eaglLayer.opaque = SDL_getenv("UIKIT_TRANSPARENT") ? NO : YES;
9 | eaglLayer.drawableProperties = @{
10 | kEAGLDrawablePropertyRetainedBacking:@(retained),
11 | kEAGLDrawablePropertyColorFormat:colorFormat
12 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "60x60",
21 | "scale" : "3x"
22 | }
23 | ],
24 | "info" : {
25 | "version" : 1,
26 | "author" : "xcode"
27 | }
28 | }
--------------------------------------------------------------------------------
/kivy_ios/recipes/cymunk/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Author: Lawrence Du, Lukasz Mach
3 | E-mail: larrydu88@gmail.com, maho@pagema.net
4 | """
5 |
6 | from kivy_ios.toolchain import CythonRecipe
7 |
8 |
9 | class CymunkRecipe(CythonRecipe):
10 | version = 'master'
11 | url = 'https://github.com/kivy/cymunk/archive/{version}.zip'
12 | name = 'cymunk'
13 | pre_build_ext = True
14 | library = 'libcymunk.a'
15 |
16 | depends = ['python']
17 |
18 | def get_recipe_env(self, arch):
19 | ret = super(CymunkRecipe, self).get_recipe_env(arch)
20 | ret['CFLAGS'] += ' -Wno-implicit-function-declaration'
21 | return ret
22 |
23 |
24 | recipe = CymunkRecipe()
25 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | skipsdist = True
3 | envlist = pep8
4 | basepython = python3
5 |
6 | [testenv]
7 | deps = -r{toxinidir}/requirements.txt
8 | setenv =
9 | PYTHONPATH={toxinidir}
10 |
11 | [testenv:pep8]
12 | deps = flake8
13 | commands = flake8 kivy_ios/ tests/ .ci/ setup.py toolchain.py
14 |
15 |
16 | [flake8]
17 | ignore =
18 | # Closing bracket does not match indentation of opening bracket's line
19 | E123,
20 | # Continuation line over-indented for hanging indent
21 | E126,
22 | # Line too long (82 > 79 characters)
23 | E501,
24 | # Line break occurred before a binary operator
25 | W503,
26 | # Line break occurred after a binary operator
27 | W504
28 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/README.txt:
--------------------------------------------------------------------------------
1 | Pictures
2 | ========
3 |
4 | A very simple image browser, supporting the reading only from images/
5 | directory right now.
6 | So put any images files inside images/ directory, and start the app !
7 |
8 | Android
9 | -------
10 |
11 | You can copy/paste this directory into /sdcard/kivy/pictures in your
12 | android device.
13 |
14 |
15 | Licences
16 | --------
17 |
18 | * faust_github.jpg: lucie's cat accepted to share his face
19 | * 5552597274_de8b3fb5d2_b.jpg: http://www.flickr.com/photos/chialin-gallery/5552597274/sizes/l/
20 | * 5509213687_ffd18df0b9_b.jpg: http://www.flickr.com/photos/orsomk/5509213687/sizes/l/
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: 'feature request'
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/python.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from kivy_ios.toolchain import Recipe
3 | import logging
4 | from os.path import join
5 |
6 | logger = logging.getLogger(__name__)
7 |
8 |
9 | class PythonAliasRecipe(Recipe):
10 | """
11 | Note this recipe was created to handle both python2 and python3.
12 | As python2 support was dropped, this could probably be simplified.
13 | """
14 | is_alias = True
15 |
16 | def init_after_import(self, ctx):
17 | python = ctx.state.get("python")
18 | if not python:
19 | python = "python3"
20 | self.depends = [python]
21 | self.recipe_dir = join(ctx.root_dir, "recipes", python)
22 |
23 |
24 | recipe = PythonAliasRecipe()
25 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/hostpython3/allow-cflags-override.patch:
--------------------------------------------------------------------------------
1 | --- setuptools.orig/_distutils/sysconfig.py 2023-02-18 18:21:53
2 | +++ setuptools/_distutils/sysconfig.py 2023-02-18 18:23:17
3 | @@ -329,7 +329,9 @@
4 | if 'LDFLAGS' in os.environ:
5 | ldshared = ldshared + ' ' + os.environ['LDFLAGS']
6 | if 'CFLAGS' in os.environ:
7 | - cflags = cflags + ' ' + os.environ['CFLAGS']
8 | + # cflags = cflags + ' ' + os.environ['CFLAGS']
9 | + # TODO: we may have found a bug in distutils?
10 | + cflags = os.environ['CFLAGS']
11 | ldshared = ldshared + ' ' + os.environ['CFLAGS']
12 | if 'CPPFLAGS' in os.environ:
13 | cpp = cpp + ' ' + os.environ['CPPFLAGS']
14 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | name = kivy-ios
3 | version = 2023.01.29
4 | description = Kivy for iOS
5 | license = MIT License
6 | long_description = file: README.md
7 | long_description_content_type = text/markdown
8 | author = The Kivy team
9 | author_email = kivy-dev@googlegroups.com
10 | url = https://github.com/kivy/kivy-ios
11 |
12 | [options]
13 | python_requires >= "3.6.0"
14 | install_requires =
15 | Cython
16 | cookiecutter
17 | pbxproj
18 | Pillow
19 | requests
20 | sh
21 | packages = find:
22 | # note this is a bit excessive as it includes absolutely everything
23 | # make sure you run with from a clean directory
24 | include_package_data = True
25 |
26 | [options.entry_points]
27 | console_scripts =
28 | toolchain = kivy_ios.toolchain:main
--------------------------------------------------------------------------------
/kivy_ios/recipes/python3/ctypes_duplicate.patch:
--------------------------------------------------------------------------------
1 | diff -Naur Python-3.8.2.orig/Modules/_ctypes/cfield.c Python-3.8.2/Modules/_ctypes/cfield.c
2 | --- Python-3.8.2.orig/Modules/_ctypes/cfield.c 2020-04-13 12:23:46.000000000 +0200
3 | +++ Python-3.8.2/Modules/_ctypes/cfield.c 2020-04-13 12:24:45.000000000 +0200
4 | @@ -1636,7 +1636,7 @@
5 | struct _ffi_type **elements;
6 | } ffi_type;
7 | */
8 | -
9 | +#if 0
10 | /* align and size are bogus for void, but they must not be zero */
11 | ffi_type ffi_type_void = { 1, 1, FFI_TYPE_VOID };
12 |
13 | @@ -1663,5 +1663,5 @@
14 | FFI_TYPE_LONGDOUBLE };
15 |
16 | ffi_type ffi_type_pointer = { sizeof(void *), VOID_P_ALIGN, FFI_TYPE_POINTER };
17 | -
18 | +#endif
19 | /*---------------- EOF ----------------*/
20 |
--------------------------------------------------------------------------------
/.github/workflows/pypi-release.yml:
--------------------------------------------------------------------------------
1 | name: PyPI release
2 | on: [push]
3 |
4 | jobs:
5 | pypi_release:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v3
9 | - name: Set up Python 3.x
10 | uses: actions/setup-python@v4
11 | with:
12 | python-version: 3.x
13 | - name: Install dependencies
14 | run: |
15 | python -m pip install --upgrade setuptools wheel twine
16 | - name: Build
17 | run: |
18 | python setup.py sdist bdist_wheel
19 | twine check dist/*
20 | - name: Publish package
21 | if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
22 | uses: pypa/gh-action-pypi-publish@v1.1.0
23 | with:
24 | user: __token__
25 | password: ${{ secrets.pypi_password }}
26 |
--------------------------------------------------------------------------------
/kivy_ios/tools/biglink:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | import sys
5 | import subprocess
6 |
7 | sofiles = []
8 | for dir in sys.argv[2:]:
9 | for fn in os.listdir(dir):
10 | if fn.endswith(".so"):
11 | fn = os.path.join(dir, fn)
12 | if os.path.exists(fn + ".o") and os.path.exists(fn + ".libs"):
13 | sofiles.append(fn)
14 |
15 | args = [] # The raw argument list.
16 | for fn in sofiles:
17 | args.append(fn + ".o")
18 | args.extend(open(fn + ".libs").read().split(" "))
19 |
20 | unique_args = ' '.join(x for x in sorted(set(args)) if x.endswith('.so.o'))
21 | print('Biglink create %s library' % sys.argv[1])
22 | cmd = "ar -q %s %s" % (sys.argv[1], unique_args)
23 | print('Binlinking: {}'.format(cmd))
24 | subprocess.Popen(cmd, shell=True).communicate()
25 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/pillow/bypass-find-library.patch:
--------------------------------------------------------------------------------
1 | diff -Naur Pillow-8.2.0.orig/setup.py Pillow-8.2.0/setup.py
2 | --- Pillow-8.2.0.orig/setup.py 2021-04-05 11:11:26.000000000 +0200
3 | +++ Pillow-8.2.0/setup.py 2021-04-05 11:16:12.000000000 +0200
4 | @@ -222,12 +222,9 @@
5 |
6 |
7 | def _find_library_file(self, library):
8 | - ret = self.compiler.find_library_file(self.compiler.library_dirs, library)
9 | - if ret:
10 | - _dbg("Found library %s at %s", (library, ret))
11 | - else:
12 | - _dbg("Couldn't find library %s in %s", (library, self.compiler.library_dirs))
13 | - return ret
14 | + # The provided find method is broken on our implementation.
15 | + # We will select by --disable flags what is actually disabled.
16 | + return True
17 |
18 |
19 | def _find_include_dir(self, dirname, include):
20 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/hostpython3/disable_sysconfig_cflags.patch:
--------------------------------------------------------------------------------
1 | diff -Naur Python-3.9.2.orig/Lib/distutils/sysconfig.py Python-3.9.2/Lib/distutils/sysconfig.py
2 | --- Python-3.9.2.orig/Lib/distutils/sysconfig.py 2021-03-20 13:44:04.000000000 +0100
3 | +++ Python-3.9.2/Lib/distutils/sysconfig.py 2021-03-20 13:47:12.000000000 +0100
4 | @@ -196,6 +196,12 @@
5 | (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
6 | get_config_vars('CC', 'CXX', 'CFLAGS',
7 | 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
8 | +
9 | + """
10 | + sysconfig was overriding our cflags and extensions were failing to build.
11 | + This hack resets the cflags provided by sysconfig.
12 | + """
13 | + cflags = ""
14 |
15 | if 'CC' in os.environ:
16 | newcc = os.environ['CC']
17 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/click/__init__.py:
--------------------------------------------------------------------------------
1 | # pure-python package, this can be removed when we'll support any python package
2 | from kivy_ios.toolchain import PythonRecipe, shprint
3 | from os.path import join
4 | import sh
5 | import os
6 |
7 |
8 | class ClickRecipe(PythonRecipe):
9 | version = "7.1.2"
10 | url = "https://github.com/mitsuhiko/click/archive/{version}.zip"
11 | depends = ["python"]
12 |
13 | def install(self):
14 | arch = list(self.filtered_archs)[0]
15 | build_dir = self.get_build_dir(arch.arch)
16 | os.chdir(build_dir)
17 | hostpython = sh.Command(self.ctx.hostpython)
18 | build_env = arch.get_env()
19 | dest_dir = join(self.ctx.dist_dir, "root", "python3")
20 | build_env['PYTHONPATH'] = self.ctx.site_packages_dir
21 | shprint(hostpython, "setup.py", "install", "--prefix", dest_dir, _env=build_env)
22 |
23 |
24 | recipe = ClickRecipe()
25 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/jinja2/__init__.py:
--------------------------------------------------------------------------------
1 | # pure-python package, this can be removed when we'll support any python package
2 | from kivy_ios.toolchain import PythonRecipe, shprint
3 | from os.path import join
4 | import sh
5 | import os
6 |
7 |
8 | class Jinja2Recipe(PythonRecipe):
9 | version = "2.11.2"
10 | url = "https://github.com/mitsuhiko/jinja2/archive/{version}.zip"
11 | depends = ["python", "markupsafe"]
12 |
13 | def install(self):
14 | arch = list(self.filtered_archs)[0]
15 | build_dir = self.get_build_dir(arch.arch)
16 | os.chdir(build_dir)
17 | hostpython = sh.Command(self.ctx.hostpython)
18 | build_env = arch.get_env()
19 | dest_dir = join(self.ctx.dist_dir, "root", "python3")
20 | build_env['PYTHONPATH'] = self.ctx.site_packages_dir
21 | shprint(hostpython, "setup.py", "install", "--prefix", dest_dir, _env=build_env)
22 |
23 |
24 | recipe = Jinja2Recipe()
25 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/werkzeug/__init__.py:
--------------------------------------------------------------------------------
1 | # pure-python package, this can be removed when we'll support any python package
2 | from kivy_ios.toolchain import PythonRecipe, shprint
3 | from os.path import join
4 | import sh
5 | import os
6 |
7 |
8 | class WerkzeugRecipe(PythonRecipe):
9 | version = "1.0.1"
10 | url = "https://github.com/mitsuhiko/werkzeug/archive/{version}.zip"
11 | depends = ["python", "openssl"]
12 |
13 | def install(self):
14 | arch = list(self.filtered_archs)[0]
15 | build_dir = self.get_build_dir(arch.arch)
16 | os.chdir(build_dir)
17 | hostpython = sh.Command(self.ctx.hostpython)
18 | build_env = arch.get_env()
19 | dest_dir = join(self.ctx.dist_dir, "root", "python3")
20 | build_env['PYTHONPATH'] = self.ctx.site_packages_dir
21 | shprint(hostpython, "setup.py", "install", "--prefix", dest_dir, _env=build_env)
22 |
23 |
24 | recipe = WerkzeugRecipe()
25 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/pyyaml/__init__.py:
--------------------------------------------------------------------------------
1 | # pure-python package, this can be removed when we'll support any python package
2 | import os
3 | import sh
4 | from kivy_ios.toolchain import PythonRecipe, shprint
5 |
6 |
7 | class PyYamlRecipe(PythonRecipe):
8 | version = "3.11"
9 | url = "https://pypi.python.org/packages/source/P/PyYAML/PyYAML-{version}.tar.gz"
10 | depends = ["python"]
11 |
12 | def install(self):
13 | arch = list(self.filtered_archs)[0]
14 | build_dir = self.get_build_dir(arch.arch)
15 | os.chdir(build_dir)
16 | hostpython = sh.Command(self.ctx.hostpython)
17 | build_env = arch.get_env()
18 | dest_dir = os.path.join(self.ctx.dist_dir, "root", "python")
19 | build_env['PYTHONPATH'] = os.path.join(dest_dir, 'lib', 'python3.7', 'site-packages')
20 | shprint(hostpython, "setup.py", "install", "--prefix", dest_dir, _env=build_env)
21 |
22 |
23 | recipe = PyYamlRecipe()
24 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/flask/__init__.py:
--------------------------------------------------------------------------------
1 | # pure-python package, this can be removed when we'll support any python package
2 | from kivy_ios.toolchain import PythonRecipe, shprint
3 | from os.path import join
4 | import sh
5 | import os
6 |
7 |
8 | class FlaskRecipe(PythonRecipe):
9 | version = "1.1.2"
10 | url = "https://github.com/mitsuhiko/flask/archive/{version}.zip"
11 | depends = ["python", "jinja2", "werkzeug", "itsdangerous", "click"]
12 |
13 | def install(self):
14 | arch = list(self.filtered_archs)[0]
15 | build_dir = self.get_build_dir(arch.arch)
16 | os.chdir(build_dir)
17 | hostpython = sh.Command(self.ctx.hostpython)
18 | build_env = arch.get_env()
19 | dest_dir = join(self.ctx.dist_dir, "root", "python")
20 | build_env['PYTHONPATH'] = self.ctx.site_packages_dir
21 | shprint(hostpython, "setup.py", "install", "--prefix", dest_dir, _env=build_env)
22 |
23 |
24 | recipe = FlaskRecipe()
25 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/itsdangerous/__init__.py:
--------------------------------------------------------------------------------
1 | # pure-python package, this can be removed when we'll support any python package
2 | from kivy_ios.toolchain import PythonRecipe, shprint
3 | from kivy_ios.context_managers import cd
4 | from os.path import join
5 | import sh
6 |
7 |
8 | class ItsDangerousRecipe(PythonRecipe):
9 | version = "1.1.0"
10 | url = "https://github.com/mitsuhiko/itsdangerous/archive/{version}.zip"
11 | depends = ["python"]
12 |
13 | def install(self):
14 | arch = list(self.filtered_archs)[0]
15 | build_dir = self.get_build_dir(arch.arch)
16 | hostpython = sh.Command(self.ctx.hostpython)
17 | build_env = arch.get_env()
18 | dest_dir = join(self.ctx.dist_dir, "root", "python3")
19 | build_env['PYTHONPATH'] = self.ctx.site_packages_dir
20 | with cd(build_dir):
21 | shprint(hostpython, "setup.py", "install", "--prefix", dest_dir, _env=build_env)
22 |
23 |
24 | recipe = ItsDangerousRecipe()
25 |
--------------------------------------------------------------------------------
/.github/workflows/setup.yml:
--------------------------------------------------------------------------------
1 | name: setup
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | checks:
7 | runs-on: macos-latest
8 | steps:
9 | - name: Checkout kivy-ios
10 | uses: actions/checkout@v3
11 | - name: Set up Python 3.x
12 | uses: actions/setup-python@v4
13 | with:
14 | python-version: 3.x
15 | - name: Install dependencies
16 | run: |
17 | pip install --upgrade setuptools wheel twine
18 | - name: sdist bdist_wheel
19 | run: |
20 | python setup.py sdist bdist_wheel
21 | - name: Twine check
22 | run: |
23 | twine check dist/*
24 | - name: Local install
25 | run: |
26 | python -m venv venv
27 | . venv/bin/activate
28 | pip install dist/kivy-ios-*.tar.gz
29 | pip install Cython==0.29.33
30 | brew install autoconf automake libtool pkg-config
31 | - name: Basic toolchain commands
32 | run: |
33 | . venv/bin/activate
34 | toolchain --help
35 | toolchain recipes
36 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/libpng/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from kivy_ios.toolchain import Recipe, shprint
3 | from os.path import join
4 | import sh
5 |
6 |
7 | class PngRecipe(Recipe):
8 | version = '1.6.26'
9 | url = 'http://downloads.sourceforge.net/sourceforge/libpng/libpng-{version}.tar.gz'
10 | depends = ["python"]
11 | library = '.libs/libpng16.a'
12 |
13 | def build_arch(self, arch):
14 | build_env = arch.get_env()
15 | configure = sh.Command(join(self.build_dir, "configure"))
16 | shprint(configure,
17 | "CC={}".format(build_env["CC"]),
18 | "LD={}".format(build_env["LD"]),
19 | "CFLAGS={}".format(build_env["CFLAGS"]),
20 | "LDFLAGS={}".format(build_env["LDFLAGS"]),
21 | "--prefix=/",
22 | "--host={}".format(arch.triple),
23 | "--disable-shared")
24 | shprint(sh.make, "clean")
25 | shprint(sh.make, self.ctx.concurrent_make, _env=build_env)
26 |
27 |
28 | recipe = PngRecipe()
29 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/sdl2_ttf/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from os.path import join
3 | import sh
4 |
5 |
6 | class LibSDL2TTFRecipe(Recipe):
7 | version = "2.20.1"
8 | url = "https://github.com/libsdl-org/SDL_ttf/releases/download/release-{version}/SDL2_ttf-{version}.tar.gz"
9 | library = "Xcode/build/Release-{arch.sdk}/libSDL2_ttf.a"
10 | include_dir = "SDL_ttf.h"
11 | depends = ["sdl2"]
12 |
13 | def build_arch(self, arch):
14 | shprint(sh.xcodebuild, self.ctx.concurrent_xcodebuild,
15 | "ONLY_ACTIVE_ARCH=NO",
16 | "ARCHS={}".format(arch.arch),
17 | "BITCODE_GENERATION_MODE=bitcode",
18 | "HEADER_SEARCH_PATHS={}".format(
19 | join(self.ctx.include_dir, "common", "sdl2")),
20 | "-sdk", arch.sdk,
21 | "-project", "Xcode/SDL_ttf.xcodeproj",
22 | "-target", "Static Library",
23 | "-configuration", "Release")
24 |
25 |
26 | recipe = LibSDL2TTFRecipe()
27 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/libcurl/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from os.path import join
3 | import sh
4 |
5 |
6 | class CurlRecipe(Recipe):
7 | version = "7.65.3"
8 | url = "https://curl.haxx.se/download/curl-{version}.tar.gz"
9 | library = "lib/.libs/libcurl.a"
10 | include_dir = "include"
11 | depends = ["openssl"]
12 |
13 | def build_arch(self, arch):
14 | build_env = arch.get_env()
15 | configure = sh.Command(join(self.build_dir, "configure"))
16 | shprint(configure,
17 | "CC={}".format(build_env["CC"]),
18 | "LD={}".format(build_env["LD"]),
19 | "CFLAGS={}".format(build_env["CFLAGS"]),
20 | "LDFLAGS={}".format(build_env["LDFLAGS"]),
21 | "--prefix=/",
22 | "--host={}".format(arch.triple),
23 | "--disable-shared",
24 | "--without-libidn2")
25 | shprint(sh.make, "clean")
26 | shprint(sh.make, self.ctx.concurrent_make)
27 |
28 |
29 | recipe = CurlRecipe()
30 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/python3/dynload_shlib.patch:
--------------------------------------------------------------------------------
1 | diff -Naur Python-3.8.2.orig/Python/dynload_shlib.c Python-3.8.2/Python/dynload_shlib.c
2 | --- Python-3.8.2.orig/Python/dynload_shlib.c 2020-04-12 00:17:24.000000000 +0200
3 | +++ Python-3.8.2/Python/dynload_shlib.c 2020-04-12 00:20:10.000000000 +0200
4 | @@ -74,6 +74,15 @@
5 |
6 | PyOS_snprintf(funcname, sizeof(funcname),
7 | LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname);
8 | + /* On IOS, dlopen crash as soon as we try to open one of our library.
9 | + * Instead, we have done a redirection of linking to convert our .so into a
10 | + * .a. Then the main executable is linked with theses symbol. So, instead
11 | + * of trying to dlopen, directly do the dlsym.
12 | + * -- Mathieu
13 | + */
14 | + return (dl_funcptr) dlsym(RTLD_SELF, funcname);
15 | +
16 | + #if 0
17 |
18 | if (fp != NULL) {
19 | int i;
20 | @@ -129,4 +138,5 @@
21 | handles[nhandles++].handle = handle;
22 | p = (dl_funcptr) dlsym(handle, funcname);
23 | return p;
24 | + #endif
25 | }
26 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/hostpython.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import sys
3 | from kivy_ios.toolchain import Recipe
4 | import logging
5 |
6 | logger = logging.getLogger(__name__)
7 |
8 |
9 | class HostpythonAliasRecipe(Recipe):
10 | """
11 | Note this recipe was created to handle both hostpython2 and hostpython3.
12 | As hostpython2 support was dropped, this could probably be simplified.
13 | """
14 | is_alias = True
15 |
16 | def init_after_import(self, ctx):
17 | hostpython = ctx.state.get("hostpython")
18 | if not hostpython:
19 | # search in wanted_recipes if it's the first time
20 | if "hostpython3" in ctx.wanted_recipes:
21 | hostpython = "hostpython3"
22 | else:
23 | logger.error("No hostpython version set in the build.")
24 | logger.error("Add python3 in your recipes:")
25 | logger.error("./toolchain.py build python3 ...")
26 | sys.exit(1)
27 | if hostpython:
28 | self.depends = [hostpython]
29 |
30 |
31 | recipe = HostpythonAliasRecipe()
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010-2017 Kivy Team and other contributors
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/sdl2/disable-hidapi.patch:
--------------------------------------------------------------------------------
1 | diff -Naur SDL2-2.24.1.orig/Xcode/SDL/SDL.xcodeproj/project.pbxproj SDL2-2.24.1/Xcode/SDL/SDL.xcodeproj/project.pbxproj
2 | --- SDL2-2.24.1.orig/Xcode/SDL/SDL.xcodeproj/project.pbxproj 2023-03-10 12:58:05
3 | +++ SDL2-2.24.1/Xcode/SDL/SDL.xcodeproj/project.pbxproj 2023-03-10 12:58:49
4 | @@ -9674,7 +9674,7 @@
5 | buildSettings = {
6 | CLANG_ENABLE_OBJC_ARC = YES;
7 | CLANG_LINK_OBJC_RUNTIME = NO;
8 | - GCC_PREPROCESSOR_DEFINITIONS = GLES_SILENCE_DEPRECATION;
9 | + GCC_PREPROCESSOR_DEFINITIONS = "GLES_SILENCE_DEPRECATION SDL_HIDAPI_DISABLED=1";
10 | GCC_SYMBOLS_PRIVATE_EXTERN = YES;
11 | SKIP_INSTALL = YES;
12 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
13 | @@ -9686,7 +9686,7 @@
14 | buildSettings = {
15 | CLANG_ENABLE_OBJC_ARC = YES;
16 | CLANG_LINK_OBJC_RUNTIME = NO;
17 | - GCC_PREPROCESSOR_DEFINITIONS = GLES_SILENCE_DEPRECATION;
18 | + GCC_PREPROCESSOR_DEFINITIONS = "GLES_SILENCE_DEPRECATION SDL_HIDAPI_DISABLED=1";
19 | GCC_SYMBOLS_PRIVATE_EXTERN = YES;
20 | SKIP_INSTALL = YES;
21 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
22 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/libjpeg/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from os.path import join
3 | import sh
4 |
5 |
6 | class JpegRecipe(Recipe):
7 | version = "v9d"
8 | url = "http://www.ijg.org/files/jpegsrc.{version}.tar.gz"
9 | library = ".libs/libjpeg.a"
10 | include_dir = [
11 | ("jpeglib.h", ""),
12 | ("jconfig.h", ""),
13 | ("jerror.h", ""),
14 | ("jmorecfg.h", ""),
15 | ]
16 | include_per_arch = True
17 |
18 | def build_arch(self, arch):
19 | build_env = arch.get_env()
20 | configure = sh.Command(join(self.build_dir, "configure"))
21 | shprint(configure,
22 | "CC={}".format(build_env["CC"]),
23 | "LD={}".format(build_env["LD"]),
24 | "CFLAGS={}".format(build_env["CFLAGS"]),
25 | "LDFLAGS={}".format(build_env["LDFLAGS"]),
26 | "--prefix=/",
27 | "--host={}".format(arch.triple),
28 | "--disable-shared")
29 | shprint(sh.make, "clean")
30 | shprint(sh.make, self.ctx.concurrent_make)
31 |
32 |
33 | recipe = JpegRecipe()
34 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/sdl2_image/fix-ios-xcodebuild.patch:
--------------------------------------------------------------------------------
1 | diff --git a/Xcode/SDL_image.xcodeproj/project.pbxproj b/Xcode/SDL_image.xcodeproj/project.pbxproj
2 | index a64c8665..69565703 100644
3 | --- a/Xcode/SDL_image.xcodeproj/project.pbxproj
4 | +++ b/Xcode/SDL_image.xcodeproj/project.pbxproj
5 | @@ -7,7 +7,7 @@
6 | objects = {
7 |
8 | /* Begin PBXBuildFile section */
9 | - 007288A80F0DA79800C302A9 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007288A60F0DA79800C302A9 /* ApplicationServices.framework */; };
10 | + 007288A80F0DA79800C302A9 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007288A60F0DA79800C302A9 /* ApplicationServices.framework */; platformFilters = (macos, ); };
11 | 6313BF532785566D00F268AD /* IMG_qoi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6313BF522785566D00F268AD /* IMG_qoi.c */; };
12 | 6313BF542785566D00F268AD /* IMG_qoi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6313BF522785566D00F268AD /* IMG_qoi.c */; };
13 | AA23FC7D20A2A1B90017DFB9 /* IMG_svg.c in Sources */ = {isa = PBXBuildFile; fileRef = AA50AA461F9C7C50003B9C0C /* IMG_svg.c */; };
14 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/py3dns/ios.patch:
--------------------------------------------------------------------------------
1 | diff --git a/DNS/Base.py b/DNS/Base.py
2 | index 34a6da7..b755e79 100644
3 | --- a/DNS/Base.py
4 | +++ b/DNS/Base.py
5 | @@ -15,6 +15,7 @@ import socket, string, types, time, select
6 | import errno
7 | from . import Type,Class,Opcode
8 | import asyncore
9 | +import os
10 | #
11 | # This random generator is used for transaction ids and port selection. This
12 | # is important to prevent spurious results from lost packets, and malicious
13 | @@ -50,8 +51,12 @@ defaults= { 'protocol':'udp', 'port':53, 'opcode':Opcode.QUERY,
14 |
15 | def ParseResolvConf(resolv_path="/etc/resolv.conf"):
16 | "parses the /etc/resolv.conf file and sets defaults for name servers"
17 | - with open(resolv_path, 'r') as stream:
18 | - return ParseResolvConfFromIterable(stream)
19 | + if os.path.exists(resolv_path):
20 | + with open(resolv_path, 'r') as stream:
21 | + return ParseResolvConfFromIterable(stream)
22 | + else:
23 | + defaults['server'].extend(['8.8.8.8', '8.8.4.4'])
24 | + return
25 |
26 | def ParseResolvConfFromIterable(lines):
27 | "parses a resolv.conf formatted stream and sets defaults for name servers"
28 |
--------------------------------------------------------------------------------
/.github/workflows/support.yml:
--------------------------------------------------------------------------------
1 | name: 'Support Requests'
2 |
3 | on:
4 | issues:
5 | types: [labeled, unlabeled, reopened]
6 |
7 | permissions:
8 | issues: write
9 |
10 | jobs:
11 | action:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: dessant/support-requests@v2
15 | with:
16 | github-token: ${{ github.token }}
17 | support-label: 'support'
18 | issue-comment: >
19 | 👋 We use the issue tracker exclusively for bug reports and feature requests.
20 | However, this issue appears to be a support request. Please use our
21 | [support channels](https://github.com/kivy/kivy-ios/blob/master/README.md#support)
22 | to get help with the project.
23 |
24 |
25 | If you're having trouble installing or using kivy-ios,
26 | maybe you could be interested to [installation and requirements](https://github.com/kivy/kivy-ios/blob/master/README.md#installation--requirements).
27 |
28 |
29 | Let us know if this comment was made in error, and we'll be happy
30 | to reopen the issue.
31 | close-issue: true
32 | lock-issue: false
--------------------------------------------------------------------------------
/kivy_ios/recipes/openssl/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from os.path import join
3 | import sh
4 |
5 |
6 | arch_mapper = {'x86_64': 'darwin64-x86_64-cc',
7 | 'arm64': 'ios64-cross'}
8 |
9 |
10 | class OpensslRecipe(Recipe):
11 | version = "1.1.1l"
12 | url = "http://www.openssl.org/source/openssl-{version}.tar.gz"
13 | libraries = ["libssl.a", "libcrypto.a"]
14 | include_dir = "include"
15 | include_per_arch = True
16 |
17 | def build_arch(self, arch):
18 | build_env = arch.get_env()
19 | target = arch_mapper[arch.arch_arg()]
20 | shprint(sh.env, _env=build_env)
21 | sh.perl(join(self.build_dir, "Configure"),
22 | target,
23 | _env=build_env)
24 | if target.endswith('-cross'):
25 | with open('Makefile', 'r') as makefile:
26 | filedata = makefile.read()
27 | filedata = filedata.replace('$(CROSS_TOP)/SDKs/$(CROSS_SDK)', arch.sysroot)
28 | with open('Makefile', 'w') as makefile:
29 | makefile.write(filedata)
30 | shprint(sh.make, "clean")
31 | shprint(sh.make, self.ctx.concurrent_make, "build_libs")
32 |
33 |
34 | recipe = OpensslRecipe()
35 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/numpy/duplicated_symbols.patch:
--------------------------------------------------------------------------------
1 | diff -Naur numpy-1.24.2.orig/numpy/linalg/setup.py numpy-1.24.2/numpy/linalg/setup.py
2 | --- numpy-1.24.2.orig/numpy/linalg/setup.py 2023-03-11 19:31:34
3 | +++ numpy-1.24.2/numpy/linalg/setup.py 2023-03-11 19:32:12
4 | @@ -78,7 +78,7 @@
5 | # umath_linalg module
6 | config.add_extension(
7 | '_umath_linalg',
8 | - sources=['umath_linalg.cpp', get_lapack_lite_sources],
9 | + sources=['umath_linalg.cpp'],
10 | depends=['lapack_lite/f2c.h'],
11 | extra_info=lapack_info,
12 | extra_cxx_compile_args=NPY_CXX_FLAGS,
13 | diff -Naur numpy-1.24.2.orig/numpy/random/setup.py numpy-1.24.2/numpy/random/setup.py
14 | --- numpy-1.24.2.orig/numpy/random/setup.py 2023-03-11 19:38:04
15 | +++ numpy-1.24.2/numpy/random/setup.py 2023-03-11 19:39:48
16 | @@ -139,7 +139,6 @@
17 | config.add_extension('mtrand',
18 | sources=['mtrand.c',
19 | 'src/legacy/legacy-distributions.c',
20 | - 'src/distributions/distributions.c',
21 | ],
22 | include_dirs=['.', 'src', 'src/legacy'],
23 | libraries=mtrand_libs,
--------------------------------------------------------------------------------
/kivy_ios/recipes/markupsafe/__init__.py:
--------------------------------------------------------------------------------
1 | # pure-python package, this can be removed when we'll support any python package
2 | from kivy_ios.toolchain import PythonRecipe, shprint
3 | from os.path import join
4 | import sh
5 | import os
6 |
7 |
8 | class MarkupSafeRecipe(PythonRecipe):
9 | version = "1.1.1"
10 | url = "https://github.com/mitsuhiko/markupsafe/archive/{version}.zip"
11 | depends = ["python"]
12 |
13 | def install(self):
14 | arch = list(self.filtered_archs)[0]
15 | build_dir = self.get_build_dir(arch.arch)
16 | os.chdir(build_dir)
17 | hostpython = sh.Command(self.ctx.hostpython)
18 | build_env = arch.get_env()
19 | dest_dir = join(self.ctx.dist_dir, "root", "python3")
20 | build_env['PYTHONPATH'] = self.ctx.site_packages_dir
21 | cmd = sh.Command("sed")
22 | shprint(cmd, "-i", "", "s/,.*Feature//g", "./setup.py", _env=build_env)
23 | shprint(cmd, "-i", "", "/^speedups = Feature/,/^)$/s/.*//g", "./setup.py", _env=build_env)
24 | shprint(cmd, "-i", "", "s/features\['speedups'\].*=.*speedups/pass/g", "./setup.py", _env=build_env) # noqa: W605
25 | shprint(hostpython, "setup.py", "install", "--prefix", dest_dir, _env=build_env)
26 |
27 |
28 | recipe = MarkupSafeRecipe()
29 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/sdl2_mixer/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | import sh
3 |
4 |
5 | class LibSDL2MixerRecipe(Recipe):
6 | version = "2.6.2"
7 | url = "https://github.com/libsdl-org/SDL_mixer/releases/download/release-{version}/SDL2_mixer-{version}.tar.gz"
8 | library = "Xcode/build/Release-{arch.sdk}/libSDL2_mixer.a"
9 | include_dir = "include/SDL_mixer.h"
10 | depends = ["sdl2"]
11 | pbx_frameworks = ["ImageIO"]
12 | pbx_libraries = ["libc++"]
13 |
14 | def build_arch(self, arch):
15 | # endian.h is in /usr/include/machine/ (Since MacOs Mojave?)
16 | # header is needed by libvorbis, so We're adding that folder
17 | # to HEADER_SEARCH_PATHS
18 | shprint(sh.xcodebuild, self.ctx.concurrent_xcodebuild,
19 | "ONLY_ACTIVE_ARCH=NO",
20 | "ARCHS={}".format(arch.arch),
21 | "BITCODE_GENERATION_MODE=bitcode",
22 | "HEADER_SEARCH_PATHS=$HEADER_SEARCH_PATHS /usr/include/machine {} ".format(" ".join(arch.include_dirs)),
23 | "-sdk", arch.sdk,
24 | "-project", "Xcode/SDL_mixer.xcodeproj",
25 | "-target", "Static Library",
26 | "-configuration", "Release")
27 |
28 |
29 | recipe = LibSDL2MixerRecipe()
30 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/netifaces/__init__.py:
--------------------------------------------------------------------------------
1 | import sh
2 |
3 | from os.path import join
4 |
5 | from kivy_ios.toolchain import CythonRecipe, shprint
6 | from kivy_ios.context_managers import cd
7 |
8 |
9 | class NetifacesRecipe(CythonRecipe):
10 | version = "0.10.9"
11 | url = "https://pypi.io/packages/source/n/netifaces/netifaces-{version}.tar.gz"
12 | depends = ["python3"]
13 | python_depends = ["setuptools"]
14 | library = "libnetifaces.a"
15 | cythonize = False
16 |
17 | def dest_dir(self):
18 | return join(self.ctx.dist_dir, "root", "python3")
19 |
20 | def get_netifaces_env(self, arch):
21 | build_env = arch.get_env()
22 | build_env["PYTHONPATH"] = self.ctx.site_packages_dir
23 | return build_env
24 |
25 | def install(self):
26 | arch = list(self.filtered_archs)[0]
27 | build_dir = self.get_build_dir(arch.arch)
28 | build_env = self.get_netifaces_env(arch)
29 | hostpython = sh.Command(self.ctx.hostpython)
30 | with cd(build_dir):
31 | shprint(
32 | hostpython,
33 | "setup.py",
34 | "install",
35 | "--prefix",
36 | self.dest_dir(),
37 | _env=build_env,
38 | )
39 |
40 |
41 | recipe = NetifacesRecipe()
42 |
--------------------------------------------------------------------------------
/kivy_ios/context_managers.py:
--------------------------------------------------------------------------------
1 | """
2 | This module houses context managers to assist in the managing of state during
3 | kivy-ios builds.
4 | """
5 | from logging import getLogger
6 | from contextlib import contextmanager
7 | from os import getcwd, chdir, environ
8 | from os.path import expanduser
9 |
10 |
11 | logger = getLogger(__name__)
12 |
13 |
14 | @contextmanager
15 | def cd(newdir):
16 | """
17 | Set the current working directory to `newdir` for the duration of the
18 | context.
19 | """
20 | prevdir = getcwd()
21 | logger.info("cd {}".format(newdir))
22 | chdir(expanduser(newdir))
23 | try:
24 | yield
25 | finally:
26 | logger.info("cd {}".format(prevdir))
27 | chdir(prevdir)
28 |
29 |
30 | @contextmanager
31 | def python_path(newdir):
32 | """
33 | Set the PYTHONPATH environmnet variable to `newdir` for the duraiton of the
34 | context.
35 | """
36 | prevdir = environ.get("PYTHONPATH")
37 | logger.debug("Setting PYTHONPATH to {}".format(newdir))
38 | environ["PYTHONPATH"] = newdir
39 | try:
40 | yield
41 | finally:
42 | logger.debug("Setting PYTHONPATH to {}".format(prevdir))
43 | if prevdir is None:
44 | environ.pop("PYTHONPATH")
45 | else:
46 | environ["PYTHONPATH"] = prevdir
47 |
--------------------------------------------------------------------------------
/tests/test_python3/main.py:
--------------------------------------------------------------------------------
1 | print("Python 3 running!")
2 | import sys # noqa: E402
3 | print(f"sys.path: {sys.path}")
4 | import traceback # noqa: E402
5 |
6 | modules_to_tests = [
7 | "math", "_sre", "array",
8 | "binascii", "multiprocessing",
9 | "subprocess"
10 | ]
11 |
12 | for name in modules_to_tests:
13 | print(f"- import {name}: ", end="")
14 | try:
15 | __import__(name)
16 | print("OK")
17 | except ImportError:
18 | print("FAIL")
19 | traceback.print_exc()
20 |
21 | # test pyobjus
22 | print("- import pyobjus start")
23 | import pyobjus # noqa: F401, E402
24 | print("- import done")
25 | from pyobjus import autoclass # noqa: E402
26 | NSNotificationCenter = autoclass("NSNotificationCenter")
27 |
28 | # test ios
29 | import ios # noqa: F401, E402
30 |
31 | from kivy.app import App # noqa: E402
32 | from kivy.lang import Builder # noqa: E402
33 |
34 |
35 | class TestApp(App):
36 | def build(self):
37 | return Builder.load_string("""
38 | RelativeLayout:
39 | GridLayout:
40 | cols: 2
41 |
42 | Button:
43 | text: "Hello Python 3!"
44 | font_size: dp(48)
45 |
46 | TextInput:
47 | font_size: dp(24)
48 |
49 | Widget
50 | Widget
51 |
52 | """)
53 |
54 |
55 | TestApp().run()
56 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ffpyplayer/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe
2 | from os.path import join
3 |
4 |
5 | class FFPyplayerRecipe(CythonRecipe):
6 | version = "v4.3.5"
7 | url = "https://github.com/matham/ffpyplayer/archive/{version}.zip"
8 | library = "libffpyplayer.a"
9 | depends = ["python", "sdl2", "ffmpeg"]
10 | pbx_frameworks = [
11 | "CoreVideo", "CoreMedia", "CoreImage", "AVFoundation", "UIKit",
12 | "CoreMotion"]
13 | pbx_libraries = ["libiconv"]
14 | pre_build_ext = True
15 |
16 | def get_recipe_env(self, arch):
17 | env = super(FFPyplayerRecipe, self).get_recipe_env(arch)
18 | env["CC"] += " -I{}".format(
19 | join(self.ctx.dist_dir, "include", arch.arch, "libffi"))
20 | env["SDL_INCLUDE_DIR"] = join(self.ctx.dist_dir, "include",
21 | "common", "sdl2")
22 | env["FFMPEG_INCLUDE_DIR"] = join(self.ctx.dist_dir, "include",
23 | arch.arch, "ffmpeg")
24 | env["CONFIG_POSTPROC"] = "0"
25 | return env
26 |
27 | def prebuild_arch(self, arch):
28 | # common to all archs
29 | if self.has_marker("patched"):
30 | return
31 | self.apply_patch("misc-visibility.patch")
32 | self.set_marker("patched")
33 |
34 |
35 | recipe = FFPyplayerRecipe()
36 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/freetype/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from os.path import join
3 | import sh
4 |
5 |
6 | class FreetypeRecipe(Recipe):
7 | version = "2.5.5"
8 | url = "https://download.savannah.gnu.org/releases/freetype/freetype-old/freetype-{version}.tar.bz2"
9 | library = "objs/.libs/libfreetype.a"
10 | include_dir = ["include", ("builds/unix/ftconfig.h", "config/ftconfig.h")]
11 | include_per_arch = True
12 |
13 | def build_arch(self, arch):
14 | build_env = arch.get_env()
15 | configure = sh.Command(join(self.build_dir, "configure"))
16 | shprint(configure,
17 | "CC={}".format(build_env["CC"]),
18 | "LD={}".format(build_env["LD"]),
19 | "CFLAGS={}".format(build_env["CFLAGS"]),
20 | "LDFLAGS={}".format(build_env["LDFLAGS"]),
21 | "--prefix=/",
22 | "--host={}".format(arch.triple),
23 | "--without-png",
24 | "--without-bzip2",
25 | "--without-fsspec",
26 | "--without-harfbuzz",
27 | "--without-old-mac-fonts",
28 | "--enable-static=yes",
29 | "--enable-shared=no")
30 | shprint(sh.make, "clean")
31 | shprint(sh.make, self.ctx.concurrent_make)
32 |
33 |
34 | recipe = FreetypeRecipe()
35 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/sdl2/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | import sh
3 |
4 |
5 | class LibSDL2Recipe(Recipe):
6 | version = "2.24.1"
7 | url = "https://github.com/libsdl-org/SDL/releases/download/release-{version}/SDL2-{version}.tar.gz"
8 | library = "Xcode/SDL/build/Release-{arch.sdk}/libSDL2.a"
9 | include_dir = "include"
10 | pbx_frameworks = [
11 | "OpenGLES", "AudioToolbox", "QuartzCore", "CoreGraphics",
12 | "CoreMotion", "GameController", "AVFoundation", "Metal",
13 | "UIKit", "CoreHaptics"]
14 |
15 | def prebuild_arch(self, arch):
16 | if self.has_marker("patched"):
17 | return
18 | self.apply_patch("uikit-transparent.patch")
19 | self.apply_patch("disable-hidapi.patch")
20 | self.set_marker("patched")
21 |
22 | def build_arch(self, arch):
23 | env = arch.get_env()
24 | shprint(sh.xcodebuild, self.ctx.concurrent_xcodebuild,
25 | "ONLY_ACTIVE_ARCH=NO",
26 | "ARCHS={}".format(arch.arch),
27 | "BITCODE_GENERATION_MODE=bitcode",
28 | "CC={}".format(env['CC']),
29 | "-sdk", arch.sdk,
30 | "-project", "Xcode/SDL/SDL.xcodeproj",
31 | "-target", "Static Library-iOS",
32 | "-configuration", "Release")
33 |
34 |
35 | recipe = LibSDL2Recipe()
36 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/sdl2_image/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from os.path import join
3 | import sh
4 |
5 |
6 | class LibSDL2ImageRecipe(Recipe):
7 | version = "2.6.2"
8 | url = "https://github.com/libsdl-org/SDL_image/releases/download/release-{version}/SDL2_image-{version}.tar.gz"
9 | library = "Xcode/build/Release-{arch.sdk}/libSDL2_image.a"
10 | include_dir = "SDL_image.h"
11 | depends = ["sdl2"]
12 | pbx_frameworks = ["CoreGraphics", "MobileCoreServices"]
13 |
14 | def prebuild_arch(self, arch):
15 | if self.has_marker("patched"):
16 | return
17 | # fix-ios-xcodebuild is a patch taken from the SDL2_image repo
18 | # (See: https://github.com/libsdl-org/SDL_image/pull/292)
19 | # We will need to remove it once is included into a release
20 | self.apply_patch("fix-ios-xcodebuild.patch")
21 | self.set_marker("patched")
22 |
23 | def build_arch(self, arch):
24 | shprint(sh.xcodebuild, self.ctx.concurrent_xcodebuild,
25 | "ONLY_ACTIVE_ARCH=NO",
26 | "ARCHS={}".format(arch.arch),
27 | "BITCODE_GENERATION_MODE=bitcode",
28 | "HEADER_SEARCH_PATHS={}".format(
29 | join(self.ctx.include_dir, "common", "sdl2")),
30 | "-sdk", arch.sdk,
31 | "-project", "Xcode/SDL_image.xcodeproj",
32 | "-target", "Static Library",
33 | "-configuration", "Release")
34 |
35 |
36 | recipe = LibSDL2ImageRecipe()
37 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/bridge.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface bridge : NSObject {
5 | NSOperationQueue *queue;
6 | }
7 |
8 | @property (strong, nonatomic) CMMotionManager *motionManager;
9 | @property (nonatomic) double ac_x;
10 | @property (nonatomic) double ac_y;
11 | @property (nonatomic) double ac_z;
12 |
13 | @property (nonatomic) double gy_x;
14 | @property (nonatomic) double gy_y;
15 | @property (nonatomic) double gy_z;
16 |
17 | @property (nonatomic) double mg_x;
18 | @property (nonatomic) double mg_y;
19 | @property (nonatomic) double mg_z;
20 |
21 | @property (nonatomic) double sp_yaw;
22 | @property (nonatomic) double sp_pitch;
23 | @property (nonatomic) double sp_roll;
24 |
25 | @property (nonatomic) double g_x;
26 | @property (nonatomic) double g_y;
27 | @property (nonatomic) double g_z;
28 |
29 | @property (nonatomic) double q_x;
30 | @property (nonatomic) double q_y;
31 | @property (nonatomic) double q_z;
32 | @property (nonatomic) double q_w;
33 |
34 | @property (nonatomic) double rotation_rate_x;
35 | @property (nonatomic) double rotation_rate_y;
36 | @property (nonatomic) double rotation_rate_z;
37 |
38 | @property (nonatomic) double user_acc_x;
39 | @property (nonatomic) double user_acc_y;
40 | @property (nonatomic) double user_acc_z;
41 |
42 | @property (nonatomic) double mf_x;
43 | @property (nonatomic) double mf_y;
44 | @property (nonatomic) double mf_z;
45 |
46 | @property (nonatomic) double relative_altitude;
47 | @property (nonatomic) double pressure;
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/.ci/rebuild_updated_recipes.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """
3 | Continuous Integration helper script.
4 | Automatically detects recipes modified in a changeset (compares with master)
5 | and recompiles them.
6 |
7 | Current limitations:
8 | - will fail on conflicting requirements
9 | """
10 | import sh
11 | import subprocess
12 | from fnmatch import fnmatch
13 | from constants import CORE_RECIPES, BROKEN_RECIPES
14 |
15 |
16 | def modified_recipes(branch="origin/master"):
17 | """
18 | Returns a set of modified recipes between the current branch and the one
19 | in param.
20 | """
21 | # using the contrib version on purpose rather than sh.git, since it comes
22 | # with a bunch of fixes, e.g. disabled TTY, see:
23 | # https://stackoverflow.com/a/20128598/185510
24 | sh.contrib.git.fetch("origin", "master")
25 | git_diff = sh.contrib.git.diff("--name-only", "--diff-filter=d", branch)
26 | recipes = set()
27 | for file_path in git_diff:
28 | if fnmatch(file_path, "kivy_ios/recipes/*/__init__.py\n"):
29 | recipe = file_path.split("/")[2]
30 | recipes.add(recipe)
31 | return recipes
32 |
33 |
34 | def main():
35 | recipes = modified_recipes()
36 | recipes -= CORE_RECIPES
37 | recipes -= BROKEN_RECIPES
38 | updated_recipes = " ".join(recipes)
39 | if updated_recipes != "":
40 | subprocess.run(
41 | f"toolchain build {updated_recipes}", shell=True, check=True
42 | )
43 | else:
44 | print("Nothing to do. No updated recipes.")
45 |
46 |
47 | if __name__ == "__main__":
48 | main()
49 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/hostopenssl/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import HostRecipe, shprint
2 | from os.path import join
3 | import sh
4 | import logging
5 |
6 | logger = logging.getLogger(__name__)
7 |
8 | arch_mapper = {'x86_64': 'darwin64-x86_64-cc',
9 | 'arm64': 'darwin64-arm64-cc'}
10 |
11 |
12 | class HostOpensslRecipe(HostRecipe):
13 | version = "1.1.1l"
14 | url = "http://www.openssl.org/source/openssl-{version}.tar.gz"
15 |
16 | def get_build_env(self):
17 | build_env = self.ctx.env.copy()
18 | self.build_env = build_env
19 | return build_env
20 |
21 | def build_arch(self, arch):
22 | build_env = self.get_build_env()
23 | configure = sh.Command(join(self.build_dir, "Configure"))
24 | shprint(configure,
25 | arch_mapper[arch.arch],
26 | _env=build_env)
27 | shprint(sh.make, "clean")
28 | shprint(sh.make, self.ctx.concurrent_make, "build_libs")
29 |
30 | def install(self):
31 | arch = self.archs[0]
32 | sh.mkdir('-p', join(self.ctx.dist_dir, 'hostopenssl'))
33 | sh.cp('-r', join(self.get_build_dir(arch), 'include'),
34 | join(self.ctx.dist_dir, 'hostopenssl', 'include'))
35 | sh.mkdir('-p', join(self.ctx.dist_dir, 'hostopenssl', 'lib'))
36 | sh.cp(join(self.get_build_dir(arch), 'libssl.a'),
37 | join(self.ctx.dist_dir, 'hostopenssl', 'lib'))
38 | sh.cp(join(self.get_build_dir(arch), 'libcrypto.a'),
39 | join(self.ctx.dist_dir, 'hostopenssl', 'lib'))
40 |
41 |
42 | recipe = HostOpensslRecipe()
43 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ios/src/ios_browser.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Browser support
3 | */
4 |
5 | #import
6 | #import
7 | #include
8 | #include "ios_wrapper.h"
9 |
10 | void ios_open_url(char *url)
11 | {
12 | NSString *nsurl = [NSString stringWithCString:(char *)url encoding:NSUTF8StringEncoding];
13 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString: nsurl]];
14 | }
15 |
16 | /*
17 | * Webview support
18 | */
19 | void load_url_webview(char *url, int x, int y, int width, int height)
20 | {
21 | NSString *nsurl = [NSString stringWithCString:(char *)url encoding:NSUTF8StringEncoding];
22 | WKWebView *webView = [[WKWebView alloc] initWithFrame: CGRectMake(x, y, width, height)];
23 | UIWindow *window = [[UIApplication sharedApplication] keyWindow];
24 | UIView *view = [window.rootViewController view];
25 | [view addSubview:webView];
26 | NSURL *ur = [[NSURL alloc] initWithString: nsurl];
27 | NSURLRequest *req = [[NSURLRequest alloc] initWithURL: ur];
28 | [webView loadRequest: req];
29 | [req release];
30 | [ur release];
31 |
32 | UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
33 | [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
34 | [button setTitle:@"X" forState:UIControlStateNormal];
35 | button.frame = CGRectMake(0.0, 0.0, 40, 40);
36 | [button addTarget:webView
37 | action:@selector(removeFromSuperview) forControlEvents:UIControlEventTouchDown];
38 | [webView addSubview:button];
39 | [button release];
40 | [webView release];
41 | }
42 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
22 |
23 | **Versions**
24 |
25 | * Python :
26 | * MacOS version :
27 | * XCode Version :
28 | * Cython version :
29 |
30 | **Describe the bug**
31 | // REPLACE ME: A clear and concise description of what the bug is.
32 |
33 | **To Reproduce**
34 | // REPLACE ME: Add your `toolchain.py ....` command or a complete explanation of what you did so We can reproduce your error.
35 |
36 | **Expected behavior**
37 | // REPLACE ME: A clear and concise description of what you expected to happen.
38 |
39 | **Logs**
40 | ```
41 | // REPLACE ME: Paste the build output containing the error
42 | ```
43 |
44 | **Screenshots**
45 |
49 |
50 | **Additional context**
51 | Add any other context about the problem here.
52 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/pictures.kv:
--------------------------------------------------------------------------------
1 | #:kivy 1.0
2 | #:import kivy kivy
3 | #:import win kivy.core.window
4 |
5 | FloatLayout:
6 | canvas:
7 | Color:
8 | rgb: 1, 1, 1
9 | Rectangle:
10 | source: 'data/images/background.jpg'
11 | size: self.size
12 |
13 | BoxLayout:
14 | padding: 10
15 | spacing: 10
16 | size_hint: 1, None
17 | pos_hint: {'top': 1}
18 | height: 44
19 | Image:
20 | size_hint: None, None
21 | size: 24, 24
22 | source: 'data/logo/kivy-icon-24.png'
23 | Label:
24 | height: 24
25 | text_size: self.width, None
26 | color: (1, 1, 1, .8)
27 | text: 'Kivy %s - Pictures' % kivy.__version__
28 |
29 |
30 |
31 | :
32 | # each time a picture is created, the image can delay the loading
33 | # as soon as the image is loaded, ensure that the center is changed
34 | # to the center of the screen.
35 | on_size: self.center = win.Window.center
36 | size: image.size
37 | size_hint: None, None
38 |
39 | Image:
40 | id: image
41 | source: root.source
42 |
43 | # create initial image to be 400 pixels width
44 | size: 400, 400 / self.image_ratio
45 |
46 | # add shadow background
47 | canvas.before:
48 | Color:
49 | rgba: 1,1,1,1
50 | BorderImage:
51 | source: 'shadow32.png'
52 | border: (36,36,36,36)
53 | size:(self.width+72, self.height+72)
54 | pos: (-36,-36)
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIcons
12 |
13 | CFBundleIdentifier
14 | {{ cookiecutter.domain_name }}
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | ${PRODUCT_NAME}
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | 1.1
23 | CFBundleVersion
24 | 1.1
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | Launch Screen
29 | UIStatusBarHidden
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationLandscapeLeft
34 | UIInterfaceOrientationLandscapeRight
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationPortraitUpsideDown
37 |
38 | UISupportedInterfaceOrientations~ipad
39 |
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 | UIInterfaceOrientationPortrait
43 | UIInterfaceOrientationPortraitUpsideDown
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ios/src/ios_filechooser.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #include "ios_wrapper.h"
4 |
5 | @interface NativeImagePicker : NSObject
6 | @end
7 | @implementation NativeImagePicker
8 |
9 | - (NSString*) getFileName:(NSURL *) ns_url {
10 | // Return the file name without the path or file extention
11 | NSString *image_name = ns_url.pathComponents.lastObject;
12 | NSArray *listItems = [image_name componentsSeparatedByString:@"."];
13 | NSString *ret = listItems[0];
14 | return ret;
15 | }
16 |
17 | - (NSString*) writeToPNG: (NSDictionary *) info {
18 | /* Given the info frozen dictionary returned by the file picker, convert
19 | the image selected to a PNG and return the full path. */
20 |
21 | // Get the image name, stripped of path and extention
22 | NSString *image_name = [self getFileName: info[UIImagePickerControllerImageURL]];
23 |
24 | // Get the png representation of the image
25 | UIImage *image = info[UIImagePickerControllerOriginalImage];
26 | NSData *imageData = UIImagePNGRepresentation(image);
27 |
28 | // Generate the final image destination
29 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
30 | NSString *documentsDirectory = [paths objectAtIndex:0];
31 | NSString *imagePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", image_name]];
32 |
33 | // Write the image data to the file
34 | if (![imageData writeToFile:imagePath atomically:NO])
35 | {
36 | NSLog(@"Failed to cache image data to disk");
37 | return @"";
38 | }
39 | else
40 | {
41 | NSLog(@"the cachedImagedPath is %@",imagePath);
42 | return imagePath;
43 | }
44 | }
45 | @end
--------------------------------------------------------------------------------
/kivy_ios/recipes/pycrypto/__init__.py:
--------------------------------------------------------------------------------
1 | '''Recipe for pycrypto on ios
2 | '''
3 | from kivy_ios.toolchain import CythonRecipe, shprint
4 | from kivy_ios.context_managers import cd
5 | from os.path import join
6 | import sh
7 |
8 |
9 | class PycryptoRecipe(CythonRecipe):
10 | version = "2.6.1"
11 | url = "https://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-{version}.tar.gz"
12 | depends = ["python", "openssl"]
13 | include_per_arch = True
14 | library = "libpycrypto.a"
15 |
16 | def build_arch(self, arch):
17 | build_env = arch.get_env()
18 | self.apply_patch('hash_SHA2_template.c.patch', target_dir=self.build_dir + '/src')
19 | configure = sh.Command(join(self.build_dir, "configure"))
20 | shprint(configure,
21 | "CC={}".format(build_env["CC"]),
22 | "LD={}".format(build_env["LD"]),
23 | "CFLAGS={}".format(build_env["CFLAGS"]),
24 | "LDFLAGS={} -Wno-error ".format(build_env["LDFLAGS"]),
25 | "--prefix=/",
26 | "--host={}".format(arch),
27 | "ac_cv_func_malloc_0_nonnull=yes",
28 | "ac_cv_func_realloc_0_nonnull=yes")
29 | super(PycryptoRecipe, self).build_arch(arch)
30 |
31 | def install(self):
32 | arch = list(self.filtered_archs)[0]
33 | build_dir = self.get_build_dir(arch.arch)
34 | hostpython = sh.Command(self.ctx.hostpython)
35 | build_env = arch.get_env()
36 | dest_dir = join(self.ctx.dist_dir, "root", "python")
37 | build_env['PYTHONPATH'] = join(dest_dir, 'lib', 'python3.7', 'site-packages')
38 | with cd(build_dir):
39 | shprint(hostpython, "setup.py", "install", "--prefix", dest_dir, _env=build_env)
40 |
41 |
42 | recipe = PycryptoRecipe()
43 |
--------------------------------------------------------------------------------
/kivy_ios/tools/cythonize.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | import sys
5 | import subprocess
6 |
7 | # resolve cython executable
8 | cython = None
9 |
10 |
11 | def resolve_cython():
12 | global cython
13 | for executable in ('cython', 'cython-2.7'):
14 | for path in os.environ['PATH'].split(':'):
15 | if not os.path.exists(path):
16 | continue
17 | if executable in os.listdir(path):
18 | cython = os.path.join(path, executable)
19 | return
20 |
21 |
22 | def do(fn):
23 | print('cythonize:', fn)
24 | assert fn.endswith('.pyx')
25 | parts = fn.split('/')
26 | if parts[0] == '.':
27 | parts.pop(0)
28 | modname = parts[-1][:-4]
29 | package = '_'.join(parts[:-1])
30 |
31 | # cythonize
32 | subprocess.Popen([cython, fn], env=os.environ).communicate()
33 |
34 | if not package:
35 | print('no need to rewrite', fn)
36 | else:
37 | # get the .c, and change the initXXX
38 | fn_c = fn[:-3] + 'c'
39 | with open(fn_c) as fd:
40 | data = fd.read()
41 | modname = modname.split('.')[-1]
42 | pac_mod = '{}_{}'.format(package, modname)
43 | fmts = ('init{}(void)', 'PyInit_{}(void)', 'Pyx_NAMESTR("{}")', '"{}",')
44 | for i, fmt in enumerate(fmts):
45 | pat = fmt.format(modname)
46 | sub = fmt.format(pac_mod)
47 | print('{}: {} -> {}'.format(i + 1, pat, sub))
48 | data = data.replace(pat, sub)
49 | print('rewrite', fn_c)
50 | with open(fn_c, 'w') as fd:
51 | fd.write(data)
52 |
53 |
54 | if __name__ == '__main__':
55 | print('-- cythonize', sys.argv)
56 | resolve_cython()
57 | for fn in sys.argv[1:]:
58 | do(fn)
59 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ffpyplayer/misc-visibility.patch:
--------------------------------------------------------------------------------
1 | diff --git a/ffpyplayer/clib/misc.c b/ffpyplayer/clib/misc.c
2 | index 55181d1..6011ffa 100644
3 | --- a/ffpyplayer/clib/misc.c
4 | +++ b/ffpyplayer/clib/misc.c
5 | @@ -1,8 +1,7 @@
6 | -
7 | #include "misc.h"
8 |
9 | #define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0
10 | -void print_all_libs_info(int flags, int level)
11 | +void __attribute__ ((visibility ("hidden"))) print_all_libs_info(int flags, int level)
12 | {
13 | #if CONFIG_AVUTIL
14 | PRINT_LIB_INFO(avutil, AVUTIL, flags, level);
15 | @@ -30,7 +29,7 @@ void print_all_libs_info(int flags, int level)
16 | #endif
17 | }
18 |
19 | -const AVOption *opt_find(void *obj, const char *name, const char *unit,
20 | +const AVOption __attribute__ ((visibility ("hidden"))) *opt_find(void *obj, const char *name, const char *unit,
21 | int opt_flags, int search_flags)
22 | {
23 | const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags);
24 | @@ -40,7 +39,7 @@ const AVOption *opt_find(void *obj, const char *name, const char *unit,
25 | }
26 |
27 | #define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0
28 | -int opt_default(const char *opt, const char *arg,
29 | +int __attribute__ ((visibility ("hidden"))) opt_default(const char *opt, const char *arg,
30 | struct SwsContext *sws_opts, AVDictionary **sws_dict, AVDictionary **swr_opts,
31 | AVDictionary **resample_opts, AVDictionary **format_opts, AVDictionary **codec_opts)
32 | {
33 | @@ -140,7 +139,7 @@ int opt_default(const char *opt, const char *arg,
34 | return AVERROR_OPTION_NOT_FOUND;
35 | }
36 |
37 | -int get_plane_sizes(int size[4], int required_plane[4], enum AVPixelFormat pix_fmt,
38 | +int __attribute__ ((visibility ("hidden"))) get_plane_sizes(int size[4], int required_plane[4], enum AVPixelFormat pix_fmt,
39 | int height, const int linesizes[4])
40 | {
41 | int i, total_size;
42 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/libzbar/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from os.path import join
3 | import sh
4 |
5 |
6 | class LibZBarRecipe(Recipe):
7 |
8 | version = '0.10'
9 |
10 | url = 'https://github.com/ZBar/ZBar/archive/{version}.zip'
11 |
12 | depends = ['hostpython3']
13 |
14 | library = 'zbar/.libs/libzbar.a'
15 |
16 | include_per_arch = True
17 | include_dir = [
18 | ("include", "")
19 | ]
20 |
21 | def prebuild_arch(self, arch):
22 | if self.has_marker("patched"):
23 | return
24 | self.apply_patch("werror.patch")
25 | self.set_marker("patched")
26 |
27 | def build_arch(self, arch):
28 | super(LibZBarRecipe, self).build_arch(arch)
29 | build_env = arch.get_env()
30 | build_env["CFLAGS"] = " ".join([
31 | "-I{}".format(join(self.ctx.dist_dir, "build", "libiconv", arch.arch)) +
32 | " -arch {}".format(arch.arch), build_env['CFLAGS']
33 | ])
34 | shprint(sh.Command('autoreconf'), '-vif')
35 | shprint(
36 | sh.Command('./configure'),
37 | "CC={}".format(build_env["CC"]),
38 | "LD={}".format(build_env["LD"]),
39 | "CFLAGS={}".format(build_env["CFLAGS"]),
40 | "LDFLAGS={}".format(build_env["LDFLAGS"]),
41 | "--host={}".format(arch.triple),
42 | '--target={}'.format(arch.triple),
43 | # Python bindings are compiled in a separated recipe
44 | '--with-python=no',
45 | '--with-gtk=no',
46 | '--with-qt=no',
47 | '--with-x=no',
48 | '--with-jpeg=no',
49 | '--with-imagemagick=no',
50 | '--enable-pthread=no',
51 | '--enable-video=no',
52 | "--disable-shared",
53 | _env=build_env)
54 | shprint(sh.make, 'clean')
55 | shprint(sh.make, _env=build_env)
56 |
57 |
58 | recipe = LibZBarRecipe()
59 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/kivy/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe
2 | from os.path import join
3 | import logging
4 | import shutil
5 |
6 | logger = logging.getLogger(__name__)
7 |
8 |
9 | class KivyRecipe(CythonRecipe):
10 | version = "0e77e2ab94e54ebaf1f232f5dd66d4d103e08fbb" # 2.1.0 + camera enhancements
11 | url = "https://github.com/kivy/kivy/archive/{version}.zip"
12 | library = "libkivy.a"
13 | depends = ["sdl2", "sdl2_image", "sdl2_mixer", "sdl2_ttf", "ios",
14 | "pyobjus", "python"]
15 | python_depends = ["certifi"]
16 | pbx_frameworks = ["OpenGLES", "Accelerate", "CoreMedia", "CoreVideo"]
17 | pre_build_ext = True
18 |
19 | def get_recipe_env(self, arch):
20 | env = super().get_recipe_env(arch)
21 | env["KIVY_SDL2_PATH"] = ":".join([
22 | join(self.ctx.dist_dir, "include", "common", "sdl2"),
23 | join(self.ctx.dist_dir, "include", "common", "sdl2_image"),
24 | join(self.ctx.dist_dir, "include", "common", "sdl2_ttf"),
25 | join(self.ctx.dist_dir, "include", "common", "sdl2_mixer")])
26 | return env
27 |
28 | def build_arch(self, arch):
29 | self._patch_setup()
30 | super().build_arch(arch)
31 |
32 | def _patch_setup(self):
33 | # patch setup to remove some functionnalities
34 | pyconfig = join(self.build_dir, "setup.py")
35 |
36 | def _remove_line(lines, pattern):
37 | for line in lines[:]:
38 | if pattern in line:
39 | lines.remove(line)
40 | with open(pyconfig) as fd:
41 | lines = fd.readlines()
42 | _remove_line(lines, "flags['libraries'] = ['GLESv2']")
43 | with open(pyconfig, "w") as fd:
44 | fd.writelines(lines)
45 |
46 | def reduce_python_package(self):
47 | dest_dir = join(self.ctx.site_packages_dir, "kivy")
48 | shutil.rmtree(join(dest_dir, "tools"))
49 | shutil.rmtree(join(dest_dir, "tests"))
50 |
51 |
52 | recipe = KivyRecipe()
53 |
--------------------------------------------------------------------------------
/kivy_ios/tools/liblink:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 | import subprocess
5 | from os import environ
6 |
7 | libs = [ ]
8 | objects = [ ]
9 | output = None
10 |
11 |
12 | i = 1
13 | while i < len(sys.argv):
14 | opt = sys.argv[i]
15 | i += 1
16 |
17 | if opt == "-o":
18 | output = sys.argv[i]
19 | i += 1
20 | continue
21 |
22 | if opt.startswith("-l") or opt.startswith("-L"):
23 | libs.append(opt)
24 | continue
25 |
26 | if opt in ("-r", "-pipe", "-no-cpp-precomp"):
27 | continue
28 |
29 | if opt in ("--sysroot", "-isysroot", "-framework", "-undefined",
30 | "-macosx_version_min"):
31 | i += 1
32 | continue
33 |
34 | if opt.startswith("-I"):
35 | continue
36 |
37 | if opt.startswith("-m"):
38 | continue
39 |
40 | if opt.startswith("-f"):
41 | continue
42 |
43 | if opt.startswith("-O"):
44 | continue
45 |
46 | if opt.startswith("-g"):
47 | continue
48 |
49 | if opt.startswith("-D"):
50 | continue
51 |
52 | if opt.startswith('-arch'):
53 | continue
54 |
55 | if opt.startswith("-Wl,"):
56 | continue
57 |
58 | if opt.startswith("-W"):
59 | continue
60 |
61 | if opt.startswith("-"):
62 | print(sys.argv)
63 | print("Unknown option: ", opt)
64 | sys.exit(1)
65 |
66 | if not opt.endswith('.o'):
67 | continue
68 |
69 | objects.append(opt)
70 |
71 |
72 | f = open(output, "w")
73 | f.close()
74 |
75 | f = open(output + ".libs", "w")
76 | f.write(" ".join(libs))
77 | f.close()
78 |
79 | print('Liblink redirect linking with', objects)
80 | ld = environ.get('ARM_LD')
81 | arch = environ.get('ARCH', 'arm64')
82 | min_version_flag = environ.get('KIVY_MIN_VERSION_FLAG', '-ios_version_min')
83 | call = [ld, '-r', '-o', output + '.o', min_version_flag, '9.0', '-arch', arch]
84 | if min_version_flag == "-ios_version_min":
85 | call += ["-bitcode_bundle"]
86 | call += objects
87 | print("Linking: {}".format(" ".join(call)))
88 | subprocess.call(call)
89 |
--------------------------------------------------------------------------------
/tests/test_libs/main.py:
--------------------------------------------------------------------------------
1 | import traceback
2 | from time import sleep
3 |
4 | FAILED = []
5 | SUCCESS = []
6 |
7 |
8 | def test_kivy():
9 | import kivy
10 | import kivy.event
11 | import kivy.core.window
12 | import kivy.uix.widget # noqa: F401
13 |
14 |
15 | def test_audiostream():
16 | from audiostream import get_output
17 | from audiostream.sources.wave import SineSource
18 | stream = get_output(channels=2, rate=22050, buffersize=128)
19 | source = SineSource(stream, 220)
20 | source.start()
21 | sleep(.5)
22 | source.stop()
23 |
24 |
25 | def test_numpy():
26 | print("NPY: test import numpy")
27 | import numpy as np
28 | print("NPY: basic calculation")
29 | print(np.ones(10) * np.sin(2))
30 | print("NPY: access to random module")
31 | print(np.random.mtrand.beta(1, 2))
32 | print("NPY: access to fft")
33 | print(np.fft.fft(np.exp(2j * np.pi * np.arange(8) / 8)))
34 | print("NPY: access to linalg")
35 | from numpy import linalg as LA
36 | a = np.array([[1., 2.], [3., 4.]])
37 | ainv = LA.inv(a)
38 | print(np.allclose(np.dot(a, ainv), np.eye(2)))
39 |
40 |
41 | def test_curly():
42 | import curly # noqa: F401
43 |
44 |
45 | def run_test(f, name):
46 | # run a single test
47 | print("=> Run", name)
48 | try:
49 | f()
50 | SUCCESS.append(name)
51 | except Exception:
52 | print("!! Failed", name)
53 | traceback.print_exc()
54 | FAILED.append(name)
55 |
56 |
57 | def run():
58 | # auto find test and run
59 | for key in globals():
60 | if not key.startswith("test_"):
61 | continue
62 | print("FOUND", key)
63 | func = globals()[key]
64 | run_test(func, key)
65 | # print summary
66 | print("")
67 | print("=== [ LIBS SUMMARY ] ===")
68 | print("")
69 | print("{}/{} tests".format(
70 | len(SUCCESS),
71 | len(SUCCESS) + len(FAILED)
72 | ))
73 | print("Success: ", ", ".join(SUCCESS))
74 | print("Failed: ", ", ".join(FAILED))
75 |
76 |
77 | if __name__ == "__main__":
78 | run()
79 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/pillow/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe, shprint
2 | from os.path import join
3 | import sh
4 | import os
5 |
6 |
7 | class PillowRecipe(CythonRecipe):
8 | version = "8.2.0"
9 | url = "https://pypi.python.org/packages/source/P/Pillow/Pillow-{version}.tar.gz"
10 | library = "libpillow.a"
11 | depends = [
12 | "hostpython3",
13 | "freetype",
14 | "libjpeg",
15 | "python3",
16 | "ios",
17 | ]
18 | python_depends = ["setuptools"]
19 | pbx_libraries = ["libz", "libbz2"]
20 | include_per_arch = True
21 | cythonize = False
22 |
23 | def prebuild_arch(self, arch):
24 | if self.has_marker("patched"):
25 | return
26 | self.apply_patch("bypass-find-library.patch")
27 | self.set_marker("patched")
28 |
29 | def get_recipe_env(self, arch):
30 | env = super().get_recipe_env(arch)
31 | env["C_INCLUDE_PATH"] = join(arch.sysroot, "usr", "include")
32 | env["LIBRARY_PATH"] = join(arch.sysroot, "usr", "lib")
33 | env["CFLAGS"] += " ".join(
34 | [
35 | " -I{}".format(join(self.ctx.dist_dir, "include", arch.arch, "freetype"))
36 | + " -I{}".format(
37 | join(self.ctx.dist_dir, "include", arch.arch, "libjpeg")
38 | )
39 | + " -arch {}".format(arch.arch)
40 | ]
41 | )
42 | env["PATH"] = os.environ["PATH"]
43 | env[
44 | "PKG_CONFIG"
45 | ] = "ios-pkg-config" # ios-pkg-config does not exists, is needed to disable the pkg-config usage.
46 | return env
47 |
48 | def build_arch(self, arch):
49 | build_env = self.get_recipe_env(arch)
50 | hostpython3 = sh.Command(self.ctx.hostpython)
51 | shprint(
52 | hostpython3,
53 | "setup.py",
54 | "build_ext",
55 | "--disable-tiff",
56 | "--disable-webp",
57 | "--disable-jpeg2000",
58 | "--disable-lcms",
59 | "--disable-platform-guessing",
60 | "-g",
61 | _env=build_env,
62 | )
63 | self.biglink()
64 |
65 |
66 | recipe = PillowRecipe()
67 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/libffi/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | import sh
3 | from os.path import exists, join
4 |
5 |
6 | class LibffiRecipe(Recipe):
7 | version = "3.4.2"
8 | url = "https://github.com/libffi/libffi/releases/download/v{version}/libffi-{version}.tar.gz"
9 | library = "build/Release-{arch.sdk}/libffi.a"
10 | include_per_arch = True
11 | include_dir = "build_{arch.sdk}-{arch_arg}/include"
12 | include_name = "ffi"
13 | archs = ["arm64", "x86_64"]
14 |
15 | def prebuild_arch(self, arch):
16 | if self.has_marker("patched"):
17 | return
18 | self.apply_patch("enable-tramp-build.patch")
19 | shprint(sh.sed,
20 | "-i.bak",
21 | "s/-miphoneos-version-min=7.0/-miphoneos-version-min=9.0/g",
22 | "generate-darwin-source-and-headers.py")
23 | shprint(sh.sed,
24 | "-i.bak",
25 | "s/build_target(ios_simulator_platform, platform_headers)/print('Skipping i386')/g",
26 | "generate-darwin-source-and-headers.py")
27 | self.set_marker("patched")
28 |
29 | def build_arch(self, arch):
30 | if exists("generate-darwin-source-and-headers.py"):
31 | shprint(
32 | sh.mv,
33 | "generate-darwin-source-and-headers.py",
34 | "_generate-darwin-source-and-headers.py")
35 | shprint(sh.touch, "generate-darwin-source-and-headers.py")
36 | python3 = sh.Command("python3")
37 | shprint(python3, "_generate-darwin-source-and-headers.py", "--only-ios")
38 | shprint(sh.xcodebuild, self.ctx.concurrent_xcodebuild,
39 | "ONLY_ACTIVE_ARCH=NO",
40 | "ARCHS={}".format("x86_64 arm64" if arch.arch == "x86_64" else arch.arch),
41 | "BITCODE_GENERATION_MODE=bitcode",
42 | "-sdk", arch.sdk,
43 | "-project", "libffi.xcodeproj",
44 | "-target", "libffi-iOS",
45 | "-configuration", "Release")
46 |
47 | def install_include(self):
48 | super().install_include()
49 |
50 | include_name = self.include_name or self.name
51 | src_dir = join(self.ctx.include_dir, "arm64", include_name)
52 | dest_dir = join(self.ctx.include_dir, "ios-arm64-simulator")
53 | shprint(sh.rm, "-rf", join(dest_dir, include_name))
54 | shprint(sh.ln, "-s", src_dir, dest_dir)
55 |
56 | recipe = LibffiRecipe()
57 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/numpy/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import CythonRecipe
2 | from os.path import join
3 | import sh
4 | import shutil
5 |
6 |
7 | class NumpyRecipe(CythonRecipe):
8 | version = "1.24.2"
9 | url = "https://pypi.python.org/packages/source/n/numpy/numpy-{version}.tar.gz"
10 | library = "libnumpy.a"
11 | libraries = ["libnpymath.a", "libnpyrandom.a"]
12 | include_dir = "numpy/core/include"
13 | depends = ["python"]
14 | hostpython_prerequisites = ["Cython"]
15 | cythonize = False
16 |
17 | def prebuild_arch(self, arch):
18 | if self.has_marker("patched"):
19 | return
20 | self.apply_patch("skip-math-test.patch")
21 | self.apply_patch("duplicated_symbols.patch")
22 | self.set_marker("patched")
23 |
24 | def get_recipe_env(self, arch):
25 | env = super().get_recipe_env(arch)
26 | # CC must have the CFLAGS with arm arch, because numpy tries first to
27 | # compile and execute an empty C to see if the compiler works. This is
28 | # obviously not working when crosscompiling
29 | env["CC"] = "{} {}".format(env["CC"], env["CFLAGS"])
30 | # Disable Accelerate.framework by disabling the optimized BLAS and LAPACK libraries cause it's now unsupported
31 | env["NPY_BLAS_ORDER"] = ""
32 | env["NPY_LAPACK_ORDER"] = ""
33 | return env
34 |
35 | def build_arch(self, arch):
36 | super().build_arch(arch)
37 | sh.cp(sh.glob(join(self.build_dir, "build", "temp.*", "libnpy*.a")),
38 | self.build_dir)
39 |
40 | def reduce_python_package(self):
41 | dest_dir = join(self.ctx.site_packages_dir, "numpy")
42 | shutil.rmtree(join(dest_dir, "core", "include"))
43 | shutil.rmtree(join(dest_dir, "core", "tests"))
44 | shutil.rmtree(join(dest_dir, "distutils"))
45 | shutil.rmtree(join(dest_dir, "doc"))
46 | shutil.rmtree(join(dest_dir, "f2py", "tests"))
47 | shutil.rmtree(join(dest_dir, "fft", "tests"))
48 | shutil.rmtree(join(dest_dir, "lib", "tests"))
49 | shutil.rmtree(join(dest_dir, "linalg", "tests"))
50 | shutil.rmtree(join(dest_dir, "ma", "tests"))
51 | shutil.rmtree(join(dest_dir, "matrixlib", "tests"))
52 | shutil.rmtree(join(dest_dir, "polynomial", "tests"))
53 | shutil.rmtree(join(dest_dir, "random", "tests"))
54 | shutil.rmtree(join(dest_dir, "tests"))
55 | sh.rm(join(dest_dir, "core", "lib", "libnpymath.a"))
56 | sh.rm(join(dest_dir, "random", "lib", "libnpyrandom.a"))
57 |
58 |
59 | recipe = NumpyRecipe()
60 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/Storyboards/Launch Screen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/python3/configure.patch:
--------------------------------------------------------------------------------
1 | diff -Naur Python-3.10.10.orig/configure Python-3.10.10/configure
2 | --- Python-3.10.10.orig/configure 2023-02-12 15:08:28
3 | +++ Python-3.10.10/configure 2023-02-12 15:10:45
4 | @@ -3344,6 +3344,15 @@
5 | *-*-cygwin*)
6 | ac_sys_system=Cygwin
7 | ;;
8 | + *-apple-ios)
9 | + ac_sys_system=iOS
10 | + ;;
11 | + *-apple-tvos)
12 | + ac_sys_system=tvOS
13 | + ;;
14 | + *-apple-watchos)
15 | + ac_sys_system=watchOS
16 | + ;;
17 | *-*-vxworks*)
18 | ac_sys_system=VxWorks
19 | ;;
20 | @@ -3391,6 +3400,15 @@
21 | _host_cpu=$host_cpu
22 | esac
23 | ;;
24 | + *-apple-*)
25 | + case "$host_cpu" in
26 | + arm*)
27 | + _host_cpu=arm
28 | + ;;
29 | + *)
30 | + _host_cpu=$host_cpu
31 | + esac
32 | + ;;
33 | *-*-cygwin*)
34 | _host_cpu=
35 | ;;
36 | @@ -3469,6 +3487,13 @@
37 | define_xopen_source=no;;
38 | Darwin/[12][0-9].*)
39 | define_xopen_source=no;;
40 | + # On iOS, defining _POSIX_C_SOURCE also disables platform specific features.
41 | + iOS/*)
42 | + define_xopen_source=no;;
43 | + tvOS/*)
44 | + define_xopen_source=no;;
45 | + watchOS/*)
46 | + define_xopen_source=no;;
47 | # On QNX 6.3.2, defining _XOPEN_SOURCE prevents netdb.h from
48 | # defining NI_NUMERICHOST.
49 | QNX/6.3.2)
50 | @@ -5389,6 +5414,12 @@
51 | case $ac_sys_system in #(
52 | Darwin*) :
53 | MULTIARCH="" ;; #(
54 | + iOS*) :
55 | + MULTIARCH="" ;; #(
56 | + tvOS*) :
57 | + MULTIARCH="" ;; #(
58 | + watchOS*) :
59 | + MULTIARCH="" ;; #(
60 | FreeBSD*) :
61 | MULTIARCH="" ;; #(
62 | *) :
63 | @@ -6249,11 +6280,17 @@
64 | fi
65 |
66 | if test "$cross_compiling" = yes; then
67 | - case "$READELF" in
68 | - readelf|:)
69 | - as_fn_error $? "readelf for the host is required for cross builds" "$LINENO" 5
70 | - ;;
71 | - esac
72 | + case "$host" in
73 | + *-apple-*os)
74 | + # readelf not required for iOS cross builds.
75 | + ;;
76 | + *)
77 | + case "$READELF" in
78 | + readelf|:)
79 | + as_fn_error $? "readelf for the host is required for cross builds" "$LINENO" 5
80 | + ;;
81 | + esac
82 | + esac
83 | fi
84 |
85 |
86 | @@ -7051,7 +7088,6 @@
87 | # tweak BASECFLAGS based on compiler and platform
88 | case $GCC in
89 | yes)
90 | - CFLAGS_NODIST="$CFLAGS_NODIST -std=c99"
91 |
92 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wextra" >&5
93 | $as_echo_n "checking for -Wextra... " >&6; }
94 | @@ -11912,6 +11948,10 @@
95 | then
96 | case $ac_sys_system/$ac_sys_release in
97 | hp*|HP*) DYNLOADFILE="dynload_hpux.o";;
98 | + # Dynamic loading on iOS
99 | + iOS/*) DYNLOADFILE="dynload_shlib.o";;
100 | + tvOS/*) DYNLOADFILE="dynload_shlib.o";;
101 | + watchOS/*) DYNLOADFILE="dynload_shlib.o";;
102 | *)
103 | # use dynload_shlib.c and dlopen() if we have it; otherwise stub
104 | # out any dynamic loading
105 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/zbarlight/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 | from kivy_ios.toolchain import Recipe
3 | from os.path import join
4 | import sh
5 | import fnmatch
6 | from distutils.dir_util import copy_tree
7 |
8 |
9 | class ZbarLightRecipe(Recipe):
10 | version = '1.2'
11 | url = 'https://github.com/Polyconseil/zbarlight/archive/{version}.tar.gz'
12 | library = "zbarlight.a"
13 | depends = ['hostpython3', 'python3', 'libzbar']
14 | pbx_libraries = ["libz", "libbz2", 'libc++', 'libsqlite3', 'CoreMotion']
15 | include_per_arch = True
16 |
17 | def get_zbar_env(self, arch):
18 | build_env = arch.get_env()
19 | dest_dir = join(self.ctx.dist_dir, "root", "python")
20 | build_env["IOSROOT"] = self.ctx.root_dir
21 | build_env["IOSSDKROOT"] = arch.sysroot
22 | build_env["LDSHARED"] = join(self.ctx.root_dir, "tools", "liblink")
23 | build_env["ARM_LD"] = build_env["LD"]
24 | build_env["ARCH"] = arch.arch
25 | build_env["C_INCLUDE_PATH"] = join(arch.sysroot, "usr", "include")
26 | build_env["LIBRARY_PATH"] = join(arch.sysroot, "usr", "lib")
27 | build_env['PYTHONPATH'] = join(dest_dir, 'lib', 'python3.7', 'site-packages')
28 | build_env["CFLAGS"] = " ".join([
29 | " -I{}".format(join(self.ctx.dist_dir, "include", arch.arch, "libzbar", 'zbar')) +
30 | " -arch {}".format(arch.arch)
31 | ])
32 | build_env['LDFLAGS'] += " -lios -lpython -lzbar"
33 | return build_env
34 |
35 | def build_arch(self, arch):
36 | build_env = self.get_zbar_env(arch)
37 | hostpython = sh.Command(self.ctx.hostpython)
38 | shprint(hostpython, "setup.py", "build", # noqa: F821
39 | _env=build_env)
40 | self.apply_patch("zbarlight_1_2.patch") # Issue getting the version, hard coding for now
41 | self.biglink()
42 |
43 | def install(self):
44 | arch = list(self.filtered_archs)[0]
45 | build_dir = join(self.get_build_dir(arch.arch), 'build',
46 | 'lib.macosx-10.13-x86_64-2.7', 'zbarlight')
47 | dist_dir = join(self.ctx.dist_dir, 'root', 'python3', 'lib',
48 | 'python3.7', 'site-packages', 'zbarlight')
49 | # Patch before Copying
50 | # self.apply_patch("zbarlight_1_2.patch")#Issue getting the version, hard coding for now
51 | copy_tree(build_dir, dist_dir)
52 | os.remove(join(dist_dir, '_zbarlight.c'))
53 |
54 | def _patch__init__(self):
55 | init = join(self.ctx.dist_dir, 'root', 'python3', 'lib', 'python3.7',
56 | 'site-packages', 'zbarlight', "__init__.py")
57 | shprint( # noqa: F821
58 | sh.sed, "-i.bak",
59 | "s/__version__ = pkg_resources.get_distribution('zbarlight').version'"
60 | "/__version__ = '{version}'/g",
61 | init)
62 |
63 | def biglink(self):
64 | dirs = []
65 | for root, dirnames, filenames in os.walk(self.build_dir):
66 | if fnmatch.filter(filenames, "*.so.libs"):
67 | dirs.append(root)
68 | cmd = sh.Command(join(self.ctx.root_dir, "tools", "biglink"))
69 | shprint(cmd, join(self.build_dir, "zbarlight.a"), *dirs) # noqa: F821
70 |
71 |
72 | recipe = ZbarLightRecipe()
73 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/python3/ModulesSetup:
--------------------------------------------------------------------------------
1 | #####################################################################
2 | # Static compilation instructions for all binary modules.
3 | #####################################################################
4 |
5 | *static*
6 | _asyncio _asynciomodule.c
7 | _bisect _bisectmodule.c
8 | _blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c
9 | _sqlite3 _sqlite/cache.c \
10 | _sqlite/connection.c \
11 | _sqlite/cursor.c \
12 | _sqlite/microprotocols.c \
13 | _sqlite/module.c \
14 | _sqlite/prepare_protocol.c \
15 | _sqlite/row.c \
16 | _sqlite/statement.c \
17 | _sqlite/util.c -DSQLITE_OMIT_LOAD_EXTENSION
18 | _bz2 _bz2module.c -I$(srcdir)/../bzip2/include -L$(srcdir)/../Support/BZip2 -lbz2
19 | _codecs_cn cjkcodecs/_codecs_cn.c
20 | _codecs_hk cjkcodecs/_codecs_hk.c
21 | _codecs_iso2022 cjkcodecs/_codecs_iso2022.c
22 | _codecs_jp cjkcodecs/_codecs_jp.c
23 | _codecs_kr cjkcodecs/_codecs_kr.c
24 | _codecs_tw cjkcodecs/_codecs_tw.c
25 | _contextvars _contextvarsmodule.c
26 | _crypt _cryptmodule.c
27 | _csv _csv.c
28 | _datetime _datetimemodule.c
29 | _elementtree _elementtree.c \
30 | -I$(srcdir)/Modules/expat
31 | -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI
32 | _hashlib _hashopenssl.c -lssl -DUSE_SSL
33 | _heapq _heapqmodule.c
34 | _json _json.c
35 | _lsprof _lsprof.o rotatingtree.c
36 | # _lzma _lzmamodule.c -I$(srcdir)/../xz/include -L$(srcdir)/../Support/XZ -llzma
37 | _md5 md5module.c
38 | _multibytecodec cjkcodecs/multibytecodec.c
39 | # _multiprocessing _multiprocessing/multiprocessing.c _multiprocessing/semaphore.c
40 | _opcode _opcode.c
41 | _queue _queuemodule.c
42 | _pickle _pickle.c
43 | # _posixsubprocess _posixsubprocess.c
44 | _random _randommodule.c
45 | _sha1 sha1module.c
46 | _sha3 _sha3/sha3module.c
47 | _sha256 sha256module.c
48 | _sha512 sha512module.c
49 | _socket socketmodule.c
50 | _ssl _ssl.c -lssl -DUSE_SSL
51 | _struct _struct.c
52 | array arraymodule.c
53 | audioop audioop.c
54 | binascii binascii.c
55 | cmath cmathmodule.c _math.c
56 | fcntl fcntlmodule.c
57 | grp grpmodule.c
58 | math mathmodule.c
59 | mmap mmapmodule.c
60 | pyexpat expat/xmlparse.c \
61 | expat/xmlrole.c \
62 | expat/xmltok.c \
63 | pyexpat.c \
64 | -I$(srcdir)/Modules/expat \
65 | -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI -DXML_DEV_URANDOM
66 | resource resource.c
67 | select selectmodule.c
68 | syslog syslogmodule.c
69 | termios termios.c
70 | unicodedata unicodedata.c
71 | zlib zlibmodule.c -I$(prefix)/include -lz
72 |
73 | #####################################################################
74 | # Testing modules
75 | #####################################################################
76 | _ctypes_test _ctypes/_ctypes_test.c
77 | _testbuffer _testbuffer.c
78 | _testinternalcapi _testinternalcapi.c
79 | _testimportmultiple _testimportmultiple.c
80 |
81 | #####################################################################
82 | # Modules that require additional frameworks
83 | #####################################################################
84 | #_curses _cursesmodule.c -lcurses -ltermcap
85 | #_curses_panel _curses_panel.c -lpanel -lncurses
86 | #_dbm _dbmmodule.c
87 | #_gdbm _gdbmmodule.c -I/usr/local/include -L/usr/local/lib -lgdbm
88 | #_tkinter _tkinter.c tkappinit.c -DWITH_APPINIT -I... -L...
89 | #nis nismodule.c -lnsl
90 | #ossaudiodev
91 | #readline readline.c -lreadline -ltermcap
92 | #spwd spwdmodule.c
93 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/numpy/skip-math-test.patch:
--------------------------------------------------------------------------------
1 | diff -Naur numpy-1.24.2.orig/numpy/core/setup.py numpy-1.24.2/numpy/core/setup.py
2 | --- numpy-1.24.2.orig/numpy/core/setup.py 2023-03-11 19:49:17
3 | +++ numpy-1.24.2/numpy/core/setup.py 2023-03-11 19:51:42
4 | @@ -429,27 +429,7 @@
5 |
6 | def check_mathlib(config_cmd):
7 | # Testing the C math library
8 | - mathlibs = []
9 | - mathlibs_choices = [[], ["m"], ["cpml"]]
10 | - mathlib = os.environ.get("MATHLIB")
11 | - if mathlib:
12 | - mathlibs_choices.insert(0, mathlib.split(","))
13 | - for libs in mathlibs_choices:
14 | - if config_cmd.check_func(
15 | - "log",
16 | - libraries=libs,
17 | - call_args="0",
18 | - decl="double log(double);",
19 | - call=True
20 | - ):
21 | - mathlibs = libs
22 | - break
23 | - else:
24 | - raise RuntimeError(
25 | - "math library missing; rerun setup.py after setting the "
26 | - "MATHLIB env variable"
27 | - )
28 | - return mathlibs
29 | + return ["m"]
30 |
31 |
32 | def visibility_define(config):
33 | @@ -716,49 +696,7 @@
34 | subst_dict = dict([("sep", os.path.sep), ("pkgname", "numpy.core")])
35 |
36 | def get_mathlib_info(*args):
37 | - # Another ugly hack: the mathlib info is known once build_src is run,
38 | - # but we cannot use add_installed_pkg_config here either, so we only
39 | - # update the substitution dictionary during npymath build
40 | - config_cmd = config.get_config_cmd()
41 | - # Check that the toolchain works, to fail early if it doesn't
42 | - # (avoid late errors with MATHLIB which are confusing if the
43 | - # compiler does not work).
44 | - for lang, test_code, note in (
45 | - ('c', 'int main(void) { return 0;}', ''),
46 | - ('c++', (
47 | - 'int main(void)'
48 | - '{ auto x = 0.0; return static_cast(x); }'
49 | - ), (
50 | - 'note: A compiler with support for C++11 language '
51 | - 'features is required.'
52 | - )
53 | - ),
54 | - ):
55 | - is_cpp = lang == 'c++'
56 | - if is_cpp:
57 | - # this a workaround to get rid of invalid c++ flags
58 | - # without doing big changes to config.
59 | - # c tested first, compiler should be here
60 | - bk_c = config_cmd.compiler
61 | - config_cmd.compiler = bk_c.cxx_compiler()
62 | -
63 | - # Check that Linux compiler actually support the default flags
64 | - if hasattr(config_cmd.compiler, 'compiler'):
65 | - config_cmd.compiler.compiler.extend(NPY_CXX_FLAGS)
66 | - config_cmd.compiler.compiler_so.extend(NPY_CXX_FLAGS)
67 | -
68 | - st = config_cmd.try_link(test_code, lang=lang)
69 | - if not st:
70 | - # rerun the failing command in verbose mode
71 | - config_cmd.compiler.verbose = True
72 | - config_cmd.try_link(test_code, lang=lang)
73 | - raise RuntimeError(
74 | - f"Broken toolchain: cannot link a simple {lang.upper()} "
75 | - f"program. {note}"
76 | - )
77 | - if is_cpp:
78 | - config_cmd.compiler = bk_c
79 | - mlibs = check_mathlib(config_cmd)
80 | + mlibs = check_mathlib(None)
81 |
82 | posix_mlib = ' '.join(['-l%s' % l for l in mlibs])
83 | msvc_mlib = ' '.join(['%s.lib' % l for l in mlibs])
--------------------------------------------------------------------------------
/kivy_ios/recipes/ffmpeg/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from os.path import join
3 | import sh
4 |
5 |
6 | class FFMpegRecipe(Recipe):
7 | version = "n4.4.2"
8 | url = "https://github.com/FFmpeg/FFmpeg/archive/{version}.zip"
9 | include_per_arch = True
10 | include_dir = "dist/include"
11 | optional_depends = ["openssl"]
12 | libraries = [
13 | "libavcodec/libavcodec.a",
14 | "libavdevice/libavdevice.a",
15 | "libavfilter/libavfilter.a",
16 | "libavformat/libavformat.a",
17 | "libavresample/libavresample.a",
18 | "libavutil/libavutil.a",
19 | "libswresample/libswresample.a",
20 | "libswscale/libswscale.a",
21 | ]
22 | pbx_frameworks = ["VideoToolbox"]
23 |
24 | def build_arch(self, arch):
25 | options = [
26 | "--disable-everything",
27 | "--enable-parsers",
28 | "--enable-decoders",
29 | "--enable-demuxers",
30 | "--enable-filter=aresample,resample,crop,scale",
31 | "--enable-protocol=file,http,rtmp",
32 | "--enable-pic",
33 | "--enable-small",
34 | "--enable-hwaccels",
35 | "--enable-static",
36 | "--disable-shared",
37 | # libpostproc is GPL: https://ffmpeg.org/pipermail/ffmpeg-user/2012-February/005162.html
38 | "--enable-gpl",
39 | # disable some unused algo
40 | # note: "golomb" are the one used in our video test, so don't use --disable-golomb
41 | # note: and for aac decoding: "rdft", "mdct", and "fft" are needed
42 | "--disable-dxva2",
43 | "--disable-vdpau",
44 | "--disable-vaapi",
45 | "--disable-dct",
46 | # disable binaries / doc
47 | "--enable-cross-compile",
48 | "--disable-debug",
49 | "--disable-programs",
50 | "--disable-doc",
51 | "--enable-pic",
52 | "--enable-avresample"]
53 |
54 | if "openssl.build_all" in self.ctx.state:
55 | options += [
56 | "--enable-openssl",
57 | "--enable-nonfree",
58 | "--enable-protocol=https,tls_openssl"]
59 |
60 | build_env = arch.get_env()
61 | build_env["VERBOSE"] = "1"
62 | configure = sh.Command(join(self.build_dir, "configure"))
63 | shprint(configure,
64 | "--target-os=darwin",
65 | "--arch={}".format(arch.arch),
66 | "--cc={}".format(build_env["CC"]),
67 | "--prefix={}/dist".format(self.build_dir),
68 | "--extra-cflags={}".format(build_env["CFLAGS"]),
69 | "--extra-cxxflags={}".format(build_env["CFLAGS"]),
70 | "--extra-ldflags={}".format(build_env["LDFLAGS"]),
71 | "--disable-x86asm",
72 | *options,
73 | _env=build_env)
74 | """
75 | shprint(sh.sed,
76 | "-i.bak",
77 | "s/HAVE_CLOSESOCKET=yes//g",
78 | "config.mak")
79 | shprint(sh.sed,
80 | "-i.bak",
81 | "s/#define HAVE_CLOSESOCKET 1//g",
82 | "config.h")
83 | if exists("config.asm"):
84 | shprint(sh.sed,
85 | "-i.bak",
86 | "s/%define HAVE_CLOSESOCKET 1//g",
87 | "config.asm")
88 | """
89 | shprint(sh.make, "clean", _env=build_env)
90 | shprint(sh.make, self.ctx.concurrent_make, _env=build_env)
91 | shprint(sh.make, "install")
92 |
93 |
94 | recipe = FFMpegRecipe()
95 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ios/src/ios_mail.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Email support
3 | *
4 | * Very basic, could be upgraded to support HTML, and multiple attachment. No
5 | * need to let the user manipulate directly uikit API.
6 | */
7 |
8 | #import
9 | #import
10 | #import
11 | #include "ios_wrapper.h"
12 |
13 | /* guess the view controller from our SDL window.
14 | */
15 | UIViewController *get_viewcontroller(void) {
16 | UIWindow *window = [[UIApplication sharedApplication] keyWindow];
17 | if ( window == NULL ) {
18 | printf("ios_wrapper: unable to get key window from shared application\n");
19 | return NULL;
20 | }
21 | // return window.rootViewController;
22 | UIView* view = [window.subviews objectAtIndex:0];
23 | id nextResponder = [view nextResponder];
24 | if( [nextResponder isKindOfClass:[UIViewController class]] )
25 | return (UIViewController *)nextResponder;
26 | return NULL;
27 | }
28 |
29 | @interface InAppEmailViewController : UIViewController {
30 | ios_send_email_cb callback;
31 | void * userdata;
32 | }
33 |
34 | @property(nonatomic, assign) ios_send_email_cb callback;
35 | @property(nonatomic, assign) void *userdata;
36 |
37 | @end
38 |
39 | @implementation InAppEmailViewController
40 |
41 | @synthesize userdata;
42 | @synthesize callback;
43 |
44 | - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
45 | static char *statuses[] = {"unknown", "cancelled", "saved", "sent", "failed"};
46 |
47 | if ( callback != NULL ) {
48 | char *status = statuses[0];
49 | switch (result)
50 | {
51 | case MFMailComposeResultCancelled: status = statuses[1]; break;
52 | case MFMailComposeResultSaved: status = statuses[2]; break;
53 | case MFMailComposeResultSent: status = statuses[3]; break;
54 | case MFMailComposeResultFailed: status = statuses[4]; break;
55 | default: break;
56 | }
57 | callback(status, userdata);
58 | }
59 |
60 | UIViewController* viewController = [controller presentingViewController];
61 | [viewController dismissModalViewControllerAnimated:YES];
62 | }
63 |
64 | @end
65 |
66 | int ios_send_email(char *subject, char *text, char *mimetype, char *filename,
67 | char *filename_alias, ios_send_email_cb callback, void *userdata)
68 | {
69 | UIViewController* viewController = get_viewcontroller();
70 | if ( viewController == NULL ) {
71 | printf("ios_send_email: unable to get view controller.\n");
72 | return 0;
73 | }
74 |
75 | if (! [MFMailComposeViewController canSendMail]) {
76 | printf("ios_send_email: no available mail provider configured.\n");
77 | return -1;
78 | }
79 |
80 | MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
81 | InAppEmailViewController *inAppVc = [[InAppEmailViewController alloc] init];
82 | inAppVc.callback = callback;
83 | inAppVc.userdata = userdata;
84 | controller.mailComposeDelegate = inAppVc;
85 |
86 | if ( subject != NULL ) {
87 | NSString *nssubject = [NSString stringWithCString:(char *)subject encoding:NSUTF8StringEncoding];
88 | [controller setSubject:nssubject];
89 | }
90 |
91 | if ( text != NULL ) {
92 | NSString *nstext = [NSString stringWithCString:(char *)text encoding:NSUTF8StringEncoding];
93 | [controller setMessageBody:nstext isHTML:NO];
94 | }
95 |
96 | if ( mimetype != NULL && filename != NULL ) {
97 | NSString *nsmimetype = [NSString stringWithCString:(char *)mimetype encoding:NSUTF8StringEncoding];
98 | NSString *nsfilename = [NSString stringWithCString:(char *)filename encoding:NSUTF8StringEncoding];
99 | NSString *nsalias = [NSString stringWithCString:(char *)filename_alias encoding:NSUTF8StringEncoding];
100 | NSData *myData = [NSData dataWithContentsOfFile:nsfilename];
101 | [controller addAttachmentData:myData mimeType:nsmimetype fileName:nsalias];
102 | }
103 |
104 | controller.modalPresentationStyle = UIModalPresentationPageSheet;
105 | [viewController presentModalViewController:controller animated:YES];
106 | [controller release];
107 |
108 | return 1;
109 | }
--------------------------------------------------------------------------------
/kivy_ios/recipes/kivent_core/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Author: Lawrence Du
3 | E-mail: larrydu88@gmail.com
4 | """
5 |
6 | from kivy_ios.toolchain import CythonRecipe, shprint
7 | import sh
8 | from os.path import join
9 | from os import chdir
10 | import logging
11 |
12 | logger = logging.getLogger(__name__)
13 |
14 |
15 | class KiventCoreRecipe(CythonRecipe):
16 | version = 'master'
17 | url = 'https://github.com/kivy/kivent/archive/{version}.zip'
18 | name = 'kivent_core'
19 | depends = ['libffi', 'kivy'] # note: unsure if libffi is necessary here
20 | pre_build_ext = False
21 | subbuilddir = False
22 | cythonize = True
23 | pbx_frameworks = ["OpenGLES"] # note: This line may be unnecessary
24 |
25 | def get_recipe_env(self, arch):
26 | env = super(KiventCoreRecipe, self).get_recipe_env(arch)
27 | env['CYTHONPATH'] = self.get_recipe(
28 | 'kivy', self.ctx).get_build_dir(arch.arch)
29 | return env
30 |
31 | def get_build_dir(self, arch, sub=False):
32 | """
33 | Call this to get the correct build_dir, where setup.py is located which is
34 | actually under modules/core/setup.py
35 | """
36 | builddir = super(KiventCoreRecipe, self).get_build_dir(str(arch))
37 | if sub or self.subbuilddir:
38 | core_build_dir = join(builddir, 'modules', 'core')
39 | logger.info("Core build directory is located at {}".format(core_build_dir))
40 | return core_build_dir
41 | else:
42 | logger.info("Building in {}".format(builddir))
43 | return builddir
44 |
45 | def build_arch(self, arch):
46 | """
47 | Override build.arch to avoid calling setup.py here (Call it in
48 | install() instead).
49 | """
50 | self.subbuildir = True
51 | self.cythonize_build()
52 | self.biglink()
53 | self.subbuilddir = False
54 |
55 | def install(self):
56 | """
57 | This method simply builds the command line call for calling
58 | kivent_core/modules/core/setup.py
59 |
60 | This constructs the equivalent of the command
61 | "$python setup.py build_ext install"
62 | only with the environment variables altered for each different architecture
63 | The appropriate version of kivy also needs to be added to the path, and this
64 | differs for each architecture (i386, x86_64, armv7, etc)
65 |
66 | Note: This method is called by build_all() in toolchain.py
67 |
68 | """
69 | arch = list(self.filtered_archs)[0]
70 |
71 | build_dir = self.get_build_dir(arch.arch, sub=True)
72 | logger.info("Building kivent_core {} in {}".format(arch.arch, build_dir))
73 | chdir(build_dir)
74 | hostpython = sh.Command(self.ctx.hostpython)
75 |
76 | # Get the appropriate environment for this recipe (including CYTHONPATH)
77 | # build_env = arch.get_env()
78 | build_env = self.get_recipe_env(arch)
79 |
80 | dest_dir = join(self.ctx.dist_dir, "root", "python")
81 | build_env['PYTHONPATH'] = join(dest_dir, 'lib', 'python3.7', 'site-packages')
82 |
83 | # Add Architecture specific kivy path for 'import kivy' to PYTHONPATH
84 | arch_kivy_path = self.get_recipe('kivy', self.ctx).get_build_dir(arch.arch)
85 | build_env['PYTHONPATH'] = join(build_env['PYTHONPATH'], ':', arch_kivy_path)
86 |
87 | # Make sure you call kivent_core/modules/core/setup.py
88 | subdir_path = self.get_build_dir(str(arch), sub=True)
89 | setup_path = join(subdir_path, "setup.py")
90 |
91 | # Print out directories for sanity check
92 | logger.info("ENVS", build_env)
93 | logger.info("ROOT", self.ctx.root_dir)
94 | logger.info("BUILD", self.ctx.build_dir)
95 | logger.info("INCLUDE", self.ctx.include_dir)
96 | logger.info("DISTDIR", self.ctx.dist_dir)
97 | logger.info("ARCH KIVY LOC", self.get_recipe('kivy', self.ctx).get_build_dir(arch.arch))
98 |
99 | shprint(hostpython, setup_path, "build_ext", "install", _env=build_env)
100 |
101 |
102 | recipe = KiventCoreRecipe()
103 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/hostpython3/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import HostRecipe, shprint
2 | from os.path import join
3 | import os
4 | import sh
5 | import shutil
6 | import logging
7 | from kivy_ios.context_managers import cd
8 |
9 |
10 | logger = logging.getLogger(__name__)
11 |
12 |
13 | class Hostpython3Recipe(HostRecipe):
14 | version = "3.10.10"
15 | url = "https://www.python.org/ftp/python/{version}/Python-{version}.tgz"
16 | depends = ["hostopenssl"]
17 | optional_depends = []
18 | build_subdir = 'native-build'
19 |
20 | def init_with_ctx(self, ctx):
21 | super().init_with_ctx(ctx)
22 | self.set_hostpython(self, "3.10")
23 | self.ctx.so_suffix = ".cpython-310m-darwin.so"
24 | self.ctx.hostpython = join(self.ctx.dist_dir, "hostpython3", "bin", "python")
25 | self.ctx.hostpgen = join(self.ctx.dist_dir, "hostpython3", "bin", "pgen")
26 | logger.info("Global: hostpython located at {}".format(self.ctx.hostpython))
27 | logger.info("Global: hostpgen located at {}".format(self.ctx.hostpgen))
28 |
29 | def get_build_subdir(self, arch):
30 | return join(self.get_build_dir(arch), self.build_subdir)
31 |
32 | def prebuild_arch(self, arch):
33 | if self.has_marker("patched"):
34 | return
35 | self.apply_patch("disable_sysconfig_cflags.patch")
36 | self.copy_file("ModulesSetup", "Modules/Setup.local")
37 | self.set_marker("patched")
38 |
39 | def postbuild_arch(self, arch):
40 | return
41 |
42 | def get_build_env(self):
43 | sdk_path = sh.xcrun("--sdk", "macosx", "--show-sdk-path").strip()
44 |
45 | build_env = self.ctx.env.copy()
46 | ccache = (build_env["CCACHE"] + ' ') if 'CCACHE' in build_env else ''
47 | build_env["CC"] = ccache + "clang -Qunused-arguments -fcolor-diagnostics"
48 | build_env["LDFLAGS"] = " ".join([
49 | "-lsqlite3",
50 | "-lffi",
51 | ])
52 | build_env["CFLAGS"] = " ".join([
53 | "--sysroot={}".format(sdk_path),
54 | "-mmacosx-version-min=10.12",
55 | ])
56 | return build_env
57 |
58 | def build_arch(self, arch):
59 | build_env = self.get_build_env()
60 |
61 | configure = sh.Command(join(self.build_dir, "configure"))
62 |
63 | build_subdir = self.get_build_subdir(arch.arch)
64 | os.makedirs(build_subdir, exist_ok=True)
65 |
66 | with cd(build_subdir):
67 | shprint(configure,
68 | "ac_cv_func_preadv=no",
69 | "ac_cv_func_pwritev=no",
70 | "ac_cv_func_sendfile=no",
71 | "--prefix={}".format(join(self.ctx.dist_dir, "hostpython3")),
72 | "--with-openssl={}".format(join(self.ctx.dist_dir, 'hostopenssl')),
73 | _env=build_env)
74 | shprint(sh.make, "-C", build_subdir, self.ctx.concurrent_make,
75 | _env=build_env)
76 |
77 | def install(self):
78 | arch = list(self.filtered_archs)[0]
79 | build_env = self.get_build_env()
80 | build_subdir = self.get_build_subdir(arch.arch)
81 | build_env["PATH"] = os.environ["PATH"]
82 | shprint(sh.make, self.ctx.concurrent_make,
83 | "-C", build_subdir,
84 | "install",
85 | _env=build_env)
86 | shutil.copy(
87 | join(self.ctx.dist_dir, "hostpython3", "bin", "python3"),
88 | join(self.ctx.dist_dir, "hostpython3", "bin", "python"))
89 |
90 | # hostpython3 installs bundled versions of `pip`
91 | # and `setuptools` in `lib/python3.10/site-packages`.
92 | # This is fine, but `setuptools` have a bug that prevents
93 | # it from working properly when cross-compiling, so we
94 | # patch it here.
95 | # We can't do that before cause the packaged setuptools
96 | # is installed from a wheel.
97 | self.apply_patch(
98 | "allow-cflags-override.patch",
99 | join(
100 | self.ctx.dist_dir,
101 | "hostpython3",
102 | "lib",
103 | "python3.10",
104 | "site-packages",
105 | "setuptools",
106 | ),
107 | )
108 |
109 |
110 | recipe = Hostpython3Recipe()
111 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/bridge.m:
--------------------------------------------------------------------------------
1 | #import "bridge.h"
2 |
3 | @implementation bridge
4 |
5 | CMAltimeter *altimeterManager;
6 |
7 | - (id) init {
8 | if(self = [super init]) {
9 | self.motionManager = [[CMMotionManager alloc] init];
10 | queue = [[NSOperationQueue alloc] init];
11 | }
12 | return self;
13 | }
14 |
15 | - (void)startAccelerometer {
16 |
17 | if ([self.motionManager isAccelerometerAvailable] == YES) {
18 | [self.motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
19 | self.ac_x = accelerometerData.acceleration.x;
20 | self.ac_y = accelerometerData.acceleration.y;
21 | self.ac_z = accelerometerData.acceleration.z;
22 | }];
23 | }
24 | }
25 |
26 | - (void)startGyroscope {
27 |
28 | if ([self.motionManager isGyroAvailable] == YES) {
29 | [self.motionManager startGyroUpdatesToQueue:queue withHandler:^(CMGyroData *gyroData, NSError *error) {
30 | self.gy_x = gyroData.rotationRate.x;
31 | self.gy_y = gyroData.rotationRate.y;
32 | self.gy_z = gyroData.rotationRate.z;
33 | }];
34 | }
35 | }
36 |
37 | - (void)startMagnetometer {
38 |
39 | if (self.motionManager.magnetometerAvailable) {
40 | [self.motionManager startMagnetometerUpdatesToQueue:queue withHandler:^(CMMagnetometerData *magnetometerData, NSError *error) {
41 | self.mg_x = magnetometerData.magneticField.x;
42 | self.mg_y = magnetometerData.magneticField.y;
43 | self.mg_z = magnetometerData.magneticField.z;
44 | }];
45 | }
46 | }
47 |
48 | - (void)startDeviceMotion {
49 |
50 | if (self.motionManager.deviceMotionAvailable) {
51 | [self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical toQueue:queue withHandler:^(CMDeviceMotion *deviceMotion, NSError *error) {
52 | self.sp_roll = deviceMotion.attitude.roll;
53 | self.sp_pitch = deviceMotion.attitude.pitch;
54 | self.sp_yaw = deviceMotion.attitude.yaw;
55 |
56 | self.g_x = deviceMotion.gravity.x;
57 | self.g_y = deviceMotion.gravity.y;
58 | self.g_z = deviceMotion.gravity.z;
59 |
60 | self.rotation_rate_x = deviceMotion.rotationRate.x;
61 | self.rotation_rate_y = deviceMotion.rotationRate.y;
62 | self.rotation_rate_z = deviceMotion.rotationRate.z;
63 |
64 | self.user_acc_x = deviceMotion.userAcceleration.x;
65 | self.user_acc_y = deviceMotion.userAcceleration.y;
66 | self.user_acc_z = deviceMotion.userAcceleration.z;
67 |
68 | self.q_x = deviceMotion.attitude.quaternion.x;
69 | self.q_y = deviceMotion.attitude.quaternion.y;
70 | self.q_z = deviceMotion.attitude.quaternion.z;
71 | self.q_w = deviceMotion.attitude.quaternion.w;
72 | }];
73 | }
74 | }
75 |
76 | - (void)startDeviceMotionWithReferenceFrame {
77 |
78 | if (self.motionManager.deviceMotionAvailable) {
79 | [self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryCorrectedZVertical toQueue:queue withHandler:^(CMDeviceMotion *deviceMotion, NSError *error) {
80 | self.mf_x = deviceMotion.magneticField.field.x;
81 | self.mf_y = deviceMotion.magneticField.field.y;
82 | self.mf_z = deviceMotion.magneticField.field.z;
83 | }];
84 | }
85 | }
86 |
87 | - (void)startRelativeAltitude {
88 |
89 | if ([CMAltimeter isRelativeAltitudeAvailable]) {
90 | altimeterManager = [[CMAltimeter alloc] init];
91 | [altimeterManager startRelativeAltitudeUpdatesToQueue:queue withHandler:^(CMAltitudeData *altitudeData, NSError *error) {
92 | self.relative_altitude = altitudeData.relativeAltitude.floatValue;
93 | self.pressure = altitudeData.pressure.floatValue;
94 | }];
95 | }
96 | }
97 |
98 | - (void) stopAccelerometer {
99 | [self.motionManager stopAccelerometerUpdates];
100 | }
101 |
102 | - (void) stopGyroscope {
103 | [self.motionManager stopGyroUpdates];
104 | }
105 |
106 | - (void) stopMagnetometer {
107 | [self.motionManager stopMagnetometerUpdates];
108 | }
109 |
110 | - (void) stopDeviceMotion {
111 | [self.motionManager stopDeviceMotionUpdates];
112 | }
113 |
114 | - (void) stopRelativeAltitude {
115 | [altimeterManager stopRelativeAltitudeUpdates];
116 | }
117 |
118 | - (void) dealloc {
119 | [self.motionManager release];
120 | [queue release];
121 | [super dealloc];
122 | }
123 |
124 | @end
125 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/libffi/enable-tramp-build.patch:
--------------------------------------------------------------------------------
1 | diff -Naur libffi-3.4.2.orig/libffi.xcodeproj/project.pbxproj libffi-3.4.2/libffi.xcodeproj/project.pbxproj
2 | --- libffi-3.4.2.orig/libffi.xcodeproj/project.pbxproj 2022-04-03 22:11:12.000000000 +0200
3 | +++ libffi-3.4.2/libffi.xcodeproj/project.pbxproj 2022-04-03 22:17:06.000000000 +0200
4 | @@ -10,6 +10,10 @@
5 | 43B5D3F81D35473200D1E1FD /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */; };
6 | 43B5D3FA1D3547CE00D1E1FD /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */; };
7 | 43E9A5C81D352C1500926A8F /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */; };
8 | + AC0D110927FA355D001BCB3D /* tramp.c in Sources */ = {isa = PBXBuildFile; fileRef = AC0D110827FA355D001BCB3D /* tramp.c */; };
9 | + AC0D110A27FA355D001BCB3D /* tramp.c in Sources */ = {isa = PBXBuildFile; fileRef = AC0D110827FA355D001BCB3D /* tramp.c */; };
10 | + AC0D110B27FA355D001BCB3D /* tramp.c in Sources */ = {isa = PBXBuildFile; fileRef = AC0D110827FA355D001BCB3D /* tramp.c */; };
11 | + AC0D110C27FA355D001BCB3D /* tramp.c in Sources */ = {isa = PBXBuildFile; fileRef = AC0D110827FA355D001BCB3D /* tramp.c */; };
12 | DBFA714A187F1D8600A76262 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; };
13 | DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713F187F1D8600A76262 /* ffi_common.h */; };
14 | DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7140187F1D8600A76262 /* fficonfig.h */; };
15 | @@ -130,6 +134,7 @@
16 | 43E9A5DB1D35374400926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = ""; };
17 | 43E9A5DC1D35375400926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = ""; };
18 | 43E9A5DD1D35375400926A8F /* internal64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal64.h; sourceTree = ""; };
19 | + AC0D110827FA355D001BCB3D /* tramp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tramp.c; path = src/tramp.c; sourceTree = SOURCE_ROOT; };
20 | DB13B1661849DF1E0010F42D /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
21 | DB13B1911849DF510010F42D /* ffi.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = ffi.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
22 | DBFA713E187F1D8600A76262 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = ""; };
23 | @@ -214,6 +219,7 @@
24 | DBFA7142187F1D8600A76262 /* src */ = {
25 | isa = PBXGroup;
26 | children = (
27 | + AC0D110827FA355D001BCB3D /* tramp.c */,
28 | DBFA7143187F1D8600A76262 /* closures.c */,
29 | DBFA7145187F1D8600A76262 /* dlmalloc.c */,
30 | DBFA7147187F1D8600A76262 /* prep_cif.c */,
31 | @@ -513,6 +519,7 @@
32 | 43E9A5C81D352C1500926A8F /* unix64_x86_64.S in Sources */,
33 | DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */,
34 | DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */,
35 | + AC0D110927FA355D001BCB3D /* tramp.c in Sources */,
36 | DBFA714E187F1D8600A76262 /* closures.c in Sources */,
37 | DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */,
38 | 43B5D3F81D35473200D1E1FD /* ffiw64_x86_64.c in Sources */,
39 | @@ -535,6 +542,7 @@
40 | DBFA715B187F1D8600A76262 /* types.c in Sources */,
41 | DBFA7159187F1D8600A76262 /* raw_api.c in Sources */,
42 | DBFA714F187F1D8600A76262 /* closures.c in Sources */,
43 | + AC0D110B27FA355D001BCB3D /* tramp.c in Sources */,
44 | DBFA7194187F1DA100A76262 /* unix64_x86_64.S in Sources */,
45 | FDDB2F461F5D691E00EF414E /* win64_x86_64.S in Sources */,
46 | );
47 | @@ -547,6 +555,7 @@
48 | FDB52FB31F6144FA00AA92E6 /* unix64_x86_64.S in Sources */,
49 | FDB52FB51F6144FA00AA92E6 /* ffi64_x86_64.c in Sources */,
50 | FDB52FB61F6144FA00AA92E6 /* ffi_armv7.c in Sources */,
51 | + AC0D110A27FA355D001BCB3D /* tramp.c in Sources */,
52 | FDB52FB71F6144FA00AA92E6 /* closures.c in Sources */,
53 | FDB52FB81F6144FA00AA92E6 /* sysv_armv7.S in Sources */,
54 | FDB52FB91F6144FA00AA92E6 /* ffiw64_x86_64.c in Sources */,
55 | @@ -569,6 +578,7 @@
56 | FDDB2F4F1F5D846400EF414E /* types.c in Sources */,
57 | FDDB2F501F5D846400EF414E /* raw_api.c in Sources */,
58 | FDDB2F511F5D846400EF414E /* closures.c in Sources */,
59 | + AC0D110C27FA355D001BCB3D /* tramp.c in Sources */,
60 | FDDB2F521F5D846400EF414E /* unix64_x86_64.S in Sources */,
61 | FDDB2F531F5D846400EF414E /* win64_x86_64.S in Sources */,
62 | );
63 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ios/src/ios_utils.m:
--------------------------------------------------------------------------------
1 | /*
2 | * iOS utils
3 | *
4 | */
5 |
6 | #import
7 | #import
8 | #import
9 | #include "ios_wrapper.h"
10 |
11 |
12 | float ios_uiscreen_get_scale() {
13 | float scale = 1.0;
14 | if ([[UIScreen mainScreen] respondsToSelector:@selector(nativeScale)]) {
15 | scale = [[UIScreen mainScreen] nativeScale];
16 | };
17 | return scale;
18 | }
19 |
20 | int ios_uiscreen_get_dpi() {
21 | /*
22 | * dpi function from src/video/uikit/SDL_uikitmodes.m (SDL2)
23 | */
24 |
25 | /*
26 | * A well up to date list of device info can be found here:
27 | * https://github.com/lmirosevic/GBDeviceInfo/blob/master/GBDeviceInfo/GBDeviceInfo_iOS.m
28 | */
29 | NSDictionary* devices = @{
30 | @"iPhone1,1": @163,
31 | @"iPhone1,2": @163,
32 | @"iPhone2,1": @163,
33 | @"iPhone3,1": @326,
34 | @"iPhone3,2": @326,
35 | @"iPhone3,3": @326,
36 | @"iPhone4,1": @326,
37 | @"iPhone5,1": @326,
38 | @"iPhone5,2": @326,
39 | @"iPhone5,3": @326,
40 | @"iPhone5,4": @326,
41 | @"iPhone6,1": @326,
42 | @"iPhone6,2": @326,
43 | @"iPhone7,1": @401,
44 | @"iPhone7,2": @326,
45 | @"iPhone8,1": @326,
46 | @"iPhone8,2": @401,
47 | @"iPhone8,4": @326,
48 | @"iPhone9,1": @326,
49 | @"iPhone9,2": @401,
50 | @"iPhone9,3": @326,
51 | @"iPhone9,4": @401,
52 | @"iPhone10,1": @326,
53 | @"iPhone10,2": @401,
54 | @"iPhone10,3": @458,
55 | @"iPhone10,4": @326,
56 | @"iPhone10,5": @401,
57 | @"iPhone10,6": @458,
58 | @"iPhone11,2": @458,
59 | @"iPhone11,4": @458,
60 | @"iPhone11,6": @458,
61 | @"iPhone11,8": @326,
62 | @"iPhone12,1": @326,
63 | @"iPhone12,3": @458,
64 | @"iPhone12,5": @458,
65 | @"iPhone12,8": @326,
66 | @"iPhone13,1": @476,
67 | @"iPhone13,2": @460,
68 | @"iPhone13,3": @460,
69 | @"iPhone13,4": @458,
70 | @"iPhone14,2": @460,
71 | @"iPhone14,3": @458,
72 | @"iPhone14,4": @476,
73 | @"iPhone14,5": @460,
74 | @"iPhone14,6": @326,
75 | @"iPad1,1": @132,
76 | @"iPad2,1": @132,
77 | @"iPad2,2": @132,
78 | @"iPad2,3": @132,
79 | @"iPad2,4": @132,
80 | @"iPad2,5": @163,
81 | @"iPad2,6": @163,
82 | @"iPad2,7": @163,
83 | @"iPad3,1": @264,
84 | @"iPad3,2": @264,
85 | @"iPad3,3": @264,
86 | @"iPad3,4": @264,
87 | @"iPad3,5": @264,
88 | @"iPad3,6": @264,
89 | @"iPad4,1": @264,
90 | @"iPad4,2": @264,
91 | @"iPad4,3": @264,
92 | @"iPad4,4": @326,
93 | @"iPad4,5": @326,
94 | @"iPad4,6": @326,
95 | @"iPad4,7": @326,
96 | @"iPad4,8": @326,
97 | @"iPad4,9": @326,
98 | @"iPad5,1": @326,
99 | @"iPad5,2": @326,
100 | @"iPad5,3": @264,
101 | @"iPad5,4": @264,
102 | @"iPad6,3": @264,
103 | @"iPad6,4": @264,
104 | @"iPad6,7": @264,
105 | @"iPad6,8": @264,
106 | @"iPad6,11": @264,
107 | @"iPad6,12": @264,
108 | @"iPad7,1": @264,
109 | @"iPad7,2": @264,
110 | @"iPad7,3": @264,
111 | @"iPad7,4": @264,
112 | @"iPad7,5": @264,
113 | @"iPad7,6": @264,
114 | @"iPad7,11": @264,
115 | @"iPad7,12": @264,
116 | @"iPad8,1": @264,
117 | @"iPad8,2": @264,
118 | @"iPad8,3": @264,
119 | @"iPad8,4": @264,
120 | @"iPad8,5": @264,
121 | @"iPad8,6": @264,
122 | @"iPad8,7": @264,
123 | @"iPad8,8": @264,
124 | @"iPad11,1": @326,
125 | @"iPad11,2": @326,
126 | @"iPad11,3": @326,
127 | @"iPad11,4": @326,
128 | @"iPod1,1": @163,
129 | @"iPod2,1": @163,
130 | @"iPod3,1": @163,
131 | @"iPod4,1": @326,
132 | @"iPod5,1": @326,
133 | @"iPod7,1": @326,
134 | @"iPod9,1": @326,
135 | };
136 | struct utsname systemInfo;
137 | uname(&systemInfo);
138 | NSString* deviceName = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
139 | id foundDPI = devices[deviceName];
140 | if (foundDPI) {
141 | return (float)[foundDPI integerValue];
142 | } else {
143 | /*
144 | * Estimate the DPI based on the screen scale multiplied by the base DPI for the device
145 | * type (e.g. based on iPhone 1 and iPad 1)
146 | */
147 | float scale = ios_uiscreen_get_scale();
148 | float dpi = 160 * scale;
149 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
150 | dpi = 132 * scale;
151 | } else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
152 | dpi = 163 * scale;
153 | }
154 | return dpi;
155 | }
156 | }
157 |
158 | padding ios_get_safe_area() {
159 | padding safearea;
160 | if (@available(iOS 11.0, *)){
161 | UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
162 | safearea.top = window.safeAreaInsets.top;
163 | safearea.bottom = window.safeAreaInsets.bottom;
164 | safearea.left = window.safeAreaInsets.left;
165 | safearea.right = window.safeAreaInsets.right;
166 | } else {
167 | safearea.top = 0;
168 | safearea.bottom = 0;
169 | safearea.left = 0;
170 | safearea.right = 0;
171 | }
172 | return safearea;
173 | }
174 |
--------------------------------------------------------------------------------
/.github/workflows/kivy_ios.yml:
--------------------------------------------------------------------------------
1 | name: kivy-ios
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | flake8:
7 | name: Flake8 tests
8 | runs-on: macos-latest
9 | steps:
10 | - name: Checkout kivy-ios
11 | uses: actions/checkout@v3
12 | - name: Set up Python
13 | uses: actions/setup-python@v4
14 | with:
15 | python-version: 3.x
16 | - name: Run flake8
17 | run: |
18 | python -m pip install --upgrade pip
19 | pip install tox>=2.0
20 | tox -e pep8
21 |
22 | build_python3_kivy:
23 | runs-on: ${{ matrix.runs_on }}
24 | strategy:
25 | matrix:
26 | include:
27 | - runs_on: macos-latest
28 | python: 3.x
29 | - runs_on: apple-silicon-m1
30 | python: '3.11'
31 | steps:
32 | - name: Checkout kivy-ios
33 | uses: actions/checkout@v3
34 | - name: Set up Python 3.x
35 | # Needs to be skipped on our self-hosted runners tagged as 'apple-silicon-m1'
36 | if: ${{ matrix.runs_on != 'apple-silicon-m1' }}
37 | uses: actions/setup-python@v4
38 | with:
39 | python-version: ${{ matrix.python }}
40 | - name: Install requirements
41 | run: |
42 | source .ci/utils.sh
43 | arm64_set_path_and_python_version ${{ matrix.python }}
44 | brew install libjpeg
45 | pip3 install wheel
46 | pip3 install -r requirements.txt
47 | brew install autoconf automake libtool pkg-config
48 | brew link libtool
49 | pip3 install Cython==0.29.33
50 | sudo gem install xcpretty
51 | - name: Install kivy-ios
52 | run: |
53 | source .ci/utils.sh
54 | arm64_set_path_and_python_version ${{ matrix.python }}
55 | python setup.py install
56 | - name: Build Python & Kivy
57 | run: |
58 | source .ci/utils.sh
59 | arm64_set_path_and_python_version ${{ matrix.python }}
60 | toolchain build python3 kivy
61 | - name: Checkout kivy for tests apps
62 | uses: actions/checkout@v3
63 | with:
64 | repository: kivy/kivy
65 | path: kivy-ci-clone
66 | - name: Create & Build test project
67 | run: |
68 | source .ci/utils.sh
69 | arm64_set_path_and_python_version ${{ matrix.python }}
70 | .ci/test_project.sh
71 |
72 | build_python3_kivy_venv:
73 | runs-on: ${{ matrix.runs_on }}
74 | strategy:
75 | matrix:
76 | include:
77 | - runs_on: macos-latest
78 | python: 3.x
79 | - runs_on: apple-silicon-m1
80 | python: '3.11'
81 | steps:
82 | - name: Checkout kivy-ios
83 | uses: actions/checkout@v3
84 | - name: Set up Python 3.x
85 | # Needs to be skipped on our self-hosted runners tagged as 'apple-silicon-m1'
86 | if: ${{ matrix.runs_on != 'apple-silicon-m1' }}
87 | uses: actions/setup-python@v4
88 | with:
89 | python-version: ${{ matrix.python }}
90 | - name: Install requirements
91 | run: |
92 | source .ci/utils.sh
93 | arm64_set_path_and_python_version ${{ matrix.python }}
94 | python -m venv venv
95 | . venv/bin/activate
96 | brew install libjpeg
97 | pip install wheel
98 | pip install -r requirements.txt
99 | pip install sh
100 | brew install autoconf automake libtool pkg-config
101 | brew link libtool
102 | pip install Cython==0.29.33
103 | sudo gem install xcpretty
104 | - name: Install kivy-ios
105 | run: |
106 | source .ci/utils.sh
107 | arm64_set_path_and_python_version ${{ matrix.python }}
108 | python setup.py install
109 | - name: Build Python & Kivy
110 | run: |
111 | source .ci/utils.sh
112 | arm64_set_path_and_python_version ${{ matrix.python }}
113 | . venv/bin/activate
114 | toolchain build python3 kivy
115 | - name: Checkout kivy for tests apps
116 | uses: actions/checkout@v3
117 | with:
118 | repository: kivy/kivy
119 | path: kivy-ci-clone
120 | - name: Create & Build test project
121 | run: |
122 | source .ci/utils.sh
123 | arm64_set_path_and_python_version ${{ matrix.python }}
124 | . venv/bin/activate
125 | .ci/test_project.sh
126 |
127 | build_updated_recipes:
128 | needs: flake8
129 | runs-on: ${{ matrix.runs_on }}
130 | strategy:
131 | matrix:
132 | include:
133 | - runs_on: macos-latest
134 | python: 3.x
135 | - runs_on: apple-silicon-m1
136 | python: '3.11'
137 | steps:
138 | - name: Checkout kivy-ios
139 | uses: actions/checkout@v3
140 | - name: Set up Python 3.x
141 | # Needs to be skipped on our self-hosted runners tagged as 'apple-silicon-m1'
142 | if: ${{ matrix.runs_on != 'apple-silicon-m1' }}
143 | uses: actions/setup-python@v4
144 | with:
145 | python-version: ${{ matrix.python }}
146 | - name: Install requirements
147 | run: |
148 | source .ci/utils.sh
149 | arm64_set_path_and_python_version ${{ matrix.python }}
150 | brew install libjpeg
151 | pip3 install wheel
152 | pip3 install -r requirements.txt
153 | brew install autoconf automake libtool pkg-config
154 | brew link libtool
155 | pip3 install Cython==0.29.33
156 | - name: Install kivy-ios
157 | run: |
158 | source .ci/utils.sh
159 | arm64_set_path_and_python_version ${{ matrix.python }}
160 | python setup.py install
161 | - name: Build updated recipes
162 | run: |
163 | source .ci/utils.sh
164 | arm64_set_path_and_python_version ${{ matrix.python }}
165 | python3 .ci/rebuild_updated_recipes.py
166 |
--------------------------------------------------------------------------------
/kivy_ios.egg-info/SOURCES.txt:
--------------------------------------------------------------------------------
1 | .gitignore
2 | CHANGELOG.md
3 | LICENSE
4 | MANIFEST.in
5 | README.md
6 | pyproject.toml
7 | requirements.txt
8 | setup.cfg
9 | setup.py
10 | toolchain.py
11 | tox.ini
12 | .ci/constants.py
13 | .ci/rebuild_updated_recipes.py
14 | .ci/test_project.sh
15 | .github/ISSUE_TEMPLATE/bug_report.md
16 | .github/ISSUE_TEMPLATE/feature_request.md
17 | .github/workflows/kivy_ios.yml
18 | .github/workflows/pypi-release.yml
19 | .github/workflows/setup.yml
20 | kivy_ios/__init__.py
21 | kivy_ios/context_managers.py
22 | kivy_ios/toolchain.py
23 | kivy_ios.egg-info/PKG-INFO
24 | kivy_ios.egg-info/SOURCES.txt
25 | kivy_ios.egg-info/dependency_links.txt
26 | kivy_ios.egg-info/entry_points.txt
27 | kivy_ios.egg-info/requires.txt
28 | kivy_ios.egg-info/top_level.txt
29 | kivy_ios/recipes/__init__.py
30 | kivy_ios/recipes/hostpython.py
31 | kivy_ios/recipes/python.py
32 | kivy_ios/recipes/audiostream/__init__.py
33 | kivy_ios/recipes/click/__init__.py
34 | kivy_ios/recipes/curly/__init__.py
35 | kivy_ios/recipes/cymunk/__init__.py
36 | kivy_ios/recipes/ffmpeg/__init__.py
37 | kivy_ios/recipes/ffpyplayer/__init__.py
38 | kivy_ios/recipes/ffpyplayer/misc-visibility.patch
39 | kivy_ios/recipes/flask/__init__.py
40 | kivy_ios/recipes/freetype/__init__.py
41 | kivy_ios/recipes/host_setuptools/__init__.py
42 | kivy_ios/recipes/host_setuptools/setuptools/README.rst
43 | kivy_ios/recipes/host_setuptools3/__init__.py
44 | kivy_ios/recipes/host_setuptools3/setuptools/README.rst
45 | kivy_ios/recipes/hostlibffi/__init__.py
46 | kivy_ios/recipes/hostlibffi/ffi-3.0.13-sysv.S.patch
47 | kivy_ios/recipes/hostlibffi/fix-win32-unreferenced-symbol.patch
48 | kivy_ios/recipes/hostlibffi/generate-darwin-source-and-headers-python3-items.patch
49 | kivy_ios/recipes/hostlibffi/libffi-xcode10.patch
50 | kivy_ios/recipes/hostlibffi/public_include.patch
51 | kivy_ios/recipes/hostlibffi/staticlib.patch
52 | kivy_ios/recipes/hostlibffi/staticlib2.patch
53 | kivy_ios/recipes/hostopenssl/__init__.py
54 | kivy_ios/recipes/hostpython3/ModulesSetup
55 | kivy_ios/recipes/hostpython3/__init__.py
56 | kivy_ios/recipes/hostpython3/disable_sysconfig_cflags.patch
57 | kivy_ios/recipes/ios/__init__.py
58 | kivy_ios/recipes/ios/src/ios.pyx
59 | kivy_ios/recipes/ios/src/ios_browser.m
60 | kivy_ios/recipes/ios/src/ios_filechooser.m
61 | kivy_ios/recipes/ios/src/ios_mail.m
62 | kivy_ios/recipes/ios/src/ios_utils.m
63 | kivy_ios/recipes/ios/src/ios_wrapper.h
64 | kivy_ios/recipes/ios/src/setup.py
65 | kivy_ios/recipes/itsdangerous/__init__.py
66 | kivy_ios/recipes/jinja2/__init__.py
67 | kivy_ios/recipes/kivent_core/__init__.py
68 | kivy_ios/recipes/kivy/__init__.py
69 | kivy_ios/recipes/libcurl/__init__.py
70 | kivy_ios/recipes/libffi/__init__.py
71 | kivy_ios/recipes/libffi/ffi-3.0.13-sysv.S.patch
72 | kivy_ios/recipes/libffi/fix-win32-unreferenced-symbol.patch
73 | kivy_ios/recipes/libffi/generate-darwin-source-and-headers-python3-items.patch
74 | kivy_ios/recipes/libjpeg/__init__.py
75 | kivy_ios/recipes/libpng/__init__.py
76 | kivy_ios/recipes/libzbar/__init__.py
77 | kivy_ios/recipes/libzbar/werror.patch
78 | kivy_ios/recipes/markupsafe/__init__.py
79 | kivy_ios/recipes/netifaces/__init__.py
80 | kivy_ios/recipes/numpy/__init__.py
81 | kivy_ios/recipes/numpy/duplicated_symbols.patch
82 | kivy_ios/recipes/openssl/__init__.py
83 | kivy_ios/recipes/photolibrary/__init__.py
84 | kivy_ios/recipes/pillow/__init__.py
85 | kivy_ios/recipes/pillow/bypass-find-library.patch
86 | kivy_ios/recipes/plyer/__init__.py
87 | kivy_ios/recipes/pycrypto/__init__.py
88 | kivy_ios/recipes/pycrypto/hash_SHA2_template.c.patch
89 | kivy_ios/recipes/pykka/__init__.py
90 | kivy_ios/recipes/pyobjus/__init__.py
91 | kivy_ios/recipes/python3/ModulesSetup
92 | kivy_ios/recipes/python3/ModulesSetup.mobile
93 | kivy_ios/recipes/python3/__init__.py
94 | kivy_ios/recipes/python3/config.sub.patch
95 | kivy_ios/recipes/python3/configure.patch
96 | kivy_ios/recipes/python3/ctypes_duplicate.patch
97 | kivy_ios/recipes/python3/dynload_shlib.patch
98 | kivy_ios/recipes/python3/posixmodule.patch
99 | kivy_ios/recipes/python3/mock_modules/_sqlite3/__init__.py
100 | kivy_ios/recipes/python3/mock_modules/_sqlite3/_sqlite3.cpython-39-darwin.so
101 | kivy_ios/recipes/pyyaml/__init__.py
102 | kivy_ios/recipes/sdl2/__init__.py
103 | kivy_ios/recipes/sdl2/uikit-transparent.patch
104 | kivy_ios/recipes/sdl2_image/__init__.py
105 | kivy_ios/recipes/sdl2_mixer/__init__.py
106 | kivy_ios/recipes/sdl2_ttf/__init__.py
107 | kivy_ios/recipes/werkzeug/__init__.py
108 | kivy_ios/recipes/zbarlight/__init__.py
109 | kivy_ios/recipes/zbarlight/zbarlight_1_2.patch
110 | kivy_ios/tools/__init__.py
111 | kivy_ios/tools/biglink
112 | kivy_ios/tools/cythonize.py
113 | kivy_ios/tools/liblink
114 | kivy_ios/tools/external/__init__.py
115 | kivy_ios/tools/external/xcassets.py
116 | kivy_ios/tools/templates/cookiecutter.json
117 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/bridge.h
118 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/bridge.m
119 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/icon.png
120 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/main.m
121 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}-Info.plist
122 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default-568h@2x.png
123 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default-667h@2x.png
124 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default-763h@3x.png
125 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default-Landscape.png
126 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default-Landscape@2x.png
127 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default-Portrait.png
128 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default-Portrait@2x~ipad.png
129 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default-Portrait@3x~ipad.png
130 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default.png
131 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default@2x.png
132 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/LaunchImages/Default@3x.png
133 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/README.txt
134 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/android.txt
135 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/pictures.kv
136 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/shadow32.png
137 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/.empty
138 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/5509213687_ffd18df0b9_b.jpg
139 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/5552597274_de8b3fb5d2_b.jpg
140 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/YourApp/images/faust_github.jpg
141 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}.xcodeproj/project.pbxproj
142 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}.xcodeproj/project.xcworkspace/contents.xcworkspacedata
143 | kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}/Images.xcassets/AppIcon.appiconset/Contents.json
144 | tests/test_libs/main.py
145 | tests/test_python3/main.m
146 | tests/test_python3/main.py
--------------------------------------------------------------------------------
/tests/test_python3/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // test_python3
4 | //
5 |
6 | #import
7 | #import
8 | #include "/Users/tito/code/kivy-ios/dist/root/python3/include/python3.7m/Python.h"
9 | #include "/Users/tito/code/kivy-ios/dist/include/common/sdl2/SDL_main.h"
10 | #include
11 |
12 | void export_orientation();
13 | void load_custom_builtin_importer();
14 |
15 | int main(int argc, char *argv[]) {
16 | int ret = 0;
17 |
18 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
19 |
20 | // Change the executing path to YourApp
21 | chdir("YourApp");
22 |
23 | // Special environment to prefer .pyo, and don't write bytecode if .py are found
24 | // because the process will not have a write attribute on the device.
25 | // putenv("PYTHONOPTIMIZE=2");
26 | putenv("PYTHONDONTWRITEBYTECODE=1");
27 | putenv("PYTHONNOUSERSITE=1");
28 | putenv("PYTHONPATH=.");
29 | // putenv("PYTHONVERBOSE=1");
30 | putenv("PYTHONUNBUFFERED=1");
31 | // putenv("PYOBJUS_DEBUG=1");
32 |
33 | // Kivy environment to prefer some implementation on iOS platform
34 | putenv("KIVY_BUILD=ios");
35 | putenv("KIVY_NO_CONFIG=1");
36 | putenv("KIVY_NO_FILELOG=1");
37 | putenv("KIVY_WINDOW=sdl2");
38 | putenv("KIVY_IMAGE=imageio,tex");
39 | putenv("KIVY_AUDIO=sdl2");
40 | putenv("KIVY_GL_BACKEND=sdl2");
41 | #ifndef DEBUG
42 | putenv("KIVY_NO_CONSOLELOG=1");
43 | #endif
44 |
45 | // Export orientation preferences for Kivy
46 | export_orientation();
47 |
48 | NSString * resourcePath = [[NSBundle mainBundle] resourcePath];
49 | #if PY_MAJOR_VERSION == 2
50 | NSLog(@"PythonHome is: %s", (char *)[resourcePath UTF8String]);
51 | Py_SetPythonHome((char *)[resourcePath UTF8String]);
52 | #else
53 | NSString *python_home = [NSString stringWithFormat:@"PYTHONHOME=%@", resourcePath, nil];
54 | putenv((char *)[python_home UTF8String]);
55 |
56 | NSString *python_path = [NSString stringWithFormat:@"PYTHONPATH=%@:%@/lib/python3.7/:%@/lib/python3.7/site-packages", resourcePath, resourcePath, resourcePath, nil];
57 | putenv((char *)[python_path UTF8String]);
58 |
59 | NSString *tmp_path = [NSString stringWithFormat:@"TMP=%@/tmp", resourcePath, nil];
60 | putenv((char *)[tmp_path UTF8String]);
61 | #endif
62 |
63 | NSLog(@"Initializing python");
64 | Py_Initialize();
65 |
66 | #if PY_MAJOR_VERSION == 2
67 | PySys_SetArgv(argc, argv);
68 | #else
69 | wchar_t** python_argv = PyMem_RawMalloc(sizeof(wchar_t *) *argc);
70 | for (int i = 0; i < argc; i++)
71 | python_argv[i] = Py_DecodeLocale(argv[i], NULL);
72 | PySys_SetArgv(argc, python_argv);
73 | #endif
74 |
75 | // If other modules are using the thread, we need to initialize them before.
76 | PyEval_InitThreads();
77 |
78 | // Add an importer for builtin modules
79 | load_custom_builtin_importer();
80 |
81 | // Search and start main.py
82 | #if PY_MAJOR_VERSION == 2
83 | #define MAIN_EXT @"pyo"
84 | #else
85 | #define MAIN_EXT @"py"
86 | #endif
87 |
88 | const char * prog = [
89 | [[NSBundle mainBundle] pathForResource:@"YourApp/main" ofType:MAIN_EXT] cStringUsingEncoding:
90 | NSUTF8StringEncoding];
91 | NSLog(@"Running main.py: %s", prog);
92 | FILE* fd = fopen(prog, "r");
93 | if ( fd == NULL ) {
94 | ret = 1;
95 | NSLog(@"Unable to open main.py, abort.");
96 | } else {
97 | ret = PyRun_SimpleFileEx(fd, prog, 1);
98 | if (ret != 0)
99 | NSLog(@"Application quit abnormally!");
100 | }
101 |
102 | Py_Finalize();
103 | NSLog(@"Leaving");
104 |
105 | [pool release];
106 |
107 | // Look like the app still runs even when we left here.
108 | exit(ret);
109 | return ret;
110 | }
111 |
112 | // This method reads the available orientations from the Info.plist file and
113 | // shares them via an environment variable. Kivy will automatically set the
114 | // orientation according to this environment value, if it exists. To restrict
115 | // the allowed orientation, please see the comments inside.
116 | void export_orientation() {
117 | NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
118 | NSArray *orientations = [info objectForKey:@"UISupportedInterfaceOrientations"];
119 |
120 | // Orientation restrictions
121 | // ========================
122 | // Comment or uncomment blocks 1-3 in order the limit orientation support
123 |
124 | // 1. Landscape only
125 | // NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION=LandscapeLeft LandscapeRight"];
126 |
127 | // 2. Portrait only
128 | // NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION=Portrait PortraitUpsideDown"];
129 |
130 | // 3. All orientations
131 | NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION="];
132 | for (int i = 0; i < [orientations count]; i++) {
133 | NSString *item = [orientations objectAtIndex:i];
134 | item = [item substringFromIndex:22];
135 | if (i > 0)
136 | result = [result stringByAppendingString:@" "];
137 | result = [result stringByAppendingString:item];
138 | }
139 | // ========================
140 |
141 | putenv((char *)[result UTF8String]);
142 | NSLog(@"Available orientation: %@", result);
143 | }
144 |
145 | void load_custom_builtin_importer() {
146 | static const char *custom_builtin_importer = \
147 | "import sys, imp, types\n" \
148 | "from os import environ\n" \
149 | "from os.path import exists, join\n" \
150 | "try:\n" \
151 | " # python 3\n"
152 | " import _imp\n" \
153 | " EXTS = _imp.extension_suffixes()\n" \
154 | " sys.modules['subprocess'] = types.ModuleType(name='subprocess')\n" \
155 | "except ImportError:\n" \
156 | " EXTS = ['.so']\n"
157 | "# Fake redirection to supress console output\n" \
158 | "if environ.get('KIVY_NO_CONSOLE', '0') == '1':\n" \
159 | " class fakestd(object):\n" \
160 | " def write(self, *args, **kw): pass\n" \
161 | " def flush(self, *args, **kw): pass\n" \
162 | " sys.stdout = fakestd()\n" \
163 | " sys.stderr = fakestd()\n" \
164 | "# Custom builtin importer for precompiled modules\n" \
165 | "class CustomBuiltinImporter(object):\n" \
166 | " def find_module(self, fullname, mpath=None):\n" \
167 | " # print(f'find_module() fullname={fullname} mpath={mpath}')\n" \
168 | " if '.' not in fullname:\n" \
169 | " return\n" \
170 | " if not mpath:\n" \
171 | " return\n" \
172 | " part = fullname.rsplit('.')[-1]\n" \
173 | " for ext in EXTS:\n" \
174 | " fn = join(list(mpath)[0], '{}{}'.format(part, ext))\n" \
175 | " # print('find_module() {}'.format(fn))\n" \
176 | " if exists(fn):\n" \
177 | " return self\n" \
178 | " return\n" \
179 | " def load_module(self, fullname):\n" \
180 | " f = fullname.replace('.', '_')\n" \
181 | " mod = sys.modules.get(f)\n" \
182 | " if mod is None:\n" \
183 | " # print('LOAD DYNAMIC', f, sys.modules.keys())\n" \
184 | " try:\n" \
185 | " mod = imp.load_dynamic(f, f)\n" \
186 | " except ImportError:\n" \
187 | " import traceback; traceback.print_exc();\n" \
188 | " # print('LOAD DYNAMIC FALLBACK', fullname)\n" \
189 | " mod = imp.load_dynamic(fullname, fullname)\n" \
190 | " sys.modules[fullname] = mod\n" \
191 | " return mod\n" \
192 | " return mod\n" \
193 | "sys.meta_path.insert(0, CustomBuiltinImporter())";
194 | PyRun_SimpleString(custom_builtin_importer);
195 | }
196 |
--------------------------------------------------------------------------------
/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // {{ cookiecutter.project_name }}
4 | //
5 |
6 | #import
7 | #import
8 | #include "Python.h"
9 | #include "{{ cookiecutter.dist_dir }}/include/common/sdl2/SDL_main.h"
10 | #include
11 |
12 | void export_orientation();
13 | void load_custom_builtin_importer();
14 |
15 | int main(int argc, char *argv[]) {
16 | int ret = 0;
17 |
18 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
19 |
20 | // Change the executing path to YourApp
21 | chdir("YourApp");
22 |
23 | // Special environment to prefer .pyo, and don't write bytecode if .py are found
24 | // because the process will not have a write attribute on the device.
25 | putenv("PYTHONOPTIMIZE=2");
26 | putenv("PYTHONDONTWRITEBYTECODE=1");
27 | putenv("PYTHONNOUSERSITE=1");
28 | putenv("PYTHONPATH=.");
29 | putenv("PYTHONUNBUFFERED=1");
30 | putenv("LC_CTYPE=UTF-8");
31 | // putenv("PYTHONVERBOSE=1");
32 | // putenv("PYOBJUS_DEBUG=1");
33 |
34 | // Kivy environment to prefer some implementation on iOS platform
35 | putenv("KIVY_BUILD=ios");
36 | putenv("KIVY_WINDOW=sdl2");
37 | putenv("KIVY_IMAGE=imageio,tex,gif,sdl2");
38 | putenv("KIVY_AUDIO=sdl2");
39 | putenv("KIVY_GL_BACKEND=sdl2");
40 |
41 | // IOS_IS_WINDOWED=True disables fullscreen and then statusbar is shown
42 | putenv("IOS_IS_WINDOWED=False");
43 |
44 | #ifndef DEBUG
45 | putenv("KIVY_NO_CONSOLELOG=1");
46 | #endif
47 |
48 | // Export orientation preferences for Kivy
49 | export_orientation();
50 |
51 | NSString * resourcePath = [[NSBundle mainBundle] resourcePath];
52 | NSString *python_home = [NSString stringWithFormat:@"PYTHONHOME=%@", resourcePath, nil];
53 | putenv((char *)[python_home UTF8String]);
54 |
55 | NSString *python_path = [NSString stringWithFormat:@"PYTHONPATH=%@:%@/lib/python3.10/:%@/lib/python3.10/site-packages:.", resourcePath, resourcePath, resourcePath, nil];
56 | putenv((char *)[python_path UTF8String]);
57 |
58 | NSString *tmp_path = [NSString stringWithFormat:@"TMP=%@/tmp", resourcePath, nil];
59 | putenv((char *)[tmp_path UTF8String]);
60 |
61 | NSLog(@"Initializing python");
62 | Py_Initialize();
63 |
64 | wchar_t** python_argv = PyMem_RawMalloc(sizeof(wchar_t *) *argc);
65 | for (int i = 0; i < argc; i++)
66 | python_argv[i] = Py_DecodeLocale(argv[i], NULL);
67 | PySys_SetArgv(argc, python_argv);
68 |
69 | // If other modules are using the thread, we need to initialize them before.
70 | PyEval_InitThreads();
71 |
72 | // Add an importer for builtin modules
73 | load_custom_builtin_importer();
74 |
75 | // Search and start main.py
76 | #define MAIN_EXT @"pyc"
77 |
78 | const char * prog = [
79 | [[NSBundle mainBundle] pathForResource:@"YourApp/main" ofType:MAIN_EXT] cStringUsingEncoding:
80 | NSUTF8StringEncoding];
81 | NSLog(@"Running main.py: %s", prog);
82 | FILE* fd = fopen(prog, "r");
83 | if ( fd == NULL ) {
84 | ret = 1;
85 | NSLog(@"Unable to open main.py, abort.");
86 | } else {
87 | ret = PyRun_SimpleFileEx(fd, prog, 1);
88 | if (ret != 0)
89 | NSLog(@"Application quit abnormally!");
90 | }
91 |
92 | Py_Finalize();
93 | NSLog(@"Leaving");
94 |
95 | [pool release];
96 |
97 | // Look like the app still runs even when we left here.
98 | exit(ret);
99 | return ret;
100 | }
101 |
102 | // This method reads the available orientations from the Info.plist file and
103 | // shares them via an environment variable. Kivy will automatically set the
104 | // orientation according to this environment value, if it exists. To restrict
105 | // the allowed orientation, please see the comments inside.
106 | void export_orientation() {
107 | NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
108 | NSArray *orientations = [info objectForKey:@"UISupportedInterfaceOrientations"];
109 |
110 | // Orientation restrictions
111 | // ========================
112 | // Comment or uncomment blocks 1-3 in order the limit orientation support
113 |
114 | // 1. Landscape only
115 | // NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION=LandscapeLeft LandscapeRight"];
116 |
117 | // 2. Portrait only
118 | // NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION=Portrait PortraitUpsideDown"];
119 |
120 | // 3. All orientations
121 | NSString *result = [[NSString alloc] initWithString:@"KIVY_ORIENTATION="];
122 | for (int i = 0; i < [orientations count]; i++) {
123 | NSString *item = [orientations objectAtIndex:i];
124 | item = [item substringFromIndex:22];
125 | if (i > 0)
126 | result = [result stringByAppendingString:@" "];
127 | result = [result stringByAppendingString:item];
128 | }
129 | // ========================
130 |
131 | putenv((char *)[result UTF8String]);
132 | NSLog(@"Available orientation: %@", result);
133 | }
134 |
135 | void load_custom_builtin_importer() {
136 | static const char *custom_builtin_importer = \
137 | "import sys, imp, types\n" \
138 | "from os import environ\n" \
139 | "from os.path import exists, join\n" \
140 | "try:\n" \
141 | " # python 3\n"
142 | " import _imp\n" \
143 | " EXTS = _imp.extension_suffixes()\n" \
144 | " sys.modules['subprocess'] = types.ModuleType(name='subprocess')\n" \
145 | " sys.modules['subprocess'].PIPE = None\n" \
146 | " sys.modules['subprocess'].STDOUT = None\n" \
147 | " sys.modules['subprocess'].DEVNULL = None\n" \
148 | " sys.modules['subprocess'].CalledProcessError = Exception\n" \
149 | " sys.modules['subprocess'].check_output = None\n" \
150 | "except ImportError:\n" \
151 | " EXTS = ['.so']\n"
152 | "# Fake redirection to supress console output\n" \
153 | "if environ.get('KIVY_NO_CONSOLE', '0') == '1':\n" \
154 | " class fakestd(object):\n" \
155 | " def write(self, *args, **kw): pass\n" \
156 | " def flush(self, *args, **kw): pass\n" \
157 | " sys.stdout = fakestd()\n" \
158 | " sys.stderr = fakestd()\n" \
159 | "# Custom builtin importer for precompiled modules\n" \
160 | "class CustomBuiltinImporter(object):\n" \
161 | " def find_module(self, fullname, mpath=None):\n" \
162 | " # print(f'find_module() fullname={fullname} mpath={mpath}')\n" \
163 | " if '.' not in fullname:\n" \
164 | " return\n" \
165 | " if not mpath:\n" \
166 | " return\n" \
167 | " part = fullname.rsplit('.')[-1]\n" \
168 | " for ext in EXTS:\n" \
169 | " fn = join(list(mpath)[0], '{}{}'.format(part, ext))\n" \
170 | " # print('find_module() {}'.format(fn))\n" \
171 | " if exists(fn):\n" \
172 | " return self\n" \
173 | " return\n" \
174 | " def load_module(self, fullname):\n" \
175 | " f = fullname.replace('.', '_')\n" \
176 | " mod = sys.modules.get(f)\n" \
177 | " if mod is None:\n" \
178 | " # print('LOAD DYNAMIC', f, sys.modules.keys())\n" \
179 | " try:\n" \
180 | " mod = imp.load_dynamic(f, f)\n" \
181 | " except ImportError:\n" \
182 | " # import traceback; traceback.print_exc();\n" \
183 | " # print('LOAD DYNAMIC FALLBACK', fullname)\n" \
184 | " mod = imp.load_dynamic(fullname, fullname)\n" \
185 | " sys.modules[fullname] = mod\n" \
186 | " return mod\n" \
187 | " return mod\n" \
188 | "sys.meta_path.insert(0, CustomBuiltinImporter())";
189 | PyRun_SimpleString(custom_builtin_importer);
190 | }
191 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/python3/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy_ios.toolchain import Recipe, shprint
2 | from kivy_ios.context_managers import cd
3 | from os.path import join
4 | import sh
5 | import os
6 | import logging
7 |
8 | logger = logging.getLogger(__name__)
9 |
10 |
11 | class Python3Recipe(Recipe):
12 | version = "3.10.10"
13 | url = "https://www.python.org/ftp/python/{version}/Python-{version}.tgz"
14 | depends = ["hostpython3", "libffi", "openssl"]
15 | library = "libpython3.10.a"
16 | pbx_libraries = ["libz", "libbz2", "libsqlite3"]
17 |
18 | def init_with_ctx(self, ctx):
19 | super().init_with_ctx(ctx)
20 | self.set_python(self, "3.10")
21 | ctx.python_ver_dir = "python3.10"
22 | ctx.python_prefix = join(ctx.dist_dir, "root", "python3")
23 | ctx.site_packages_dir = join(
24 | ctx.python_prefix, "lib", ctx.python_ver_dir, "site-packages")
25 |
26 | def prebuild_arch(self, arch):
27 | # common to all archs
28 | if self.has_marker("patched"):
29 | return
30 | self.apply_patch("configure.patch")
31 | self.apply_patch("posixmodule.patch")
32 | self.apply_patch("dynload_shlib.patch")
33 | self.apply_patch("ctypes_duplicate.patch")
34 | self.copy_file("ModulesSetup", "Modules/Setup.local")
35 | self.append_file("ModulesSetup.mobile", "Modules/Setup.local")
36 | self.set_marker("patched")
37 |
38 | def postbuild_arch(self, arch):
39 | # We need to skip remove_junk, because we need to keep few files.
40 | # A cleanup will be done in the final step.
41 | return
42 |
43 | def get_build_env(self, arch):
44 | build_env = arch.get_env()
45 | build_env["PATH"] = "{}:{}".format(
46 | join(self.ctx.dist_dir, "hostpython3", "bin"),
47 | os.environ["PATH"])
48 | build_env["CFLAGS"] += " --sysroot={}".format(arch.sysroot)
49 | return build_env
50 |
51 | def build_arch(self, arch):
52 | build_env = self.get_build_env(arch)
53 | configure = sh.Command(join(self.build_dir, "configure"))
54 | py_arch = arch.arch_arg()
55 | if py_arch == "arm64":
56 | py_arch = "aarch64"
57 | prefix = join(self.ctx.dist_dir, "root", "python3")
58 | shprint(configure,
59 | "CC={}".format(build_env["CC"]),
60 | "LD={}".format(build_env["LD"]),
61 | "CFLAGS={}".format(build_env["CFLAGS"].replace("-fembed-bitcode", "")),
62 | "LDFLAGS={} -undefined dynamic_lookup".format(build_env["LDFLAGS"]),
63 | "ac_cv_file__dev_ptmx=yes",
64 | "ac_cv_file__dev_ptc=no",
65 | "ac_cv_little_endian_double=yes",
66 | "ac_cv_func_memrchr=no",
67 | "ac_cv_func_getentropy=no",
68 | "ac_cv_func_getresuid=no",
69 | "ac_cv_func_getresgid=no",
70 | "ac_cv_func_setresgid=no",
71 | "ac_cv_func_setresuid=no",
72 | "ac_cv_func_plock=no",
73 | "ac_cv_func_dup3=no",
74 | "ac_cv_func_pipe2=no",
75 | "ac_cv_func_preadv=no",
76 | "ac_cv_func_pwritev=no",
77 | "ac_cv_func_preadv2=no",
78 | "ac_cv_func_pwritev2=no",
79 | "ac_cv_func_mkfifoat=no",
80 | "ac_cv_func_mknodat=no",
81 | "ac_cv_func_posix_fadvise=no",
82 | "ac_cv_func_posix_fallocate=no",
83 | "ac_cv_func_sigwaitinfo=no",
84 | "ac_cv_func_sigtimedwait=no",
85 | "ac_cv_func_clock_settime=no",
86 | "ac_cv_func_pthread_getcpuclockid=no",
87 | "ac_cv_func_sched_setscheduler=no",
88 | "ac_cv_func_sched_setparam=no",
89 | "ac_cv_func_clock_gettime=no",
90 | "ac_cv_func_rtpSpawn=no",
91 | "ac_cv_func_fdwalk=no",
92 | "ac_cv_func_futimesat=no",
93 | "ac_cv_func_copy_file_range=no",
94 | "ac_cv_func_fexecve=no",
95 | "ac_cv_func_execve=no",
96 | "ac_cv_func_sched_rr_get_interval=no",
97 | "ac_cv_func_explicit_bzero=no",
98 | "ac_cv_func_explicit_memset=no",
99 | "ac_cv_func_close_range=no",
100 | "ac_cv_func_splice=no",
101 | "ac_cv_func_mremap=no",
102 | "--host={}-apple-ios".format(py_arch),
103 | "--build=x86_64-apple-darwin",
104 | "--prefix={}".format(prefix),
105 | "--without-ensurepip",
106 | "--with-system-ffi",
107 | "--enable-ipv6",
108 | "PYTHON_FOR_BUILD=_PYTHON_PROJECT_BASE=$(abs_builddir) \
109 | _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) \
110 | PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib\
111 | _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH)\
112 | {}".format(sh.Command(self.ctx.hostpython)),
113 | _env=build_env)
114 | shprint(sh.make, self.ctx.concurrent_make, "CFLAGS={}".format(build_env["CFLAGS"]))
115 |
116 | def install(self):
117 | arch = list(self.filtered_archs)[0]
118 | build_env = self.get_build_env(arch)
119 | build_dir = self.get_build_dir(arch.arch)
120 | shprint(sh.make, self.ctx.concurrent_make,
121 | "-C", build_dir,
122 | "install",
123 | "prefix={}".format(join(self.ctx.dist_dir, "root", "python3")),
124 | _env=build_env)
125 | self.reduce_python()
126 |
127 | def reduce_python(self):
128 | logger.info("Reduce python")
129 | logger.info("Remove files unlikely to be used")
130 | with cd(join(self.ctx.dist_dir, "root", "python3")):
131 | sh.rm("-rf", "bin", "share")
132 | # platform binaries and configuration
133 | with cd(join(
134 | self.ctx.dist_dir, "root", "python3", "lib",
135 | "python3.10", "config-3.10-darwin")):
136 | sh.rm(
137 | "libpython3.10.a",
138 | "python.o",
139 | "config.c.in",
140 | "makesetup",
141 | "install-sh",
142 | )
143 |
144 | # cleanup pkgconfig and compiled lib
145 | with cd(join(self.ctx.dist_dir, "root", "python3", "lib")):
146 | sh.rm("-rf", "pkgconfig", "libpython3.10.a")
147 |
148 | # cleanup python libraries
149 | with cd(join(
150 | self.ctx.dist_dir, "root", "python3", "lib", "python3.10")):
151 | sh.rm("-rf", "wsgiref", "curses", "idlelib", "lib2to3",
152 | "ensurepip", "turtledemo", "lib-dynload", "venv",
153 | "pydoc_data")
154 | sh.find(".", "-path", "*/test*/*", "-delete")
155 | sh.find(".", "-name", "*.exe", "-type", "f", "-delete")
156 | sh.find(".", "-name", "test*", "-type", "d", "-delete")
157 | sh.find(".", "-iname", "*.pyc", "-delete")
158 | sh.find(".", "-path", "*/__pycache__/*", "-delete")
159 | sh.find(".", "-name", "__pycache__", "-type", "d", "-delete")
160 |
161 | # now precompile to Python bytecode
162 | hostpython = sh.Command(self.ctx.hostpython)
163 | shprint(hostpython, "-m", "compileall", "-f", "-b")
164 | # sh.find(".", "-iname", "*.py", "-delete")
165 |
166 | # some pycache are recreated after compileall
167 | sh.find(".", "-path", "*/__pycache__/*", "-delete")
168 | sh.find(".", "-name", "__pycache__", "-type", "d", "-delete")
169 |
170 | # create the lib zip
171 | logger.info("Create a python3.10.zip")
172 | sh.mv("config-3.10-darwin", "..")
173 | sh.mv("site-packages", "..")
174 | sh.zip("-r", "../python310.zip", sh.glob("*"))
175 | sh.rm("-rf", sh.glob("*"))
176 | sh.mv("../config-3.10-darwin", ".")
177 | sh.mv("../site-packages", ".")
178 |
179 |
180 | recipe = Python3Recipe()
181 |
--------------------------------------------------------------------------------
/kivy_ios/recipes/ios/src/ios.pyx:
--------------------------------------------------------------------------------
1 | '''
2 | IOS module
3 | ==========
4 |
5 | IOS module is wrapping some part of the IOS features.
6 |
7 | '''
8 |
9 | from cpython cimport Py_INCREF, Py_DECREF
10 | from os.path import basename
11 |
12 | cdef extern from "ios_wrapper.h":
13 | ctypedef void (*ios_send_email_cb)(char *, void *)
14 | ctypedef struct padding:
15 | float top
16 | float bottom
17 | float right
18 | float left
19 | int ios_send_email(char *subject, char *text, char *mimetype, char
20 | *filename, char *filename_alias, ios_send_email_cb cb, void *userdata)
21 | void ios_open_url(char *url)
22 | void load_url_webview(char *url, int x, int y, int width, int height)
23 | float ios_uiscreen_get_scale()
24 | int ios_uiscreen_get_dpi()
25 | padding ios_get_safe_area()
26 |
27 | cdef void _send_email_done(char *status, void *data):
28 | cdef object callback =