Ver Fonte

build_apps: Add support for iOS using the existing build_apps infrastructure.

Donny Lawrence há 5 anos atrás
pai
commit
4051fe6d36

+ 2 - 1
CMakeLists.txt

@@ -124,6 +124,7 @@ option(BUILD_DTOOL "Build the dtool source tree." ON)
 option(BUILD_PANDA "Build the panda source tree." ON)
 option(BUILD_DIRECT "Build the direct source tree." ON)
 option(BUILD_PANDATOOL "Build the pandatool source tree." ON)
+option(BUILD_DEPLOYSTUB "Build deploy-stub. Will also be built if BUILD_PANDATOOL is true." ON)
 option(BUILD_CONTRIB "Build the contrib source tree." ON)
 option(BUILD_MODELS "Build/install the built-in models." ON)
 
@@ -144,7 +145,7 @@ if(BUILD_DIRECT)
   add_subdirectory(direct "${CMAKE_BINARY_DIR}/direct")
 endif()
 
-if(BUILD_PANDATOOL)
+if(BUILD_PANDATOOL OR BUILD_DEPLOYSTUB)
   add_subdirectory(pandatool "${CMAKE_BINARY_DIR}/pandatool")
 endif()
 

+ 3 - 0
direct/src/dcparse/CMakeLists.txt

@@ -1,3 +1,6 @@
+if (IS_IOS)
+  return()
+endif()
 add_executable(p3dcparse dcparse.cxx)
 target_link_libraries(p3dcparse p3direct)
 install(TARGETS p3dcparse EXPORT Direct COMPONENT Direct DESTINATION ${CMAKE_INSTALL_BINDIR})

+ 7 - 5
direct/src/dist/FreezeTool.py

@@ -677,7 +677,7 @@ lc_layouts = {
 lc_indices_to_slide = {
     b'__PANDA': [4, 6],
     b'__LINKEDIT': [3, 5],
-    LC_DYLD_INFO_ONLY: [2, 4, 8, 10],
+    LC_DYLD_INFO_ONLY: [2, 4, 6, 8, 10],
     LC_SYMTAB: [2, 4],
     LC_DYSYMTAB: [14],
     LC_FUNCTION_STARTS: [2],
@@ -1801,7 +1801,7 @@ class Freezer:
             # trouble importing it as a builtin module.  Synthesize a frozen
             # module that loads it dynamically.
             if '.' in moduleName:
-                if self.platform.startswith("macosx") and not use_console:
+                if self.platform.startswith("macosx") or self.platform.startswith("ios") and not use_console:
                     # We write the Frameworks directory to sys.path[0].
                     code = 'import sys;del sys.modules["%s"];import sys,os,imp;imp.load_dynamic("%s",os.path.join(sys.path[0], "%s%s"))' % (moduleName, moduleName, moduleName, modext)
                 else:
@@ -1840,8 +1840,10 @@ class Freezer:
         if self.platform.startswith('win'):
             # We don't use mmap on Windows.  Align just for good measure.
             blob_align = 32
+        elif self.platform.startswith('ios'):
+            # Align to page size, so that it can be mmapped. Page size is 16KB on iOS, 4KB everywhere else.
+            blob_align = 16384
         else:
-            # Align to page size, so that it can be mmapped.
             blob_align = 4096
 
         # Also determine the total blob size now.  Add padding to the end.
@@ -1852,14 +1854,14 @@ class Freezer:
 
         # TODO: Support creating custom sections in universal binaries.
         append_blob = True
-        if self.platform.startswith('macosx') and len(bitnesses) == 1:
+        if self.platform.startswith('macosx') or self.platform.startswith('ios') and len(bitnesses) == 1:
             # If our deploy-stub has a __PANDA segment, we know we're meant to
             # put our blob there rather than attach it to the end.
             load_commands = self._parse_macho_load_commands(stub_data)
             if b'__PANDA' in load_commands.keys():
                 append_blob = False
 
-        if self.platform.startswith("macosx") and not append_blob:
+        if self.platform.startswith("macosx") or self.platform.startswith('ios') and not append_blob:
             # Take this time to shift any Mach-O structures around to fit our
             # blob. We don't need to worry about aligning the offset since the
             # compiler already took care of that when creating the segment.

+ 65 - 1
direct/src/dist/commands.py

@@ -169,6 +169,26 @@ if os.path.isdir(tcl_dir):
 del os
 """
 
+# As of April 2020, this is required for apps to be submitted to the App Store.
+IOS_LAUNCH_STORYBOARD = u"""
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17700" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
+    </dependencies>
+    <scenes>
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController"/>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
+"""
+
 
 class build_apps(setuptools.Command):
     description = 'build Panda3D applications'
@@ -421,6 +441,46 @@ class build_apps(setuptools.Command):
             pef.write_changes()
             pef.close()
 
+    def bundle_ios_app(self, builddir):
+        appname = '{}.app'.format(self.macos_main_app)
+        appdir = os.path.join(builddir, appname)
+
+        self.announce('Bundling iOS app into {}'.format(appdir),
+                      distutils.log.INFO)
+
+        os.makedirs(appdir)
+
+        for fname in os.listdir(builddir):
+            src = os.path.join(builddir, fname)
+            if appdir in src:
+                continue
+
+            dst = appdir
+            shutil.move(src, dst)
+
+        # Write out Info.plist
+        plist = {
+            'CFBundleName': appname,
+            'CFBundleDisplayName': appname,
+            # TODO use name from setup.py/cfg
+            'CFBundleIdentifier': 'com.panda3d.app',  # TODO
+            'CFBundleVersion': '0.0.0',  # TODO get from setup.py
+            'CFBundlePackageType': 'APPL',
+            'CFBundleSignature': '',  # TODO
+            'CFBundleExecutable': self.macos_main_app,
+            'UILaunchStoryboardName': 'LaunchScreen'
+        }
+
+        with open(os.path.join(appdir, 'Info.plist'), 'wb') as f:
+            if hasattr(plistlib, 'dump'):
+                plistlib.dump(plist, f)
+            else:
+                plistlib.writePlist(plist, f)
+
+        # Write out the launch screen storyboard.
+        with open(os.path.join(appdir, 'LaunchScreen.storyboard'), 'w') as f:
+            f.write(IOS_LAUNCH_STORYBOARD)
+
     def bundle_macos_app(self, builddir):
         """Bundle built runtime into a .app for macOS"""
 
@@ -650,7 +710,7 @@ class build_apps(setuptools.Command):
             target_path = os.path.join(builddir, appname)
 
             stub_name = 'deploy-stub'
-            if platform.startswith('win') or 'macosx' in platform:
+            if platform.startswith('win') or platform.startswith('macosx') or platform.startswith('ios'):
                 if not use_console:
                     stub_name = 'deploy-stubw'
 
@@ -699,6 +759,7 @@ class build_apps(setuptools.Command):
             search_path = [builddir]
             if use_wheels:
                 search_path.append(os.path.join(p3dwhlfn, 'deploy_libs'))
+                search_path.append(os.path.join(p3dwhlfn, 'panda3d'))
             self.copy_dependencies(target_path, builddir, search_path, stub_name)
 
             freezer_extras.update(freezer.extras)
@@ -921,6 +982,9 @@ class build_apps(setuptools.Command):
         if self.macos_main_app and 'macosx' in platform:
             self.bundle_macos_app(builddir)
 
+        if self.macos_main_app and 'ios' in platform:
+            self.bundle_ios_app(builddir)
+
     def add_dependency(self, name, target_dir, search_path, referenced_by):
         """ Searches for the given DLL on the search path.  If it exists,
         copies it to the target_dir. """

+ 0 - 8
direct/src/dist/py_xcproj/panda-app-target/AppDelegate.h

@@ -1,8 +0,0 @@
-#import <UIKit/UIKit.h>
-
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
-
-@property (strong, nonatomic) UIWindow *window;
-
-@end
-

+ 0 - 21
direct/src/dist/py_xcproj/panda-app-target/AppDelegate.m

@@ -1,21 +0,0 @@
-#import "AppDelegate.h"
-
-#include "PandaViewController.h"
-
-@implementation AppDelegate
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
-  
-  self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
-
-  PandaViewController *vc = [[PandaViewController alloc] init];
-  self.window.rootViewController = vc;
-  
-  [vc startPythonApp:@"${py_module_main}"];
-
-  [self.window makeKeyAndVisible];
-  
-  return YES;
-}
-
-@end

+ 0 - 29
direct/src/dist/py_xcproj/panda-app-target/Base.lproj/LaunchScreen.storyboard

@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
-    <device id="retina6_1" orientation="portrait">
-        <adaptation id="fullscreen"/>
-    </device>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
-        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <scenes>
-        <!--View Controller-->
-        <scene sceneID="EHf-IW-A2E">
-            <objects>
-                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
-                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
-                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
-                    </view>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="53" y="375"/>
-        </scene>
-    </scenes>
-</document>

+ 0 - 43
direct/src/dist/py_xcproj/panda-app-target/Info.plist

@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>$$(DEVELOPMENT_LANGUAGE)</string>
-	<key>CFBundleExecutable</key>
-	<string>$$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>1.0</string>
-	<key>CFBundleVersion</key>
-	<string>1</string>
-	<key>LSRequiresIPhoneOS</key>
-	<true/>
-	<key>UILaunchStoryboardName</key>
-	<string>LaunchScreen</string>
-	<key>UIRequiredDeviceCapabilities</key>
-	<array>
-		<string>armv7</string>
-	</array>
-	<key>UISupportedInterfaceOrientations</key>
-	<array>
-		<string>UIInterfaceOrientationPortrait</string>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-	</array>
-	<key>UISupportedInterfaceOrientations~ipad</key>
-	<array>
-		<string>UIInterfaceOrientationPortrait</string>
-		<string>UIInterfaceOrientationPortraitUpsideDown</string>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-	</array>
-</dict>
-</plist>

+ 0 - 8
direct/src/dist/py_xcproj/panda-app-target/main.m

@@ -1,8 +0,0 @@
-#import <UIKit/UIKit.h>
-#import "AppDelegate.h"
-
-int main(int argc, char * argv[]) {
-  @autoreleasepool {
-      return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
-  }
-}

+ 0 - 297
direct/src/dist/py_xcproj/panda-app-template.xcodeproj/project.pbxproj

@@ -1,297 +0,0 @@
-// !$$*UTF8*$$!
-{
-	archiveVersion = 1;
-	classes = {
-	};
-	objectVersion = 50;
-	objects = {
-
-/* Begin PBXBuildFile section */
-		F1E315CB22DE3C1D009AC9E9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E315CA22DE3C1D009AC9E9 /* AppDelegate.m */; };
-		F1E315D622DE3C1F009AC9E9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F1E315D422DE3C1F009AC9E9 /* LaunchScreen.storyboard */; };
-		F1E315D922DE3C1F009AC9E9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E315D822DE3C1F009AC9E9 /* main.m */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXFileReference section */
-		F1E315C622DE3C1D009AC9E9 /* ${app_name}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${app_name}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
-		F1E315C922DE3C1D009AC9E9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
-		F1E315CA22DE3C1D009AC9E9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
-		F1E315D522DE3C1F009AC9E9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
-		F1E315D722DE3C1F009AC9E9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		F1E315D822DE3C1F009AC9E9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
-		F1E315C322DE3C1D009AC9E9 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
-		F1E315BB22DE3B81009AC9E9 = {
-			isa = PBXGroup;
-			children = (
-				F1E315C822DE3C1D009AC9E9 /* ${app_name} */,
-				F1E315C722DE3C1D009AC9E9 /* Products */,
-			);
-			sourceTree = "<group>";
-		};
-		F1E315C722DE3C1D009AC9E9 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				F1E315C622DE3C1D009AC9E9 /* ${app_name}.app */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		F1E315C822DE3C1D009AC9E9 /* ${app_name} */ = {
-			isa = PBXGroup;
-			children = (
-				F1E315C922DE3C1D009AC9E9 /* AppDelegate.h */,
-				F1E315CA22DE3C1D009AC9E9 /* AppDelegate.m */,
-				F1E315D422DE3C1F009AC9E9 /* LaunchScreen.storyboard */,
-				F1E315D722DE3C1F009AC9E9 /* Info.plist */,
-				F1E315D822DE3C1F009AC9E9 /* main.m */,
-			);
-			path = "${app_name}";
-			sourceTree = "<group>";
-		};
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
-		F1E315C522DE3C1D009AC9E9 /* ${app_name} */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = F1E315DA22DE3C1F009AC9E9 /* Build configuration list for PBXNativeTarget "${app_name}" */;
-			buildPhases = (
-				F1E315C222DE3C1D009AC9E9 /* Sources */,
-				F1E315C322DE3C1D009AC9E9 /* Frameworks */,
-				F1E315C422DE3C1D009AC9E9 /* Resources */,
-				F113D35A22EE18EF00640DC0 /* ShellScript */,
-				F113D38822EE795200640DC0 /* Copy Game Files */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = "${app_name}";
-			productName = "${app_name}";
-			productReference = F1E315C622DE3C1D009AC9E9 /* ${app_name}.app */;
-			productType = "com.apple.product-type.application";
-		};
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
-		F1E315BC22DE3B81009AC9E9 /* Project object */ = {
-			isa = PBXProject;
-			attributes = {
-				LastUpgradeCheck = 1020;
-				TargetAttributes = {
-					F1E315C522DE3C1D009AC9E9 = {
-						CreatedOnToolsVersion = 10.2.1;
-					};
-				};
-			};
-			buildConfigurationList = F1E315BF22DE3B81009AC9E9 /* Build configuration list for PBXProject "panda-app-template" */;
-			compatibilityVersion = "Xcode 9.3";
-			developmentRegion = en;
-			hasScannedForEncodings = 0;
-			knownRegions = (
-				en,
-				Base,
-			);
-			mainGroup = F1E315BB22DE3B81009AC9E9;
-			productRefGroup = F1E315C722DE3C1D009AC9E9 /* Products */;
-			projectDirPath = "";
-			projectRoot = "";
-			targets = (
-				F1E315C522DE3C1D009AC9E9 /* ${app_name} */,
-			);
-		};
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
-		F1E315C422DE3C1D009AC9E9 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				F1E315D622DE3C1F009AC9E9 /* LaunchScreen.storyboard in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
-		F1E315C222DE3C1D009AC9E9 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				F1E315D922DE3C1F009AC9E9 /* main.m in Sources */,
-				F1E315CB22DE3C1D009AC9E9 /* AppDelegate.m in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXVariantGroup section */
-		F1E315D422DE3C1F009AC9E9 /* LaunchScreen.storyboard */ = {
-			isa = PBXVariantGroup;
-			children = (
-				F1E315D522DE3C1F009AC9E9 /* Base */,
-			);
-			name = LaunchScreen.storyboard;
-			sourceTree = "<group>";
-		};
-/* End PBXVariantGroup section */
-
-/* Begin PBXShellScriptBuildPhase section */
-		F113D35A22EE18EF00640DC0 /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-			);
-			name = "Copy and Sign Library Files";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "cp -R \"$$PROJECT_DIR/$$PROJECT_NAME/deploy$$EFFECTIVE_PLATFORM_NAME/\" \"$$BUILT_PRODUCTS_DIR/$$FRAMEWORKS_FOLDER_PATH\"\nfor f in `find -s \"$$BUILT_PRODUCTS_DIR/$$FRAMEWORKS_FOLDER_PATH\" -name \"*.so\" -o -name \"*.dylib\"`; do codesign -s \"$$CODE_SIGN_IDENTITY\" $$f; done\n";
-		};
-		F113D38822EE795200640DC0 /* Copy Game Files */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-			);
-			name = "Copy Game Files";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "cp -r \"${game_dir}/\" \"$$BUILT_PRODUCTS_DIR/$$WRAPPER_NAME\"\n";
-		};
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin XCBuildConfiguration section */
-		F1E315C122DE3B81009AC9E9 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-			};
-			name = Release;
-		};
-		F1E315DC22DE3C1F009AC9E9 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
-				CLANG_CXX_LIBRARY = "libc++";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_ENABLE_OBJC_WEAK = YES;
-				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_COMMA = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
-				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
-				CLANG_WARN_STRICT_PROTOTYPES = YES;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				CODE_SIGN_IDENTITY = "iPhone Developer";
-				CODE_SIGN_STYLE = Automatic;
-				COPY_PHASE_STRIP = NO;
-				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				ENABLE_BITCODE = NO;
-				ENABLE_NS_ASSERTIONS = NO;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu11;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				"HEADER_SEARCH_PATHS[sdk=iphoneos*]" = "$$(PROJECT_DIR)/$$(PROJECT_NAME)/deploy-iphoneos/include";
-				"HEADER_SEARCH_PATHS[sdk=iphonesimulator*]" = "$$(PROJECT_DIR)/$$(PROJECT_NAME)/deploy-iphonesimulator/include";
-				INFOPLIST_FILE = "${app_name}/Info.plist";
-				IPHONEOS_DEPLOYMENT_TARGET = ${deploy_target};
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$$(inherited)",
-					"@executable_path/Frameworks",
-					"@executable_path/Frameworks/python/lib",
-					"@executable_path/Frameworks/${sitepackages_dir}/panda3d",
-				);
-				"LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = (
-					"$$(PROJECT_DIR)/$$(PROJECT_NAME)/deploy-iphoneos/python/lib",
-					"$$(PROJECT_DIR)/$$(PROJECT_NAME)/deploy-iphoneos/${sitepackages_dir}/panda3d",
-				);
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = (
-					"$$(PROJECT_DIR)/$$(PROJECT_NAME)/deploy-iphonesimulator/python/lib",
-					"$$(PROJECT_DIR)/$$(PROJECT_NAME)/deploy-iphonesimulator/${sitepackages_dir}/panda3d",
-				);
-				MTL_ENABLE_DEBUG_INFO = NO;
-				MTL_FAST_MATH = YES;
-				OTHER_LDFLAGS = "-lpandagles2 -lpython${py_ver}m";
-				PRODUCT_NAME = "$$(TARGET_NAME)";
-				SDKROOT = iphoneos;
-				SUPPORTED_PLATFORMS = ${supported_platforms};
-				TARGETED_DEVICE_FAMILY = "1,2";
-				VALIDATE_PRODUCT = YES;
-				VALID_ARCHS = (
-					${archs_list},
-				);
-			};
-			name = Release;
-		};
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
-		F1E315BF22DE3B81009AC9E9 /* Build configuration list for PBXProject "panda-app-template" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				F1E315C122DE3B81009AC9E9 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		F1E315DA22DE3C1F009AC9E9 /* Build configuration list for PBXNativeTarget "${app_name}" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				F1E315DC22DE3C1F009AC9E9 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-/* End XCConfigurationList section */
-	};
-	rootObject = F1E315BC22DE3B81009AC9E9 /* Project object */;
-}

+ 0 - 91
direct/src/dist/py_xcproj/panda-app-template.xcodeproj/xcshareddata/xcschemes/panda-app-target.xcscheme

@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "1020"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "F1E315C522DE3C1D009AC9E9"
-               BuildableName = "${app_name}.app"
-               BlueprintName = "${app_name}"
-               ReferencedContainer = "container:${app_name}.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Release"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <Testables>
-      </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "F1E315C522DE3C1D009AC9E9"
-            BuildableName = "${app_name}.app"
-            BlueprintName = "${app_name}"
-            ReferencedContainer = "container:${app_name}.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Release"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "F1E315C522DE3C1D009AC9E9"
-            BuildableName = "${app_name}.app"
-            BlueprintName = "${app_name}"
-            ReferencedContainer = "container:${app_name}.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-      <AdditionalOptions>
-      </AdditionalOptions>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Release"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "F1E315C522DE3C1D009AC9E9"
-            BuildableName = "${app_name}.app"
-            BlueprintName = "${app_name}"
-            ReferencedContainer = "container:${app_name}.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Release">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>

+ 1 - 4
dtool/Config.cmake

@@ -338,10 +338,7 @@ mark_as_advanced(USE_MEMORY_DLMALLOC USE_MEMORY_PTMALLOC2
 if(IS_IOS)
 
   set(CMAKE_MACOSX_BUNDLE OFF)
-
-  # A bug in CMake (https://gitlab.kitware.com/cmake/cmake/issues/19375) causes
-  # MACOSX_RPATH to not be respected on iOS.
-  set(CMAKE_INSTALL_NAME_DIR "@rpath")
+  set(CMAKE_MACOSX_RPATH ON)
 
   # Check if THIRDPARTY_DIRECTORY is defined, and warn the user if it isn't.
   if(NOT THIRDPARTY_DIRECTORY)

+ 2 - 2
dtool/Package.cmake

@@ -195,8 +195,8 @@ endif()
 get_directory_property(_old_cache_vars CACHE_VARIABLES)
 
 if(CMAKE_SYSTEM_NAME MATCHES "iOS")
-  set(Python_LIBRARY ${Python_ROOT}/Python.framework/libPython.a)
-  set(Python_INCLUDE_DIR ${Python_ROOT}/Python.framework/Headers)
+  set(Python_LIBRARY ${Python_ROOT}/lib/libpython3.8.a)
+  set(Python_INCLUDE_DIR ${Python_ROOT}/include/python3.8)
   find_package(Python ${WANT_PYTHON_VERSION} QUIET COMPONENTS Development)
 else()
   find_package(Python ${WANT_PYTHON_VERSION} QUIET COMPONENTS Interpreter Development)

+ 1 - 1
dtool/src/dtoolutil/filename.cxx

@@ -1131,7 +1131,7 @@ to_os_specific() const {
   Filename standard(*this);
   standard.standardize();
 
-#ifdef IS_OSX
+#if defined(IS_OSX) || defined(IS_IOS)
   if (get_type() == T_dso) {
     std::string workname = standard.get_fullpath();
     size_t dot = workname.rfind('.');

+ 7 - 1
dtool/src/prc/configPageManager.cxx

@@ -124,10 +124,13 @@ reload_implicit_pages() {
   const BlobInfo *blobinfo = (const BlobInfo *)GetProcAddress(GetModuleHandle(NULL), "blobinfo");
 #elif defined(RTLD_MAIN_ONLY)
   const BlobInfo *blobinfo = (const BlobInfo *)dlsym(RTLD_MAIN_ONLY, "blobinfo");
+  void (*load_blobinfo_pointers)() = (void (*)())dlsym(RTLD_MAIN_ONLY, "load_blobinfo_pointers");
 //#elif defined(RTLD_SELF)
 //  const BlobInfo *blobinfo = (const BlobInfo *)dlsym(RTLD_SELF, "blobinfo");
 #else
-  const BlobInfo *blobinfo = (const BlobInfo *)dlsym(dlopen(NULL, RTLD_NOW), "blobinfo");
+  void *handle = dlopen(NULL, RTLD_NOW);
+  const BlobInfo *blobinfo = (const BlobInfo *)dlsym(handle, "blobinfo");
+  const void (*load_blobinfo_pointers)() = dlsym(handle, "load_blobinfo_pointers");
 #endif
   if (blobinfo == nullptr) {
 #ifndef _WIN32
@@ -139,6 +142,9 @@ reload_implicit_pages() {
   }
 
   if (blobinfo != nullptr) {
+    if (blobinfo->module_table == nullptr) {
+      load_blobinfo_pointers();
+    }
     if (blobinfo->num_pointers >= 11 && blobinfo->main_dir != nullptr) {
       ExecutionEnvironment::set_environment_variable("MAIN_DIR", blobinfo->main_dir);
     } else {

+ 22 - 17
makepanda/makewheel.py

@@ -144,7 +144,8 @@ class TargetInfo:
                  soabi='',
                  python_version=None,
                  python_root=sys.exec_prefix,
-                 sys_platform=get_host()):
+                 sys_platform=get_host(),
+                 static_panda=False):
         """
         With no arguments, it will be assumed that the target is the same as the
         host (which will be most cases).
@@ -174,6 +175,7 @@ class TargetInfo:
         self.python_version = python_version
         self.python_root = python_root
         self.sys_platform = sys_platform
+        self.static_panda = static_panda
 
         self.platform_tag = self.platform_tag.replace('-', '_').replace('.', '_')
 
@@ -234,7 +236,7 @@ class TargetInfo:
     @property
     def extension_suffix(self):
         if 'ios' in self.platform_tag:
-            return '.so'
+            return '.a' if self.static_panda else '.so'
         if self.soabi != '':
             ext = '.pyd' if self.sys_platform == 'win32' else '.so'
             return '.' + self.soabi + ext
@@ -698,6 +700,8 @@ def makewheel(version, output_dir, target_info):
     if sys.version_info < (3, 5):
         raise Exception("Python 3.5 is required to produce a wheel.")
 
+    platform = target_info.platform_tag
+
     if platform is None:
         # Determine the platform from the build.
         platform_dat = os.path.join(output_dir, 'tmp', 'platform.dat')
@@ -794,11 +798,12 @@ if __debug__:
 
     ext_suffix = target_info.extension_suffix
 
-    for file in os.listdir(panda3d_dir):
+    module_dir = libs_dir if target_info.static_panda else panda3d_dir
+    for file in os.listdir(module_dir):
         if file == '__init__.py':
             pass
-        elif file.endswith('.py') or (file.endswith(ext_suffix) and '.' not in file[:-len(ext_suffix)]):
-            source_path = os.path.join(panda3d_dir, file)
+        elif file.endswith('.py') or (file.endswith(ext_suffix) and '.' not in file[:-len(ext_suffix)]) or file.startswith('libpy'):
+            source_path = os.path.join(module_dir, file)
 
             if file.endswith('.pyd') and target_info.sys_platform == 'cygwin':
                 # Rename it to .dll for cygwin Python to be able to load it.
@@ -810,7 +815,11 @@ if __debug__:
 
     # And copy the extension modules from the Python installation into the
     # deploy_libs directory, for use by deploy-ng.
-    ext_suffix = '.pyd' if target_info.sys_platform in ('win32', 'cygwin') else '.so'
+    if target_info.static_panda:
+        ext_suffix = '.lib' if target_info.sys_platform in ('win32', 'cygwin') else '.a'
+    else:
+        ext_suffix = '.pyd' if target_info.sys_platform in ('win32', 'cygwin') else '.so'
+
     ext_mod_dir = target_info.python_ext_module_dir
 
     if not 'ios' in target_info.platform_tag:
@@ -826,20 +835,15 @@ if __debug__:
 
                 whl.write_file(target_path, source_path)
 
-    if 'ios' in target_info.platform_tag:
-        # Copy over the PandaViewController.h header file.
-        include_dir = join(output_dir, 'include/panda3d')
-        whl.write_file('deploy_libs/include/PandaViewController.h', join(include_dir, 'PandaViewController.h'))
-
     # Add plug-ins.
     for lib in PLUGIN_LIBS:
         plugin_name = 'lib' + lib
         if target_info.sys_platform in ('win32', 'cygwin'):
-            plugin_name += '.dll'
+            plugin_name += '.lib' if target_info.static_panda else '.dll'
         elif target_info.sys_platform in ('darwin', 'ios'):
-            plugin_name += '.dylib'
+            plugin_name += '.a' if target_info.static_panda else '.dylib'
         else:
-            plugin_name += '.so'
+            plugin_name += '.a' if target_info.static_panda else '.so'
         plugin_path = os.path.join(libs_dir, plugin_name)
         if os.path.isfile(plugin_path):
             whl.write_file('panda3d/' + plugin_name, plugin_path)
@@ -924,10 +928,10 @@ if __debug__:
             else:
                 raise Exception('Platform string does not specify one of ' + archs)
 
-        python_dir = os.path.abspath(join('thirdparty', 'ios-libs-%s' % arch, 'python', 'lib'))
+        python_dir = target_info.python_root
         pylib_name = ''
         for filename in os.listdir(python_dir):
-            if os.path.isfile(os.path.join(python_dir, filename)) and 'libpython' in filename and filename.endswith('dylib'):
+            if os.path.isfile(os.path.join(python_dir, filename)) and 'libpython' in filename:
                 pylib_name = filename
         pylib_path = join(python_dir, pylib_name)
     else:
@@ -958,9 +962,10 @@ if __name__ == "__main__":
     parser.add_option('', '--pyver', dest = 'python_version', help = 'Custom Python version we\'re making the wheel for.')
     parser.add_option('', '--pyroot', dest = 'python_root', help = 'Custom root of Python installation.', default = sys.exec_prefix)
     parser.add_option('', '--sysplatform', dest = 'sys_platform', help = 'Output of "sys.platform" on the target', default = get_host())
+    parser.add_option('', '--static', dest = 'static_panda', help = 'If the Panda libraries we\'re packaging are statically linked', action = 'store_true', default = False)
     (options, args) = parser.parse_args()
 
-    ti_opts = {key: options.__dict__[key] for key in ('platform_tag', 'soabi', 'python_version', 'python_root', 'sys_platform')}
+    ti_opts = {key: options.__dict__[key] for key in ('platform_tag', 'soabi', 'python_version', 'python_root', 'sys_platform', 'static_panda')}
     target_info = TargetInfo(**ti_opts)
 
     global verbose

+ 1 - 0
panda/CMakeLists.txt

@@ -35,6 +35,7 @@ add_subdirectory(src/glxdisplay)
 add_subdirectory(src/gobj)
 add_subdirectory(src/grutil)
 add_subdirectory(src/gsgbase)
+add_subdirectory(src/ios)
 add_subdirectory(src/linmath)
 add_subdirectory(src/mathutil)
 add_subdirectory(src/movies)

+ 4 - 0
panda/metalibs/panda/CMakeLists.txt

@@ -20,6 +20,10 @@ if(HAVE_FREETYPE)
   list(APPEND PANDA_LINK_TARGETS p3pnmtext)
 endif()
 
+# if(IS_IOS)
+#   list(APPEND PANDA_LINK_TARGETS p3ios)
+# endif()
+
 set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "CoreDevel")
 add_metalib(panda INIT init_libpanda panda.h COMPONENTS ${PANDA_LINK_TARGETS})
 unset(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME)

+ 0 - 7
panda/metalibs/pandagles2/CMakeLists.txt

@@ -22,13 +22,6 @@ add_metalib(pandagles2 ${MODULE_TYPE}
   COMPONENTS ${PANDAGLES2_LINK_TARGETS})
 unset(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME)
 
-if(CMAKE_SYSTEM_NAME STREQUAL iOS)
-  # We won't be linking with libpython until the wrapper app itself is built,
-  # so we'll quelch the errors that get spit out when trying to build with
-  # missing symbols.
-  target_link_options(pandagles2 PRIVATE -undefined dynamic_lookup)
-endif()
-
 install(TARGETS pandagles2
   EXPORT OpenGLES2 COMPONENT OpenGLES2
   DESTINATION ${MODULE_DESTINATION}

+ 1 - 0
panda/src/configfiles/panda.prc.in

@@ -2,6 +2,7 @@
 ################################# DO NOT EDIT ###########################
 
 # Some paths first...
+$<$<NOT:$<PLATFORM_ID:iOS>>:#> plugin-path $MAIN_DIR
 plugin-path $THIS_PRC_DIR/${PLUGINS_PATH}
 model-path $MAIN_DIR
 model-path $THIS_PRC_DIR/${MODELS_PARENT_PATH}

+ 1 - 4
panda/src/eagldisplay/CMakeLists.txt

@@ -9,7 +9,6 @@ set(P3EAGLDISPLAY_HEADERS
   eaglGraphicsWindow.h eaglGraphicsWindow.I
   eaglGraphicsBuffer.h
   pandaEAGLView.h
-  PandaViewController.h
 )
 
 set(P3EAGLDISPLAY_SOURCES
@@ -19,7 +18,6 @@ set(P3EAGLDISPLAY_SOURCES
   eaglGraphicsWindow.mm
   eaglGraphicsBuffer.mm
   pandaEAGLView.mm
-  PandaViewController.mm
 )
 
 composite_sources(p3eagldisplay P3EAGLDISPLAY_SOURCES)
@@ -27,7 +25,6 @@ add_component_library(p3eagldisplay SYMBOL BUILDING_PANDA_EAGLDISPLAY
   ${P3EAGLDISPLAY_HEADERS} ${P3EAGLDISPLAY_SOURCES})
 target_link_libraries(p3eagldisplay p3gles2gsg panda)
 
-target_include_directories(p3eagldisplay PUBLIC ${PYTHON_INCLUDE_DIRS})
 target_compile_options(p3eagldisplay PRIVATE -fobjc-arc)
 
 # Frameworks:
@@ -38,4 +35,4 @@ target_link_libraries(p3eagldisplay ${UIKIT_LIBRARY} ${QUARTZCORE_LIBRARY})
 if(NOT BUILD_METALIBS)
   install(TARGETS p3eagldisplay EXPORT GLES COMPONENT GLES DESTINATION lib)
 endif()
-install(FILES ${P3EAGLDISPLAY_HEADERS} COMPONENT GLES DESTINATION include/panda3d)
+install(FILES ${P3EAGLDISPLAY_HEADERS} COMPONENT GLES DESTINATION include/panda3d)

+ 0 - 4
panda/src/eagldisplay/eaglGraphicsWindow.h

@@ -29,10 +29,6 @@ class EAGLGraphicsStateGuardian;
  */
 class EAGLGraphicsWindow : public GraphicsWindow {
 public:
-  static PandaViewController *next_view_controller;
-  static TrueMutexImpl vc_lock;
-  static TrueConditionVarImpl vc_condition;
-
   EAGLGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
                      const std::string &name,
                      const FrameBufferProperties &fb_prop,

+ 4 - 18
panda/src/eagldisplay/eaglGraphicsWindow.mm

@@ -23,10 +23,6 @@
 
 TypeHandle EAGLGraphicsWindow::_type_handle;
 
-PandaViewController *EAGLGraphicsWindow::next_view_controller = nil;
-TrueMutexImpl EAGLGraphicsWindow::vc_lock;
-TrueConditionVarImpl EAGLGraphicsWindow::vc_condition = TrueConditionVarImpl(EAGLGraphicsWindow::vc_lock);
-
 // See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocAssociativeReferences.html
 // for what this is doing. Since UITouches don't come with an ID (or any member
 // that can meaningfully be converted to one), we can attach our own using the
@@ -177,24 +173,14 @@ open_window() {
   // reset the GSG before it tries to use it.
   eaglgsg->lock_context();
 
-  // Create the view we're going to render into, and attach it to the supplied
-  // view controller if given.
-  PandaViewController *vc = EAGLGraphicsWindow::next_view_controller;
   dispatch_sync(dispatch_get_main_queue(), ^{
-    CGRect frame = vc ? vc.view.frame : UIScreen.mainScreen.bounds;
-    _view = [[PandaEAGLView alloc] initWithFrame:frame graphicsWindow:this];
+    UIWindow *main_window = UIApplication.sharedApplication.windows[0];
+    _view = [[PandaEAGLView alloc] initWithFrame:main_window.frame graphicsWindow:this];
+    main_window.rootViewController.view = _view;
     _backing_buffer->_layer = _view.layer;
-    _properties.set_size(frame.size.width, frame.size.height);
-    if (vc) {
-      vc.view = _view;
-    }
+    _properties.set_size(_view.frame.size.width, _view.frame.size.height);
   });
 
-  EAGLGraphicsWindow::next_view_controller = nil;
-  EAGLGraphicsWindow::vc_lock.lock();
-  EAGLGraphicsWindow::vc_condition.notify();
-  EAGLGraphicsWindow::vc_lock.unlock();
-
   [EAGLContext setCurrentContext:eaglgsg->_context];
   
   eaglgsg->reset_if_new();

+ 45 - 42
pandatool/CMakeLists.txt

@@ -2,48 +2,51 @@ if(NOT BUILD_PANDA)
   message(FATAL_ERROR "Cannot build pandatool without panda!  Please enable the BUILD_PANDA option.")
 endif()
 
-# Include pandatool source directories
-add_subdirectory(src/assimp)
-add_subdirectory(src/bam)
-add_subdirectory(src/converter)
-add_subdirectory(src/daeegg)
-add_subdirectory(src/daeprogs)
+if(BUILD_PANDATOOL)
+  # Include pandatool source directories
+  add_subdirectory(src/assimp)
+  add_subdirectory(src/bam)
+  add_subdirectory(src/converter)
+  add_subdirectory(src/daeegg)
+  add_subdirectory(src/daeprogs)
+  add_subdirectory(src/dxf)
+  add_subdirectory(src/dxfegg)
+  add_subdirectory(src/dxfprogs)
+  add_subdirectory(src/eggbase)
+  add_subdirectory(src/eggcharbase)
+  add_subdirectory(src/eggprogs)
+  add_subdirectory(src/egg-mkfont)
+  add_subdirectory(src/egg-optchar)
+  add_subdirectory(src/egg-palettize)
+  add_subdirectory(src/egg-qtess)
+  add_subdirectory(src/flt)
+  add_subdirectory(src/fltegg)
+  add_subdirectory(src/fltprogs)
+  add_subdirectory(src/gtk-stats)
+  add_subdirectory(src/imagebase)
+  add_subdirectory(src/imageprogs)
+  add_subdirectory(src/lwo)
+  add_subdirectory(src/lwoegg)
+  add_subdirectory(src/lwoprogs)
+  add_subdirectory(src/miscprogs)
+  add_subdirectory(src/objegg)
+  add_subdirectory(src/objprogs)
+  add_subdirectory(src/palettizer)
+  add_subdirectory(src/pandatoolbase)
+  add_subdirectory(src/pfmprogs)
+  add_subdirectory(src/progbase)
+  add_subdirectory(src/pstatserver)
+  add_subdirectory(src/ptloader)
+  add_subdirectory(src/text-stats)
+  add_subdirectory(src/vrml)
+  add_subdirectory(src/vrmlegg)
+  add_subdirectory(src/vrmlprogs)
+  add_subdirectory(src/win-stats)
+  add_subdirectory(src/xfile)
+  add_subdirectory(src/xfileegg)
+  add_subdirectory(src/xfileprogs)
+endif()
+
 add_subdirectory(src/deploy-stub)
-add_subdirectory(src/dxf)
-add_subdirectory(src/dxfegg)
-add_subdirectory(src/dxfprogs)
-add_subdirectory(src/eggbase)
-add_subdirectory(src/eggcharbase)
-add_subdirectory(src/eggprogs)
-add_subdirectory(src/egg-mkfont)
-add_subdirectory(src/egg-optchar)
-add_subdirectory(src/egg-palettize)
-add_subdirectory(src/egg-qtess)
-add_subdirectory(src/flt)
-add_subdirectory(src/fltegg)
-add_subdirectory(src/fltprogs)
-add_subdirectory(src/gtk-stats)
-add_subdirectory(src/imagebase)
-add_subdirectory(src/imageprogs)
-add_subdirectory(src/lwo)
-add_subdirectory(src/lwoegg)
-add_subdirectory(src/lwoprogs)
-add_subdirectory(src/miscprogs)
-add_subdirectory(src/objegg)
-add_subdirectory(src/objprogs)
-add_subdirectory(src/palettizer)
-add_subdirectory(src/pandatoolbase)
-add_subdirectory(src/pfmprogs)
-add_subdirectory(src/progbase)
-add_subdirectory(src/pstatserver)
-add_subdirectory(src/ptloader)
-add_subdirectory(src/text-stats)
-add_subdirectory(src/vrml)
-add_subdirectory(src/vrmlegg)
-add_subdirectory(src/vrmlprogs)
-add_subdirectory(src/win-stats)
-add_subdirectory(src/xfile)
-add_subdirectory(src/xfileegg)
-add_subdirectory(src/xfileprogs)
 
 export_targets(Tools)

+ 53 - 23
pandatool/src/deploy-stub/CMakeLists.txt

@@ -2,38 +2,68 @@ if(NOT HAVE_PYTHON)
   return()
 endif()
 
-add_executable(deploy-stub deploy-stub.c)
-
-if(IS_OSX)
-  target_link_options(deploy-stub PRIVATE -sectcreate __PANDA __panda /dev/null)
-  set_target_properties(deploy-stub PROPERTIES
-    INSTALL_RPATH "@executable_path"
-    BUILD_WITH_INSTALL_RPATH ON)
-elseif(WIN32)
-  target_sources(deploy-stub frozen_dllmain.c)
-elseif(IS_LINUX OR IS_FREEBSD)
-  set_target_properties(deploy-stub PROPERTIES
-    INSTALL_RPATH "$ORIGIN"
-    BUILD_WITH_INSTALL_RPATH ON)
-endif()
+if(NOT IS_IOS)
+  add_executable(deploy-stub deploy-stub.c)
 
-target_link_libraries(deploy-stub Python::Python)
-install(TARGETS deploy-stub)
+  if(APPLE)
+    target_link_options(deploy-stub PRIVATE -sectcreate __PANDA __panda /dev/null)
+    set_target_properties(deploy-stub PROPERTIES
+      INSTALL_RPATH "@executable_path"
+      BUILD_WITH_INSTALL_RPATH ON)
+    if(IS_IOS)
+      target_sources(deploy-stub PRIVATE ios_main.m)
+      find_library(UIKIT_LIBRARY UIKit)
+      target_link_libraries(deploy-stub ${UIKIT_LIBRARY})
+      target_link_options(deploy-stub PRIVATE -undefined dynamic_lookup)
+    endif()
+  elseif(WIN32)
+    target_sources(deploy-stub PRIVATE frozen_dllmain.c)
+  elseif(IS_LINUX OR IS_FREEBSD)
+    set_target_properties(deploy-stub PROPERTIES
+      INSTALL_RPATH "$ORIGIN"
+      BUILD_WITH_INSTALL_RPATH ON)
+  endif()
+
+  target_link_libraries(deploy-stub Python::Python)
+  install(TARGETS deploy-stub EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR})
+endif()
 
-if(WIN32 OR IS_OSX)
+if(WIN32 OR APPLE)
   add_executable(deploy-stubw deploy-stub.c)
 
-  if(IS_OSX)
+  if(APPLE)
+    if(IS_IOS)
+      set(_rpath "@executable_path")
+      target_sources(deploy-stubw PRIVATE ios_main.m)
+    else()
+      set(_rpath "@executable_path/../Frameworks")
+    endif()
+    target_compile_definitions(deploy-stubw PRIVATE MACOS_APP_BUNDLE=1)
     target_link_options(deploy-stubw PRIVATE -sectcreate __PANDA __panda /dev/null)
+
     set_target_properties(deploy-stubw PROPERTIES
-      INSTALL_RPATH "@executable_path/../Frameworks"
-      BUILD_WITH_INSTALL_RPATH ON)
-    target_compile_definitions(deploy-stubw PRIVATE MACOS_APP_BUNDLE=1)
+      UNITY_BUILD OFF
+      INSTALL_RPATH ${_rpath}
+      BUILD_WITH_INSTALL_RPATH ON
+      XCODE_PRODUCT_TYPE "com.apple.product-type.application")
+
+    if(IS_IOS)
+      find_library(UIKIT_LIBRARY UIKit)
+
+      target_link_libraries(deploy-stubw ${UIKIT_LIBRARY} OpenSSL::SSL OpenSSL::Crypto p3ios)
+      target_link_options(deploy-stubw PRIVATE -undefined dynamic_lookup)
+
+      set_target_properties(deploy-stubw PROPERTIES
+        XCODE_PRODUCT_TYPE "com.apple.product-type.library.static"
+        XCODE_ATTRIBUTE_MACH_O_TYPE "mh_execute"
+        XCODE_ATTRIBUTE_EXECUTABLE_PREFIX ""
+        XCODE_ATTRIBUTE_EXECUTABLE_SUFFIX "")
+    endif()
   elseif(WIN32)
-    target_sources(deploy-stubw frozen_dllmain.c)
+    target_sources(deploy-stubw PRIVATE frozen_dllmain.c)
     set_property(TARGET deploy-stubw WIN32_EXECUTABLE)
   endif()
 
   target_link_libraries(deploy-stubw Python::Python)
-  install(TARGETS deploy-stubw)
+  install(TARGETS deploy-stubw EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR})
 endif()

+ 74 - 32
pandatool/src/deploy-stub/deploy-stub.c

@@ -16,6 +16,7 @@
 #ifdef __APPLE__
 #  include <mach-o/dyld.h>
 #  include <libgen.h>
+#  include <TargetConditionals.h>
 #endif
 
 #include <stdio.h>
@@ -52,6 +53,7 @@ volatile struct {
   // The reason we initialize it to -1 is because otherwise, smart linkers may
   // end up putting it in the .bss section for zero-initialized data.
 } blobinfo = {(uint64_t)-1};
+void *blob;
 
 #ifdef MS_WINDOWS
 #  define WIN32_LEAN_AND_MEAN
@@ -101,6 +103,13 @@ static int supports_code_page(UINT cp) {
 }
 #endif
 
+#if TARGET_OS_IPHONE
+extern void ios_ensure_thread_safety();
+extern int ios_main(int argc, char *argv[]);
+
+int stored_argc;
+#endif
+
 /**
  * Sets the main_dir field of the blobinfo structure, but only if it wasn't
  * already set.
@@ -446,7 +455,11 @@ int Py_FrozenMain(int argc, char **argv)
       return 1;
     }
     const char *dir = dirname(resolved);
+#if TARGET_OS_IPHONE
+    strcpy(buffer, dir);
+#else
     sprintf(buffer, "%s/../Frameworks", dir);
+#endif
 
     PyObject *sys_path = PyList_New(1);
     PyList_SET_ITEM(sys_path, 0, PyUnicode_FromString(buffer));
@@ -455,7 +468,11 @@ int Py_FrozenMain(int argc, char **argv)
 
     // Now, store a path to the Resources directory into the main_dir pointer,
     // for ConfigPageManager to read out and assign to MAIN_DIR.
+#if TARGET_OS_IPHONE
+    strcpy(buffer, dir);
+#else
     sprintf(buffer, "%s/../Resources", dir);
+#endif
     set_main_dir(buffer);
 
     // Finally, chdir to it, so that regular Python files are read from the
@@ -492,6 +509,12 @@ error:
     return sts;
 }
 
+#if TARGET_OS_IPHONE
+void Py_FrozenMain_Threaded(void *argv_ptr) {
+  Py_FrozenMain(stored_argc, (char **)argv_ptr);
+}
+#endif
+
 /**
  * Maps the binary blob at the given memory address to memory, and returns the
  * pointer to the beginning of it.
@@ -571,6 +594,41 @@ static void unmap_blob(void *blob) {
   }
 }
 
+__attribute__((__visibility__("default")))
+void *load_blobinfo_pointers() {
+    if (blob == NULL) {
+        blob = map_blob((off_t)blobinfo.blob_offset, (size_t)blobinfo.blob_size);
+        assert(blob != NULL);
+    }
+
+    // Offset the pointers in the header using the base mmap address.
+    if (blobinfo.version > 0 && blobinfo.num_pointers > 0) {
+        uint32_t i;
+        assert(blobinfo.num_pointers <= MAX_NUM_POINTERS);
+        for (i = 0; i < blobinfo.num_pointers; ++i) {
+            // Only offset if the pointer is non-NULL.  Except for the first
+            // pointer, which may never be NULL and usually (but not always)
+            // points to the beginning of the blob.
+            if (i == 0 || blobinfo.pointers[i] != 0) {
+                blobinfo.pointers[i] = (void *)((uintptr_t)blobinfo.pointers[i] + (uintptr_t)blob);
+            }
+        }
+    } else {
+        blobinfo.pointers[0] = blob;
+    }
+
+    // Offset the pointers in the module table using the base mmap address.
+    struct _frozen *moddef = blobinfo.pointers[0];
+    while (moddef->name) {
+        moddef->name = (char *)((uintptr_t)moddef->name + (uintptr_t)blob);
+        if (moddef->code != 0) {
+            moddef->code = (unsigned char *)((uintptr_t)moddef->code + (uintptr_t)blob);
+        }
+        //printf("MOD: %s %p %d\n", moddef->name, (void*)moddef->code, moddef->size);
+        moddef++;
+    }
+}
+
 /**
  * Main entry point to deploy-stub.
  */
@@ -580,9 +638,7 @@ int wmain(int argc, wchar_t *argv[]) {
 int main(int argc, char *argv[]) {
 #endif
   int retval;
-  struct _frozen *moddef;
   const char *log_filename;
-  void *blob = NULL;
   log_filename = NULL;
 
 #ifdef __APPLE__
@@ -606,37 +662,11 @@ int main(int argc, char *argv[]) {
 
   // If we have a blob offset, we have to map the blob to memory.
   if (blobinfo.version == 0 || blobinfo.blob_offset != 0) {
-    void *blob = map_blob((off_t)blobinfo.blob_offset, (size_t)blobinfo.blob_size);
-    assert(blob != NULL);
-
-    // Offset the pointers in the header using the base mmap address.
-    if (blobinfo.version > 0 && blobinfo.num_pointers > 0) {
-      uint32_t i;
-      assert(blobinfo.num_pointers <= MAX_NUM_POINTERS);
-      for (i = 0; i < blobinfo.num_pointers; ++i) {
-        // Only offset if the pointer is non-NULL.  Except for the first
-        // pointer, which may never be NULL and usually (but not always)
-        // points to the beginning of the blob.
-        if (i == 0 || blobinfo.pointers[i] != 0) {
-          blobinfo.pointers[i] = (void *)((uintptr_t)blobinfo.pointers[i] + (uintptr_t)blob);
-        }
-      }
-      if (blobinfo.num_pointers >= 12) {
-        log_filename = blobinfo.pointers[11];
-      }
-    } else {
-      blobinfo.pointers[0] = blob;
+    if (blobinfo.pointers[0] == NULL) {
+      load_blobinfo_pointers();
     }
-
-    // Offset the pointers in the module table using the base mmap address.
-    moddef = blobinfo.pointers[0];
-    while (moddef->name) {
-      moddef->name = (char *)((uintptr_t)moddef->name + (uintptr_t)blob);
-      if (moddef->code != 0) {
-        moddef->code = (unsigned char *)((uintptr_t)moddef->code + (uintptr_t)blob);
-      }
-      //printf("MOD: %s %p %d\n", moddef->name, (void*)moddef->code, moddef->size);
-      moddef++;
+    if (blobinfo.version > 0 && blobinfo.num_pointers > 0 && blobinfo.num_pointers >= 12) {
+      log_filename = blobinfo.pointers[11];
     }
   }
 
@@ -653,7 +683,19 @@ int main(int argc, char *argv[]) {
 
   // Run frozen application
   PyImport_FrozenModules = blobinfo.pointers[0];
+
+#if TARGET_OS_IPHONE
+  stored_argc = argc;
+  ios_ensure_thread_safety();
+
+  pthread_t thread_id;
+  pthread_create(&thread_id, NULL, Py_FrozenMain_Threaded, argv);
+  pthread_detach(thread_id);
+
+  retval = ios_main(argc, argv);
+#else
   retval = Py_FrozenMain(argc, argv);
+#endif
 
   fflush(stdout);
   fflush(stderr);