diff --git a/.github/workflows/kivy_ios.yml b/.github/workflows/kivy_ios.yml index 052cef3e1..b932ee102 100644 --- a/.github/workflows/kivy_ios.yml +++ b/.github/workflows/kivy_ios.yml @@ -47,6 +47,36 @@ jobs: run: | .ci/test_project.sh + build_python3_kivy_metalangle: + runs-on: macos-latest + env: + KIVYIOS_USE_METALANGLE: 1 + steps: + - name: Checkout kivy-ios + uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: '3.8.x' + - name: Install requirements + run: | + pip3 install -r requirements.txt + brew install autoconf automake libtool pkg-config + brew link libtool + pip3 install Cython==0.29.17 + gem install xcpretty + - name: Build Python & Kivy with MetalANGLE support + run: | + python toolchain.py build python3 kivy + - name: Checkout kivy for tests apps + uses: actions/checkout@v2 + with: + repository: kivy/kivy + path: kivy-ci-clone + - name: Create & Build test project + run: | + .ci/test_project.sh + build_python3_kivy_venv: runs-on: macos-latest steps: diff --git a/kivy_ios/recipes/kivy/__init__.py b/kivy_ios/recipes/kivy/__init__.py index 108baa52c..2adbea8df 100644 --- a/kivy_ios/recipes/kivy/__init__.py +++ b/kivy_ios/recipes/kivy/__init__.py @@ -1,5 +1,6 @@ from kivy_ios.toolchain import CythonRecipe from os.path import join +import os import logging import shutil @@ -17,7 +18,7 @@ class KivyRecipe(CythonRecipe): depends = ["sdl2", "sdl2_image", "sdl2_mixer", "sdl2_ttf", "ios", "pyobjus", "python", "host_setuptools3"] python_depends = ["certifi"] - pbx_frameworks = ["OpenGLES", "Accelerate", "CoreMedia", "CoreVideo"] + pbx_frameworks = ["Accelerate", "CoreMedia", "CoreVideo"] pre_build_ext = True def get_recipe_env(self, arch): @@ -41,9 +42,17 @@ def _remove_line(lines, pattern): for line in lines[:]: if pattern in line: lines.remove(line) + + def _sub_pattern(lines, pattern_old, pattern_new): + for i, line in enumerate(lines[:]): + if pattern_old in line: + lines[i] = lines[i].replace(pattern_old, pattern_new) + with open(pyconfig) as fd: lines = fd.readlines() _remove_line(lines, "flags['libraries'] = ['GLESv2']") + if os.environ.get("KIVYIOS_USE_METALANGLE"): + _sub_pattern(lines, "OpenGLES", "MetalANGLE") with open(pyconfig, "w") as fd: fd.writelines(lines) diff --git a/kivy_ios/recipes/sdl2/__init__.py b/kivy_ios/recipes/sdl2/__init__.py index 387b3f077..0c06e7e3b 100644 --- a/kivy_ios/recipes/sdl2/__init__.py +++ b/kivy_ios/recipes/sdl2/__init__.py @@ -1,36 +1,84 @@ from kivy_ios.toolchain import Recipe, shprint +from os.path import join +import os import sh class LibSDL2Recipe(Recipe): - # version = "2.0.9" - # url = "https://www.libsdl.org/release/SDL2-{version}.tar.gz" - version = "7cc4fc886d9e" - url = "https://hg.libsdl.org/SDL/archive/{version}.tar.gz" - library = "Xcode-iOS/SDL/build/Release-{arch.sdk}/libSDL2.a" + version = "ios-use-metalangle" + url = "https://github.com/misl6/SDL/archive/refs/heads/feature/{version}.zip" + + metalangle_baseurl = ( + "https://github.com/kakashidinho/metalangle/releases/download/gles3-0.0.6" + ) + metalangle_arch_map = dict( + x86_64="MetalANGLE.framework.ios.simulator.zip", + arm64="MetalANGLE.framework.ios.zip", + ) + + library = "Xcode/SDL/build/Release-{arch.sdk}/libSDL2.a" include_dir = "include" pbx_frameworks = [ - "OpenGLES", "AudioToolbox", "QuartzCore", "CoreGraphics", - "CoreMotion", "GameController", "AVFoundation", "Metal", - "UIKit"] + "AudioToolbox", + "QuartzCore", + "CoreGraphics", + "CoreMotion", + "GameController", + "AVFoundation", + "Metal", + "UIKit", + "CoreHaptics", + ] + + def __init__(self): + if os.environ.get("KIVYIOS_USE_METALANGLE"): + self.frameworks = ["MetalANGLE"] + self.pbx_frameworks.append("MetalANGLE") + else: + self.pbx_frameworks.append("OpenGLES") def prebuild_arch(self, arch): if self.has_marker("patched"): return - self.apply_patch("uikit-transparent.patch") + # self.apply_patch("uikit-transparent.patch") + if os.environ.get("KIVYIOS_USE_METALANGLE"): + self.apply_patch("enable-metalangle.patch") + downloaded_file = self.download_file( + join(self.metalangle_baseurl, self.metalangle_arch_map[arch.arch]), + self.metalangle_arch_map[arch.arch], + ) + self.extract_file( + downloaded_file, + join(self.get_build_dir(arch.arch), "Xcode/SDL/third-party/frameworks"), + ) + if arch.arch == "arm64": + self.extract_file( + downloaded_file, + join(self.ctx.dist_dir, "frameworks"), + ) self.set_marker("patched") + def install_frameworks(self): + pass + def build_arch(self, arch): env = arch.get_env() - shprint(sh.xcodebuild, self.ctx.concurrent_xcodebuild, - "ONLY_ACTIVE_ARCH=NO", - "ARCHS={}".format(arch.arch), - "BITCODE_GENERATION_MODE=bitcode", - "CC={}".format(env['CC']), - "-sdk", arch.sdk, - "-project", "Xcode-iOS/SDL/SDL.xcodeproj", - "-target", "libSDL-iOS", - "-configuration", "Release") + shprint( + sh.xcodebuild, + self.ctx.concurrent_xcodebuild, + "ONLY_ACTIVE_ARCH=NO", + "ARCHS={}".format(arch.arch), + "BITCODE_GENERATION_MODE=bitcode", + "CC={}".format(env["CC"]), + "-sdk", + arch.sdk, + "-project", + "Xcode/SDL/SDL.xcodeproj", + "-target", + "Static Library-iOS", + "-configuration", + "Release", + ) recipe = LibSDL2Recipe() diff --git a/kivy_ios/recipes/sdl2/enable-metalangle.patch b/kivy_ios/recipes/sdl2/enable-metalangle.patch new file mode 100644 index 000000000..c4ca0c801 --- /dev/null +++ b/kivy_ios/recipes/sdl2/enable-metalangle.patch @@ -0,0 +1,15 @@ +diff -Naur SDL-feature-ios-use-metalangle.orig/include/SDL_config_iphoneos.h SDL-feature-ios-use-metalangle/include/SDL_config_iphoneos.h +--- SDL-feature-ios-use-metalangle.orig/include/SDL_config_iphoneos.h 2021-04-30 23:56:59.000000000 +0200 ++++ SDL-feature-ios-use-metalangle/include/SDL_config_iphoneos.h 2021-04-30 23:57:26.000000000 +0200 +@@ -173,9 +173,9 @@ + #if !TARGET_OS_MACCATALYST + #define SDL_VIDEO_OPENGL_ES2 1 + #define SDL_VIDEO_OPENGL_ES 1 +-#define SDL_VIDEO_RENDER_OGL_ES 1 ++#define SDL_VIDEO_RENDER_OGL_ES 0 + #define SDL_VIDEO_RENDER_OGL_ES2 1 +-#define SDL_VIDEO_OPENGL_METALANGLE 0 ++#define SDL_VIDEO_OPENGL_METALANGLE 1 + #endif + + /* Metal supported on 64-bit devices running iOS 8.0 and tvOS 9.0 and newer diff --git a/kivy_ios/toolchain.py b/kivy_ios/toolchain.py index 65a1b8e8b..dd521fb40 100755 --- a/kivy_ios/toolchain.py +++ b/kivy_ios/toolchain.py @@ -1231,17 +1231,19 @@ def update_pbxproj(filename, pbx_frameworks=None): group = project.get_or_create_group("Frameworks") g_classes = project.get_or_create_group("Classes") file_options = FileOptions(embed_framework=False, code_sign_on_copy=True) + file_options_embed = FileOptions(embed_framework=True, code_sign_on_copy=True) for framework in pbx_frameworks: - framework_name = "{}.framework".format(framework) - if framework_name in frameworks: + if framework in frameworks: logger.info("Ensure {} is in the project (pbx_frameworks, local)".format(framework)) - f_path = join(ctx.dist_dir, "frameworks", framework_name) + f_path = join(ctx.dist_dir, "frameworks", f"{framework}.framework") + project.add_file(f_path, parent=group, tree="DEVELOPER_DIR", + force=False, file_options=file_options_embed) else: logger.info("Ensure {} is in the project (pbx_frameworks, system)".format(framework)) f_path = join(sysroot, "System", "Library", "Frameworks", "{}.framework".format(framework)) - project.add_file(f_path, parent=group, tree="DEVELOPER_DIR", - force=False, file_options=file_options) + project.add_file(f_path, parent=group, tree="DEVELOPER_DIR", + force=False, file_options=file_options) for library in pbx_libraries: logger.info("Ensure {} is in the project (pbx_libraries, dylib+tbd)".format(library)) f_path = join(sysroot, "usr", "lib", diff --git a/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}.xcodeproj/project.pbxproj b/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}.xcodeproj/project.pbxproj index 5d2392801..aefac8d98 100755 --- a/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}.xcodeproj/project.pbxproj +++ b/kivy_ios/tools/templates/{{ cookiecutter.project_name }}-ios/{{ cookiecutter.project_name }}.xcodeproj/project.pbxproj @@ -27,6 +27,20 @@ 59994E3B148E85C800863906 /* YourApp in Resources */ = {isa = PBXBuildFile; fileRef = 59994E3A148E85C800863906 /* YourApp */; }; /* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + EF5745029C423687AC1203A1 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 01532DA9137C099F0076F6BF /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = ""; }; 1D6058910D05DD3D006BFB54 /* {{ cookiecutter.project_name }}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = {{ cookiecutter.project_name }}.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -143,6 +157,7 @@ 1D60588D0D05DD3D006BFB54 /* Resources */, 1D60588E0D05DD3D006BFB54 /* Sources */, 1D60588F0D05DD3D006BFB54 /* Frameworks */, + EF5745029C423687AC1203A1 /* Embed Frameworks */, ); buildRules = ( );