diff --git a/drivers/apple_embedded/SCsub b/drivers/apple_embedded/SCsub index 7a4b82bd9e0..7cf6599d60d 100644 --- a/drivers/apple_embedded/SCsub +++ b/drivers/apple_embedded/SCsub @@ -1,6 +1,10 @@ #!/usr/bin/env python from misc.utility.scons_hints import * +from SCons.Script import Glob + +from platform_methods import setup_swift_builder + Import("env") env_apple_embedded = env.Clone() @@ -8,9 +12,21 @@ env_apple_embedded = env.Clone() # Enable module support env_apple_embedded.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) +# Configure Swift builder +apple_platform = env["APPLE_PLATFORM"] +sdk_path = env["APPLE_SDK_PATH"] +current_path = Dir(".").abspath +bridging_header_filename = "bridging_header_apple_embedded.h" +swift_files = Glob("*.swift") +swift_file_names = list(map(lambda f: f.name, swift_files)) +setup_swift_builder( + env_apple_embedded, apple_platform, sdk_path, current_path, bridging_header_filename, swift_file_names +) + # Use bundled Vulkan headers vulkan_dir = "#thirdparty/vulkan" env_apple_embedded.Prepend(CPPPATH=[vulkan_dir, vulkan_dir + "/include"]) # Driver source files -env_apple_embedded.add_source_files(env.drivers_sources, "*.mm") +env_apple_embedded.add_source_files(env_apple_embedded.drivers_sources, "*.mm") +env_apple_embedded.add_source_files(env_apple_embedded.drivers_sources, "*.swift") diff --git a/drivers/apple_embedded/app.swift b/drivers/apple_embedded/app.swift new file mode 100644 index 00000000000..c94b5d1ed73 --- /dev/null +++ b/drivers/apple_embedded/app.swift @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* app.swift */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +import SwiftUI +import UIKit + +struct GodotSwiftUIViewController: UIViewControllerRepresentable { + + func makeUIViewController(context: Context) -> GDTViewController { + let viewController = GDTViewController() + GDTAppDelegateService.viewController = viewController + return viewController + } + + func updateUIViewController(_ uiViewController: GDTViewController, context: Context) { + // NOOP + } + +} + +@main +struct SwiftUIApp: App { + @UIApplicationDelegateAdaptor(GDTApplicationDelegate.self) var appDelegate + @Environment(\.scenePhase) private var scenePhase + + var body: some Scene { + WindowGroup { + GodotSwiftUIViewController() + .ignoresSafeArea() + // UIViewControllerRepresentable does not call viewWillDisappear() nor viewDidDisappear() when + // backgrounding the app, or closing the app's main window, update the renderer here. + .onChange(of: scenePhase) { phase in + // For some reason UIViewControllerRepresentable is not calling viewWillDisappear() + // nor viewDidDisappear when closing the app's main window, call it here so we + // stop the renderer. + switch phase { + case .active: + print("GodotSwiftUIViewController scene active") + GDTAppDelegateService.viewController?.godotView.startRendering() + case .inactive: + print("GodotSwiftUIViewController scene inactive") + GDTAppDelegateService.viewController?.godotView.stopRendering() + case .background: + print("GodotSwiftUIViewController scene backgrounded") + GDTAppDelegateService.viewController?.godotView.stopRendering() + @unknown default: + print("unknown default") + } + } + } + } +} diff --git a/drivers/apple_embedded/app_delegate_service.h b/drivers/apple_embedded/app_delegate_service.h index 6314d6060b3..d2372fdd11a 100644 --- a/drivers/apple_embedded/app_delegate_service.h +++ b/drivers/apple_embedded/app_delegate_service.h @@ -36,7 +36,6 @@ @interface GDTAppDelegateService : NSObject -@property(strong, nonatomic) UIWindow *window; -@property(strong, class, readonly, nonatomic) GDTViewController *viewController; +@property(strong, class, nonatomic) GDTViewController *viewController; @end diff --git a/drivers/apple_embedded/app_delegate_service.mm b/drivers/apple_embedded/app_delegate_service.mm index 07b52b9d9c6..7c433a48359 100644 --- a/drivers/apple_embedded/app_delegate_service.mm +++ b/drivers/apple_embedded/app_delegate_service.mm @@ -31,8 +31,8 @@ #import "app_delegate_service.h" #import "godot_view_apple_embedded.h" +#import "godot_view_controller.h" #import "os_apple_embedded.h" -#import "view_controller.h" #include "core/config/project_settings.h" #import "drivers/coreaudio/audio_driver_coreaudio.h" @@ -41,10 +41,8 @@ #import #import -#define kRenderingFrequency 60 - -extern int gargc; -extern char **gargv; +int gargc; +char **gargv; extern int apple_embedded_main(int, char **); extern void apple_embedded_finish(); @@ -66,18 +64,23 @@ static GDTViewController *mainViewController = nil; return mainViewController; } ++ (void)setViewController:(GDTViewController *)viewController { + mainViewController = viewController; +} + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // TODO: might be required to make an early return, so app wouldn't crash because of timeout. // TODO: logo screen is not displayed while shaders are compiling // DummyViewController(Splash/LoadingViewController) -> setup -> GodotViewController -#if !defined(VISIONOS_ENABLED) - // Create a full-screen window - CGRect windowBounds = [[UIScreen mainScreen] bounds]; - self.window = [[UIWindow alloc] initWithFrame:windowBounds]; -#else - self.window = [[UIWindow alloc] init]; -#endif + // Fetch the command-line arguments from NSProcessInfo + NSArray *arguments = [[NSProcessInfo processInfo] arguments]; + gargc = (int)[arguments count]; + gargv = (char **)malloc(sizeof(char *) * gargc); + for (int i = 0; i < gargc; i++) { + NSString *arg = arguments[i]; + gargv[i] = strdup([arg UTF8String]); + } int err = apple_embedded_main(gargc, gargv); @@ -87,23 +90,12 @@ static GDTViewController *mainViewController = nil; return NO; } - GDTViewController *viewController = [[GDTViewController alloc] init]; - viewController.godotView.useCADisplayLink = bool(GLOBAL_DEF("display.iOS/use_cadisplaylink", true)) ? YES : NO; - viewController.godotView.renderingInterval = 1.0 / kRenderingFrequency; - - self.window.rootViewController = viewController; - - // Show the window - [self.window makeKeyAndVisible]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAudioInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; - mainViewController = viewController; - int sessionCategorySetting = GLOBAL_GET("audio/general/ios/session_category"); // Initialize with default Ambient category. diff --git a/drivers/apple_embedded/apple_embedded.mm b/drivers/apple_embedded/apple_embedded.mm index 33d23061f07..7e8fd4af032 100644 --- a/drivers/apple_embedded/apple_embedded.mm +++ b/drivers/apple_embedded/apple_embedded.mm @@ -31,7 +31,7 @@ #import "apple_embedded.h" #import "app_delegate_service.h" -#import "view_controller.h" +#import "godot_view_controller.h" #import #import diff --git a/drivers/apple_embedded/bridging_header_apple_embedded.h b/drivers/apple_embedded/bridging_header_apple_embedded.h new file mode 100644 index 00000000000..ea608ecae2b --- /dev/null +++ b/drivers/apple_embedded/bridging_header_apple_embedded.h @@ -0,0 +1,36 @@ +/**************************************************************************/ +/* bridging_header_apple_embedded.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#import "app_delegate_service.h" +#import "godot_app_delegate.h" +#import "godot_view_apple_embedded.h" +#import "godot_view_controller.h" diff --git a/drivers/apple_embedded/display_server_apple_embedded.mm b/drivers/apple_embedded/display_server_apple_embedded.mm index 886a17dcef0..dfaaf7cb567 100644 --- a/drivers/apple_embedded/display_server_apple_embedded.mm +++ b/drivers/apple_embedded/display_server_apple_embedded.mm @@ -32,12 +32,12 @@ #import "app_delegate_service.h" #import "apple_embedded.h" +#import "godot_keyboard_input_view.h" #import "godot_view_apple_embedded.h" +#import "godot_view_controller.h" #import "key_mapping_apple_embedded.h" -#import "keyboard_input_view.h" #import "os_apple_embedded.h" #import "tts_apple_embedded.h" -#import "view_controller.h" #include "core/config/project_settings.h" #include "core/io/file_access_pack.h" @@ -612,9 +612,8 @@ void DisplayServerAppleEmbedded::window_set_size(const Size2i p_size, WindowID p } Size2i DisplayServerAppleEmbedded::window_get_size(WindowID p_window) const { - id appDelegate = [[UIApplication sharedApplication] delegate]; - CGRect windowBounds = appDelegate.window.bounds; - return Size2i(windowBounds.size.width, windowBounds.size.height) * screen_get_max_scale(); + CGRect viewBounds = GDTAppDelegateService.viewController.view.bounds; + return Size2i(viewBounds.size.width, viewBounds.size.height) * screen_get_max_scale(); } Size2i DisplayServerAppleEmbedded::window_get_size_with_decorations(WindowID p_window) const { diff --git a/drivers/apple_embedded/godot_app_delegate.mm b/drivers/apple_embedded/godot_app_delegate.mm index 7e78b3fc3ba..8d3acbe86ee 100644 --- a/drivers/apple_embedded/godot_app_delegate.mm +++ b/drivers/apple_embedded/godot_app_delegate.mm @@ -31,6 +31,7 @@ #import "godot_app_delegate.h" #import "app_delegate_service.h" +#include "core/typedefs.h" @implementation GDTApplicationDelegate @@ -120,6 +121,9 @@ static NSMutableArray *services = nil; // MARK: Life-Cycle +// UIApplication lifecycle has become deprecated in favor of UIScene lifecycle +GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wdeprecated-declarations") + - (void)applicationDidBecomeActive:(UIApplication *)application { for (GDTAppDelegateServiceProtocol *service in services) { if (![service respondsToSelector:_cmd]) { @@ -461,3 +465,5 @@ static NSMutableArray *services = nil; */ @end + +GODOT_CLANG_WARNING_POP diff --git a/drivers/apple_embedded/keyboard_input_view.h b/drivers/apple_embedded/godot_keyboard_input_view.h similarity index 97% rename from drivers/apple_embedded/keyboard_input_view.h rename to drivers/apple_embedded/godot_keyboard_input_view.h index 3f57d6d2687..f96b036b050 100644 --- a/drivers/apple_embedded/keyboard_input_view.h +++ b/drivers/apple_embedded/godot_keyboard_input_view.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* keyboard_input_view.h */ +/* godot_keyboard_input_view.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/drivers/apple_embedded/keyboard_input_view.mm b/drivers/apple_embedded/godot_keyboard_input_view.mm similarity index 98% rename from drivers/apple_embedded/keyboard_input_view.mm rename to drivers/apple_embedded/godot_keyboard_input_view.mm index 3079d5a5235..9cbc9a0f48f 100644 --- a/drivers/apple_embedded/keyboard_input_view.mm +++ b/drivers/apple_embedded/godot_keyboard_input_view.mm @@ -1,5 +1,5 @@ /**************************************************************************/ -/* keyboard_input_view.mm */ +/* godot_keyboard_input_view.mm */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#import "keyboard_input_view.h" +#import "godot_keyboard_input_view.h" #import "display_server_apple_embedded.h" #import "os_apple_embedded.h" diff --git a/drivers/apple_embedded/godot_view_apple_embedded.h b/drivers/apple_embedded/godot_view_apple_embedded.h index 0694d3a4c90..7d5d16141a5 100644 --- a/drivers/apple_embedded/godot_view_apple_embedded.h +++ b/drivers/apple_embedded/godot_view_apple_embedded.h @@ -55,7 +55,7 @@ class String; @property(strong, readonly, nonatomic) CALayer *renderingLayer; @property(assign, readonly, nonatomic) BOOL canRender; -@property(assign, nonatomic) NSTimeInterval renderingInterval; +@property(assign, nonatomic) float preferredFrameRate; // Can be extended by subclasses - (void)godot_commonInit; @@ -63,8 +63,8 @@ class String; // Implemented in subclasses - (CALayer *)initializeRenderingForDriver:(NSString *)driverName; -- (void)stopRendering; - (void)startRendering; +- (void)stopRendering; @end diff --git a/drivers/apple_embedded/godot_view_apple_embedded.mm b/drivers/apple_embedded/godot_view_apple_embedded.mm index dd6ba3f5d2b..8f187703a24 100644 --- a/drivers/apple_embedded/godot_view_apple_embedded.mm +++ b/drivers/apple_embedded/godot_view_apple_embedded.mm @@ -60,6 +60,8 @@ static const float earth_gravity = 9.80665; @property(strong, nonatomic) CMMotionManager *motionManager; +@property(assign, nonatomic) BOOL delegateDidFinishSetUp; + @end @implementation GDTView @@ -117,6 +119,9 @@ static const float earth_gravity = 9.80665; } - (void)godot_commonInit { + self.preferredFrameRate = 60; + self.useCADisplayLink = bool(GLOBAL_DEF("display.AppleEmbedded/use_cadisplaylink", true)) ? YES : NO; + #if !defined(VISIONOS_ENABLED) self.contentScaleFactor = [UIScreen mainScreen].scale; #endif @@ -197,17 +202,12 @@ static const float earth_gravity = 9.80665; if (self.useCADisplayLink) { self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawView)]; - - if (GLOBAL_GET("display/window/ios/allow_high_refresh_rate")) { - self.displayLink.preferredFramesPerSecond = 120; - } else { - self.displayLink.preferredFramesPerSecond = 60; - } + self.displayLink.preferredFramesPerSecond = self.preferredFrameRate; // Setup DisplayLink in main thread [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; } else { - self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60) target:self selector:@selector(drawView) userInfo:nil repeats:YES]; + self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / self.preferredFrameRate) target:self selector:@selector(drawView) userInfo:nil repeats:YES]; } } @@ -240,10 +240,10 @@ static const float earth_gravity = 9.80665; return; } - if (self.delegate) { - BOOL delegateFinishedSetup = [self.delegate godotViewFinishedSetup:self]; - - if (!delegateFinishedSetup) { + if (self.delegate && !self.delegateDidFinishSetUp) { + [self layoutRenderingLayer]; // Trigger DisplayServerVisionOS::resize_window after Main::start() + self.delegateDidFinishSetUp = [self.delegate godotViewFinishedSetup:self]; + if (!_delegateDidFinishSetUp) { return; } } @@ -262,8 +262,8 @@ static const float earth_gravity = 9.80665; } } -- (void)setRenderingInterval:(NSTimeInterval)renderingInterval { - _renderingInterval = renderingInterval; +- (void)setPreferredFrameRate:(float)preferredFrameRate { + _preferredFrameRate = preferredFrameRate; if (self.canRender) { [self stopRendering]; @@ -272,6 +272,11 @@ static const float earth_gravity = 9.80665; } - (void)layoutSubviews { + [super layoutSubviews]; + [self layoutRenderingLayer]; +} + +- (void)layoutRenderingLayer { if (self.renderingLayer) { self.renderingLayer.frame = self.bounds; [self.renderingLayer layoutDisplayLayer]; @@ -280,8 +285,6 @@ static const float earth_gravity = 9.80665; DisplayServerAppleEmbedded::get_singleton()->resize_window(self.bounds.size); } } - - [super layoutSubviews]; } // MARK: - Input @@ -415,28 +418,10 @@ static const float earth_gravity = 9.80665; // our orientation which is not a good thing when you're trying to get // your user to move the screen in all directions and want consistent // output - - ///@TODO Using [[UIApplication sharedApplication] statusBarOrientation] - /// is a bit of a hack. Godot obviously knows the orientation so maybe - /// we - // can use that instead? (note that left and right seem swapped) - - UIInterfaceOrientation interfaceOrientation = UIInterfaceOrientationUnknown; - -#if !defined(VISIONOS_ENABLED) -#if __IPHONE_OS_VERSION_MAX_ALLOWED < 140000 - interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; +#if defined(VISIONOS_ENABLED) + UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].delegate.window.windowScene.effectiveGeometry.interfaceOrientation; #else - if (@available(iOS 13, *)) { - interfaceOrientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation; -#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR - } else { - interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; -#endif - } -#endif -#else - interfaceOrientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation; + UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation; #endif switch (interfaceOrientation) { diff --git a/drivers/apple_embedded/view_controller.h b/drivers/apple_embedded/godot_view_controller.h similarity index 97% rename from drivers/apple_embedded/view_controller.h rename to drivers/apple_embedded/godot_view_controller.h index 949e3040c90..b5d8e7043fa 100644 --- a/drivers/apple_embedded/view_controller.h +++ b/drivers/apple_embedded/godot_view_controller.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* view_controller.h */ +/* godot_view_controller.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/drivers/apple_embedded/view_controller.mm b/drivers/apple_embedded/godot_view_controller.mm similarity index 96% rename from drivers/apple_embedded/view_controller.mm rename to drivers/apple_embedded/godot_view_controller.mm index 15dc1daf16e..94d52b17346 100644 --- a/drivers/apple_embedded/view_controller.mm +++ b/drivers/apple_embedded/godot_view_controller.mm @@ -1,5 +1,5 @@ /**************************************************************************/ -/* view_controller.mm */ +/* godot_view_controller.mm */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#import "view_controller.h" +#import "godot_view_controller.h" #import "display_server_apple_embedded.h" +#import "godot_keyboard_input_view.h" #import "godot_view_apple_embedded.h" #import "godot_view_renderer.h" #import "key_mapping_apple_embedded.h" -#import "keyboard_input_view.h" #import "os_apple_embedded.h" #include "core/config/project_settings.h" @@ -168,6 +168,16 @@ [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; } +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self.godotView startRendering]; +} + +- (void)viewDidDisappear:(BOOL)animated { + [self.godotView stopRendering]; + [super viewDidDisappear:animated]; +} + - (void)observeKeyboard { print_verbose("Setting up keyboard input view."); self.keyboardView = [GDTKeyboardInputView new]; diff --git a/drivers/apple_embedded/os_apple_embedded.mm b/drivers/apple_embedded/os_apple_embedded.mm index 07d1f8a270c..08621ddc095 100644 --- a/drivers/apple_embedded/os_apple_embedded.mm +++ b/drivers/apple_embedded/os_apple_embedded.mm @@ -35,7 +35,7 @@ #import "app_delegate_service.h" #import "display_server_apple_embedded.h" #import "godot_view_apple_embedded.h" -#import "view_controller.h" +#import "godot_view_controller.h" #include "core/config/project_settings.h" #include "core/io/dir_access.h" diff --git a/editor/export/editor_export_platform_apple_embedded.cpp b/editor/export/editor_export_platform_apple_embedded.cpp index 30334300862..820666a4b9b 100644 --- a/editor/export/editor_export_platform_apple_embedded.cpp +++ b/editor/export/editor_export_platform_apple_embedded.cpp @@ -638,35 +638,6 @@ String EditorExportPlatformAppleEmbedded::_process_config_file_line(const Ref(), - false }; config_data.plist_content += p_preset->get("application/additional_plist_content").operator String() + "\n"; diff --git a/editor/export/editor_export_platform_apple_embedded.h b/editor/export/editor_export_platform_apple_embedded.h index 283392cf8ae..6e6f6cd02d0 100644 --- a/editor/export/editor_export_platform_apple_embedded.h +++ b/editor/export/editor_export_platform_apple_embedded.h @@ -142,7 +142,6 @@ protected: String modules_buildphase; String modules_buildgrp; Vector capabilities; - bool use_swift_runtime; }; struct CodeSigningDetails { diff --git a/editor/export/plugin_config_apple_embedded.cpp b/editor/export/plugin_config_apple_embedded.cpp index eb7b6ebd142..5e9933777a9 100644 --- a/editor/export/plugin_config_apple_embedded.cpp +++ b/editor/export/plugin_config_apple_embedded.cpp @@ -184,7 +184,6 @@ PluginConfigAppleEmbedded PluginConfigAppleEmbedded::load_plugin_config(Refget_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_NAME_KEY, String()); - plugin_config.use_swift_runtime = config_file->get_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_USE_SWIFT_KEY, false); plugin_config.initialization_method = config_file->get_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_INITIALIZE_KEY, String()); plugin_config.deinitialization_method = config_file->get_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_DEINITIALIZE_KEY, String()); diff --git a/editor/export/plugin_config_apple_embedded.h b/editor/export/plugin_config_apple_embedded.h index 1cb28909463..eee1de83f44 100644 --- a/editor/export/plugin_config_apple_embedded.h +++ b/editor/export/plugin_config_apple_embedded.h @@ -37,7 +37,6 @@ The `config` section and fields are required and defined as follow: - **name**: name of the plugin - **binary**: path to static `.a` library -- **use_swift_runtime**: optional boolean field used to determine if Swift runtime is used The `dependencies` and fields are optional. - **linked**: dependencies that should only be linked. @@ -56,7 +55,6 @@ struct PluginConfigAppleEmbedded { inline static const char *CONFIG_SECTION = "config"; inline static const char *CONFIG_NAME_KEY = "name"; inline static const char *CONFIG_BINARY_KEY = "binary"; - inline static const char *CONFIG_USE_SWIFT_KEY = "use_swift_runtime"; inline static const char *CONFIG_INITIALIZE_KEY = "initialization"; inline static const char *CONFIG_DEINITIALIZE_KEY = "deinitialization"; @@ -93,7 +91,6 @@ struct PluginConfigAppleEmbedded { // Required config section String name; String binary; - bool use_swift_runtime; String initialization_method; String deinitialization_method; diff --git a/methods.py b/methods.py index 25fc5813a17..b0fab65f657 100644 --- a/methods.py +++ b/methods.py @@ -42,8 +42,8 @@ def add_source_files_orig(self, sources, files, allow_gen=False): files = [f for f in files if not str(f).endswith(".gen.cpp")] # Add each path as compiled Object following environment (self) configuration - for path in files: - obj = self.Object(path) + for file in files: + obj = self.Object(file) if obj in sources: print_warning('Object "{}" already included in environment sources.'.format(obj)) continue @@ -437,6 +437,7 @@ def no_verbose(env): env["CXXCOMSTR"] = compile_source_message env["CCCOMSTR"] = compile_source_message + env["SWIFTCOMSTR"] = compile_source_message env["SHCCCOMSTR"] = compile_shared_source_message env["SHCXXCOMSTR"] = compile_shared_source_message env["ARCOMSTR"] = link_library_message @@ -630,19 +631,19 @@ def detect_darwin_sdk_path(platform, env): elif platform == "ios": sdk_name = "iphoneos" - var_name = "IOS_SDK_PATH" + var_name = "APPLE_SDK_PATH" elif platform == "iossimulator": sdk_name = "iphonesimulator" - var_name = "IOS_SDK_PATH" + var_name = "APPLE_SDK_PATH" elif platform == "visionos": sdk_name = "xros" - var_name = "VISIONOS_SDK_PATH" + var_name = "APPLE_SDK_PATH" elif platform == "visionossimulator": sdk_name = "xrsimulator" - var_name = "VISIONOS_SDK_PATH" + var_name = "APPLE_SDK_PATH" else: raise Exception("Invalid platform argument passed to detect_darwin_sdk_path") diff --git a/misc/dist/apple_embedded_xcode/godot_apple_embedded.xcodeproj/project.pbxproj b/misc/dist/apple_embedded_xcode/godot_apple_embedded.xcodeproj/project.pbxproj index 6af6b2452f6..10e5226dd61 100644 --- a/misc/dist/apple_embedded_xcode/godot_apple_embedded.xcodeproj/project.pbxproj +++ b/misc/dist/apple_embedded_xcode/godot_apple_embedded.xcodeproj/project.pbxproj @@ -10,7 +10,7 @@ 1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; }; DEADBEEF2F582BE20003B888 /* $binary.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.xcframework */; }; $modules_buildfile - $swift_runtime_buildfile + 90B4C2B62680C7E90039117A /* dummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90B4C2B52680C7E90039117A /* dummy.swift */; }; 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */; }; D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D07CD44D1C5D589C00B7FB28 /* Images.xcassets */; }; $moltenvk_buildfile @@ -38,7 +38,8 @@ 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = "$binary/dylibs"; sourceTree = ""; }; DEADBEEF1F582BE20003B888 /* $binary.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = godot; path = "$binary.xcframework"; sourceTree = ""; }; $modules_fileref - $swift_runtime_fileref + 90B4C2AA2680BC560039117A /* dummy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "dummy.h"; sourceTree = ""; }; + 90B4C2B52680C7E90039117A /* dummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "dummy.swift"; sourceTree = ""; }; 1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "$binary.entitlements"; sourceTree = ""; }; 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = ""; }; $moltenvk_fileref @@ -109,7 +110,8 @@ D07CD44D1C5D589C00B7FB28 /* Images.xcassets */, D0BCFE4218AEBDA2004A7AAE /* Supporting Files */, 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */, - $swift_runtime_binary_files + 90B4C2AA2680BC560039117A /* dummy.h */, + 90B4C2B52680C7E90039117A /* dummy.swift */, ); path = "$binary"; sourceTree = ""; @@ -155,7 +157,7 @@ TargetAttributes = { D0BCFE3318AEBDA2004A7AAE = { DevelopmentTeam = $team_id; - $swift_runtime_migration + LastSwiftMigration = 1250; ProvisioningStyle = Automatic; SystemCapabilities = { }; @@ -202,7 +204,7 @@ buildActionMask = 2147483647; files = ( 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */, - $swift_runtime_build_phase + 90B4C2B62680C7E90039117A /* dummy.swift */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -340,7 +342,9 @@ TARGETED_DEVICE_FAMILY = "$targeted_device_family"; VALID_ARCHS = "$valid_archs"; WRAPPER_EXTENSION = app; - $swift_runtime_build_settings + CLANG_ENABLE_MODULES = YES; + SWIFT_OBJC_BRIDGING_HEADER = "$binary/dummy.h"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -375,7 +379,9 @@ TARGETED_DEVICE_FAMILY = "$targeted_device_family"; VALID_ARCHS = "$valid_archs"; WRAPPER_EXTENSION = app; - $swift_runtime_build_settings + CLANG_ENABLE_MODULES = YES; + SWIFT_OBJC_BRIDGING_HEADER = "$binary/dummy.h"; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/platform/ios/detect.py b/platform/ios/detect.py index f996bf7781c..b7953ceb79d 100644 --- a/platform/ios/detect.py +++ b/platform/ios/detect.py @@ -27,7 +27,7 @@ def get_opts(): ("vulkan_sdk_path", "Path to the Vulkan SDK", ""), # APPLE_TOOLCHAIN_PATH Example: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain (("APPLE_TOOLCHAIN_PATH", "IOS_TOOLCHAIN_PATH"), "Path to the Apple toolchain", ""), - ("IOS_SDK_PATH", "Path to the iOS SDK", ""), + (("APPLE_SDK_PATH", "IOS_SDK_PATH"), "Path to the iOS SDK", ""), (("apple_target_triple", "ios_triple"), "Triple for the corresponding target Apple platform toolchain", ""), BoolVariable(("simulator", "ios_simulator"), "Build for Simulator", False), BoolVariable("generate_bundle", "Generate an APP bundle after building iOS/macOS binaries", False), @@ -101,15 +101,16 @@ def configure(env: "SConsEnvironment"): ## Compile flags if env["simulator"]: - detect_darwin_sdk_path("iossimulator", env) - env.Append(ASFLAGS=["-mios-simulator-version-min=12.0"]) - env.Append(CCFLAGS=["-mios-simulator-version-min=12.0"]) + env["APPLE_PLATFORM"] = "iossimulator" + env.Append(ASFLAGS=["-mios-simulator-version-min=14.0"]) + env.Append(CCFLAGS=["-mios-simulator-version-min=14.0"]) env.Append(CPPDEFINES=["IOS_SIMULATOR"]) env.extra_suffix = ".simulator" + env.extra_suffix else: - detect_darwin_sdk_path("ios", env) - env.Append(ASFLAGS=["-miphoneos-version-min=12.0"]) - env.Append(CCFLAGS=["-miphoneos-version-min=12.0"]) + env["APPLE_PLATFORM"] = "ios" + env.Append(ASFLAGS=["-miphoneos-version-min=14.0"]) + env.Append(CCFLAGS=["-miphoneos-version-min=14.0"]) + detect_darwin_sdk_path(env["APPLE_PLATFORM"], env) if env["arch"] == "x86_64": if not env["simulator"]: @@ -121,7 +122,7 @@ def configure(env: "SConsEnvironment"): CCFLAGS=( "-fobjc-arc -arch x86_64" " -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks" - " -fasm-blocks -isysroot $IOS_SDK_PATH" + " -fasm-blocks -isysroot $APPLE_SDK_PATH" ).split() ) env.Append(ASFLAGS=["-arch", "x86_64"]) @@ -131,7 +132,7 @@ def configure(env: "SConsEnvironment"): "-fobjc-arc -arch arm64 -fmessage-length=0" " -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits" " -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies" - " -isysroot $IOS_SDK_PATH".split() + " -isysroot $APPLE_SDK_PATH".split() ) ) env.Append(ASFLAGS=["-arch", "arm64"]) @@ -141,8 +142,8 @@ def configure(env: "SConsEnvironment"): env.Prepend( CPPPATH=[ - "$IOS_SDK_PATH/usr/include", - "$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers", + "$APPLE_SDK_PATH/usr/include", + "$APPLE_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers", ] ) @@ -157,9 +158,9 @@ def configure(env: "SConsEnvironment"): env.AppendUnique(CPPDEFINES=["METAL_ENABLED", "RD_ENABLED"]) env.Prepend( CPPPATH=[ - "$IOS_SDK_PATH/System/Library/Frameworks/Metal.framework/Headers", - "$IOS_SDK_PATH/System/Library/Frameworks/MetalFX.framework/Headers", - "$IOS_SDK_PATH/System/Library/Frameworks/QuartzCore.framework/Headers", + "$APPLE_SDK_PATH/System/Library/Frameworks/Metal.framework/Headers", + "$APPLE_SDK_PATH/System/Library/Frameworks/MetalFX.framework/Headers", + "$APPLE_SDK_PATH/System/Library/Frameworks/QuartzCore.framework/Headers", ] ) env.Prepend(CPPEXTPATH=["#thirdparty/spirv-cross"]) @@ -176,6 +177,6 @@ def configure(env: "SConsEnvironment"): env.Append(CCFLAGS=["-Wno-module-import-in-extern-c"]) env.Prepend( CPPPATH=[ - "$IOS_SDK_PATH/System/Library/Frameworks/OpenGLES.framework/Headers", + "$APPLE_SDK_PATH/System/Library/Frameworks/OpenGLES.framework/Headers", ] ) diff --git a/platform/ios/godot_view_ios.mm b/platform/ios/godot_view_ios.mm index f8d049feef4..c267ac397d0 100644 --- a/platform/ios/godot_view_ios.mm +++ b/platform/ios/godot_view_ios.mm @@ -32,6 +32,7 @@ #import "display_layer_ios.h" +#include "core/config/project_settings.h" #include "core/error/error_macros.h" @interface GDTViewIOS () @@ -83,5 +84,11 @@ GODOT_CLANG_WARNING_POP @end GDTView *GDTViewCreate() { - return [GDTViewIOS new]; + GDTViewIOS *view = [GDTViewIOS new]; + if (GLOBAL_GET("display/window/ios/allow_high_refresh_rate")) { + view.preferredFrameRate = 120; + } else { + view.preferredFrameRate = 60; + } + return view; } diff --git a/platform/ios/main_ios.mm b/platform/ios/main_ios.mm index 8f7700f6ed3..fe7e2022ca7 100644 --- a/platform/ios/main_ios.mm +++ b/platform/ios/main_ios.mm @@ -37,28 +37,14 @@ #import #include -int gargc; -char **gargv; - static OS_IOS *os = nullptr; -int main(int argc, char *argv[]) { +int apple_embedded_main(int argc, char **argv) { #if defined(VULKAN_ENABLED) //MoltenVK - enable full component swizzling support setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1); #endif - gargc = argc; - gargv = argv; - - @autoreleasepool { - NSString *className = NSStringFromClass([GDTApplicationDelegate class]); - UIApplicationMain(argc, argv, nil, className); - } - return 0; -} - -int apple_embedded_main(int argc, char **argv) { change_to_launch_dir(argv); os = new OS_IOS(); diff --git a/platform/visionos/detect.py b/platform/visionos/detect.py index 678c628a192..787d51e5d9c 100644 --- a/platform/visionos/detect.py +++ b/platform/visionos/detect.py @@ -25,8 +25,8 @@ def get_opts(): return [ # APPLE_TOOLCHAIN_PATH Example: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain - (("APPLE_TOOLCHAIN_PATH", "IOS_TOOLCHAIN_PATH"), "Path to the Apple toolchain", ""), - ("VISIONOS_SDK_PATH", "Path to the visionOS SDK", ""), + ("APPLE_TOOLCHAIN_PATH", "Path to the Apple toolchain", ""), + (("APPLE_SDK_PATH", "VISIONOS_SDK_PATH"), "Path to the visionOS SDK", ""), ("apple_target_triple", "Triple for corresponding target Apple platform toolchain", ""), BoolVariable("simulator", "Build for Simulator", False), BoolVariable("generate_bundle", "Generate an APP bundle after building visionOS/macOS binaries", False), @@ -102,15 +102,16 @@ def configure(env: "SConsEnvironment"): ## Compile flags if env["simulator"]: - detect_darwin_sdk_path("visionossimulator", env) - env.Append(ASFLAGS=["-mtargetos=xros2.0-simulator"]) - env.Append(CCFLAGS=["-mtargetos=xros2.0-simulator"]) + env["APPLE_PLATFORM"] = "visionossimulator" + env.Append(ASFLAGS=["-mtargetos=xros26.0-simulator"]) + env.Append(CCFLAGS=["-mtargetos=xros26.0-simulator"]) env.Append(CPPDEFINES=["VISIONOS_SIMULATOR"]) env.extra_suffix = ".simulator" + env.extra_suffix else: - detect_darwin_sdk_path("visionos", env) - env.Append(ASFLAGS=["-mtargetos=xros2.0"]) - env.Append(CCFLAGS=["-mtargetos=xros2.0"]) + env["APPLE_PLATFORM"] = "visionos" + env.Append(ASFLAGS=["-mtargetos=xros26.0"]) + env.Append(CCFLAGS=["-mtargetos=xros26.0"]) + detect_darwin_sdk_path(env["APPLE_PLATFORM"], env) if env["arch"] == "arm64": env.Append( @@ -118,7 +119,7 @@ def configure(env: "SConsEnvironment"): "-fobjc-arc -arch arm64 -fmessage-length=0" " -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits" " -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies" - " -isysroot $VISIONOS_SDK_PATH".split() + " -isysroot $APPLE_SDK_PATH".split() ) ) env.Append(ASFLAGS=["-arch", "arm64"]) @@ -128,8 +129,8 @@ def configure(env: "SConsEnvironment"): env.Prepend( CPPPATH=[ - "$VISIONOS_SDK_PATH/usr/include", - "$VISIONOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers", + "$APPLE_SDK_PATH/usr/include", + "$APPLE_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers", ] ) @@ -148,9 +149,9 @@ def configure(env: "SConsEnvironment"): env.AppendUnique(CPPDEFINES=["METAL_ENABLED", "RD_ENABLED"]) env.Prepend( CPPPATH=[ - "$VISIONOS_SDK_PATH/System/Library/Frameworks/Metal.framework/Headers", - "$VISIONOS_SDK_PATH/System/Library/Frameworks/MetalFX.framework/Headers", - "$VISIONOS_SDK_PATH/System/Library/Frameworks/QuartzCore.framework/Headers", + "$APPLE_SDK_PATH/System/Library/Frameworks/Metal.framework/Headers", + "$APPLE_SDK_PATH/System/Library/Frameworks/MetalFX.framework/Headers", + "$APPLE_SDK_PATH/System/Library/Frameworks/QuartzCore.framework/Headers", ] ) env.Prepend(CPPPATH=["#thirdparty/spirv-cross"]) diff --git a/platform/visionos/export/export_plugin.h b/platform/visionos/export/export_plugin.h index da5fd1c098c..7535710089c 100644 --- a/platform/visionos/export/export_plugin.h +++ b/platform/visionos/export/export_plugin.h @@ -41,7 +41,7 @@ class EditorExportPlatformVisionOS : public EditorExportPlatformAppleEmbedded { virtual String get_sdk_name() const override { return "xros"; } virtual const Vector get_device_types() const override { return device_types; } - virtual String get_minimum_deployment_target() const override { return "2.0"; } + virtual String get_minimum_deployment_target() const override { return "26.0"; } virtual Vector get_icon_infos() const override; diff --git a/platform/visionos/godot_view_visionos.mm b/platform/visionos/godot_view_visionos.mm index d2ed6dd827b..e1b0b6353a9 100644 --- a/platform/visionos/godot_view_visionos.mm +++ b/platform/visionos/godot_view_visionos.mm @@ -76,5 +76,7 @@ GODOT_CLANG_WARNING_POP @end GDTView *GDTViewCreate() { - return [GDTViewVisionOS new]; + GDTViewVisionOS *view = [GDTViewVisionOS new]; + view.preferredFrameRate = 90; + return view; } diff --git a/platform/visionos/main_visionos.mm b/platform/visionos/main_visionos.mm index c6bea151a7a..3e392307c86 100644 --- a/platform/visionos/main_visionos.mm +++ b/platform/visionos/main_visionos.mm @@ -37,27 +37,8 @@ #import #include -int gargc; -char **gargv; - static OS_VisionOS *os = nullptr; -int main(int argc, char *argv[]) { -#if defined(VULKAN_ENABLED) - //MoltenVK - enable full component swizzling support - setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1); -#endif - - gargc = argc; - gargv = argv; - - @autoreleasepool { - NSString *className = NSStringFromClass([GDTApplicationDelegate class]); - UIApplicationMain(argc, argv, nil, className); - } - return 0; -} - int apple_embedded_main(int argc, char **argv) { change_to_launch_dir(argv); diff --git a/platform_methods.py b/platform_methods.py index 5d5f4b60bfa..09774cc54e3 100644 --- a/platform_methods.py +++ b/platform_methods.py @@ -243,3 +243,85 @@ def generate_bundle_apple_embedded(platform, framework_dir, framework_dir_sim, u zip_dir = env.Dir("#bin/" + (app_prefix + extra_suffix).replace(".", "_")).abspath shutil.make_archive(zip_dir, "zip", root_dir=app_dir) shutil.rmtree(app_dir) + + +def setup_swift_builder(env, apple_platform, sdk_path, current_path, bridging_header_filename, all_swift_files): + from SCons.Script import Action, Builder + + if apple_platform == "macos": + target_suffix = "macosx10.9" + + elif apple_platform == "ios": + target_suffix = "ios14.0" # iOS 14.0 needed for SwiftUI lifecycle + + elif apple_platform == "iossimulator": + target_suffix = "ios14.0-simulator" # iOS 14.0 needed for SwiftUI lifecycle + + elif apple_platform == "visionos": + target_suffix = "xros26.0" + + elif apple_platform == "visionossimulator": + target_suffix = "xros26.0-simulator" + + else: + raise Exception("Invalid platform argument passed to detect_darwin_sdk_path") + + swiftc_target = env["arch"] + "-apple-" + target_suffix + + env["ALL_SWIFT_FILES"] = all_swift_files + env["CURRENT_PATH"] = current_path + frontend_path = "$APPLE_TOOLCHAIN_PATH/usr/bin/swift-frontend" + bridging_header_path = current_path + "/" + bridging_header_filename + env["SWIFTC"] = frontend_path + " -frontend -c" # Swift compiler + env["SWIFTCFLAGS"] = [ + "-cxx-interoperability-mode=default", + "-emit-object", + "-target", + swiftc_target, + "-sdk", + sdk_path, + "-import-objc-header", + bridging_header_path, + "-swift-version", + "6", + "-parse-as-library", + "-module-name", + "godot_swift_module", + "-I./", # Pass the current directory as the header root so bridging headers can include files from any point of the hierarchy + ] + + if env["debug_symbols"]: + env.Append(SWIFTCFLAGS=["-g"]) + + if env["optimize"] in ["speed", "speed_trace"]: + env.Append(SWIFTCFLAGS=["-O"]) + + elif env["optimize"] == "size": + env.Append(SWIFTCFLAGS=["-Osize"]) + + elif env["optimize"] in ["debug", "none"]: + env.Append(SWIFTCFLAGS=["-Onone"]) + + def generate_swift_action(source, target, env, for_signature): + fullpath_swift_files = [env["CURRENT_PATH"] + "/" + file for file in env["ALL_SWIFT_FILES"]] + fullpath_swift_files.remove(source[0].abspath) + + fullpath_swift_files_string = '"' + '" "'.join(fullpath_swift_files) + '"' + compile_command = "$SWIFTC " + fullpath_swift_files_string + " -primary-file $SOURCE -o $TARGET $SWIFTCFLAGS" + + swift_comdstr = env.get("SWIFTCOMSTR") + if swift_comdstr is not None: + swift_action = Action(compile_command, cmdstr=swift_comdstr) + else: + swift_action = Action(compile_command) + + return swift_action + + # Define Builder for Swift files + swift_builder = Builder( + generator=generate_swift_action, suffix=env["OBJSUFFIX"], src_suffix=".swift", emitter=methods.redirect_emitter + ) + + env.Append(BUILDERS={"Swift": swift_builder}) + env["BUILDERS"]["Library"].add_src_builder("Swift") + env["BUILDERS"]["Object"].add_action(".swift", Action(generate_swift_action, generator=1))