From db673a22363c2f06b5dcf97200a4b7afa525ce9b Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Thu, 5 Mar 2026 13:23:30 -0800 Subject: [PATCH 01/37] Revive reaction diffusion iOS app The xcode project still shells out to build the generators, which is not ideal. But there's a host-arch test file now that's built with cmake, so we can at least make sure the generators don't rot. Co-authored-by: Claude Code --- apps/CMakeLists.txt | 2 +- apps/HelloiOS/CMakeLists.txt | 61 ++++++ .../HelloiOS.xcodeproj/project.pbxproj | 40 ++-- apps/HelloiOS/HelloiOS/AppDelegate.mm | 88 +------- apps/HelloiOS/HelloiOS/HalideView.h | 4 +- apps/HelloiOS/HelloiOS/HalideView.mm | 29 ++- apps/HelloiOS/HelloiOS/HalideViewController.h | 11 - .../HelloiOS/HelloiOS/HalideViewController.mm | 57 +++-- apps/HelloiOS/HelloiOS/HelloiOS-Info.plist | 28 +++ apps/HelloiOS/HelloiOS/HelloiOS-Prefix.pch | 6 - .../LaunchImage.launchimage/Contents.json | 51 ----- apps/HelloiOS/HelloiOS/SceneDelegate.h | 7 + apps/HelloiOS/HelloiOS/SceneDelegate.mm | 32 +++ .../reaction_diffusion_2_generator.cpp | 70 ++---- apps/HelloiOS/README.md | 202 ++++++++++++++++++ apps/HelloiOS/build_halide_generators.sh | 191 +++++++++++++++++ apps/HelloiOS/test_reaction_diffusion_2.cpp | 81 +++++++ 17 files changed, 702 insertions(+), 258 deletions(-) create mode 100644 apps/HelloiOS/CMakeLists.txt delete mode 100644 apps/HelloiOS/HelloiOS/Images.xcassets/LaunchImage.launchimage/Contents.json create mode 100644 apps/HelloiOS/HelloiOS/SceneDelegate.h create mode 100644 apps/HelloiOS/HelloiOS/SceneDelegate.mm create mode 100644 apps/HelloiOS/README.md create mode 100755 apps/HelloiOS/build_halide_generators.sh create mode 100644 apps/HelloiOS/test_reaction_diffusion_2.cpp diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 6ffd7966a991..1a0432a56ead 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -31,7 +31,7 @@ endif() # add_app(HelloAndroid) # TODO(#5374): missing CMake build # add_app(HelloAndroidCamera2) # TODO(#5374): missing CMake build # add_app(HelloPyTorch) # TODO(#5374): missing CMake build -# add_app(HelloiOS) # TODO(#5374): missing CMake build +add_app(HelloiOS) # add_app(auto_viz) # TODO(#5374): missing CMake build add_app(bgu) add_app(bilateral_grid) diff --git a/apps/HelloiOS/CMakeLists.txt b/apps/HelloiOS/CMakeLists.txt new file mode 100644 index 000000000000..887b910fd012 --- /dev/null +++ b/apps/HelloiOS/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 3.28) +project(HelloiOS CXX C) + +enable_testing() + +# Set up language settings +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED YES) +set(CMAKE_CXX_EXTENSIONS NO) + +# Find Halide +find_package(Halide REQUIRED) + +# This CMakeLists.txt only supports host builds for testing generators. +# For iOS app builds, use the checked-in Xcode project: HelloiOS.xcodeproj +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + message(FATAL_ERROR + "This CMakeLists.txt does not support iOS cross-compilation.\n" + "For iOS app builds, use the Xcode project:\n" + " open HelloiOS.xcodeproj\n" + "Then build and run in Xcode (Cmd+R).\n" + "\n" + "This CMakeLists.txt is only for testing generators on the host platform.") +endif() + +message(STATUS "HelloiOS: Building host test only") + +# Build the generator for host +add_halide_generator(reaction_diffusion_2.generator + SOURCES HelloiOS/reaction_diffusion_2_generator.cpp) + +# Generate libraries for host platform +add_halide_library(reaction_diffusion_2_init FROM reaction_diffusion_2.generator + GENERATOR reaction_diffusion_2_init + FUNCTION_NAME reaction_diffusion_2_init) + +add_halide_library(reaction_diffusion_2_update FROM reaction_diffusion_2.generator + GENERATOR reaction_diffusion_2_update + FUNCTION_NAME reaction_diffusion_2_update) + +add_halide_library(reaction_diffusion_2_render FROM reaction_diffusion_2.generator + GENERATOR reaction_diffusion_2_render + FUNCTION_NAME reaction_diffusion_2_render) + +# Create a test executable that exercises the generators +add_executable(test_reaction_diffusion_2 test_reaction_diffusion_2.cpp) +target_link_libraries(test_reaction_diffusion_2 PRIVATE + reaction_diffusion_2_init + reaction_diffusion_2_update + reaction_diffusion_2_render + Halide::Runtime) + +# Add CTest +add_test(NAME HelloiOS_generators_test + COMMAND test_reaction_diffusion_2) +set_tests_properties(HelloiOS_generators_test PROPERTIES + LABELS HelloiOS) + +message(STATUS "HelloiOS: Host test target configured") +message(STATUS " Run test: ctest -V") +message(STATUS " For iOS app, use the Xcode project: open HelloiOS.xcodeproj") diff --git a/apps/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index 0e2206cf010b..ccef15930299 100644 --- a/apps/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 3D6C4DC5198051DB002AD41E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3D6C4DC3198051DB002AD41E /* InfoPlist.strings */; }; 3D6C4DC7198051DB002AD41E /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D6C4DC6198051DB002AD41E /* main.mm */; }; 3D6C4DCB198051DB002AD41E /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D6C4DCA198051DB002AD41E /* AppDelegate.mm */; }; + D59E709A4EFA46E189F1616F /* SceneDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A758E1CE83F463E8FDCA6DB /* SceneDelegate.mm */; }; 3D6C4DCD198051DB002AD41E /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3D6C4DCC198051DB002AD41E /* Images.xcassets */; }; 3D6C4DEB19805225002AD41E /* HalideView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D6C4DEA19805225002AD41E /* HalideView.mm */; }; 3D6C4DF619805438002AD41E /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D6C4DF519805438002AD41E /* QuartzCore.framework */; }; @@ -52,6 +53,8 @@ 3D6C4DC8198051DB002AD41E /* HelloiOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HelloiOS-Prefix.pch"; sourceTree = ""; }; 3D6C4DC9198051DB002AD41E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 3D6C4DCA198051DB002AD41E /* AppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.mm; sourceTree = ""; }; + D9F43BA292384C879F5FE013 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; + 2A758E1CE83F463E8FDCA6DB /* SceneDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.mm; sourceTree = ""; }; 3D6C4DCC198051DB002AD41E /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 3D6C4DE919805225002AD41E /* HalideView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HalideView.h; sourceTree = ""; }; 3D6C4DEA19805225002AD41E /* HalideView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HalideView.mm; sourceTree = ""; }; @@ -135,6 +138,8 @@ children = ( 3D6C4DC9198051DB002AD41E /* AppDelegate.h */, 3D6C4DCA198051DB002AD41E /* AppDelegate.mm */, + D9F43BA292384C879F5FE013 /* SceneDelegate.h */, + 2A758E1CE83F463E8FDCA6DB /* SceneDelegate.mm */, 3D6C4DEC1980522C002AD41E /* reaction_diffusion_2_generator.cpp */, 3D6C4DE919805225002AD41E /* HalideView.h */, 3D6C4DEA19805225002AD41E /* HalideView.mm */, @@ -184,14 +189,14 @@ 3D6C4DAF198051DB002AD41E /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0820; - ORGANIZATIONNAME = "Andrew Adams"; + LastUpgradeCheck = 1600; }; buildConfigurationList = 3D6C4DB2198051DB002AD41E /* Build configuration list for PBXProject "HelloiOS" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 3D6C4DAE198051DB002AD41E; @@ -223,9 +228,9 @@ files = ( ); inputPaths = ( - "$(SRCROOT)/reaction_diffusion_2_generator.cpp", - "$(SRCROOT)/../../bin/libHalide.a", - "$(SRCROOT)/../../include/Halide.h", + "$(SRCROOT)/build_halide_generators.sh", + "$(SRCROOT)/HelloiOS/reaction_diffusion_2_generator.cpp", + "$(SRCROOT)/../../tools/GenGen.cpp", ); outputPaths = ( "$(DERIVED_FILE_DIR)/reaction_diffusion_2_generator", @@ -244,7 +249,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "echo \"${SRCROOT}\"\ncd \"${SRCROOT}/HelloiOS\"\n\n# Echoing commands to output makes it easier to debug XCode failures.\n# Failure on undefined vars is always a good idea.\nset -ex\n\n# xcode puts all sorts of junk in the environment which\n# prevents building a binary for osx (instead of ios).\n# sudo'ing to yourself gives a fresh environment.\nsudo -u ${USER} \\\nc++ reaction_diffusion_2_generator.cpp ${SRCROOT}/../../tools/GenGen.cpp \\\n-std=c++17 \\\n-fno-rtti \\\n-I ${SRCROOT}/../../include \\\n-I ${SRCROOT}/../../build/include \\\n-I ${SRCROOT}/../../tools \\\n-arch x86_64 \\\n-L ${SRCROOT}/../../bin \\\n-lHalide \\\n-o ${DERIVED_FILE_DIR}/reaction_diffusion_2_generator\n\n\nif [ \"${arch}\" == \"x86_64\" ]\nthen\n# assume simulator, which requires osx rather than ios\nTARGET=x86-64-osx\nelse\n# TODO: sniff arm-32 builds here; for now, just assume arm-64 only\nTARGET=arm-64-ios\nfi\n\nfor GEN in init update render; do\n(cd ${DERIVED_FILE_DIR}; \\\nDYLD_LIBRARY_PATH=${SRCROOT}/../../bin:${SRCROOT}/../../build/lib \\\n./reaction_diffusion_2_generator -g reaction_diffusion_2_${GEN} -f reaction_diffusion_2_${GEN} -n reaction_diffusion_2_${GEN} -o ${DERIVED_FILE_DIR} target=${TARGET}-user_context)\ndone\n\nfor GEN in init update render; do\n(cd ${DERIVED_FILE_DIR}; \\\nDYLD_LIBRARY_PATH=${SRCROOT}/../../bin:${SRCROOT}/../../build/lib \\\n./reaction_diffusion_2_generator -g reaction_diffusion_2_${GEN} -f reaction_diffusion_2_metal_${GEN} -n reaction_diffusion_2_metal_${GEN} -o ${DERIVED_FILE_DIR} target=${TARGET}-metal-user_context)\ndone\n"; + shellScript = "\"${SRCROOT}/build_halide_generators.sh\"\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -255,6 +260,7 @@ files = ( 3D6C4DEB19805225002AD41E /* HalideView.mm in Sources */, 3D6C4DCB198051DB002AD41E /* AppDelegate.mm in Sources */, + D59E709A4EFA46E189F1616F /* SceneDelegate.mm in Sources */, 3D6C4DC7198051DB002AD41E /* main.mm in Sources */, 1440FDD11DDF9E2600B55760 /* HalideViewController.mm in Sources */, ); @@ -278,7 +284,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -312,7 +318,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -323,7 +329,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -350,7 +356,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -361,17 +367,16 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_BITCODE = NO; GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HelloiOS/HelloiOS-Prefix.pch"; INFOPLIST_FILE = "HelloiOS/HelloiOS-Info.plist"; - PRODUCT_BUNDLE_IDENTIFIER = "Halide.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "$(SRCROOT)../../../include/"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include/"; "USER_HEADER_SEARCH_PATHS[arch=*]" = "$(SRCROOT)/../../include/"; WRAPPER_EXTENSION = app; }; @@ -381,18 +386,17 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_BITCODE = NO; GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HelloiOS/HelloiOS-Prefix.pch"; INFOPLIST_FILE = "HelloiOS/HelloiOS-Info.plist"; - PRODUCT_BUNDLE_IDENTIFIER = "Halide.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include/"; - "USER_HEADER_SEARCH_PATHS[arch=*]" = ../../../../include/; + "USER_HEADER_SEARCH_PATHS[arch=*]" = "$(SRCROOT)/../../include/"; WRAPPER_EXTENSION = app; }; name = Release; diff --git a/apps/HelloiOS/HelloiOS/AppDelegate.mm b/apps/HelloiOS/HelloiOS/AppDelegate.mm index 93557445a5d6..0c3172f5de7c 100644 --- a/apps/HelloiOS/HelloiOS/AppDelegate.mm +++ b/apps/HelloiOS/HelloiOS/AppDelegate.mm @@ -1,91 +1,21 @@ #import "AppDelegate.h" -#import "HalideView.h" -#import "HalideViewController.h" @implementation AppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - - HalideViewController *halide_view_controller = [[HalideViewController alloc] init]; - - self.window.rootViewController = halide_view_controller; - - const int kBorderX = 10; - const int kBorderY = 40; - - // Add a view for image output - int image_width, image_height; - HalideView *output_image = [HalideView alloc]; - { - CGRect box = self.window.frame; - box.origin.x += kBorderX; - box.origin.y += kBorderY; - box.size.width -= kBorderX*2; - box.size.height -= kBorderY*2; - image_width = box.size.width; - image_height = box.size.height; - output_image = [output_image initWithFrame:box]; - output_image.backgroundColor = [UIColor blackColor]; - [self.window addSubview: output_image]; - [output_image setUserInteractionEnabled:true]; -#if HAS_METAL_SDK - output_image.use_metal = true; -#endif - } - halide_view_controller.halide_view = output_image; - - - // Add a view for text output - UITextView *output_log = [UITextView alloc]; - { - CGRect box = self.window.frame; - box.origin.x += kBorderX; - box.origin.y += kBorderY + image_height; - box.size.width -= box.origin.x + kBorderX; - box.size.height -= image_height + kBorderY; - output_log = [output_log initWithFrame: box]; - UIFont *font = [UIFont systemFontOfSize:20]; - [output_log setFont:font]; - [self.window addSubview: output_log]; - } - output_image.outputLog = output_log; - - // Override point for customization after application launch. - self.window.backgroundColor = [UIColor whiteColor]; - [self.window makeKeyAndVisible]; - +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { return YES; } -- (void)applicationWillResignActive:(UIApplication *)application -{ - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application -{ - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +- (UISceneConfiguration *)application:(UIApplication *)application + configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession + options:(UISceneConnectionOptions *)options { + UISceneConfiguration *configuration = [[UISceneConfiguration alloc] initWithName:@"Default Configuration" + sessionRole:connectingSceneSession.role]; + configuration.delegateClass = NSClassFromString(@"SceneDelegate"); + return configuration; } -- (void)applicationWillEnterForeground:(UIApplication *)application -{ - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { } -- (void)applicationDidBecomeActive:(UIApplication *)application -{ - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - -} - -- (void)applicationWillTerminate:(UIApplication *)application -{ - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - - @end diff --git a/apps/HelloiOS/HelloiOS/HalideView.h b/apps/HelloiOS/HelloiOS/HalideView.h index de4506bb7dda..60441ee52db1 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.h +++ b/apps/HelloiOS/HelloiOS/HalideView.h @@ -1,6 +1,6 @@ #include -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0 && !(TARGET_IPHONE_SIMULATOR || TARGET_OS_SIMULATOR) +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_13_0 #define HAS_METAL_SDK 1 #else #define HAS_METAL_SDK 0 @@ -21,7 +21,7 @@ @property CGPoint touch_position; @property bool touch_active; -@property UITextView *outputLog; +@property UILabel *statsLabel; #if HAS_METAL_SDK @property bool use_metal; diff --git a/apps/HelloiOS/HelloiOS/HalideView.mm b/apps/HelloiOS/HelloiOS/HalideView.mm index 2e00cd2ceae1..71daafd220f8 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.mm +++ b/apps/HelloiOS/HelloiOS/HalideView.mm @@ -61,6 +61,7 @@ - (void)initCommon { self.opaque = YES; self.backgroundColor = nil; + self.userInteractionEnabled = YES; #if HAS_METAL_SDK _metalLayer = (CAMetalLayer *)self.layer; @@ -115,7 +116,7 @@ - (void)initBufsWithWidth: (int)w height: (int)h using_metal: (bool) using_metal const int pad_pixels = (64 / sizeof(int32_t)); const int row_stride = (w + pad_pixels - 1) & ~(pad_pixels - 1); const halide_dimension_t pixelBufShape[] = { - {0, w, c}, + {0, row_stride, c}, {0, h, c * row_stride}, {0, c, 1} }; @@ -124,6 +125,9 @@ - (void)initBufsWithWidth: (int)w height: (int)h using_metal: (bool) using_metal // and memory managed by Buffer itself pixel_buf = Buffer(nullptr, 3, pixelBufShape); pixel_buf.allocate(); + // the blit command requires the padding to exist even on the last row, + // so we allocate it padded then crop. + pixel_buf.crop(0, 0, w); } - (void)didMoveToWindow @@ -155,12 +159,11 @@ - (instancetype)initWithCoder:(NSCoder *)coder - (void)updateLogWith: (double) elapsedTime using_metal: (bool) using_metal { #if HAS_METAL_SDK - NSString *mode = using_metal ? @"(Metal; Double-tap for CPU)" : @"(CPU; Double-tap for Metal)"; + NSString *mode = using_metal ? @"Metal (double-tap for CPU)" : @"CPU (double-tap for Metal)"; #else - NSString *mode = @"(CPU; Metal not available)"; + NSString *mode = @"CPU only"; #endif - [self.outputLog setText: [NSString stringWithFormat:@"Halide routine takes %0.3f ms %@", - elapsedTime * 1000, mode]]; + self.statsLabel.text = [NSString stringWithFormat:@"%.1f ms • %@", elapsedTime * 1000, mode]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { @@ -191,7 +194,8 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - (void)renderOneFrame: (const HalideFuncs &) halide_funcs using_metal: (bool) using_metal { - int tx = -100, ty = -100; + // -1 is interpreted as no touch event + int tx = -1, ty = -1; if (self.touch_active) { // Note that buf/bounds is not necessarily the same as self.contentScaleFactor tx = (int) (self.touch_position.x * buf1.dim(0).extent() / self.bounds.size.width); @@ -242,17 +246,13 @@ - (void)initiateRender id texture = drawable.texture; // handle display changes here - if (texture.width != buf1.dim(0).extent() || + if (!buf1.data() || + texture.width != buf1.dim(0).extent() || texture.height != buf1.dim(1).extent() || buf1.dim(0).stride() != required_stride) { // set the metal layer to the drawable size in case orientation or size changes CGSize drawableSize = self.bounds.size; - - // The Metal schedule for our Halide code requires that - // the image be exact multiples of 8 in x & y - drawableSize.width = ((long)drawableSize.width + 7) & ~7; - drawableSize.height = ((long)drawableSize.height + 7) & ~7; _metalLayer.drawableSize = drawableSize; [self initBufsWithWidth: drawableSize.width height: drawableSize.height using_metal: using_metal]; @@ -282,8 +282,8 @@ - (void)initiateRender copyFromBuffer:buffer sourceOffset: 0 sourceBytesPerRow: bytesPerRow - sourceBytesPerImage: pixel_buf.size_in_bytes() - sourceSize: image_size + sourceBytesPerImage: pixel_buf.dim(1).stride() * pixel_buf.dim(1).extent() // Not sizeInBytes because we're also copying the padding on the last row + sourceSize: image_size toTexture: drawable.texture destinationSlice: 0 destinationLevel: 0 @@ -296,7 +296,6 @@ - (void)initiateRender }); }]; [commandBuffer commit]; - [_commandQueue insertDebugCaptureBoundary]; } #else float f = self.contentScaleFactor; diff --git a/apps/HelloiOS/HelloiOS/HalideViewController.h b/apps/HelloiOS/HelloiOS/HalideViewController.h index ff363a2637b4..623acdbfc5c8 100644 --- a/apps/HelloiOS/HelloiOS/HalideViewController.h +++ b/apps/HelloiOS/HelloiOS/HalideViewController.h @@ -1,15 +1,4 @@ -#ifndef HelloiOS_HalideViewController_h -#define HelloiOS_HalideViewController_h - -#import "HalideView.h" #import @interface HalideViewController : UIViewController - -@property HalideView *halide_view; - -- (void)viewWillAppear:(BOOL)animated; - @end - -#endif \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS/HalideViewController.mm b/apps/HelloiOS/HelloiOS/HalideViewController.mm index e48c0f4afd8f..008b9d150ab8 100644 --- a/apps/HelloiOS/HelloiOS/HalideViewController.mm +++ b/apps/HelloiOS/HelloiOS/HalideViewController.mm @@ -1,33 +1,44 @@ #import "HalideViewController.h" #import "HalideView.h" -#import -@implementation HalideViewController -{ - HalideView *_halide_view; +@implementation HalideViewController { + HalideView *_halideView; + UILabel *_statsLabel; } -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - [_halide_view initiateRender]; -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - [_halide_view touchesBegan:touches withEvent:event]; -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - [_halide_view touchesMoved:touches withEvent:event]; +- (void)loadView { + // Create the HalideView as the main view + _halideView = [[HalideView alloc] initWithFrame:CGRectZero]; + _halideView.backgroundColor = [UIColor blackColor]; + +#if HAS_METAL_SDK + _halideView.use_metal = YES; +#endif + + self.view = _halideView; + + // Add stats label at the bottom + _statsLabel = [[UILabel alloc] init]; + _statsLabel.textColor = [UIColor whiteColor]; + _statsLabel.font = [UIFont systemFontOfSize:14]; + _statsLabel.numberOfLines = 0; + _statsLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_statsLabel]; + + // Pin label to bottom with safe area + [NSLayoutConstraint activateConstraints:@[ + [_statsLabel.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:10], + [_statsLabel.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-10], + [_statsLabel.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:-10] + ]]; + + // Give HalideView a reference to the label for updates + _halideView.statsLabel = _statsLabel; } -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - [_halide_view touchesEnded:touches withEvent:event]; -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - [_halide_view touchesCancelled:touches withEvent:event]; +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [_halideView initiateRender]; } - @end diff --git a/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist b/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist index f407f17fd556..011d924089a1 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist +++ b/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist @@ -24,6 +24,34 @@ 1.0 LSRequiresIPhoneOS + UIRequiredDeviceCapabilities + + arm64 + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + SceneDelegate + + + + + UILaunchScreen + + UIColorName + + UIImageName + + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/apps/HelloiOS/HelloiOS/HelloiOS-Prefix.pch b/apps/HelloiOS/HelloiOS/HelloiOS-Prefix.pch index 743435c9bee5..3fdee9d3d6b7 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS-Prefix.pch +++ b/apps/HelloiOS/HelloiOS/HelloiOS-Prefix.pch @@ -4,12 +4,6 @@ // The contents of this file are implicitly included at the beginning of every source file. // -#import - -#ifndef __IPHONE_3_0 -#warning "This project uses features only available in iOS SDK 3.0 and later." -#endif - #ifdef __OBJC__ #import #import diff --git a/apps/HelloiOS/HelloiOS/Images.xcassets/LaunchImage.launchimage/Contents.json b/apps/HelloiOS/HelloiOS/Images.xcassets/LaunchImage.launchimage/Contents.json deleted file mode 100644 index 6f870a4629d2..000000000000 --- a/apps/HelloiOS/HelloiOS/Images.xcassets/LaunchImage.launchimage/Contents.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "images" : [ - { - "orientation" : "portrait", - "idiom" : "iphone", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "subtype" : "retina4", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS/SceneDelegate.h b/apps/HelloiOS/HelloiOS/SceneDelegate.h new file mode 100644 index 000000000000..bb1f9b301c6a --- /dev/null +++ b/apps/HelloiOS/HelloiOS/SceneDelegate.h @@ -0,0 +1,7 @@ +#import + +@interface SceneDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/apps/HelloiOS/HelloiOS/SceneDelegate.mm b/apps/HelloiOS/HelloiOS/SceneDelegate.mm new file mode 100644 index 000000000000..f64d63ec8888 --- /dev/null +++ b/apps/HelloiOS/HelloiOS/SceneDelegate.mm @@ -0,0 +1,32 @@ +#import "SceneDelegate.h" +#import "HalideViewController.h" + +@implementation SceneDelegate + +- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { + if (![scene isKindOfClass:[UIWindowScene class]]) { + return; + } + + UIWindowScene *windowScene = (UIWindowScene *)scene; + self.window = [[UIWindow alloc] initWithWindowScene:windowScene]; + self.window.rootViewController = [[HalideViewController alloc] init]; + [self.window makeKeyAndVisible]; +} + +- (void)sceneDidDisconnect:(UIScene *)scene { +} + +- (void)sceneDidBecomeActive:(UIScene *)scene { +} + +- (void)sceneWillResignActive:(UIScene *)scene { +} + +- (void)sceneWillEnterForeground:(UIScene *)scene { +} + +- (void)sceneDidEnterBackground:(UIScene *)scene { +} + +@end diff --git a/apps/HelloiOS/HelloiOS/reaction_diffusion_2_generator.cpp b/apps/HelloiOS/HelloiOS/reaction_diffusion_2_generator.cpp index 308ef39344f9..e589065f86c6 100644 --- a/apps/HelloiOS/HelloiOS/reaction_diffusion_2_generator.cpp +++ b/apps/HelloiOS/HelloiOS/reaction_diffusion_2_generator.cpp @@ -35,7 +35,10 @@ class ReactionDiffusion2Update : public Halide::Generator> new_state{"new_state"}; void generate() { - clamped = Halide::BoundaryConditions::repeat_edge(state); + // Add a boundary condition to the old state that treats out of bounds values as random + clamped = Halide::BoundaryConditions::constant_exterior(state, random_float(frame)); + + // Diffusion blur_x(x, y, c) = (clamped(x - 3, y, c) + clamped(x - 1, y, c) + @@ -62,14 +65,16 @@ class ReactionDiffusion2Update : public Halide::Generator 0, dR * alpha, dR); + // We'll massively speed up the reaction where the user touches + Expr dx = x - mouse_x; + Expr dy = y - mouse_y; + Expr radius = dx * dx + dy * dy; + Expr bump = 0.002f * state.dim(0).extent() * state.dim(1).extent() / max(1.0f, radius); + bump = select(mouse_x >= 0, bump, 0.0f); - Expr t = 0.1f; + Expr t = 0.04f + bump; R += t * dR; G += t * dG; @@ -81,25 +86,6 @@ class ReactionDiffusion2Update : public Halide::Generator()); - blur - .compute_at(new_state, yi) - .vectorize(x, natural_vector_size()); - clamped + .store_in(MemoryType::Stack) .store_at(new_state, y) - .compute_at(new_state, yi); + .compute_at(new_state, yi) + .vectorize(Halide::_0, natural_vector_size()); } } private: Func blur_x, blur_y, blur, clamped; Var x, y, xi, yi, c; - RDom clobber; }; class ReactionDiffusion2Render : public Halide::Generator { @@ -170,7 +136,7 @@ class ReactionDiffusion2Render : public Halide::Generator +#include +#include +#include "HalideRuntime.h" +#include "HalideBuffer.h" + +// Generated headers +#include "reaction_diffusion_2_init.h" +#include "reaction_diffusion_2_update.h" +#include "reaction_diffusion_2_render.h" + +using namespace Halide::Runtime; + +int main(int argc, char **argv) { + const int width = 128; + const int height = 128; + + try { + std::cout << "Testing HelloiOS reaction-diffusion generators..." << std::endl; + + // Allocate buffers + Buffer state(width, height, 3); + // Rendered buffer must be interleaved (channels in innermost dimension) + Buffer rendered = Buffer::make_interleaved(width, height, 4); + + // Test init generator + std::cout << " Testing reaction_diffusion_2_init..." << std::endl; + int result = reaction_diffusion_2_init(state); + if (result != 0) { + std::cerr << " ERROR: init failed with code " << result << std::endl; + return 1; + } + std::cout << " ✓ init passed" << std::endl; + + // Test update generator (run a few iterations) + std::cout << " Testing reaction_diffusion_2_update..." << std::endl; + int mouse_x = width / 2; + int mouse_y = height / 2; + int frame = 0; + for (int i = 0; i < 10; i++) { + result = reaction_diffusion_2_update(state, mouse_x, mouse_y, frame, state); + if (result != 0) { + std::cerr << " ERROR: update failed at iteration " << i + << " with code " << result << std::endl; + return 1; + } + frame++; + } + std::cout << " ✓ update passed (10 iterations)" << std::endl; + + // Test render generator + std::cout << " Testing reaction_diffusion_2_render..." << std::endl; + int output_bgra = 0; // Use RGBA format for testing + result = reaction_diffusion_2_render(state, output_bgra, rendered); + if (result != 0) { + std::cerr << " ERROR: render failed with code " << result << std::endl; + return 1; + } + std::cout << " ✓ render passed" << std::endl; + + // Sanity check: verify rendered output has some non-zero values + bool has_data = false; + for (int y = 0; y < height && !has_data; y++) { + for (int x = 0; x < width && !has_data; x++) { + if (rendered(x, y, 0) != 0 || rendered(x, y, 1) != 0 || rendered(x, y, 2) != 0) { + has_data = true; + } + } + } + if (!has_data) { + std::cerr << " WARNING: Rendered output is all zeros (unexpected)" << std::endl; + } + + std::cout << "✅ All HelloiOS generators passed!" << std::endl; + return 0; + + } catch (const std::exception &e) { + std::cerr << "ERROR: Exception caught: " << e.what() << std::endl; + return 1; + } +} From 521adc66ff93b60454cfd12183ff666bcbe17093 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 5 Mar 2026 18:01:40 -0500 Subject: [PATCH 02/37] Redo the HelloiOS build --- apps/HelloiOS/CMakeLists.txt | 149 ++++-- .../HelloiOS.xcodeproj/project.pbxproj | 428 ------------------ apps/HelloiOS/HelloiOS/HelloiOS-Info.plist | 6 +- apps/HelloiOS/README.md | 242 ++++------ apps/HelloiOS/build.sh | 55 +++ apps/HelloiOS/build_halide_generators.sh | 191 -------- apps/HelloiOS/test_reaction_diffusion_2.cpp | 81 ---- 7 files changed, 238 insertions(+), 914 deletions(-) delete mode 100644 apps/HelloiOS/HelloiOS.xcodeproj/project.pbxproj create mode 100755 apps/HelloiOS/build.sh delete mode 100755 apps/HelloiOS/build_halide_generators.sh delete mode 100644 apps/HelloiOS/test_reaction_diffusion_2.cpp diff --git a/apps/HelloiOS/CMakeLists.txt b/apps/HelloiOS/CMakeLists.txt index 887b910fd012..142106f0cca1 100644 --- a/apps/HelloiOS/CMakeLists.txt +++ b/apps/HelloiOS/CMakeLists.txt @@ -1,61 +1,114 @@ cmake_minimum_required(VERSION 3.28) -project(HelloiOS CXX C) +project(HelloiOS LANGUAGES C CXX) -enable_testing() - -# Set up language settings set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) -# Find Halide -find_package(Halide REQUIRED) +find_package(HalideHelpers REQUIRED CMAKE_FIND_ROOT_PATH_BOTH) + +add_halide_generator( + reaction_diffusion_2_generator + SOURCES HelloiOS/reaction_diffusion_2_generator.cpp +) + +# A host configure only needs to export the generator package for the iOS build. +if (NOT CMAKE_SYSTEM_NAME STREQUAL "iOS") + return() +endif () + +enable_language(OBJC) +enable_language(OBJCXX) + +set(HELLOIOS_DEVELOPMENT_TEAM "" CACHE STRING + "Optional Apple development team identifier for code signing") -# This CMakeLists.txt only supports host builds for testing generators. -# For iOS app builds, use the checked-in Xcode project: HelloiOS.xcodeproj -if(CMAKE_SYSTEM_NAME STREQUAL "iOS") +if (NOT HelloiOS-halide_generators_FOUND) message(FATAL_ERROR - "This CMakeLists.txt does not support iOS cross-compilation.\n" - "For iOS app builds, use the Xcode project:\n" - " open HelloiOS.xcodeproj\n" - "Then build and run in Xcode (Cmd+R).\n" - "\n" - "This CMakeLists.txt is only for testing generators on the host platform.") -endif() - -message(STATUS "HelloiOS: Building host test only") - -# Build the generator for host -add_halide_generator(reaction_diffusion_2.generator - SOURCES HelloiOS/reaction_diffusion_2_generator.cpp) - -# Generate libraries for host platform -add_halide_library(reaction_diffusion_2_init FROM reaction_diffusion_2.generator - GENERATOR reaction_diffusion_2_init - FUNCTION_NAME reaction_diffusion_2_init) - -add_halide_library(reaction_diffusion_2_update FROM reaction_diffusion_2.generator - GENERATOR reaction_diffusion_2_update - FUNCTION_NAME reaction_diffusion_2_update) - -add_halide_library(reaction_diffusion_2_render FROM reaction_diffusion_2.generator - GENERATOR reaction_diffusion_2_render - FUNCTION_NAME reaction_diffusion_2_render) - -# Create a test executable that exercises the generators -add_executable(test_reaction_diffusion_2 test_reaction_diffusion_2.cpp) -target_link_libraries(test_reaction_diffusion_2 PRIVATE + "HelloiOS iOS builds require host-built generators. " + "Set -DHelloiOS-halide_generators_ROOT=... or add the host build " + "directory to CMAKE_PREFIX_PATH.") +endif () + +set(helloios_generator_target HelloiOS::halide_generators::reaction_diffusion_2_generator) +foreach (stage IN ITEMS init update render) + add_halide_library(reaction_diffusion_2_${stage} + FROM ${helloios_generator_target} + GENERATOR reaction_diffusion_2_${stage} + FUNCTION_NAME reaction_diffusion_2_${stage} + FEATURES user_context) + + add_halide_library(reaction_diffusion_2_metal_${stage} + FROM ${helloios_generator_target} + GENERATOR reaction_diffusion_2_${stage} + FUNCTION_NAME reaction_diffusion_2_metal_${stage} + FEATURES metal user_context) +endforeach () + +find_library(COREGRAPHICS_FRAMEWORK CoreGraphics REQUIRED) +find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED) +find_library(METAL_FRAMEWORK Metal REQUIRED) +find_library(QUARTZCORE_FRAMEWORK QuartzCore REQUIRED) +find_library(UIKIT_FRAMEWORK UIKit REQUIRED) + +add_executable( + HelloiOS MACOSX_BUNDLE + HelloiOS/AppDelegate.h + HelloiOS/AppDelegate.mm + HelloiOS/HalideView.h + HelloiOS/HalideView.mm + HelloiOS/HalideViewController.h + HelloiOS/HalideViewController.mm + HelloiOS/SceneDelegate.h + HelloiOS/SceneDelegate.mm + HelloiOS/main.mm + HelloiOS/Images.xcassets + HelloiOS/en.lproj/InfoPlist.strings +) + +target_link_libraries( + HelloiOS PRIVATE + Halide::Runtime reaction_diffusion_2_init reaction_diffusion_2_update reaction_diffusion_2_render - Halide::Runtime) + reaction_diffusion_2_metal_init + reaction_diffusion_2_metal_update + reaction_diffusion_2_metal_render + ${COREGRAPHICS_FRAMEWORK} + ${FOUNDATION_FRAMEWORK} + ${METAL_FRAMEWORK} + ${QUARTZCORE_FRAMEWORK} + ${UIKIT_FRAMEWORK} +) -# Add CTest -add_test(NAME HelloiOS_generators_test - COMMAND test_reaction_diffusion_2) -set_tests_properties(HelloiOS_generators_test PROPERTIES - LABELS HelloiOS) +set_target_properties( + HelloiOS PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/HelloiOS/HelloiOS-Info.plist" + MACOSX_BUNDLE_GUI_IDENTIFIER "org.halide.HelloiOS" + MACOSX_BUNDLE_BUNDLE_NAME "HelloiOS" + MACOSX_BUNDLE_BUNDLE_VERSION "1.0" + MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0" + OBJCXX_STANDARD 17 + OBJCXX_STANDARD_REQUIRED YES + XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon" + XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES" + XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.halide.HelloiOS" + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2" +) -message(STATUS "HelloiOS: Host test target configured") -message(STATUS " Run test: ctest -V") -message(STATUS " For iOS app, use the Xcode project: open HelloiOS.xcodeproj") +if (HELLOIOS_DEVELOPMENT_TEAM) + set_target_properties( + HelloiOS PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGN_STYLE "Automatic" + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${HELLOIOS_DEVELOPMENT_TEAM}" + ) +else () + set_target_properties( + HelloiOS PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" + XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO" + ) +endif () diff --git a/apps/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS.xcodeproj/project.pbxproj deleted file mode 100644 index ccef15930299..000000000000 --- a/apps/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ /dev/null @@ -1,428 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1440FDD11DDF9E2600B55760 /* HalideViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1440FDD01DDF9E2600B55760 /* HalideViewController.mm */; }; - 14F463431E1F0BC2002C2EA2 /* reaction_diffusion_2_init.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14F463421E1F0BC2002C2EA2 /* reaction_diffusion_2_init.a */; }; - 14F463461E1F14C5002C2EA2 /* reaction_diffusion_2_render.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14F463441E1F14C5002C2EA2 /* reaction_diffusion_2_render.a */; }; - 14F463471E1F14C5002C2EA2 /* reaction_diffusion_2_update.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14F463451E1F14C5002C2EA2 /* reaction_diffusion_2_update.a */; }; - 14F463511E1F1501002C2EA2 /* reaction_diffusion_2_metal_init.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14F463491E1F1501002C2EA2 /* reaction_diffusion_2_metal_init.a */; }; - 14F463521E1F1501002C2EA2 /* reaction_diffusion_2_metal_render.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14F4634B1E1F1501002C2EA2 /* reaction_diffusion_2_metal_render.a */; }; - 14F463531E1F1501002C2EA2 /* reaction_diffusion_2_metal_update.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14F4634D1E1F1501002C2EA2 /* reaction_diffusion_2_metal_update.a */; }; - 29A23DAC1B33E68C00A92A6F /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29A23DAB1B33E68C00A92A6F /* Metal.framework */; }; - 3D6C4DBB198051DB002AD41E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D6C4DBA198051DB002AD41E /* Foundation.framework */; }; - 3D6C4DBD198051DB002AD41E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D6C4DBC198051DB002AD41E /* CoreGraphics.framework */; }; - 3D6C4DBF198051DB002AD41E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D6C4DBE198051DB002AD41E /* UIKit.framework */; }; - 3D6C4DC5198051DB002AD41E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3D6C4DC3198051DB002AD41E /* InfoPlist.strings */; }; - 3D6C4DC7198051DB002AD41E /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D6C4DC6198051DB002AD41E /* main.mm */; }; - 3D6C4DCB198051DB002AD41E /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D6C4DCA198051DB002AD41E /* AppDelegate.mm */; }; - D59E709A4EFA46E189F1616F /* SceneDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A758E1CE83F463E8FDCA6DB /* SceneDelegate.mm */; }; - 3D6C4DCD198051DB002AD41E /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3D6C4DCC198051DB002AD41E /* Images.xcassets */; }; - 3D6C4DEB19805225002AD41E /* HalideView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D6C4DEA19805225002AD41E /* HalideView.mm */; }; - 3D6C4DF619805438002AD41E /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D6C4DF519805438002AD41E /* QuartzCore.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 1440FDCF1DDF9E2600B55760 /* HalideViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HalideViewController.h; sourceTree = ""; }; - 1440FDD01DDF9E2600B55760 /* HalideViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HalideViewController.mm; sourceTree = ""; }; - 14F463421E1F0BC2002C2EA2 /* reaction_diffusion_2_init.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = reaction_diffusion_2_init.a; sourceTree = ""; }; - 14F463441E1F14C5002C2EA2 /* reaction_diffusion_2_render.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = reaction_diffusion_2_render.a; sourceTree = ""; }; - 14F463451E1F14C5002C2EA2 /* reaction_diffusion_2_update.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = reaction_diffusion_2_update.a; sourceTree = ""; }; - 14F463481E1F1501002C2EA2 /* reaction_diffusion_2_init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reaction_diffusion_2_init.h; sourceTree = ""; }; - 14F463491E1F1501002C2EA2 /* reaction_diffusion_2_metal_init.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = reaction_diffusion_2_metal_init.a; sourceTree = ""; }; - 14F4634A1E1F1501002C2EA2 /* reaction_diffusion_2_metal_init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reaction_diffusion_2_metal_init.h; sourceTree = ""; }; - 14F4634B1E1F1501002C2EA2 /* reaction_diffusion_2_metal_render.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = reaction_diffusion_2_metal_render.a; sourceTree = ""; }; - 14F4634C1E1F1501002C2EA2 /* reaction_diffusion_2_metal_render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reaction_diffusion_2_metal_render.h; sourceTree = ""; }; - 14F4634D1E1F1501002C2EA2 /* reaction_diffusion_2_metal_update.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = reaction_diffusion_2_metal_update.a; sourceTree = ""; }; - 14F4634E1E1F1501002C2EA2 /* reaction_diffusion_2_metal_update.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reaction_diffusion_2_metal_update.h; sourceTree = ""; }; - 14F4634F1E1F1501002C2EA2 /* reaction_diffusion_2_render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reaction_diffusion_2_render.h; sourceTree = ""; }; - 14F463501E1F1501002C2EA2 /* reaction_diffusion_2_update.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reaction_diffusion_2_update.h; sourceTree = ""; }; - 29A23DAB1B33E68C00A92A6F /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; - 3D6C4DB7198051DB002AD41E /* HelloiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloiOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 3D6C4DBA198051DB002AD41E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 3D6C4DBC198051DB002AD41E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 3D6C4DBE198051DB002AD41E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 3D6C4DC2198051DB002AD41E /* HelloiOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HelloiOS-Info.plist"; sourceTree = ""; }; - 3D6C4DC4198051DB002AD41E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 3D6C4DC6198051DB002AD41E /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.mm; sourceTree = ""; }; - 3D6C4DC8198051DB002AD41E /* HelloiOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HelloiOS-Prefix.pch"; sourceTree = ""; }; - 3D6C4DC9198051DB002AD41E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 3D6C4DCA198051DB002AD41E /* AppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.mm; sourceTree = ""; }; - D9F43BA292384C879F5FE013 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; - 2A758E1CE83F463E8FDCA6DB /* SceneDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.mm; sourceTree = ""; }; - 3D6C4DCC198051DB002AD41E /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 3D6C4DE919805225002AD41E /* HalideView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HalideView.h; sourceTree = ""; }; - 3D6C4DEA19805225002AD41E /* HalideView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HalideView.mm; sourceTree = ""; }; - 3D6C4DEC1980522C002AD41E /* reaction_diffusion_2_generator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reaction_diffusion_2_generator.cpp; sourceTree = ""; }; - 3D6C4DF519805438002AD41E /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 3D6C4DB4198051DB002AD41E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 29A23DAC1B33E68C00A92A6F /* Metal.framework in Frameworks */, - 14F463431E1F0BC2002C2EA2 /* reaction_diffusion_2_init.a in Frameworks */, - 14F463471E1F14C5002C2EA2 /* reaction_diffusion_2_update.a in Frameworks */, - 3D6C4DF619805438002AD41E /* QuartzCore.framework in Frameworks */, - 14F463461E1F14C5002C2EA2 /* reaction_diffusion_2_render.a in Frameworks */, - 3D6C4DBD198051DB002AD41E /* CoreGraphics.framework in Frameworks */, - 3D6C4DBF198051DB002AD41E /* UIKit.framework in Frameworks */, - 14F463511E1F1501002C2EA2 /* reaction_diffusion_2_metal_init.a in Frameworks */, - 3D6C4DBB198051DB002AD41E /* Foundation.framework in Frameworks */, - 14F463531E1F1501002C2EA2 /* reaction_diffusion_2_metal_update.a in Frameworks */, - 14F463521E1F1501002C2EA2 /* reaction_diffusion_2_metal_render.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 14F4631C1E1EE4EE002C2EA2 /* Derived */ = { - isa = PBXGroup; - children = ( - 14F463481E1F1501002C2EA2 /* reaction_diffusion_2_init.h */, - 14F463491E1F1501002C2EA2 /* reaction_diffusion_2_metal_init.a */, - 14F4634A1E1F1501002C2EA2 /* reaction_diffusion_2_metal_init.h */, - 14F4634B1E1F1501002C2EA2 /* reaction_diffusion_2_metal_render.a */, - 14F4634C1E1F1501002C2EA2 /* reaction_diffusion_2_metal_render.h */, - 14F4634D1E1F1501002C2EA2 /* reaction_diffusion_2_metal_update.a */, - 14F4634E1E1F1501002C2EA2 /* reaction_diffusion_2_metal_update.h */, - 14F4634F1E1F1501002C2EA2 /* reaction_diffusion_2_render.h */, - 14F463501E1F1501002C2EA2 /* reaction_diffusion_2_update.h */, - 14F463421E1F0BC2002C2EA2 /* reaction_diffusion_2_init.a */, - 14F463441E1F14C5002C2EA2 /* reaction_diffusion_2_render.a */, - 14F463451E1F14C5002C2EA2 /* reaction_diffusion_2_update.a */, - ); - name = Derived; - sourceTree = DERIVED_FILE_DIR; - }; - 3D6C4DAE198051DB002AD41E = { - isa = PBXGroup; - children = ( - 3D6C4DC0198051DB002AD41E /* HelloiOS */, - 3D6C4DB9198051DB002AD41E /* Frameworks */, - 3D6C4DB8198051DB002AD41E /* Products */, - ); - sourceTree = ""; - }; - 3D6C4DB8198051DB002AD41E /* Products */ = { - isa = PBXGroup; - children = ( - 3D6C4DB7198051DB002AD41E /* HelloiOS.app */, - ); - name = Products; - sourceTree = ""; - }; - 3D6C4DB9198051DB002AD41E /* Frameworks */ = { - isa = PBXGroup; - children = ( - 14F4631C1E1EE4EE002C2EA2 /* Derived */, - 29A23DAB1B33E68C00A92A6F /* Metal.framework */, - 3D6C4DF519805438002AD41E /* QuartzCore.framework */, - 3D6C4DBA198051DB002AD41E /* Foundation.framework */, - 3D6C4DBC198051DB002AD41E /* CoreGraphics.framework */, - 3D6C4DBE198051DB002AD41E /* UIKit.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 3D6C4DC0198051DB002AD41E /* HelloiOS */ = { - isa = PBXGroup; - children = ( - 3D6C4DC9198051DB002AD41E /* AppDelegate.h */, - 3D6C4DCA198051DB002AD41E /* AppDelegate.mm */, - D9F43BA292384C879F5FE013 /* SceneDelegate.h */, - 2A758E1CE83F463E8FDCA6DB /* SceneDelegate.mm */, - 3D6C4DEC1980522C002AD41E /* reaction_diffusion_2_generator.cpp */, - 3D6C4DE919805225002AD41E /* HalideView.h */, - 3D6C4DEA19805225002AD41E /* HalideView.mm */, - 1440FDCF1DDF9E2600B55760 /* HalideViewController.h */, - 1440FDD01DDF9E2600B55760 /* HalideViewController.mm */, - 3D6C4DCC198051DB002AD41E /* Images.xcassets */, - 3D6C4DC1198051DB002AD41E /* Supporting Files */, - ); - path = HelloiOS; - sourceTree = ""; - }; - 3D6C4DC1198051DB002AD41E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 3D6C4DC2198051DB002AD41E /* HelloiOS-Info.plist */, - 3D6C4DC3198051DB002AD41E /* InfoPlist.strings */, - 3D6C4DC6198051DB002AD41E /* main.mm */, - 3D6C4DC8198051DB002AD41E /* HelloiOS-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 3D6C4DB6198051DB002AD41E /* HelloiOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3D6C4DE3198051DB002AD41E /* Build configuration list for PBXNativeTarget "HelloiOS" */; - buildPhases = ( - 3D6C4DEE19805270002AD41E /* ShellScript */, - 3D6C4DB3198051DB002AD41E /* Sources */, - 3D6C4DB4198051DB002AD41E /* Frameworks */, - 3D6C4DB5198051DB002AD41E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = HelloiOS; - productName = HelloiOS; - productReference = 3D6C4DB7198051DB002AD41E /* HelloiOS.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 3D6C4DAF198051DB002AD41E /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1600; - }; - buildConfigurationList = 3D6C4DB2198051DB002AD41E /* Build configuration list for PBXProject "HelloiOS" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - English, - en, - ); - mainGroup = 3D6C4DAE198051DB002AD41E; - productRefGroup = 3D6C4DB8198051DB002AD41E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 3D6C4DB6198051DB002AD41E /* HelloiOS */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 3D6C4DB5198051DB002AD41E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3D6C4DC5198051DB002AD41E /* InfoPlist.strings in Resources */, - 3D6C4DCD198051DB002AD41E /* Images.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3D6C4DEE19805270002AD41E /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/build_halide_generators.sh", - "$(SRCROOT)/HelloiOS/reaction_diffusion_2_generator.cpp", - "$(SRCROOT)/../../tools/GenGen.cpp", - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_generator", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_init.a", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_init.h", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_update.a", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_update.h", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_render.a", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_render.h", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_metal_init.a", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_metal_init.h", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_metal_update.a", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_metal_update.h", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_metal_render.a", - "$(DERIVED_FILE_DIR)/reaction_diffusion_2_metal_render.h", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/bash; - shellScript = "\"${SRCROOT}/build_halide_generators.sh\"\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 3D6C4DB3198051DB002AD41E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3D6C4DEB19805225002AD41E /* HalideView.mm in Sources */, - 3D6C4DCB198051DB002AD41E /* AppDelegate.mm in Sources */, - D59E709A4EFA46E189F1616F /* SceneDelegate.mm in Sources */, - 3D6C4DC7198051DB002AD41E /* main.mm in Sources */, - 1440FDD11DDF9E2600B55760 /* HalideViewController.mm in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 3D6C4DC3198051DB002AD41E /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 3D6C4DC4198051DB002AD41E /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 3D6C4DE1198051DB002AD41E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 3D6C4DE2198051DB002AD41E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 3D6C4DE4198051DB002AD41E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Manual; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_BITCODE = NO; - GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "HelloiOS/HelloiOS-Prefix.pch"; - INFOPLIST_FILE = "HelloiOS/HelloiOS-Info.plist"; - PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; - PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include/"; - "USER_HEADER_SEARCH_PATHS[arch=*]" = "$(SRCROOT)/../../include/"; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 3D6C4DE5198051DB002AD41E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Manual; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_BITCODE = NO; - GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "HelloiOS/HelloiOS-Prefix.pch"; - INFOPLIST_FILE = "HelloiOS/HelloiOS-Info.plist"; - PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; - PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../include/"; - "USER_HEADER_SEARCH_PATHS[arch=*]" = "$(SRCROOT)/../../include/"; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 3D6C4DB2198051DB002AD41E /* Build configuration list for PBXProject "HelloiOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3D6C4DE1198051DB002AD41E /* Debug */, - 3D6C4DE2198051DB002AD41E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3D6C4DE3198051DB002AD41E /* Build configuration list for PBXNativeTarget "HelloiOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3D6C4DE4198051DB002AD41E /* Debug */, - 3D6C4DE5198051DB002AD41E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 3D6C4DAF198051DB002AD41E /* Project object */; -} diff --git a/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist b/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist index 011d924089a1..5d568f0c393c 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist +++ b/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist @@ -5,15 +5,15 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundleExecutable - ${EXECUTABLE_NAME} + $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index 58476915302e..b19270ac959d 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -1,202 +1,118 @@ -# HelloiOS - Halide iOS Demo App +# HelloiOS -An interactive reaction-diffusion simulation demonstrating Halide's ability to generate high-performance code for iOS, with dual-path rendering on both CPU and Metal GPU. +An interactive reaction-diffusion iOS demo that builds its Halide generators on +the host, then builds the iOS app and generated Halide libraries from CMake. -## What's Here +## Supported Workflow -This directory contains **two build targets**: +Use [`build.sh`](build.sh) with an iOS Halide target, for example: -1. **Host testing binary** (CMake) - Tests generators on macOS/Linux without requiring iOS -2. **iOS app** (Xcode) - Full iOS application for simulator or device +```bash +cd apps/HelloiOS +./build.sh arm-64-ios-simulator +./build.sh arm-64-ios +``` -## Prerequisites +The script does two builds: -Build Halide first: +1. A host build in `build/host` that exports `HelloiOS-halide_generators` +2. An iOS build in `build/` that imports that package, generates + the Halide pipelines, and builds `HelloiOS.app` -```bash -cd /path/to/Halide -cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=Release -cmake --build build -``` +For the iOS build, `build.sh` uses CMake's iOS cross-compilation support with: -## 1. Host Testing (Optional) +- `-DCMAKE_SYSTEM_NAME=iOS` +- `-DCMAKE_OSX_SYSROOT=iphonesimulator` when `Halide_TARGET` contains + `simulator`, otherwise `iphoneos` +- `-DCMAKE_OSX_ARCHITECTURES=arm64` +- `-DHalide_TARGET=` -Test that generators work on your host platform: +## Prerequisites -```bash -cd apps/HelloiOS +Halide must be installed first, and `Halide_ROOT` must be set to the Halide +install prefix before invoking `build.sh`. -# Point CMake to Halide install tree (not build tree) -export CMAKE_PREFIX_PATH=/path/to/Halide/install +```bash +cd /path/to/Halide +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build +cmake --install build --prefix install -# Build and run test -cmake -G Ninja -S . -B test_build -cmake --build test_build -./test_build/test_reaction_diffusion_2 +export Halide_ROOT=$PWD/install ``` -**Expected output:** -``` -Testing HelloiOS reaction-diffusion generators... - Testing reaction_diffusion_2_init... - ✓ init passed - Testing reaction_diffusion_2_update... - ✓ update passed (10 iterations) - Testing reaction_diffusion_2_render... - ✓ render passed -✅ All HelloiOS generators passed! -``` +`build.sh` sets `HalideHelpers_ROOT` from `Halide_ROOT` automatically. -**Note:** If CMake can't find Halide, you need the **install tree** (created by `cmake --install`), not the build tree. See troubleshooting below. +## Useful Environment Variables -## 2. iOS App +- `Halide_ROOT`: Halide install prefix. Required. +- `CMAKE_BUILD_TYPE`: Build configuration. Default: `Release` +- `CMAKE_OSX_DEPLOYMENT_TARGET`: iOS deployment target. Default: `15.0` +- `HELLOIOS_DEVELOPMENT_TEAM`: Optional Apple development team ID. If unset, + code signing is disabled for the generated app target. +- `HOST_BUILD_DIR`: Override the host build directory +- `IOS_BUILD_DIR`: Override the iOS build directory -### Option A: Build in Xcode (Recommended) +Example: ```bash -cd apps/HelloiOS -open HelloiOS.xcodeproj +Halide_ROOT=$HOME/halide-install \ +HELLOIOS_DEVELOPMENT_TEAM=ABCDE12345 \ +./build.sh arm-64-ios ``` -Then in Xcode: -1. Select a simulator (e.g., "iPhone 16") or connected device -2. Press **⌘ + R** to build and run +## Manual Equivalent -### Option B: Command-Line Build +If you want to drive the two builds yourself, this is the structure `build.sh` +uses. -**For simulator:** +Host generator build: ```bash -cd apps/HelloiOS -xcodebuild \ - -project HelloiOS.xcodeproj \ - -scheme HelloiOS \ - -sdk iphonesimulator \ - -configuration Release \ - build \ - CODE_SIGN_IDENTITY="" \ - CODE_SIGNING_REQUIRED=NO +cmake -S . -B build/host \ + -DHalide_ROOT=/path/to/install \ + -DHalideHelpers_ROOT=/path/to/install +cmake --build build/host --target HelloiOS-halide_generators ``` -**For device:** +iOS app build: ```bash -cd apps/HelloiOS -xcodebuild \ - -project HelloiOS.xcodeproj \ - -scheme HelloiOS \ - -sdk iphoneos \ - -configuration Release \ - build +cmake -G Xcode -S . -B build/arm-64-ios-simulator \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_ARCHITECTURES=arm64 \ + -DCMAKE_OSX_SYSROOT=iphonesimulator \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=15.0 \ + -DHalide_ROOT=/path/to/install \ + -DHalideHelpers_ROOT=/path/to/install \ + -DHalide_TARGET=arm-64-ios-simulator \ + -DHelloiOS-halide_generators_ROOT=$PWD/build/host +cmake --build build/arm-64-ios-simulator --config Release --target HelloiOS ``` -(Device builds require code signing configuration in Xcode first) - -## How It Works - -The app uses three Halide generators: - -- **reaction_diffusion_2_init** - Initialize simulation state -- **reaction_diffusion_2_update** - Update simulation each frame -- **reaction_diffusion_2_render** - Render state to pixels - -Each generator is compiled **twice** during the Xcode build: -- Once for **CPU** (ARM NEON vectorization) with target `arm-64-ios` or `arm-64-osx` (simulator) -- Once for **Metal GPU** with target `arm-64-ios-metal` or `arm-64-osx-metal` - -The app switches between CPU and Metal at runtime (double-tap to toggle). - -## Using the App - -- **Tap** - Add white circle that disturbs the pattern -- **Double-tap** - Toggle between CPU and Metal rendering -- **Status bar** - Shows rendering mode and frame time (e.g., "16.7ms Metal") +## Launching In Simulator -Expected performance: -- **Metal mode:** ~5-15ms per frame (GPU) -- **CPU mode:** ~10-30ms per frame (NEON) - -## Requirements - -- **Host testing:** CMake 3.28+, C++17 compiler, Halide install tree -- **iOS app:** macOS with Xcode 16.0+, iOS 13.0+ deployment target, Halide build tree - -## Troubleshooting - -### "Could not find libHalide.dylib" (Xcode build) - -The Xcode build script looks for Halide in: -- `../../bin/libHalide.dylib` -- `../../build/lib/libHalide.dylib` - -**Solution:** Build Halide first (see Prerequisites above). - -### "Could not find Halide" (CMake host test) - -CMake needs Halide's **install tree**, not build tree. - -**Solution:** +After building a simulator target, you can boot a device, install the app, and +launch it from the command line: ```bash -# Create install tree -cd /path/to/Halide -cmake --install build --prefix install - -# Point CMake to it -export CMAKE_PREFIX_PATH=/path/to/Halide/install -cd apps/HelloiOS -cmake -G Ninja -S . -B test_build +open -a Simulator +xcrun simctl bootstatus "iPhone 16" -b +xcrun simctl install booted build/arm-64-ios-simulator/Release-iphonesimulator/HelloiOS.app +xcrun simctl launch booted org.halide.HelloiOS ``` -**Why?** Build trees lack helper files like `HalideConfig.cmake`. Install trees are complete. - -### Code signing required (device builds) +To see the available simulator device names: -1. Open `HelloiOS.xcodeproj` -2. Select "HelloiOS" target -3. Go to "Signing & Capabilities" -4. Select your development team -5. Xcode will automatically provision the app - -### Generator build fails in Xcode - -**Check:** -- `../../tools/GenGen.cpp` exists -- `../../include/Halide.h` exists -- Halide built successfully - -The generator builds on the host (macOS), not the iOS target. The Xcode build script handles this automatically. - -### Metal shader errors - -First run may show warnings as Metal compiles shaders. If errors persist: -- Clean build: Product → Clean Build Folder (⇧⌘K) in Xcode -- Check Console: View → Debug Area → Console -- Verify deployment target is iOS 13.0+ - -## Architecture Notes - -- **Xcode project:** Hand-crafted, contains embedded build script that compiles generators -- **CMake:** Only for host testing, does NOT build iOS app -- **Why separate?** Cross-compiling generators is complex; Xcode handles it natively - -## Technical Details - -- **Reaction-diffusion:** Gray-Scott model with diffusion via 5-tap blur and coupled differential equations -- **Scheduling:** CPU uses parallelization + NEON vectorization; GPU uses tiled blocks -- **Metal:** iOS 13+ enables Metal on both devices and simulators (including Apple Silicon Macs) -- **Targets:** `arm-64-ios` for device, `arm-64-osx` or `x86-64-osx` for simulator - -## Files - -- `HelloiOS.xcodeproj` - Xcode project for iOS app -- `CMakeLists.txt` - Host testing only (rejects iOS builds) -- `test_reaction_diffusion_2.cpp` - Host test executable -- `HelloiOS/reaction_diffusion_2_generator.cpp` - Halide generators (3 pipelines) -- `HelloiOS/HalideView.mm` - Custom UIView with Metal/CoreGraphics rendering -- `HelloiOS/HalideViewController.mm` - Touch input handling -- `HelloiOS/AppDelegate.mm` - iOS app lifecycle +```bash +xcrun simctl list devices available +``` -## License +## Notes -MIT License (same as Halide). See `/LICENSE.txt` in repository root. +- [`CMakeLists.txt`](CMakeLists.txt) is the only supported CMake entry point. +- In a non-iOS configure, `CMakeLists.txt` only exports the host generator + package. +- In an iOS configure, the same file builds the generated Halide libraries and + the iOS app bundle. +- CMake generates the Xcode project in `build/`. diff --git a/apps/HelloiOS/build.sh b/apps/HelloiOS/build.sh new file mode 100755 index 000000000000..85c346b48c33 --- /dev/null +++ b/apps/HelloiOS/build.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +set -euo pipefail + +die() { + echo "$@" >&2 + exit 1 +} + +if [[ $# -ne 1 ]]; then + die "Usage: $0 " +fi + +HALIDE_TARGET="$1" +if [[ "${HALIDE_TARGET}" == "host" ]]; then + die "Halide_TARGET=host is not valid for the iOS app build." +fi + +if [[ "${HALIDE_TARGET}" == *simulator* ]]; then + CMAKE_OSX_SYSROOT=iphonesimulator +else + CMAKE_OSX_SYSROOT=iphoneos +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" + +: "${CMAKE_BUILD_TYPE:=Release}" +: "${CMAKE_OSX_DEPLOYMENT_TARGET:=15.0}" +: "${HELLOIOS_DEVELOPMENT_TEAM:=}" + +: "${HOST_BUILD_DIR:=${SCRIPT_DIR}/build/host}" +: "${IOS_BUILD_DIR:=${SCRIPT_DIR}/build/${HALIDE_TARGET}}" + +[[ -n "${Halide_ROOT:-}" ]] || die "Set Halide_ROOT in the environment to the Halide install prefix." +export HalideHelpers_ROOT="${Halide_ROOT}" + +## Phase 1: Host build of the Halide generators. + +cmake -S "${SCRIPT_DIR}" -B "${HOST_BUILD_DIR}" -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" +cmake --build "${HOST_BUILD_DIR}" + +## Phase 2: Target build of the iOS app, using the host-built Halide generators. + +cmake -G Xcode -S "${SCRIPT_DIR}" -B "${IOS_BUILD_DIR}" \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_ARCHITECTURES=arm64 \ + -DCMAKE_OSX_DEPLOYMENT_TARGET="${CMAKE_OSX_DEPLOYMENT_TARGET}" \ + -DCMAKE_OSX_SYSROOT="${CMAKE_OSX_SYSROOT}" \ + -DHelloiOS-halide_generators_ROOT="${HOST_BUILD_DIR}" \ + -DHalide_TARGET="${HALIDE_TARGET}" \ + -DHELLOIOS_DEVELOPMENT_TEAM="${HELLOIOS_DEVELOPMENT_TEAM}" + +cmake --build "${IOS_BUILD_DIR}" --config "${CMAKE_BUILD_TYPE}" + +echo "Built HelloiOS.app under ${IOS_BUILD_DIR}/${CMAKE_BUILD_TYPE}-${CMAKE_OSX_SYSROOT}/" diff --git a/apps/HelloiOS/build_halide_generators.sh b/apps/HelloiOS/build_halide_generators.sh deleted file mode 100755 index 61858157d9a0..000000000000 --- a/apps/HelloiOS/build_halide_generators.sh +++ /dev/null @@ -1,191 +0,0 @@ -#!/bin/bash -# Build Halide generators for HelloiOS -# This script is called from the Xcode build phase - -set -e # Exit on error - -echo "Building Halide generators for HelloiOS" -echo "SRCROOT: ${SRCROOT}" -echo "DERIVED_FILE_DIR: ${DERIVED_FILE_DIR}" -echo "EFFECTIVE_PLATFORM_NAME: ${EFFECTIVE_PLATFORM_NAME}" -echo "ARCHS: ${ARCHS}" - -# Detect Halide installation (use absolute path) -if [ -d "${SRCROOT}/../../install" ]; then - HALIDE_PREFIX="$(cd "${SRCROOT}/../../install" && pwd)" - HALIDE_LIB_DIR="${HALIDE_PREFIX}/lib" - HALIDE_INCLUDE_DIR="${HALIDE_PREFIX}/include" -elif [ -d "${SRCROOT}/../../build" ]; then - HALIDE_PREFIX="$(cd "${SRCROOT}/../../build" && pwd)" - HALIDE_LIB_DIR="${HALIDE_PREFIX}/lib" - HALIDE_INCLUDE_DIR="${HALIDE_PREFIX}/include" -elif [ -d "${SRCROOT}/../../bin" ]; then - # Legacy make-based build - HALIDE_PREFIX="$(cd "${SRCROOT}/../.." && pwd)" - HALIDE_LIB_DIR="${HALIDE_PREFIX}/bin" - HALIDE_INCLUDE_DIR="${HALIDE_PREFIX}/include" -else - echo "ERROR: Could not find Halide library. Please build Halide first." - echo "Expected one of:" - echo " ../../install/lib/libHalide.dylib (CMake install tree)" - echo " ../../build/lib/libHalide.dylib (CMake build tree)" - echo " ../../bin/libHalide.dylib (Make-based build)" - exit 1 -fi - -echo "Using Halide from: ${HALIDE_PREFIX}" - -# Verify library exists -if [ ! -f "${HALIDE_LIB_DIR}/libHalide.dylib" ]; then - echo "ERROR: libHalide.dylib not found at ${HALIDE_LIB_DIR}" - exit 1 -fi - -cd "${SRCROOT}/HelloiOS" - -# Build generator executable for host (macOS) -# Use xcrun to get the right compiler and explicitly target macOS -echo "Compiling generator for host (macOS)..." -# Get macOS SDK path and use explicit target triple to avoid iOS environment pollution -MACOSX_SDK="$(xcrun -sdk macosx --show-sdk-path)" -xcrun -sdk macosx clang++ \ - -target arm64-apple-macosx11.0 \ - -isysroot "${MACOSX_SDK}" \ - reaction_diffusion_2_generator.cpp \ - "${SRCROOT}/../../tools/GenGen.cpp" \ - -std=c++17 \ - -fno-rtti \ - -I "${HALIDE_INCLUDE_DIR}" \ - -I "${SRCROOT}/../../tools" \ - -L "${HALIDE_LIB_DIR}" \ - -lHalide \ - -o "${DERIVED_FILE_DIR}/reaction_diffusion_2_generator" - -echo "Generator built successfully" - -# Detect target for Halide code generation -if [[ "${EFFECTIVE_PLATFORM_NAME}" == "-iphonesimulator" ]]; then - # Simulator build - # For multi-arch builds, generate for each architecture - IFS=' ' read -ra ARCH_ARRAY <<< "${ARCHS}" - - if [ ${#ARCH_ARRAY[@]} -eq 1 ]; then - # Single architecture - ARCH="${ARCH_ARRAY[0]}" - if [[ "${ARCH}" == "x86_64" ]]; then - TARGET="x86-64-ios-simulator" - else - TARGET="arm-64-ios-simulator" - fi - echo "Generating libraries for simulator (${ARCH}): target=${TARGET}" - - # Generate all 6 libraries - for GEN in init update render; do - echo " Generating ${GEN} (CPU)..." - (cd "${DERIVED_FILE_DIR}"; \ - DYLD_LIBRARY_PATH="${HALIDE_LIB_DIR}" \ - ./reaction_diffusion_2_generator \ - -g reaction_diffusion_2_${GEN} \ - -f reaction_diffusion_2_${GEN} \ - -n reaction_diffusion_2_${GEN} \ - -o . \ - target=${TARGET}-user_context) - done - - for GEN in init update render; do - echo " Generating ${GEN} (Metal)..." - (cd "${DERIVED_FILE_DIR}"; \ - DYLD_LIBRARY_PATH="${HALIDE_LIB_DIR}" \ - ./reaction_diffusion_2_generator \ - -g reaction_diffusion_2_${GEN} \ - -f reaction_diffusion_2_metal_${GEN} \ - -n reaction_diffusion_2_metal_${GEN} \ - -o . \ - target=${TARGET}-metal-user_context) - done - else - # Multi-architecture build - generate for each arch and use lipo - echo "Multi-architecture build (${ARCHS})" - - for ARCH in "${ARCH_ARRAY[@]}"; do - if [[ "${ARCH}" == "x86_64" ]]; then - TARGET="x86-64-ios-simulator" - else - TARGET="arm-64-ios-simulator" - fi - - echo " Generating libraries for ${ARCH} (target=${TARGET})..." - ARCH_DIR="${DERIVED_FILE_DIR}/${ARCH}" - mkdir -p "${ARCH_DIR}" - - # Generate all 6 libraries for this architecture - for GEN in init update render; do - (cd "${ARCH_DIR}"; \ - DYLD_LIBRARY_PATH="${HALIDE_LIB_DIR}" \ - "${DERIVED_FILE_DIR}/reaction_diffusion_2_generator" \ - -g reaction_diffusion_2_${GEN} \ - -f reaction_diffusion_2_${GEN} \ - -n reaction_diffusion_2_${GEN} \ - -o . \ - target=${TARGET}-user_context) - done - - for GEN in init update render; do - (cd "${ARCH_DIR}"; \ - DYLD_LIBRARY_PATH="${HALIDE_LIB_DIR}" \ - "${DERIVED_FILE_DIR}/reaction_diffusion_2_generator" \ - -g reaction_diffusion_2_${GEN} \ - -f reaction_diffusion_2_metal_${GEN} \ - -n reaction_diffusion_2_metal_${GEN} \ - -o . \ - target=${TARGET}-metal-user_context) - done - done - - # Combine architectures using lipo - echo " Creating universal binaries with lipo..." - for LIB in reaction_diffusion_2_init reaction_diffusion_2_update reaction_diffusion_2_render \ - reaction_diffusion_2_metal_init reaction_diffusion_2_metal_update reaction_diffusion_2_metal_render; do - LIPO_INPUTS="" - for ARCH in "${ARCH_ARRAY[@]}"; do - LIPO_INPUTS="${LIPO_INPUTS} ${DERIVED_FILE_DIR}/${ARCH}/${LIB}.a" - done - xcrun lipo -create ${LIPO_INPUTS} -output "${DERIVED_FILE_DIR}/${LIB}.a" - done - - # Copy headers from first architecture - FIRST_ARCH="${ARCH_ARRAY[0]}" - cp "${DERIVED_FILE_DIR}/${FIRST_ARCH}"/*.h "${DERIVED_FILE_DIR}/" - fi -else - # Device build - always arm64-ios - TARGET="arm-64-ios" - echo "Generating libraries for device: target=${TARGET}" - - for GEN in init update render; do - echo " Generating ${GEN} (CPU)..." - (cd "${DERIVED_FILE_DIR}"; \ - DYLD_LIBRARY_PATH="${HALIDE_LIB_DIR}" \ - ./reaction_diffusion_2_generator \ - -g reaction_diffusion_2_${GEN} \ - -f reaction_diffusion_2_${GEN} \ - -n reaction_diffusion_2_${GEN} \ - -o . \ - target=${TARGET}-user_context) - done - - for GEN in init update render; do - echo " Generating ${GEN} (Metal)..." - (cd "${DERIVED_FILE_DIR}"; \ - DYLD_LIBRARY_PATH="${HALIDE_LIB_DIR}" \ - ./reaction_diffusion_2_generator \ - -g reaction_diffusion_2_${GEN} \ - -f reaction_diffusion_2_metal_${GEN} \ - -n reaction_diffusion_2_metal_${GEN} \ - -o . \ - target=${TARGET}-metal-user_context) - done -fi - -echo "✅ Successfully generated 6 Halide libraries (3 CPU + 3 Metal)" -ls -lh "${DERIVED_FILE_DIR}"/*.a | awk '{print " " $9 " (" $5 ")"}' diff --git a/apps/HelloiOS/test_reaction_diffusion_2.cpp b/apps/HelloiOS/test_reaction_diffusion_2.cpp deleted file mode 100644 index 4d625287ee76..000000000000 --- a/apps/HelloiOS/test_reaction_diffusion_2.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include -#include "HalideRuntime.h" -#include "HalideBuffer.h" - -// Generated headers -#include "reaction_diffusion_2_init.h" -#include "reaction_diffusion_2_update.h" -#include "reaction_diffusion_2_render.h" - -using namespace Halide::Runtime; - -int main(int argc, char **argv) { - const int width = 128; - const int height = 128; - - try { - std::cout << "Testing HelloiOS reaction-diffusion generators..." << std::endl; - - // Allocate buffers - Buffer state(width, height, 3); - // Rendered buffer must be interleaved (channels in innermost dimension) - Buffer rendered = Buffer::make_interleaved(width, height, 4); - - // Test init generator - std::cout << " Testing reaction_diffusion_2_init..." << std::endl; - int result = reaction_diffusion_2_init(state); - if (result != 0) { - std::cerr << " ERROR: init failed with code " << result << std::endl; - return 1; - } - std::cout << " ✓ init passed" << std::endl; - - // Test update generator (run a few iterations) - std::cout << " Testing reaction_diffusion_2_update..." << std::endl; - int mouse_x = width / 2; - int mouse_y = height / 2; - int frame = 0; - for (int i = 0; i < 10; i++) { - result = reaction_diffusion_2_update(state, mouse_x, mouse_y, frame, state); - if (result != 0) { - std::cerr << " ERROR: update failed at iteration " << i - << " with code " << result << std::endl; - return 1; - } - frame++; - } - std::cout << " ✓ update passed (10 iterations)" << std::endl; - - // Test render generator - std::cout << " Testing reaction_diffusion_2_render..." << std::endl; - int output_bgra = 0; // Use RGBA format for testing - result = reaction_diffusion_2_render(state, output_bgra, rendered); - if (result != 0) { - std::cerr << " ERROR: render failed with code " << result << std::endl; - return 1; - } - std::cout << " ✓ render passed" << std::endl; - - // Sanity check: verify rendered output has some non-zero values - bool has_data = false; - for (int y = 0; y < height && !has_data; y++) { - for (int x = 0; x < width && !has_data; x++) { - if (rendered(x, y, 0) != 0 || rendered(x, y, 1) != 0 || rendered(x, y, 2) != 0) { - has_data = true; - } - } - } - if (!has_data) { - std::cerr << " WARNING: Rendered output is all zeros (unexpected)" << std::endl; - } - - std::cout << "✅ All HelloiOS generators passed!" << std::endl; - return 0; - - } catch (const std::exception &e) { - std::cerr << "ERROR: Exception caught: " << e.what() << std::endl; - return 1; - } -} From a528870ae55d4a8cdf16be231fa026f973907128 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 5 Mar 2026 19:46:51 -0500 Subject: [PATCH 03/37] Remove HelloiOS from apps/CMakeLists.txt The HelloiOS build must run on macOS and be invoked twice. It isn't a superbuild, and we wouldn't want to inject a superbuild here anyway. --- apps/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 1a0432a56ead..5d10f7b474d4 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -31,7 +31,7 @@ endif() # add_app(HelloAndroid) # TODO(#5374): missing CMake build # add_app(HelloAndroidCamera2) # TODO(#5374): missing CMake build # add_app(HelloPyTorch) # TODO(#5374): missing CMake build -add_app(HelloiOS) +# add_app(HelloiOS) # don't build HelloiOS here because it isn't universal. # add_app(auto_viz) # TODO(#5374): missing CMake build add_app(bgu) add_app(bilateral_grid) From 0741098198e632e463c6068c12a49e13b80787f7 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Fri, 6 Mar 2026 18:54:49 -0500 Subject: [PATCH 04/37] Move reaction_diffusion_2_generator.cpp to Generators directory --- apps/HelloiOS/CMakeLists.txt | 2 +- .../{HelloiOS => Generators}/reaction_diffusion_2_generator.cpp | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename apps/HelloiOS/{HelloiOS => Generators}/reaction_diffusion_2_generator.cpp (100%) diff --git a/apps/HelloiOS/CMakeLists.txt b/apps/HelloiOS/CMakeLists.txt index 142106f0cca1..c1034709842e 100644 --- a/apps/HelloiOS/CMakeLists.txt +++ b/apps/HelloiOS/CMakeLists.txt @@ -9,7 +9,7 @@ find_package(HalideHelpers REQUIRED CMAKE_FIND_ROOT_PATH_BOTH) add_halide_generator( reaction_diffusion_2_generator - SOURCES HelloiOS/reaction_diffusion_2_generator.cpp + SOURCES Generators/reaction_diffusion_2_generator.cpp ) # A host configure only needs to export the generator package for the iOS build. diff --git a/apps/HelloiOS/HelloiOS/reaction_diffusion_2_generator.cpp b/apps/HelloiOS/Generators/reaction_diffusion_2_generator.cpp similarity index 100% rename from apps/HelloiOS/HelloiOS/reaction_diffusion_2_generator.cpp rename to apps/HelloiOS/Generators/reaction_diffusion_2_generator.cpp From cb42dc1ab81d827fff170bc597d3d55e03c136dc Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 11:20:55 -0500 Subject: [PATCH 05/37] Single-target Xcode-driven prototype --- .gitignore | 1 + apps/HelloiOS/CMakeLists.txt | 114 ----- apps/HelloiOS/Generators/CMakeLists.txt | 39 ++ apps/HelloiOS/Generators/rebuild-kernels.sh | 13 + .../contents.xcworkspacedata | 7 + apps/HelloiOS/HelloiOS/HalideView.mm | 2 +- .../HelloiOS.xcodeproj/project.pbxproj | 399 ++++++++++++++++++ apps/HelloiOS/README.md | 127 ++---- apps/HelloiOS/build.sh | 65 +-- 9 files changed, 542 insertions(+), 225 deletions(-) delete mode 100644 apps/HelloiOS/CMakeLists.txt create mode 100644 apps/HelloiOS/Generators/CMakeLists.txt create mode 100755 apps/HelloiOS/Generators/rebuild-kernels.sh create mode 100644 apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata create mode 100644 apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj diff --git a/.gitignore b/.gitignore index a08b8e8dd7f3..368a457c85c2 100644 --- a/.gitignore +++ b/.gitignore @@ -216,6 +216,7 @@ CMakeSettings.json # XCode *.xcworkspacedata +!apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata tools/objc/*.mobileprovision tools/objc/BUILD xcuserdata diff --git a/apps/HelloiOS/CMakeLists.txt b/apps/HelloiOS/CMakeLists.txt deleted file mode 100644 index c1034709842e..000000000000 --- a/apps/HelloiOS/CMakeLists.txt +++ /dev/null @@ -1,114 +0,0 @@ -cmake_minimum_required(VERSION 3.28) -project(HelloiOS LANGUAGES C CXX) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED YES) -set(CMAKE_CXX_EXTENSIONS NO) - -find_package(HalideHelpers REQUIRED CMAKE_FIND_ROOT_PATH_BOTH) - -add_halide_generator( - reaction_diffusion_2_generator - SOURCES Generators/reaction_diffusion_2_generator.cpp -) - -# A host configure only needs to export the generator package for the iOS build. -if (NOT CMAKE_SYSTEM_NAME STREQUAL "iOS") - return() -endif () - -enable_language(OBJC) -enable_language(OBJCXX) - -set(HELLOIOS_DEVELOPMENT_TEAM "" CACHE STRING - "Optional Apple development team identifier for code signing") - -if (NOT HelloiOS-halide_generators_FOUND) - message(FATAL_ERROR - "HelloiOS iOS builds require host-built generators. " - "Set -DHelloiOS-halide_generators_ROOT=... or add the host build " - "directory to CMAKE_PREFIX_PATH.") -endif () - -set(helloios_generator_target HelloiOS::halide_generators::reaction_diffusion_2_generator) -foreach (stage IN ITEMS init update render) - add_halide_library(reaction_diffusion_2_${stage} - FROM ${helloios_generator_target} - GENERATOR reaction_diffusion_2_${stage} - FUNCTION_NAME reaction_diffusion_2_${stage} - FEATURES user_context) - - add_halide_library(reaction_diffusion_2_metal_${stage} - FROM ${helloios_generator_target} - GENERATOR reaction_diffusion_2_${stage} - FUNCTION_NAME reaction_diffusion_2_metal_${stage} - FEATURES metal user_context) -endforeach () - -find_library(COREGRAPHICS_FRAMEWORK CoreGraphics REQUIRED) -find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED) -find_library(METAL_FRAMEWORK Metal REQUIRED) -find_library(QUARTZCORE_FRAMEWORK QuartzCore REQUIRED) -find_library(UIKIT_FRAMEWORK UIKit REQUIRED) - -add_executable( - HelloiOS MACOSX_BUNDLE - HelloiOS/AppDelegate.h - HelloiOS/AppDelegate.mm - HelloiOS/HalideView.h - HelloiOS/HalideView.mm - HelloiOS/HalideViewController.h - HelloiOS/HalideViewController.mm - HelloiOS/SceneDelegate.h - HelloiOS/SceneDelegate.mm - HelloiOS/main.mm - HelloiOS/Images.xcassets - HelloiOS/en.lproj/InfoPlist.strings -) - -target_link_libraries( - HelloiOS PRIVATE - Halide::Runtime - reaction_diffusion_2_init - reaction_diffusion_2_update - reaction_diffusion_2_render - reaction_diffusion_2_metal_init - reaction_diffusion_2_metal_update - reaction_diffusion_2_metal_render - ${COREGRAPHICS_FRAMEWORK} - ${FOUNDATION_FRAMEWORK} - ${METAL_FRAMEWORK} - ${QUARTZCORE_FRAMEWORK} - ${UIKIT_FRAMEWORK} -) - -set_target_properties( - HelloiOS PROPERTIES - MACOSX_BUNDLE TRUE - MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/HelloiOS/HelloiOS-Info.plist" - MACOSX_BUNDLE_GUI_IDENTIFIER "org.halide.HelloiOS" - MACOSX_BUNDLE_BUNDLE_NAME "HelloiOS" - MACOSX_BUNDLE_BUNDLE_VERSION "1.0" - MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0" - OBJCXX_STANDARD 17 - OBJCXX_STANDARD_REQUIRED YES - XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon" - XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES" - XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" - XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.halide.HelloiOS" - XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2" -) - -if (HELLOIOS_DEVELOPMENT_TEAM) - set_target_properties( - HelloiOS PROPERTIES - XCODE_ATTRIBUTE_CODE_SIGN_STYLE "Automatic" - XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${HELLOIOS_DEVELOPMENT_TEAM}" - ) -else () - set_target_properties( - HelloiOS PROPERTIES - XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" - XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO" - ) -endif () diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt new file mode 100644 index 000000000000..68e9de00bfcc --- /dev/null +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.28) +project(HelloiOS-Generators LANGUAGES C CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED YES) +set(CMAKE_CXX_EXTENSIONS NO) + +find_package(HalideHelpers REQUIRED) + +add_halide_generator( + reaction_diffusion_2_generator + SOURCES reaction_diffusion_2_generator.cpp +) + +foreach (stage IN ITEMS init update render) + add_halide_library(reaction_diffusion_2_${stage} + FROM reaction_diffusion_2_generator + GENERATOR reaction_diffusion_2_${stage} + FUNCTION_NAME reaction_diffusion_2_${stage} + FEATURES user_context) + + add_halide_library(reaction_diffusion_2_metal_${stage} + FROM reaction_diffusion_2_generator + GENERATOR reaction_diffusion_2_${stage} + FUNCTION_NAME reaction_diffusion_2_metal_${stage} + FEATURES metal user_context) +endforeach () + +# The IMPORTED library targets from add_halide_library are not part of the +# default build, so we create an explicit target to drive generation. +set(_all_kernel_updates "") +foreach (stage IN ITEMS init update render) + list(APPEND _all_kernel_updates + reaction_diffusion_2_${stage}.update + reaction_diffusion_2_${stage}.runtime.update + reaction_diffusion_2_metal_${stage}.update + reaction_diffusion_2_metal_${stage}.runtime.update) +endforeach () +add_custom_target(halide_kernels ALL DEPENDS ${_all_kernel_updates}) \ No newline at end of file diff --git a/apps/HelloiOS/Generators/rebuild-kernels.sh b/apps/HelloiOS/Generators/rebuild-kernels.sh new file mode 100755 index 000000000000..dd839532c35f --- /dev/null +++ b/apps/HelloiOS/Generators/rebuild-kernels.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Called by the Xcode "Build Halide Generators" run-script phase. +# Variables (CMAKE_COMMAND, GENERATORS_BUILD_DIR) come from +# GeneratorPaths.xcconfig, written by build.sh. + +set -euo pipefail + +if [ -z "${GENERATORS_BUILD_DIR:-}" ]; then + echo "error: GENERATORS_BUILD_DIR is not set. Run build.sh first to configure." + exit 1 +fi + +"$CMAKE_COMMAND" --build "$GENERATORS_BUILD_DIR" \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata b/apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..5c8ad7dae2f7 --- /dev/null +++ b/apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS/HalideView.mm b/apps/HelloiOS/HelloiOS/HalideView.mm index 71daafd220f8..ca93791f8d77 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.mm +++ b/apps/HelloiOS/HelloiOS/HalideView.mm @@ -93,7 +93,7 @@ - (void) updateFrameTime: (double) elapsed using_metal: (bool)using_metal } if ((iteration % 30) == 0) { dispatch_async(dispatch_get_main_queue(), ^(void) { - [self updateLogWith: frameElapsedEstimate using_metal: using_metal]; + [self updateLogWith: self->frameElapsedEstimate using_metal: using_metal]; }); } iteration += 1; diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..f23104bbaa80 --- /dev/null +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -0,0 +1,399 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 4A2000000000000000000001 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000002 /* AppDelegate.mm */; }; + 4A2000000000000000000002 /* HalideView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000004 /* HalideView.mm */; }; + 4A2000000000000000000003 /* HalideViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000006 /* HalideViewController.mm */; }; + 4A2000000000000000000004 /* SceneDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000008 /* SceneDelegate.mm */; }; + 4A2000000000000000000005 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000009 /* main.mm */; }; + 4A2000000000000000000006 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4A100000000000000000000A /* Images.xcassets */; }; + 4A2000000000000000000007 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4A100000000000000000000B /* InfoPlist.strings */; }; + 4A2000000000000000000008 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A100000000000000000000F /* CoreGraphics.framework */; }; + 4A2000000000000000000009 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000010 /* Foundation.framework */; }; + 4A200000000000000000000A /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000011 /* Metal.framework */; }; + 4A200000000000000000000B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000012 /* QuartzCore.framework */; }; + 4A200000000000000000000C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000013 /* UIKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 4A1000000000000000000001 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 4A1000000000000000000002 /* AppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AppDelegate.mm; sourceTree = ""; }; + 4A1000000000000000000003 /* HalideView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HalideView.h; sourceTree = ""; }; + 4A1000000000000000000004 /* HalideView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = HalideView.mm; sourceTree = ""; }; + 4A1000000000000000000005 /* HalideViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HalideViewController.h; sourceTree = ""; }; + 4A1000000000000000000006 /* HalideViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = HalideViewController.mm; sourceTree = ""; }; + 4A1000000000000000000007 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; + 4A1000000000000000000008 /* SceneDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SceneDelegate.mm; sourceTree = ""; }; + 4A1000000000000000000009 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; + 4A100000000000000000000A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 4A100000000000000000000B /* InfoPlist.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 4A100000000000000000000C /* HelloiOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HelloiOS-Info.plist"; sourceTree = ""; }; + 4A100000000000000000000D /* HelloiOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HelloiOS-Prefix.pch"; sourceTree = ""; }; + 4A100000000000000000000E /* GeneratorPaths.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = GeneratorPaths.xcconfig; path = "../Generators/build/GeneratorPaths.xcconfig"; sourceTree = SOURCE_ROOT; }; + 4A100000000000000000000F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 4A1000000000000000000010 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4A1000000000000000000011 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + 4A1000000000000000000012 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 4A1000000000000000000013 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 4A1000000000000000000014 /* HelloiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloiOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A4000000000000000000002 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A2000000000000000000008 /* CoreGraphics.framework in Frameworks */, + 4A2000000000000000000009 /* Foundation.framework in Frameworks */, + 4A200000000000000000000A /* Metal.framework in Frameworks */, + 4A200000000000000000000B /* QuartzCore.framework in Frameworks */, + 4A200000000000000000000C /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A3000000000000000000001 /* HelloiOS */ = { + isa = PBXGroup; + children = ( + 4A100000000000000000000E /* GeneratorPaths.xcconfig */, + 4A1000000000000000000001 /* AppDelegate.h */, + 4A1000000000000000000002 /* AppDelegate.mm */, + 4A1000000000000000000003 /* HalideView.h */, + 4A1000000000000000000004 /* HalideView.mm */, + 4A1000000000000000000005 /* HalideViewController.h */, + 4A1000000000000000000006 /* HalideViewController.mm */, + 4A1000000000000000000007 /* SceneDelegate.h */, + 4A1000000000000000000008 /* SceneDelegate.mm */, + 4A1000000000000000000009 /* main.mm */, + 4A100000000000000000000A /* Images.xcassets */, + 4A100000000000000000000B /* InfoPlist.strings */, + 4A100000000000000000000C /* HelloiOS-Info.plist */, + 4A100000000000000000000D /* HelloiOS-Prefix.pch */, + 4A3000000000000000000003 /* Frameworks */, + 4A3000000000000000000002 /* Products */, + ); + sourceTree = ""; + }; + 4A3000000000000000000002 /* Products */ = { + isa = PBXGroup; + children = ( + 4A1000000000000000000014 /* HelloiOS.app */, + ); + name = Products; + sourceTree = ""; + }; + 4A3000000000000000000003 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4A100000000000000000000F /* CoreGraphics.framework */, + 4A1000000000000000000010 /* Foundation.framework */, + 4A1000000000000000000011 /* Metal.framework */, + 4A1000000000000000000012 /* QuartzCore.framework */, + 4A1000000000000000000013 /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A5000000000000000000001 /* HelloiOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A7000000000000000000002 /* Build configuration list for PBXNativeTarget "HelloiOS" */; + buildPhases = ( + 4A4000000000000000000004 /* Build Halide Generators */, + 4A4000000000000000000001 /* Sources */, + 4A4000000000000000000002 /* Frameworks */, + 4A4000000000000000000003 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = HelloiOS; + productName = HelloiOS; + productReference = 4A1000000000000000000014 /* HelloiOS.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A6000000000000000000001 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1600; + }; + buildConfigurationList = 4A7000000000000000000001 /* Build configuration list for PBXProject "HelloiOS" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 4A3000000000000000000001 /* HelloiOS */; + productRefGroup = 4A3000000000000000000002 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A5000000000000000000001 /* HelloiOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4A4000000000000000000003 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A2000000000000000000006 /* Images.xcassets in Resources */, + 4A2000000000000000000007 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 4A4000000000000000000004 /* Build Halide Generators */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Build Halide Generators"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/bash; + shellScript = "exec \"${PROJECT_DIR}/../Generators/rebuild-kernels.sh\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A4000000000000000000001 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A2000000000000000000001 /* AppDelegate.mm in Sources */, + 4A2000000000000000000002 /* HalideView.mm in Sources */, + 4A2000000000000000000003 /* HalideViewController.mm in Sources */, + 4A2000000000000000000004 /* SceneDelegate.mm in Sources */, + 4A2000000000000000000005 /* main.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4A8000000000000000000001 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = 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_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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + 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; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + }; + name = Debug; + }; + 4A8000000000000000000002 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = 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_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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + 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; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 4A8000000000000000000003 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A100000000000000000000E /* GeneratorPaths.xcconfig */; + buildSettings = { + ARCHS = arm64; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGNING_ALLOWED = "$(HELLOIOS_CODE_SIGNING_ALLOWED)"; + CODE_SIGN_IDENTITY = "$(HELLOIOS_CODE_SIGN_IDENTITY)"; + DEVELOPMENT_TEAM = "$(HELLOIOS_DEVELOPMENT_TEAM)"; + ENABLE_BITCODE = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HelloiOS-Prefix.pch"; + HEADER_SEARCH_PATHS = ( + "$(GENERATORS_BUILD_DIR)", + "$(HALIDE_INCLUDE_DIR)", + ); + INFOPLIST_FILE = "HelloiOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + OTHER_LDFLAGS = ( + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render.runtime.a", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; + PRODUCT_NAME = HelloiOS; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 4A8000000000000000000004 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A100000000000000000000E /* GeneratorPaths.xcconfig */; + buildSettings = { + ARCHS = arm64; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGNING_ALLOWED = "$(HELLOIOS_CODE_SIGNING_ALLOWED)"; + CODE_SIGN_IDENTITY = "$(HELLOIOS_CODE_SIGN_IDENTITY)"; + DEVELOPMENT_TEAM = "$(HELLOIOS_DEVELOPMENT_TEAM)"; + ENABLE_BITCODE = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HelloiOS-Prefix.pch"; + HEADER_SEARCH_PATHS = ( + "$(GENERATORS_BUILD_DIR)", + "$(HALIDE_INCLUDE_DIR)", + ); + INFOPLIST_FILE = "HelloiOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + OTHER_LDFLAGS = ( + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render.runtime.a", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; + PRODUCT_NAME = HelloiOS; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A7000000000000000000001 /* Build configuration list for PBXProject "HelloiOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A8000000000000000000001 /* Debug */, + 4A8000000000000000000002 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A7000000000000000000002 /* Build configuration list for PBXNativeTarget "HelloiOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A8000000000000000000003 /* Debug */, + 4A8000000000000000000004 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A6000000000000000000001 /* Project object */; +} \ No newline at end of file diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index b19270ac959d..5bda4313e625 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -1,118 +1,75 @@ # HelloiOS -An interactive reaction-diffusion iOS demo that builds its Halide generators on -the host, then builds the iOS app and generated Halide libraries from CMake. +An interactive reaction-diffusion iOS demo powered by Halide. -## Supported Workflow - -Use [`build.sh`](build.sh) with an iOS Halide target, for example: +## Quick Start ```bash cd apps/HelloiOS -./build.sh arm-64-ios-simulator -./build.sh arm-64-ios +Halide_ROOT=/path/to/halide/install ./build.sh arm-64-ios-simulator +open HelloiOS.xcworkspace ``` -The script does two builds: +Then select the **HelloiOS** scheme in Xcode, pick a destination, and build. + +## How It Works + +The project is split into two parts: -1. A host build in `build/host` that exports `HelloiOS-halide_generators` -2. An iOS build in `build/` that imports that package, generates - the Halide pipelines, and builds `HelloiOS.app` +1. **Generators/** -- A CMake project that builds the Halide generator on the + host and runs it to produce iOS-targeted static libraries and headers for + each reaction-diffusion kernel. The `Halide_TARGET` variable controls which + architecture the generated code targets. -For the iOS build, `build.sh` uses CMake's iOS cross-compilation support with: +2. **HelloiOS/** -- A native Xcode project for the iOS app. It compiles the + Objective-C++ sources and links the generated Halide libraries. -- `-DCMAKE_SYSTEM_NAME=iOS` -- `-DCMAKE_OSX_SYSROOT=iphonesimulator` when `Halide_TARGET` contains - `simulator`, otherwise `iphoneos` -- `-DCMAKE_OSX_ARCHITECTURES=arm64` -- `-DHalide_TARGET=` +Both live in **HelloiOS.xcworkspace**. A one-time `build.sh` setup configures +and builds the CMake side, writing a `GeneratorPaths.xcconfig` that the Xcode +project reads for paths. A Run Script build phase in Xcode re-invokes +`cmake --build` so generator changes are picked up automatically. ## Prerequisites -Halide must be installed first, and `Halide_ROOT` must be set to the Halide -install prefix before invoking `build.sh`. +Halide must be built (or installed) first: ```bash cd /path/to/Halide cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build cmake --install build --prefix install - -export Halide_ROOT=$PWD/install -``` - -`build.sh` sets `HalideHelpers_ROOT` from `Halide_ROOT` automatically. - -## Useful Environment Variables - -- `Halide_ROOT`: Halide install prefix. Required. -- `CMAKE_BUILD_TYPE`: Build configuration. Default: `Release` -- `CMAKE_OSX_DEPLOYMENT_TARGET`: iOS deployment target. Default: `15.0` -- `HELLOIOS_DEVELOPMENT_TEAM`: Optional Apple development team ID. If unset, - code signing is disabled for the generated app target. -- `HOST_BUILD_DIR`: Override the host build directory -- `IOS_BUILD_DIR`: Override the iOS build directory - -Example: - -```bash -Halide_ROOT=$HOME/halide-install \ -HELLOIOS_DEVELOPMENT_TEAM=ABCDE12345 \ -./build.sh arm-64-ios -``` - -## Manual Equivalent - -If you want to drive the two builds yourself, this is the structure `build.sh` -uses. - -Host generator build: - -```bash -cmake -S . -B build/host \ - -DHalide_ROOT=/path/to/install \ - -DHalideHelpers_ROOT=/path/to/install -cmake --build build/host --target HelloiOS-halide_generators ``` -iOS app build: - -```bash -cmake -G Xcode -S . -B build/arm-64-ios-simulator \ - -DCMAKE_SYSTEM_NAME=iOS \ - -DCMAKE_OSX_ARCHITECTURES=arm64 \ - -DCMAKE_OSX_SYSROOT=iphonesimulator \ - -DCMAKE_OSX_DEPLOYMENT_TARGET=15.0 \ - -DHalide_ROOT=/path/to/install \ - -DHalideHelpers_ROOT=/path/to/install \ - -DHalide_TARGET=arm-64-ios-simulator \ - -DHelloiOS-halide_generators_ROOT=$PWD/build/host -cmake --build build/arm-64-ios-simulator --config Release --target HelloiOS -``` +## Environment Variables -## Launching In Simulator +| Variable | Default | Description | +|---|---|---| +| `Halide_ROOT` | *(required)* | Halide install prefix | +| `CMAKE_BUILD_TYPE` | `Release` | Build configuration for generators | +| `HELLOIOS_DEVELOPMENT_TEAM` | *(empty)* | Apple team ID for code signing | -After building a simulator target, you can boot a device, install the app, and -launch it from the command line: +## Launching in Simulator ```bash open -a Simulator xcrun simctl bootstatus "iPhone 16" -b -xcrun simctl install booted build/arm-64-ios-simulator/Release-iphonesimulator/HelloiOS.app +xcrun simctl install booted HelloiOS/build/Release-iphonesimulator/HelloiOS.app xcrun simctl launch booted org.halide.HelloiOS ``` -To see the available simulator device names: - -```bash -xcrun simctl list devices available -``` +Or use Xcode's Run button after building for a simulator destination. -## Notes +## Project Structure -- [`CMakeLists.txt`](CMakeLists.txt) is the only supported CMake entry point. -- In a non-iOS configure, `CMakeLists.txt` only exports the host generator - package. -- In an iOS configure, the same file builds the generated Halide libraries and - the iOS app bundle. -- CMake generates the Xcode project in `build/`. +``` +HelloiOS/ + HelloiOS.xcworkspace/ Top-level workspace + Generators/ + CMakeLists.txt Builds generator + produces iOS kernels + reaction_diffusion_2_generator.cpp + build/ Created by build.sh + HelloiOS/ + HelloiOS.xcodeproj/ Native Xcode project for the iOS app + *.h / *.mm App source files + build.sh One-time setup script +``` \ No newline at end of file diff --git a/apps/HelloiOS/build.sh b/apps/HelloiOS/build.sh index 85c346b48c33..1028bfaf4913 100755 --- a/apps/HelloiOS/build.sh +++ b/apps/HelloiOS/build.sh @@ -16,40 +16,55 @@ if [[ "${HALIDE_TARGET}" == "host" ]]; then die "Halide_TARGET=host is not valid for the iOS app build." fi -if [[ "${HALIDE_TARGET}" == *simulator* ]]; then - CMAKE_OSX_SYSROOT=iphonesimulator -else - CMAKE_OSX_SYSROOT=iphoneos -fi - SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" : "${CMAKE_BUILD_TYPE:=Release}" -: "${CMAKE_OSX_DEPLOYMENT_TARGET:=15.0}" : "${HELLOIOS_DEVELOPMENT_TEAM:=}" -: "${HOST_BUILD_DIR:=${SCRIPT_DIR}/build/host}" -: "${IOS_BUILD_DIR:=${SCRIPT_DIR}/build/${HALIDE_TARGET}}" - -[[ -n "${Halide_ROOT:-}" ]] || die "Set Halide_ROOT in the environment to the Halide install prefix." +: "${Halide_ROOT:?Set Halide_ROOT in the environment to the Halide install prefix.}" export HalideHelpers_ROOT="${Halide_ROOT}" -## Phase 1: Host build of the Halide generators. +CMAKE="$(command -v cmake)" +: "${CMAKE:?cmake not found in PATH}" + +BUILD_DIR="${SCRIPT_DIR}/Generators/build" -cmake -S "${SCRIPT_DIR}" -B "${HOST_BUILD_DIR}" -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" -cmake --build "${HOST_BUILD_DIR}" +cmake -S "${SCRIPT_DIR}/Generators" -B "${BUILD_DIR}" \ + -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \ + -DHalide_TARGET="${HALIDE_TARGET}" + +cmake --build "${BUILD_DIR}" + +## Write xcconfig for the native Xcode project. + +if [[ -n "${HELLOIOS_DEVELOPMENT_TEAM}" ]]; then + CODE_SIGNING_SETTINGS=$(cat < "${BUILD_DIR}/GeneratorPaths.xcconfig" < Date: Sat, 7 Mar 2026 11:32:03 -0500 Subject: [PATCH 06/37] use Xcode generator again --- apps/HelloiOS/Generators/rebuild-kernels.sh | 2 +- .../contents.xcworkspacedata | 3 +++ .../HelloiOS.xcodeproj/project.pbxproj | 8 ++---- apps/HelloiOS/build.sh | 26 +------------------ 4 files changed, 7 insertions(+), 32 deletions(-) diff --git a/apps/HelloiOS/Generators/rebuild-kernels.sh b/apps/HelloiOS/Generators/rebuild-kernels.sh index dd839532c35f..8532c3d64151 100755 --- a/apps/HelloiOS/Generators/rebuild-kernels.sh +++ b/apps/HelloiOS/Generators/rebuild-kernels.sh @@ -10,4 +10,4 @@ if [ -z "${GENERATORS_BUILD_DIR:-}" ]; then exit 1 fi -"$CMAKE_COMMAND" --build "$GENERATORS_BUILD_DIR" \ No newline at end of file +"$CMAKE_COMMAND" --build "$GENERATORS_BUILD_DIR" --config Release \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata b/apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata index 5c8ad7dae2f7..a73d6b168f24 100644 --- a/apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata +++ b/apps/HelloiOS/HelloiOS.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index f23104bbaa80..431575f1f648 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -296,9 +296,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_OBJC_ARC = YES; - CODE_SIGNING_ALLOWED = "$(HELLOIOS_CODE_SIGNING_ALLOWED)"; - CODE_SIGN_IDENTITY = "$(HELLOIOS_CODE_SIGN_IDENTITY)"; - DEVELOPMENT_TEAM = "$(HELLOIOS_DEVELOPMENT_TEAM)"; + CODE_SIGN_IDENTITY = "-"; ENABLE_BITCODE = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HelloiOS-Prefix.pch"; @@ -338,9 +336,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_OBJC_ARC = YES; - CODE_SIGNING_ALLOWED = "$(HELLOIOS_CODE_SIGNING_ALLOWED)"; - CODE_SIGN_IDENTITY = "$(HELLOIOS_CODE_SIGN_IDENTITY)"; - DEVELOPMENT_TEAM = "$(HELLOIOS_DEVELOPMENT_TEAM)"; + CODE_SIGN_IDENTITY = "-"; ENABLE_BITCODE = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HelloiOS-Prefix.pch"; diff --git a/apps/HelloiOS/build.sh b/apps/HelloiOS/build.sh index 1028bfaf4913..232506ae1121 100755 --- a/apps/HelloiOS/build.sh +++ b/apps/HelloiOS/build.sh @@ -18,9 +18,6 @@ fi SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" -: "${CMAKE_BUILD_TYPE:=Release}" -: "${HELLOIOS_DEVELOPMENT_TEAM:=}" - : "${Halide_ROOT:?Set Halide_ROOT in the environment to the Halide install prefix.}" export HalideHelpers_ROOT="${Halide_ROOT}" @@ -29,38 +26,17 @@ CMAKE="$(command -v cmake)" BUILD_DIR="${SCRIPT_DIR}/Generators/build" -cmake -S "${SCRIPT_DIR}/Generators" -B "${BUILD_DIR}" \ - -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \ +cmake -G Xcode -S "${SCRIPT_DIR}/Generators" -B "${BUILD_DIR}" \ -DHalide_TARGET="${HALIDE_TARGET}" -cmake --build "${BUILD_DIR}" - ## Write xcconfig for the native Xcode project. -if [[ -n "${HELLOIOS_DEVELOPMENT_TEAM}" ]]; then - CODE_SIGNING_SETTINGS=$(cat < "${BUILD_DIR}/GeneratorPaths.xcconfig" < Date: Sat, 7 Mar 2026 11:38:28 -0500 Subject: [PATCH 07/37] don't clutter the Xcode project navigator --- apps/HelloiOS/Generators/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index 68e9de00bfcc..79276cfeeaf9 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -36,4 +36,11 @@ foreach (stage IN ITEMS init update render) reaction_diffusion_2_metal_${stage}.update reaction_diffusion_2_metal_${stage}.runtime.update) endforeach () -add_custom_target(halide_kernels ALL DEPENDS ${_all_kernel_updates}) \ No newline at end of file +add_custom_target(halide_kernels ALL DEPENDS ${_all_kernel_updates}) + +# Group internal targets so they don't clutter the Xcode project navigator. +set_target_properties( + halide_kernels ${_all_kernel_updates} "${PROJECT_NAME}-halide_generators" + PROPERTIES + FOLDER "Halide Internal" +) From 2f0b8edf7e77e44a9fb70f016fefae03fa7d878c Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 12:06:33 -0500 Subject: [PATCH 08/37] Build for both device and simulator --- apps/HelloiOS/Generators/CMakeLists.txt | 45 +++++++++-------- .../HelloiOS.xcodeproj/project.pbxproj | 48 +++++++++---------- apps/HelloiOS/README.md | 2 +- apps/HelloiOS/build.sh | 17 +------ 4 files changed, 51 insertions(+), 61 deletions(-) diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index 79276cfeeaf9..ca8e33a7d5ba 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -12,30 +12,35 @@ add_halide_generator( SOURCES reaction_diffusion_2_generator.cpp ) -foreach (stage IN ITEMS init update render) - add_halide_library(reaction_diffusion_2_${stage} - FROM reaction_diffusion_2_generator - GENERATOR reaction_diffusion_2_${stage} - FUNCTION_NAME reaction_diffusion_2_${stage} - FEATURES user_context) - - add_halide_library(reaction_diffusion_2_metal_${stage} - FROM reaction_diffusion_2_generator - GENERATOR reaction_diffusion_2_${stage} - FUNCTION_NAME reaction_diffusion_2_metal_${stage} - FEATURES metal user_context) +set(_all_kernel_updates "") +set(platforms iphoneos iphonesimulator) +set(targets arm-64-ios arm-64-ios-simulator) +foreach (_suffix _target IN ZIP_LISTS platforms targets) + foreach (stage IN ITEMS init update render) + add_halide_library(reaction_diffusion_2_${stage}_${_suffix} + FROM reaction_diffusion_2_generator + GENERATOR reaction_diffusion_2_${stage} + FUNCTION_NAME reaction_diffusion_2_${stage} + TARGETS ${_target} + FEATURES user_context) + + add_halide_library(reaction_diffusion_2_metal_${stage}_${_suffix} + FROM reaction_diffusion_2_generator + GENERATOR reaction_diffusion_2_${stage} + FUNCTION_NAME reaction_diffusion_2_metal_${stage} + TARGETS ${_target} + FEATURES metal user_context) + + list(APPEND _all_kernel_updates + reaction_diffusion_2_${stage}_${_suffix}.update + reaction_diffusion_2_${stage}_${_suffix}.runtime.update + reaction_diffusion_2_metal_${stage}_${_suffix}.update + reaction_diffusion_2_metal_${stage}_${_suffix}.runtime.update) + endforeach () endforeach () # The IMPORTED library targets from add_halide_library are not part of the # default build, so we create an explicit target to drive generation. -set(_all_kernel_updates "") -foreach (stage IN ITEMS init update render) - list(APPEND _all_kernel_updates - reaction_diffusion_2_${stage}.update - reaction_diffusion_2_${stage}.runtime.update - reaction_diffusion_2_metal_${stage}.update - reaction_diffusion_2_metal_${stage}.runtime.update) -endforeach () add_custom_target(halide_kernels ALL DEPENDS ${_all_kernel_updates}) # Group internal targets so they don't clutter the Xcode project navigator. diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index 431575f1f648..8e0388f38a16 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -307,18 +307,18 @@ INFOPLIST_FILE = "HelloiOS-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; OTHER_LDFLAGS = ( - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render_$(PLATFORM_NAME).runtime.a", ); PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; PRODUCT_NAME = HelloiOS; @@ -347,18 +347,18 @@ INFOPLIST_FILE = "HelloiOS-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; OTHER_LDFLAGS = ( - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update.runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render.runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render_$(PLATFORM_NAME).a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update_$(PLATFORM_NAME).runtime.a", + "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render_$(PLATFORM_NAME).runtime.a", ); PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; PRODUCT_NAME = HelloiOS; diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index 5bda4313e625..598c541b5b60 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -6,7 +6,7 @@ An interactive reaction-diffusion iOS demo powered by Halide. ```bash cd apps/HelloiOS -Halide_ROOT=/path/to/halide/install ./build.sh arm-64-ios-simulator +Halide_ROOT=/path/to/halide/install ./build.sh open HelloiOS.xcworkspace ``` diff --git a/apps/HelloiOS/build.sh b/apps/HelloiOS/build.sh index 232506ae1121..bfd735f3ed42 100755 --- a/apps/HelloiOS/build.sh +++ b/apps/HelloiOS/build.sh @@ -2,20 +2,6 @@ set -euo pipefail -die() { - echo "$@" >&2 - exit 1 -} - -if [[ $# -ne 1 ]]; then - die "Usage: $0 " -fi - -HALIDE_TARGET="$1" -if [[ "${HALIDE_TARGET}" == "host" ]]; then - die "Halide_TARGET=host is not valid for the iOS app build." -fi - SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" : "${Halide_ROOT:?Set Halide_ROOT in the environment to the Halide install prefix.}" @@ -26,8 +12,7 @@ CMAKE="$(command -v cmake)" BUILD_DIR="${SCRIPT_DIR}/Generators/build" -cmake -G Xcode -S "${SCRIPT_DIR}/Generators" -B "${BUILD_DIR}" \ - -DHalide_TARGET="${HALIDE_TARGET}" +cmake -G Xcode -S "${SCRIPT_DIR}/Generators" -B "${BUILD_DIR}" ## Write xcconfig for the native Xcode project. From 72d54c8f52dd7a78e3f223ad972e3044b6200664 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 12:06:33 -0500 Subject: [PATCH 09/37] Set folder directly in HalideGeneratorHelpers.cmake --- cmake/HalideGeneratorHelpers.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index 324f44a31985..9981c7daa3dc 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -66,6 +66,7 @@ function(add_halide_generator TARGET) if (NOT TARGET "${gen}") if (NOT TARGET "${ARG_PACKAGE_NAME}") add_custom_target("${ARG_PACKAGE_NAME}") + set_property(TARGET "${ARG_PACKAGE_NAME}" PROPERTY FOLDER "Halide Internal") endif () if (ARG_SOURCES MATCHES ".py$") @@ -310,6 +311,7 @@ function(_Halide_library_from_generator TARGET) endif () add_custom_target("${TARGET}.update" DEPENDS ${output_files}) + set_property(TARGET "${TARGET}.update" PROPERTY FOLDER "Halide Internal") add_dependencies("${TARGET}" "${TARGET}.update") target_link_libraries("${TARGET}" INTERFACE "${ARG_USE_RUNTIME}") @@ -917,6 +919,7 @@ function(add_halide_runtime RT) DEPENDS Halide::GenRT VERBATIM) add_custom_target("${RT}.update" DEPENDS "${GEN_OUTS}") + set_property(TARGET "${RT}.update" PROPERTY FOLDER "Halide Internal") add_library("${RT}" STATIC IMPORTED GLOBAL) add_dependencies("${RT}" "${RT}.update") From 665a2569d87bfec23635efe2526c8cfeda4678fc Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 12:07:25 -0500 Subject: [PATCH 10/37] Simplify folder setting in HelloiOS --- apps/HelloiOS/Generators/CMakeLists.txt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index ca8e33a7d5ba..583a359af5ad 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -42,10 +42,4 @@ endforeach () # The IMPORTED library targets from add_halide_library are not part of the # default build, so we create an explicit target to drive generation. add_custom_target(halide_kernels ALL DEPENDS ${_all_kernel_updates}) - -# Group internal targets so they don't clutter the Xcode project navigator. -set_target_properties( - halide_kernels ${_all_kernel_updates} "${PROJECT_NAME}-halide_generators" - PROPERTIES - FOLDER "Halide Internal" -) +set_property(TARGET halide_kernels PROPERTY FOLDER "Halide Internal") From afef4f1c5e30110b2af6c6a157daec0263c6a134 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 12:14:44 -0500 Subject: [PATCH 11/37] A little more cleanup --- apps/HelloiOS/Generators/CMakeLists.txt | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index 583a359af5ad..7654040e1a44 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -15,27 +15,25 @@ add_halide_generator( set(_all_kernel_updates "") set(platforms iphoneos iphonesimulator) set(targets arm-64-ios arm-64-ios-simulator) -foreach (_suffix _target IN ZIP_LISTS platforms targets) +foreach (platform target IN ZIP_LISTS platforms targets) foreach (stage IN ITEMS init update render) - add_halide_library(reaction_diffusion_2_${stage}_${_suffix} + add_halide_library(reaction_diffusion_2_${stage}_${platform} FROM reaction_diffusion_2_generator GENERATOR reaction_diffusion_2_${stage} FUNCTION_NAME reaction_diffusion_2_${stage} - TARGETS ${_target} + TARGETS ${target} FEATURES user_context) - add_halide_library(reaction_diffusion_2_metal_${stage}_${_suffix} + add_halide_library(reaction_diffusion_2_metal_${stage}_${platform} FROM reaction_diffusion_2_generator GENERATOR reaction_diffusion_2_${stage} FUNCTION_NAME reaction_diffusion_2_metal_${stage} - TARGETS ${_target} + TARGETS ${target} FEATURES metal user_context) list(APPEND _all_kernel_updates - reaction_diffusion_2_${stage}_${_suffix}.update - reaction_diffusion_2_${stage}_${_suffix}.runtime.update - reaction_diffusion_2_metal_${stage}_${_suffix}.update - reaction_diffusion_2_metal_${stage}_${_suffix}.runtime.update) + reaction_diffusion_2_${stage}_${platform} + reaction_diffusion_2_metal_${stage}_${platform}) endforeach () endforeach () From 8a79778c930c2196ef4edec53e16dd82ab5fd415 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 12:43:46 -0500 Subject: [PATCH 12/37] Fix header selection --- apps/HelloiOS/HelloiOS/HalideView.mm | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/HelloiOS/HelloiOS/HalideView.mm b/apps/HelloiOS/HelloiOS/HalideView.mm index ca93791f8d77..f3288c541e98 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.mm +++ b/apps/HelloiOS/HelloiOS/HalideView.mm @@ -3,13 +3,24 @@ #include "HalideBuffer.h" #include "HalideRuntime.h" #include "HalideRuntimeMetal.h" -#include "reaction_diffusion_2_init.h" -#include "reaction_diffusion_2_render.h" -#include "reaction_diffusion_2_update.h" + +#define XSTR(s) STR(s) +#define STR(s) #s + +#if TARGET_IPHONE_SIMULATOR +#define HALIDE_HEADER(name) XSTR(name##_iphonesimulator.h) +#else +#define HALIDE_HEADER(name) XSTR(name##_iphoneos.h) +#endif + +#include HALIDE_HEADER(reaction_diffusion_2_init) +#include HALIDE_HEADER(reaction_diffusion_2_render) +#include HALIDE_HEADER(reaction_diffusion_2_update) + #if HAS_METAL_SDK -#include "reaction_diffusion_2_metal_init.h" -#include "reaction_diffusion_2_metal_render.h" -#include "reaction_diffusion_2_metal_update.h" +#include HALIDE_HEADER(reaction_diffusion_2_metal_init) +#include HALIDE_HEADER(reaction_diffusion_2_metal_render) +#include HALIDE_HEADER(reaction_diffusion_2_metal_update) #endif using Halide::Runtime::Buffer; From 3818887ade87b85ac2f25cc1805123f008704f74 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 12:44:06 -0500 Subject: [PATCH 13/37] Use xcodebuild directly rather than store the CMake path --- apps/HelloiOS/Generators/rebuild-kernels.sh | 6 +++--- apps/HelloiOS/README.md | 12 ++++++------ apps/HelloiOS/build.sh | 4 +--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/HelloiOS/Generators/rebuild-kernels.sh b/apps/HelloiOS/Generators/rebuild-kernels.sh index 8532c3d64151..e662d1028745 100755 --- a/apps/HelloiOS/Generators/rebuild-kernels.sh +++ b/apps/HelloiOS/Generators/rebuild-kernels.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash # Called by the Xcode "Build Halide Generators" run-script phase. -# Variables (CMAKE_COMMAND, GENERATORS_BUILD_DIR) come from -# GeneratorPaths.xcconfig, written by build.sh. +# GENERATORS_BUILD_DIR comes from GeneratorPaths.xcconfig, written by build.sh. set -euo pipefail @@ -10,4 +9,5 @@ if [ -z "${GENERATORS_BUILD_DIR:-}" ]; then exit 1 fi -"$CMAKE_COMMAND" --build "$GENERATORS_BUILD_DIR" --config Release \ No newline at end of file +xcodebuild -project "$GENERATORS_BUILD_DIR/HelloiOS-Generators.xcodeproj" \ + -target halide_kernels -configuration Release \ No newline at end of file diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index 598c541b5b60..716c5732ec4b 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -42,11 +42,11 @@ cmake --install build --prefix install ## Environment Variables -| Variable | Default | Description | -|---|---|---| -| `Halide_ROOT` | *(required)* | Halide install prefix | -| `CMAKE_BUILD_TYPE` | `Release` | Build configuration for generators | -| `HELLOIOS_DEVELOPMENT_TEAM` | *(empty)* | Apple team ID for code signing | +| Variable | Default | Description | +|-----------------------------|--------------|------------------------------------| +| `Halide_ROOT` | *(required)* | Halide install prefix | +| `CMAKE_BUILD_TYPE` | `Release` | Build configuration for generators | +| `HELLOIOS_DEVELOPMENT_TEAM` | *(empty)* | Apple team ID for code signing | ## Launching in Simulator @@ -72,4 +72,4 @@ HelloiOS/ HelloiOS.xcodeproj/ Native Xcode project for the iOS app *.h / *.mm App source files build.sh One-time setup script -``` \ No newline at end of file +``` diff --git a/apps/HelloiOS/build.sh b/apps/HelloiOS/build.sh index bfd735f3ed42..f7f76ad6e8dc 100755 --- a/apps/HelloiOS/build.sh +++ b/apps/HelloiOS/build.sh @@ -18,8 +18,6 @@ cmake -G Xcode -S "${SCRIPT_DIR}/Generators" -B "${BUILD_DIR}" cat > "${BUILD_DIR}/GeneratorPaths.xcconfig" < Date: Sat, 7 Mar 2026 12:52:58 -0500 Subject: [PATCH 14/37] All supported iPhone versions have Metal --- apps/HelloiOS/HelloiOS/HalideView.h | 21 +--- apps/HelloiOS/HelloiOS/HalideView.mm | 107 ++++-------------- .../HelloiOS/HelloiOS/HalideViewController.mm | 2 - 3 files changed, 24 insertions(+), 106 deletions(-) diff --git a/apps/HelloiOS/HelloiOS/HalideView.h b/apps/HelloiOS/HelloiOS/HalideView.h index 60441ee52db1..4d2d28042c2e 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.h +++ b/apps/HelloiOS/HelloiOS/HalideView.h @@ -1,36 +1,19 @@ -#include - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_13_0 -#define HAS_METAL_SDK 1 -#else -#define HAS_METAL_SDK 0 -#endif - #import -#import - -#if HAS_METAL_SDK #import -#endif // HAS_METAL_SDK +#import -#if HAS_METAL_SDK @interface HalideView : UIView -#else -@interface HalideView : UIImageView -#endif @property CGPoint touch_position; @property bool touch_active; @property UILabel *statsLabel; -#if HAS_METAL_SDK @property bool use_metal; // view has a handle to the metal device when created @property(nonatomic, readonly) id device; // view has a handle to the metal device when created @property(nonatomic, readonly) id commandQueue; -#endif // HAS_METAL_SDK - (void)initiateRender; -@end +@end \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS/HalideView.mm b/apps/HelloiOS/HelloiOS/HalideView.mm index f3288c541e98..49ccf6eb89f8 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.mm +++ b/apps/HelloiOS/HelloiOS/HalideView.mm @@ -17,11 +17,9 @@ #include HALIDE_HEADER(reaction_diffusion_2_render) #include HALIDE_HEADER(reaction_diffusion_2_update) -#if HAS_METAL_SDK #include HALIDE_HEADER(reaction_diffusion_2_metal_init) #include HALIDE_HEADER(reaction_diffusion_2_metal_render) #include HALIDE_HEADER(reaction_diffusion_2_metal_update) -#endif using Halide::Runtime::Buffer; @@ -37,36 +35,30 @@ reaction_diffusion_2_render }; -#if HAS_METAL_SDK static const HalideFuncs kHalideMetal = { reaction_diffusion_2_metal_init, reaction_diffusion_2_metal_update, reaction_diffusion_2_metal_render }; -#endif @implementation HalideView { @private -#if HAS_METAL_SDK __weak CAMetalLayer *_metalLayer; -#endif // HAS_METAL_SDK - + Buffer buf1; Buffer buf2; Buffer pixel_buf; - + int32_t iteration; double frameElapsedEstimate; } -#if HAS_METAL_SDK + (Class)layerClass { return [CAMetalLayer class]; } -#endif // HAS_METAL_SDK - (void)initCommon { @@ -74,18 +66,16 @@ - (void)initCommon self.backgroundColor = nil; self.userInteractionEnabled = YES; -#if HAS_METAL_SDK _metalLayer = (CAMetalLayer *)self.layer; _metalLayer.delegate = self; _device = MTLCreateSystemDefaultDevice(); _commandQueue = [_device newCommandQueue]; - + _metalLayer.device = _device; _metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; - + _metalLayer.framebufferOnly = NO; -#endif // HAS_METAL_SDK } - (void) resetFrameTime @@ -159,7 +149,7 @@ - (id)initWithFrame:(CGRect)frame - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; - + if(self) { [self initCommon]; @@ -169,11 +159,7 @@ - (instancetype)initWithCoder:(NSCoder *)coder - (void)updateLogWith: (double) elapsedTime using_metal: (bool) using_metal { -#if HAS_METAL_SDK NSString *mode = using_metal ? @"Metal (double-tap for CPU)" : @"CPU (double-tap for Metal)"; -#else - NSString *mode = @"CPU only"; -#endif self.statsLabel.text = [NSString stringWithFormat:@"%.1f ms • %@", elapsedTime * 1000, mode]; } @@ -181,13 +167,11 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* touch = [touches anyObject]; self.touch_position = [touch locationInView:self]; self.touch_active = [self pointInside:self.touch_position withEvent:event]; -#if HAS_METAL_SDK NSUInteger numTaps = [touch tapCount]; if (numTaps > 1) { self.use_metal = !self.use_metal; NSLog(@"TBTaps: %d, self.use_metal %d", (int)numTaps, (int)self.use_metal); } -#endif } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { @@ -214,22 +198,18 @@ - (void)renderOneFrame: (const HalideFuncs &) halide_funcs using_metal: (bool) u NSLog(@"touch %d %d", tx, ty); } -#if HAS_METAL_SDK const bool output_bgra = true; -#else - const bool output_bgra = false; -#endif - // A note on timing: based on our experimentation, this is indeed effective for - // timing Metal launches, not just CPU kernels. Other GPU API implementations - // may return way before actually completing kernel execution, but Metal - // (at least in this context) doesn't seem to, making this basic timing approach + // A note on timing: based on our experimentation, this is indeed effective for + // timing Metal launches, not just CPU kernels. Other GPU API implementations + // may return way before actually completing kernel execution, but Metal + // (at least in this context) doesn't seem to, making this basic timing approach // fairly effective. - // - // However, there seems to be a large minimum latency to return from the Metal launches, - // which can make this an underestimate of the potential GPU throughput; for example, - // running the update and render steps 10 times per frame (instead of once) - // converges to a steady state per-frame cost which is often much less than + // + // However, there seems to be a large minimum latency to return from the Metal launches, + // which can make this an underestimate of the potential GPU throughput; for example, + // running the update and render steps 10 times per frame (instead of once) + // converges to a steady state per-frame cost which is often much less than // the single iteration cost. double t_before = CACurrentMediaTime(); @@ -244,7 +224,6 @@ - (void)renderOneFrame: (const HalideFuncs &) halide_funcs using_metal: (bool) u - (void)initiateRender { -#if HAS_METAL_SDK bool using_metal = self.use_metal; const HalideFuncs &halide_funcs = using_metal ? kHalideMetal : kHalideCPU; const int required_stride = using_metal ? 3 : 1; @@ -261,17 +240,17 @@ - (void)initiateRender texture.width != buf1.dim(0).extent() || texture.height != buf1.dim(1).extent() || buf1.dim(0).stride() != required_stride) { - + // set the metal layer to the drawable size in case orientation or size changes CGSize drawableSize = self.bounds.size; _metalLayer.drawableSize = drawableSize; - + [self initBufsWithWidth: drawableSize.width height: drawableSize.height using_metal: using_metal]; halide_funcs.init((__bridge void *)self, buf1); [self resetFrameTime]; } - + [self renderOneFrame: halide_funcs using_metal: using_metal]; id buffer = using_metal ? @@ -289,15 +268,15 @@ - (void)initiateRender MTLOrigin origin = { 0, 0, 0 }; const int bytesPerRow = pixel_buf.dim(1).stride() * pixel_buf.type().bits / 8; - [blitEncoder - copyFromBuffer:buffer + [blitEncoder + copyFromBuffer:buffer sourceOffset: 0 sourceBytesPerRow: bytesPerRow sourceBytesPerImage: pixel_buf.dim(1).stride() * pixel_buf.dim(1).extent() // Not sizeInBytes because we're also copying the padding on the last row sourceSize: image_size toTexture: drawable.texture - destinationSlice: 0 - destinationLevel: 0 + destinationSlice: 0 + destinationLevel: 0 destinationOrigin: origin]; [blitEncoder endEncoding]; [commandBuffer addCompletedHandler: ^(id MTLCommandBuffer) { @@ -308,50 +287,10 @@ - (void)initiateRender }]; [commandBuffer commit]; } -#else - float f = self.contentScaleFactor; - int image_width = (int) (self.bounds.size.width * f); - int image_height = (int) (self.bounds.size.height * f); - const HalideFuncs &halide_funcs = kHalideCPU; - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [self initBufsWithWidth:image_width height:image_height using_metal: false]; - - CGDataProviderRef provider = - CGDataProviderCreateWithData(NULL, pixel_buf.data(), pixel_buf.size_in_bytes(), NULL); - CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); - - halide_funcs.init((__bridge void *)self, buf1); - [self resetFrameTime]; - - for (;;) { - [self renderOneFrame: halide_funcs using_metal: false]; - - const int bytesPerRow = pixel_buf.dim(1).stride() * pixel_buf.type().bits / 8; - CGImageRef image_ref = - CGImageCreate(image_width, image_height, - 8, // bitsPerComponent - 32, // bitsPerPixel - bytesPerRow, - color_space, - kCGBitmapByteOrderDefault, - provider, NULL, NO, - kCGRenderingIntentDefault); - UIImage *im = [UIImage imageWithCGImage:image_ref]; - CGImageRelease(image_ref); - - dispatch_async(dispatch_get_main_queue(), ^(void) { - [self setImage: im]; - }); - } - }); -#endif // HAS_METAL_SDK } @end -#if HAS_METAL_SDK - #ifdef __cplusplus extern "C" { #endif @@ -370,6 +309,4 @@ int halide_metal_release_context(void *user_context) { #ifdef __cplusplus } -#endif - -#endif // HAS_METAL_SDK +#endif \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS/HalideViewController.mm b/apps/HelloiOS/HelloiOS/HalideViewController.mm index 008b9d150ab8..b330ee6c7ca0 100644 --- a/apps/HelloiOS/HelloiOS/HalideViewController.mm +++ b/apps/HelloiOS/HelloiOS/HalideViewController.mm @@ -11,9 +11,7 @@ - (void)loadView { _halideView = [[HalideView alloc] initWithFrame:CGRectZero]; _halideView.backgroundColor = [UIColor blackColor]; -#if HAS_METAL_SDK _halideView.use_metal = YES; -#endif self.view = _halideView; From be58a13556b17f149c38d84c97513dac66fccf2d Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 12:57:27 -0500 Subject: [PATCH 15/37] Rename build.sh to setup.sh --- apps/HelloiOS/Generators/rebuild-kernels.sh | 4 ++-- apps/HelloiOS/{build.sh => setup.sh} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename apps/HelloiOS/{build.sh => setup.sh} (94%) diff --git a/apps/HelloiOS/Generators/rebuild-kernels.sh b/apps/HelloiOS/Generators/rebuild-kernels.sh index e662d1028745..f0be8a9368a2 100755 --- a/apps/HelloiOS/Generators/rebuild-kernels.sh +++ b/apps/HelloiOS/Generators/rebuild-kernels.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash # Called by the Xcode "Build Halide Generators" run-script phase. -# GENERATORS_BUILD_DIR comes from GeneratorPaths.xcconfig, written by build.sh. +# GENERATORS_BUILD_DIR comes from GeneratorPaths.xcconfig, written by setup.sh. set -euo pipefail if [ -z "${GENERATORS_BUILD_DIR:-}" ]; then - echo "error: GENERATORS_BUILD_DIR is not set. Run build.sh first to configure." + echo "error: GENERATORS_BUILD_DIR is not set. Run setup.sh first to configure." exit 1 fi diff --git a/apps/HelloiOS/build.sh b/apps/HelloiOS/setup.sh similarity index 94% rename from apps/HelloiOS/build.sh rename to apps/HelloiOS/setup.sh index f7f76ad6e8dc..a964f887bbe6 100755 --- a/apps/HelloiOS/build.sh +++ b/apps/HelloiOS/setup.sh @@ -17,7 +17,7 @@ cmake -G Xcode -S "${SCRIPT_DIR}/Generators" -B "${BUILD_DIR}" ## Write xcconfig for the native Xcode project. cat > "${BUILD_DIR}/GeneratorPaths.xcconfig" < Date: Sat, 7 Mar 2026 12:57:32 -0500 Subject: [PATCH 16/37] Update README.md --- apps/HelloiOS/README.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index 716c5732ec4b..b83f553ba713 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -6,7 +6,7 @@ An interactive reaction-diffusion iOS demo powered by Halide. ```bash cd apps/HelloiOS -Halide_ROOT=/path/to/halide/install ./build.sh +Halide_ROOT=/path/to/halide/install ./setup.sh open HelloiOS.xcworkspace ``` @@ -18,16 +18,19 @@ The project is split into two parts: 1. **Generators/** -- A CMake project that builds the Halide generator on the host and runs it to produce iOS-targeted static libraries and headers for - each reaction-diffusion kernel. The `Halide_TARGET` variable controls which - architecture the generated code targets. + each reaction-diffusion kernel. Kernels are generated for both `iphoneos` + and `iphonesimulator` platforms, so you can switch destinations in Xcode + without re-running setup. 2. **HelloiOS/** -- A native Xcode project for the iOS app. It compiles the - Objective-C++ sources and links the generated Halide libraries. + Objective-C++ sources and links the generated Halide libraries. The app + renders a reaction-diffusion simulation using Metal, with a CPU alternative + available via double-tap. -Both live in **HelloiOS.xcworkspace**. A one-time `build.sh` setup configures -and builds the CMake side, writing a `GeneratorPaths.xcconfig` that the Xcode -project reads for paths. A Run Script build phase in Xcode re-invokes -`cmake --build` so generator changes are picked up automatically. +Both live in **HelloiOS.xcworkspace**. A one-time `setup.sh` configures the +CMake side and writes a `GeneratorPaths.xcconfig` that the Xcode project reads +for paths. A Run Script build phase in Xcode invokes `rebuild-kernels.sh` so +generator changes are picked up automatically. ## Prerequisites @@ -42,11 +45,9 @@ cmake --install build --prefix install ## Environment Variables -| Variable | Default | Description | -|-----------------------------|--------------|------------------------------------| -| `Halide_ROOT` | *(required)* | Halide install prefix | -| `CMAKE_BUILD_TYPE` | `Release` | Build configuration for generators | -| `HELLOIOS_DEVELOPMENT_TEAM` | *(empty)* | Apple team ID for code signing | +| Variable | Default | Description | +|---------------|--------------|-----------------------| +| `Halide_ROOT` | *(required)* | Halide install prefix | ## Launching in Simulator @@ -66,10 +67,11 @@ HelloiOS/ HelloiOS.xcworkspace/ Top-level workspace Generators/ CMakeLists.txt Builds generator + produces iOS kernels + rebuild-kernels.sh Called by Xcode Run Script build phase reaction_diffusion_2_generator.cpp - build/ Created by build.sh + build/ Created by setup.sh HelloiOS/ HelloiOS.xcodeproj/ Native Xcode project for the iOS app *.h / *.mm App source files - build.sh One-time setup script + setup.sh One-time setup script ``` From 8f132678de930655128a406abcc6d12c13d1e8b6 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 13:17:29 -0500 Subject: [PATCH 17/37] Generate xcconfig from CMake --- apps/HelloiOS/Generators/CMakeLists.txt | 11 ++++++++++- apps/HelloiOS/Generators/rebuild-kernels.sh | 2 +- apps/HelloiOS/setup.sh | 20 +++----------------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index 7654040e1a44..a377db14707f 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) -find_package(HalideHelpers REQUIRED) +find_package(Halide REQUIRED) add_halide_generator( reaction_diffusion_2_generator @@ -41,3 +41,12 @@ endforeach () # default build, so we create an explicit target to drive generation. add_custom_target(halide_kernels ALL DEPENDS ${_all_kernel_updates}) set_property(TARGET halide_kernels PROPERTY FOLDER "Halide Internal") + +## Write xcconfig for the native Xcode project. +file(GENERATE + OUTPUT "${CMAKE_BINARY_DIR}/GeneratorPaths.xcconfig" + CONTENT + "// Generated by CMake -- do not edit. +GENERATORS_BUILD_DIR = ${CMAKE_CURRENT_BINARY_DIR} +HALIDE_INCLUDE_DIR = $> +") diff --git a/apps/HelloiOS/Generators/rebuild-kernels.sh b/apps/HelloiOS/Generators/rebuild-kernels.sh index f0be8a9368a2..1e972c0e715d 100755 --- a/apps/HelloiOS/Generators/rebuild-kernels.sh +++ b/apps/HelloiOS/Generators/rebuild-kernels.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Called by the Xcode "Build Halide Generators" run-script phase. -# GENERATORS_BUILD_DIR comes from GeneratorPaths.xcconfig, written by setup.sh. +# GENERATORS_BUILD_DIR comes from GeneratorPaths.xcconfig, generated by CMake. set -euo pipefail diff --git a/apps/HelloiOS/setup.sh b/apps/HelloiOS/setup.sh index a964f887bbe6..b37316e0f76f 100755 --- a/apps/HelloiOS/setup.sh +++ b/apps/HelloiOS/setup.sh @@ -2,28 +2,14 @@ set -euo pipefail -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" - : "${Halide_ROOT:?Set Halide_ROOT in the environment to the Halide install prefix.}" -export HalideHelpers_ROOT="${Halide_ROOT}" - -CMAKE="$(command -v cmake)" -: "${CMAKE:?cmake not found in PATH}" - -BUILD_DIR="${SCRIPT_DIR}/Generators/build" - -cmake -G Xcode -S "${SCRIPT_DIR}/Generators" -B "${BUILD_DIR}" -## Write xcconfig for the native Xcode project. +cd "$(dirname "${BASH_SOURCE[0]}")" -cat > "${BUILD_DIR}/GeneratorPaths.xcconfig" < Date: Sat, 7 Mar 2026 13:34:11 -0500 Subject: [PATCH 18/37] Use XCode's own propagation mechanism for includes and libraries --- apps/HelloiOS/Generators/CMakeLists.txt | 20 ++++++++--- .../HelloiOS.xcodeproj/project.pbxproj | 36 ------------------- 2 files changed, 16 insertions(+), 40 deletions(-) diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index a377db14707f..d7e8c05dc730 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -12,7 +12,7 @@ add_halide_generator( SOURCES reaction_diffusion_2_generator.cpp ) -set(_all_kernel_updates "") +set(_all_kernels "") set(platforms iphoneos iphonesimulator) set(targets arm-64-ios arm-64-ios-simulator) foreach (platform target IN ZIP_LISTS platforms targets) @@ -31,7 +31,7 @@ foreach (platform target IN ZIP_LISTS platforms targets) TARGETS ${target} FEATURES metal user_context) - list(APPEND _all_kernel_updates + list(APPEND _all_kernels reaction_diffusion_2_${stage}_${platform} reaction_diffusion_2_metal_${stage}_${platform}) endforeach () @@ -39,14 +39,26 @@ endforeach () # The IMPORTED library targets from add_halide_library are not part of the # default build, so we create an explicit target to drive generation. -add_custom_target(halide_kernels ALL DEPENDS ${_all_kernel_updates}) +add_custom_target(halide_kernels ALL DEPENDS ${_all_kernels}) set_property(TARGET halide_kernels PROPERTY FOLDER "Halide Internal") +## Build OTHER_LDFLAGS for the native Xcode project. +## $(PLATFORM_NAME) is an Xcode build setting, not a CMake variable. +set(_kernel_ldflags "") +foreach (stage IN ITEMS init update render) + foreach (variant IN ITEMS "" "metal_") + string(APPEND _kernel_ldflags + " $(GENERATORS_BUILD_DIR)/reaction_diffusion_2_${variant}${stage}_$(PLATFORM_NAME).a" + " $(GENERATORS_BUILD_DIR)/reaction_diffusion_2_${variant}${stage}_$(PLATFORM_NAME).runtime.a") + endforeach () +endforeach () + ## Write xcconfig for the native Xcode project. file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/GeneratorPaths.xcconfig" CONTENT "// Generated by CMake -- do not edit. GENERATORS_BUILD_DIR = ${CMAKE_CURRENT_BINARY_DIR} -HALIDE_INCLUDE_DIR = $> +HEADER_SEARCH_PATHS = $(inherited) ${CMAKE_CURRENT_BINARY_DIR} $> +OTHER_LDFLAGS = $(inherited)${_kernel_ldflags} ") diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index 8e0388f38a16..d4c75dedb9ea 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -300,26 +300,8 @@ ENABLE_BITCODE = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HelloiOS-Prefix.pch"; - HEADER_SEARCH_PATHS = ( - "$(GENERATORS_BUILD_DIR)", - "$(HALIDE_INCLUDE_DIR)", - ); INFOPLIST_FILE = "HelloiOS-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - OTHER_LDFLAGS = ( - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render_$(PLATFORM_NAME).runtime.a", - ); PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; PRODUCT_NAME = HelloiOS; SDKROOT = iphoneos; @@ -340,26 +322,8 @@ ENABLE_BITCODE = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HelloiOS-Prefix.pch"; - HEADER_SEARCH_PATHS = ( - "$(GENERATORS_BUILD_DIR)", - "$(HALIDE_INCLUDE_DIR)", - ); INFOPLIST_FILE = "HelloiOS-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - OTHER_LDFLAGS = ( - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render_$(PLATFORM_NAME).a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_init_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_update_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_render_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_init_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_update_$(PLATFORM_NAME).runtime.a", - "$(GENERATORS_BUILD_DIR)/reaction_diffusion_2_metal_render_$(PLATFORM_NAME).runtime.a", - ); PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; PRODUCT_NAME = HelloiOS; SDKROOT = iphoneos; From 0f19d45fb3dce2176feba3a69faace90d8b0b546 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 18:21:10 -0500 Subject: [PATCH 19/37] Just bundle an XCFramework --- apps/HelloiOS/Generators/CMakeLists.txt | 68 +++++++++++++------ apps/HelloiOS/Generators/rebuild-kernels.sh | 13 ---- apps/HelloiOS/HelloiOS/HalideView.mm | 21 ++---- .../HelloiOS.xcodeproj/project.pbxproj | 10 +-- apps/HelloiOS/README.md | 10 +-- apps/HelloiOS/setup.sh | 4 ++ 6 files changed, 67 insertions(+), 59 deletions(-) delete mode 100755 apps/HelloiOS/Generators/rebuild-kernels.sh diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index d7e8c05dc730..5ba270ca332e 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -37,28 +37,54 @@ foreach (platform target IN ZIP_LISTS platforms targets) endforeach () endforeach () -# The IMPORTED library targets from add_halide_library are not part of the -# default build, so we create an explicit target to drive generation. -add_custom_target(halide_kernels ALL DEPENDS ${_all_kernels}) -set_property(TARGET halide_kernels PROPERTY FOLDER "Halide Internal") +# Package all generated kernels into an xcframework for the native Xcode project. +set(_staging "${CMAKE_CURRENT_BINARY_DIR}/_xcfw_staging") +set(_xcfw "${CMAKE_CURRENT_BINARY_DIR}/HalideKernels.xcframework") + +set(_xcfw_commands + COMMAND ${CMAKE_COMMAND} -E rm -rf "${_staging}" "${_xcfw}") +set(_xcfw_create_args "") + +set(_halide_inc "$") + +foreach (platform IN LISTS platforms) + list(APPEND _xcfw_commands + COMMAND ${CMAKE_COMMAND} -E make_directory "${_staging}/${platform}/Headers") + + set(_platform_libs "") + foreach (stage IN ITEMS init update render) + foreach (variant IN ITEMS "" "metal_") + set(_base "reaction_diffusion_2_${variant}${stage}") + list(APPEND _platform_libs + "${CMAKE_CURRENT_BINARY_DIR}/${_base}_${platform}.a" + "${CMAKE_CURRENT_BINARY_DIR}/${_base}_${platform}.runtime.a") + list(APPEND _xcfw_commands + COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_BINARY_DIR}/${_base}_${platform}.h" + "${_staging}/${platform}/Headers/${_base}.h") + endforeach () + endforeach () -## Build OTHER_LDFLAGS for the native Xcode project. -## $(PLATFORM_NAME) is an Xcode build setting, not a CMake variable. -set(_kernel_ldflags "") -foreach (stage IN ITEMS init update render) - foreach (variant IN ITEMS "" "metal_") - string(APPEND _kernel_ldflags - " $(GENERATORS_BUILD_DIR)/reaction_diffusion_2_${variant}${stage}_$(PLATFORM_NAME).a" - " $(GENERATORS_BUILD_DIR)/reaction_diffusion_2_${variant}${stage}_$(PLATFORM_NAME).runtime.a") + # Copy Halide runtime headers into this platform slice. + foreach (_hdr IN ITEMS HalideBuffer.h HalideRuntime.h HalideRuntimeMetal.h) + list(APPEND _xcfw_commands + COMMAND ${CMAKE_COMMAND} -E copy + "${_halide_inc}/${_hdr}" + "${_staging}/${platform}/Headers/${_hdr}") endforeach () + + list(APPEND _xcfw_commands + COMMAND libtool -static -o "${_staging}/${platform}/libHalideKernels.a" ${_platform_libs}) + list(APPEND _xcfw_create_args + -library "${_staging}/${platform}/libHalideKernels.a" + -headers "${_staging}/${platform}/Headers") endforeach () -## Write xcconfig for the native Xcode project. -file(GENERATE - OUTPUT "${CMAKE_BINARY_DIR}/GeneratorPaths.xcconfig" - CONTENT - "// Generated by CMake -- do not edit. -GENERATORS_BUILD_DIR = ${CMAKE_CURRENT_BINARY_DIR} -HEADER_SEARCH_PATHS = $(inherited) ${CMAKE_CURRENT_BINARY_DIR} $> -OTHER_LDFLAGS = $(inherited)${_kernel_ldflags} -") +list(APPEND _xcfw_commands + COMMAND xcodebuild -create-xcframework ${_xcfw_create_args} -output "${_xcfw}") + +add_custom_target(halide_kernels ALL + DEPENDS ${_all_kernels} + ${_xcfw_commands} + COMMENT "Packaging HalideKernels.xcframework") +set_property(TARGET halide_kernels PROPERTY FOLDER "Halide Internal") diff --git a/apps/HelloiOS/Generators/rebuild-kernels.sh b/apps/HelloiOS/Generators/rebuild-kernels.sh deleted file mode 100755 index 1e972c0e715d..000000000000 --- a/apps/HelloiOS/Generators/rebuild-kernels.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -# Called by the Xcode "Build Halide Generators" run-script phase. -# GENERATORS_BUILD_DIR comes from GeneratorPaths.xcconfig, generated by CMake. - -set -euo pipefail - -if [ -z "${GENERATORS_BUILD_DIR:-}" ]; then - echo "error: GENERATORS_BUILD_DIR is not set. Run setup.sh first to configure." - exit 1 -fi - -xcodebuild -project "$GENERATORS_BUILD_DIR/HelloiOS-Generators.xcodeproj" \ - -target halide_kernels -configuration Release \ No newline at end of file diff --git a/apps/HelloiOS/HelloiOS/HalideView.mm b/apps/HelloiOS/HelloiOS/HalideView.mm index 49ccf6eb89f8..4b3d145535ef 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.mm +++ b/apps/HelloiOS/HelloiOS/HalideView.mm @@ -4,22 +4,13 @@ #include "HalideRuntime.h" #include "HalideRuntimeMetal.h" -#define XSTR(s) STR(s) -#define STR(s) #s +#include "reaction_diffusion_2_init.h" +#include "reaction_diffusion_2_render.h" +#include "reaction_diffusion_2_update.h" -#if TARGET_IPHONE_SIMULATOR -#define HALIDE_HEADER(name) XSTR(name##_iphonesimulator.h) -#else -#define HALIDE_HEADER(name) XSTR(name##_iphoneos.h) -#endif - -#include HALIDE_HEADER(reaction_diffusion_2_init) -#include HALIDE_HEADER(reaction_diffusion_2_render) -#include HALIDE_HEADER(reaction_diffusion_2_update) - -#include HALIDE_HEADER(reaction_diffusion_2_metal_init) -#include HALIDE_HEADER(reaction_diffusion_2_metal_render) -#include HALIDE_HEADER(reaction_diffusion_2_metal_update) +#include "reaction_diffusion_2_metal_init.h" +#include "reaction_diffusion_2_metal_render.h" +#include "reaction_diffusion_2_metal_update.h" using Halide::Runtime::Buffer; diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index d4c75dedb9ea..fb29ff6d1a9d 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 4A200000000000000000000A /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000011 /* Metal.framework */; }; 4A200000000000000000000B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000012 /* QuartzCore.framework */; }; 4A200000000000000000000C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000013 /* UIKit.framework */; }; + 4A200000000000000000000D /* HalideKernels.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A1000000000000000000015 /* HalideKernels.xcframework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -35,13 +36,13 @@ 4A100000000000000000000B /* InfoPlist.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 4A100000000000000000000C /* HelloiOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HelloiOS-Info.plist"; sourceTree = ""; }; 4A100000000000000000000D /* HelloiOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HelloiOS-Prefix.pch"; sourceTree = ""; }; - 4A100000000000000000000E /* GeneratorPaths.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = GeneratorPaths.xcconfig; path = "../Generators/build/GeneratorPaths.xcconfig"; sourceTree = SOURCE_ROOT; }; 4A100000000000000000000F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 4A1000000000000000000010 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 4A1000000000000000000011 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 4A1000000000000000000012 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 4A1000000000000000000013 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 4A1000000000000000000014 /* HelloiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloiOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A1000000000000000000015 /* HalideKernels.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = HalideKernels.xcframework; path = "../Generators/build/HalideKernels.xcframework"; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -54,6 +55,7 @@ 4A200000000000000000000A /* Metal.framework in Frameworks */, 4A200000000000000000000B /* QuartzCore.framework in Frameworks */, 4A200000000000000000000C /* UIKit.framework in Frameworks */, + 4A200000000000000000000D /* HalideKernels.xcframework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -63,7 +65,6 @@ 4A3000000000000000000001 /* HelloiOS */ = { isa = PBXGroup; children = ( - 4A100000000000000000000E /* GeneratorPaths.xcconfig */, 4A1000000000000000000001 /* AppDelegate.h */, 4A1000000000000000000002 /* AppDelegate.mm */, 4A1000000000000000000003 /* HalideView.h */, @@ -98,6 +99,7 @@ 4A1000000000000000000011 /* Metal.framework */, 4A1000000000000000000012 /* QuartzCore.framework */, 4A1000000000000000000013 /* UIKit.framework */, + 4A1000000000000000000015 /* HalideKernels.xcframework */, ); name = Frameworks; sourceTree = ""; @@ -176,7 +178,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "exec \"${PROJECT_DIR}/../Generators/rebuild-kernels.sh\"\n"; + shellScript = "xcodebuild -project \"${PROJECT_DIR}/../Generators/build/HelloiOS-Generators.xcodeproj\" -target halide_kernels -configuration Release\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -290,7 +292,6 @@ }; 4A8000000000000000000003 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4A100000000000000000000E /* GeneratorPaths.xcconfig */; buildSettings = { ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -312,7 +313,6 @@ }; 4A8000000000000000000004 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4A100000000000000000000E /* GeneratorPaths.xcconfig */; buildSettings = { ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index b83f553ba713..ca9e41849e89 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -28,9 +28,10 @@ The project is split into two parts: available via double-tap. Both live in **HelloiOS.xcworkspace**. A one-time `setup.sh` configures the -CMake side and writes a `GeneratorPaths.xcconfig` that the Xcode project reads -for paths. A Run Script build phase in Xcode invokes `rebuild-kernels.sh` so -generator changes are picked up automatically. +CMake side and bootstraps `HalideKernels.xcframework`, which bundles the +generated kernels, runtimes, and headers for both device and simulator. The +Xcode project links the xcframework directly. A Run Script build phase rebuilds +it so generator changes are picked up automatically. ## Prerequisites @@ -66,8 +67,7 @@ Or use Xcode's Run button after building for a simulator destination. HelloiOS/ HelloiOS.xcworkspace/ Top-level workspace Generators/ - CMakeLists.txt Builds generator + produces iOS kernels - rebuild-kernels.sh Called by Xcode Run Script build phase + CMakeLists.txt Builds generator + packages HalideKernels.xcframework reaction_diffusion_2_generator.cpp build/ Created by setup.sh HelloiOS/ diff --git a/apps/HelloiOS/setup.sh b/apps/HelloiOS/setup.sh index b37316e0f76f..ccc39fa2ac5d 100755 --- a/apps/HelloiOS/setup.sh +++ b/apps/HelloiOS/setup.sh @@ -8,6 +8,10 @@ cd "$(dirname "${BASH_SOURCE[0]}")" cmake -G Xcode -S Generators -B Generators/build +# Bootstrap: build kernels and package the xcframework so Xcode can load +# the project. Subsequent builds are driven by the Xcode run-script phase. +cmake --build Generators/build --config Release + echo "" echo "Setup complete. Open HelloiOS.xcworkspace in Xcode to build and run." echo "" From d5072627cc377e95c5e013559b5daa90657c6278 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 19:21:05 -0500 Subject: [PATCH 20/37] Add helpers for creating iOS xcframeworks --- cmake/HalideGeneratorHelpers.cmake | 207 ++++++++++++++++++++++++++--- 1 file changed, 186 insertions(+), 21 deletions(-) diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index 9981c7daa3dc..1a7b2049b270 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -169,10 +169,23 @@ endfunction() function(_Halide_library_from_generator TARGET) cmake_parse_arguments( PARSE_ARGV 1 ARG "" - "FUNCTION_NAME;GENERATOR;GRADIENT_DESCENT;TYPE;USE_RUNTIME" + "FILE_BASE_NAME;FUNCTION_NAME;GENERATOR;GRADIENT_DESCENT;OUTPUT_DIR;TYPE;USE_RUNTIME" "COMMAND;DEPENDS;EXTRA_OUTPUTS;PARAMS;PLUGINS;TARGETS" ) + if (NOT ARG_FILE_BASE_NAME) + set(ARG_FILE_BASE_NAME "${TARGET}") + endif () + + # OUTPUT_DIR is an absolute path. Compute a relative prefix for + # add_custom_command OUTPUT paths to avoid Xcode .rule file collisions. + cmake_path(SET ARG_OUTPUT_DIR "${ARG_OUTPUT_DIR}") + cmake_path(ABSOLUTE_PATH ARG_OUTPUT_DIR BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" NORMALIZE) + cmake_path(RELATIVE_PATH ARG_OUTPUT_DIR BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" OUTPUT_VARIABLE output_prefix) + if (output_prefix) + string(APPEND output_prefix "/") + endif () + ## "hash table" of extra outputs to extensions # Keep in sync with Module.cpp set(assembly_extension ".s") @@ -235,24 +248,24 @@ function(_Halide_library_from_generator TARGET) ## Check the type to determine outputs set(outputs c_header) - set(output_files "${TARGET}.h") + set(output_files "${output_prefix}${ARG_FILE_BASE_NAME}.h") list(LENGTH ARG_TARGETS num_targets) if (ARG_TYPE STREQUAL "object" AND num_targets GREATER 1) foreach (t IN LISTS ARG_TARGETS) - _Halide_add_output("${ARG_TYPE}" "${TARGET}-${t}") + _Halide_add_output("${ARG_TYPE}" "${output_prefix}${ARG_FILE_BASE_NAME}-${t}") endforeach () - _Halide_add_output("${ARG_TYPE}" "${TARGET}_wrapper") + _Halide_add_output("${ARG_TYPE}" "${output_prefix}${ARG_FILE_BASE_NAME}_wrapper") else () # c_source, static_library, or object with one target - _Halide_add_output("${ARG_TYPE}" "${TARGET}") + _Halide_add_output("${ARG_TYPE}" "${output_prefix}${ARG_FILE_BASE_NAME}") endif () foreach (output IN LISTS ARG_EXTRA_OUTPUTS) if (output STREQUAL "c_source" AND ARG_TYPE STREQUAL "c_source") # Skip this as it was handled above else () - _Halide_add_output("${output}" "${TARGET}") + _Halide_add_output("${output}" "${output_prefix}${ARG_FILE_BASE_NAME}") endif () endforeach () @@ -260,13 +273,13 @@ function(_Halide_library_from_generator TARGET) add_custom_command( OUTPUT ${output_files} COMMAND ${ARG_COMMAND} - -n "${TARGET}" + -n "${ARG_FILE_BASE_NAME}" -d "$" -g "${ARG_GENERATOR}" -f "${ARG_FUNCTION_NAME}" -e "$,$>>" ${plugins_args} - -o . + -o "${ARG_OUTPUT_DIR}" "target=$>" ${ARG_PARAMS} DEPENDS ${ARG_DEPENDS} ${ARG_PLUGINS} @@ -323,7 +336,7 @@ function(_Halide_library_from_generator TARGET) target_sources("${TARGET}" INTERFACE FILE_SET HEADERS - BASE_DIRS "${CMAKE_CURRENT_BINARY_DIR}" + BASE_DIRS "${ARG_OUTPUT_DIR}" FILES "${local_out_c_header}") endfunction() @@ -487,7 +500,7 @@ function(add_halide_library TARGET) endforeach () set(options C_BACKEND GRADIENT_DESCENT) - set(oneValueArgs FROM GENERATOR FUNCTION_NAME NAMESPACE USE_RUNTIME AUTOSCHEDULER HEADER ${extra_output_names} NO_THREADS NO_DL_LIBS) + set(oneValueArgs FILE_BASE_NAME FROM GENERATOR FUNCTION_NAME NAMESPACE OUTPUT_DIR USE_RUNTIME AUTOSCHEDULER HEADER ${extra_output_names} NO_THREADS NO_DL_LIBS) set(multiValueArgs DEPENDS TARGETS PARAMS PLUGINS ${features_args}) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -507,6 +520,10 @@ function(add_halide_library TARGET) message(AUTHOR_WARNING "The C backend sources will be compiled with the current CMake toolchain.") endif () + if (NOT ARG_FILE_BASE_NAME) + set(ARG_FILE_BASE_NAME "${TARGET}") + endif () + if (NOT ARG_GENERATOR) set(ARG_GENERATOR "${TARGET}") endif () @@ -515,6 +532,9 @@ function(add_halide_library TARGET) set(ARG_FUNCTION_NAME "${TARGET}") endif () + cmake_path(SET ARG_OUTPUT_DIR "${ARG_OUTPUT_DIR}") + cmake_path(ABSOLUTE_PATH ARG_OUTPUT_DIR BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" NORMALIZE) + if (ARG_NAMESPACE) set(ARG_FUNCTION_NAME "${ARG_NAMESPACE}::${ARG_FUNCTION_NAME}") endif () @@ -570,6 +590,8 @@ function(add_halide_library TARGET) add_halide_runtime( "${TARGET}.runtime" + FILE_BASE_NAME "${ARG_FILE_BASE_NAME}.runtime" + OUTPUT_DIR "${ARG_OUTPUT_DIR}" NO_DEFAULT_TARGETS TARGETS ${ARG_TARGETS} ${runtime_args} ) @@ -636,9 +658,11 @@ function(add_halide_library TARGET) COMMAND ${generator_cmd} DEPENDS ${generator_cmd_deps} ${ARG_DEPENDS} EXTRA_OUTPUTS ${extra_outputs} + FILE_BASE_NAME "${ARG_FILE_BASE_NAME}" FUNCTION_NAME "${ARG_FUNCTION_NAME}" GENERATOR "${ARG_GENERATOR}" GRADIENT_DESCENT "${ARG_GRADIENT_DESCENT}" + OUTPUT_DIR "${ARG_OUTPUT_DIR}" PARAMS ${ARG_PARAMS} PLUGINS ${ARG_PLUGINS} TYPE "${library_type}" @@ -701,9 +725,13 @@ function(add_halide_library TARGET) "${TARGET}" ${generator_args} TARGETS ${ARG_TARGETS}) endif () - # Save some info for add_halide_python_extension_library() in case it is used for this target. + # Save metadata on the library target for downstream helpers. + set_property(DIRECTORY APPEND PROPERTY Halide_BUILDSYSTEM_TARGETS "${TARGET}") set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_RUNTIME_TARGET "${ARG_USE_RUNTIME}") set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_FUNCTION_NAME "${ARG_FUNCTION_NAME}") + set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_TARGETS "${ARG_TARGETS}") + set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_FILE_BASE_NAME "${ARG_FILE_BASE_NAME}") + set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_OUTPUT_DIR "${ARG_OUTPUT_DIR}") if ("python_extension" IN_LIST extra_outputs) list(GET OUT_python_extension 0 py_ext_cpp) # These files should always be identical set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_PYTHON_EXTENSION_CPP "${py_ext_cpp}") @@ -876,10 +904,23 @@ endfunction() function(add_halide_runtime RT) set(options NO_DEFAULT_TARGETS) - set(oneValueArgs NO_THREADS NO_DL_LIBS) + set(oneValueArgs FILE_BASE_NAME NO_THREADS NO_DL_LIBS OUTPUT_DIR) set(multiValueArgs TARGETS) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if (NOT ARG_FILE_BASE_NAME) + set(ARG_FILE_BASE_NAME "${RT}") + endif () + + # OUTPUT_DIR is an absolute path. Compute a relative prefix for + # add_custom_command OUTPUT paths to avoid Xcode .rule file collisions. + cmake_path(SET ARG_OUTPUT_DIR "${ARG_OUTPUT_DIR}") + cmake_path(ABSOLUTE_PATH ARG_OUTPUT_DIR BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" NORMALIZE) + cmake_path(RELATIVE_PATH ARG_OUTPUT_DIR BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" OUTPUT_VARIABLE output_prefix) + if (output_prefix) + string(APPEND output_prefix "/") + endif () + # If no TARGETS argument, use Halide_TARGET instead if (NOT ARG_TARGETS) set(ARG_TARGETS "${Halide_TARGET}") @@ -911,10 +952,10 @@ function(add_halide_runtime RT) set(target_list "$") if (is_crosscompiling) - set(GEN_OUTS "${RT}${static_library_extension}") + set(GEN_OUTS "${output_prefix}${ARG_FILE_BASE_NAME}${static_library_extension}") add_custom_command( OUTPUT "${GEN_OUTS}" - COMMAND Halide::GenRT -r "${RT}" -o . + COMMAND Halide::GenRT -r "${ARG_FILE_BASE_NAME}" -o "${ARG_OUTPUT_DIR}" "target=$,$>" DEPENDS Halide::GenRT VERBATIM) @@ -925,7 +966,7 @@ function(add_halide_runtime RT) add_dependencies("${RT}" "${RT}.update") set_target_properties("${RT}" PROPERTIES - IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${GEN_OUTS}) + IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${GEN_OUTS}") else () list(LENGTH Halide_CMAKE_TARGET num_platforms) if (common_triple STREQUAL "cmake" AND num_platforms GREATER 1) @@ -944,13 +985,13 @@ function(add_halide_runtime RT) endif () add_custom_command( - OUTPUT "${this_rt}${object_extension}" - COMMAND Halide::GenRT -r "${this_rt}" -o . -e object + OUTPUT "${output_prefix}${this_rt}${object_extension}" + COMMAND Halide::GenRT -r "${this_rt}" -o "${ARG_OUTPUT_DIR}" -e object "target=$,$>" DEPENDS Halide::GenRT VERBATIM) - add_library("${this_rt}" STATIC "${this_rt}${object_extension}") + add_library("${this_rt}" STATIC "${ARG_OUTPUT_DIR}/${this_rt}${object_extension}") set_target_properties("${this_rt}" PROPERTIES LINKER_LANGUAGE CXX) _Halide_fix_xcode("${this_rt}") _Halide_set_osx_arch("${this_rt}" "${triple}") @@ -960,12 +1001,12 @@ function(add_halide_runtime RT) else () set(target_list "$") add_custom_command( - OUTPUT "${RT}${object_extension}" - COMMAND Halide::GenRT -r "${RT}" -o . -e object + OUTPUT "${output_prefix}${ARG_FILE_BASE_NAME}${object_extension}" + COMMAND Halide::GenRT -r "${ARG_FILE_BASE_NAME}" -o "${ARG_OUTPUT_DIR}" -e object "target=$,$>" DEPENDS Halide::GenRT VERBATIM) - add_library("${RT}" STATIC "${RT}${object_extension}") + add_library("${RT}" STATIC "${ARG_OUTPUT_DIR}/${ARG_FILE_BASE_NAME}${object_extension}") set_target_properties("${RT}" PROPERTIES LINKER_LANGUAGE CXX) _Halide_fix_xcode("${RT}") endif () @@ -1079,3 +1120,127 @@ function(_Halide_target_export_single_symbol TARGET SYMBOL) GNU_LD "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.${SYMBOL}.ldscript" ) endfunction() + +## +# Create an XCFramework bundling Halide-generated libraries for multiple Apple platforms. +## + +function(_Halide_targets_to_apple_platform OUT_PLATFORM) + # Parse the arch-bits-os triple and check for "simulator" among features. + # Input: one or more Halide target strings (e.g. "arm-64-ios-simulator-metal-user_context"). + list(GET ARGN 0 first_target) + if (NOT first_target MATCHES "^[^-]+-[^-]+-([^-]+)") + message(FATAL_ERROR "Cannot parse Halide target: ${first_target}") + endif () + + set(os "${CMAKE_MATCH_1}") + if (NOT os STREQUAL "ios") + message(FATAL_ERROR "Unsupported Apple OS '${os}' in target '${first_target}'. " + "add_halide_xcframework currently supports iOS targets only.") + endif () + + if ("${ARGN}" MATCHES "simulator") + set(${OUT_PLATFORM} "iphonesimulator" PARENT_SCOPE) + else () + set(${OUT_PLATFORM} "iphoneos" PARENT_SCOPE) + endif () +endfunction() + +function(add_halide_xcframework TARGET) + set(options "") + set(oneValueArgs "") + set(multiValueArgs LIBRARIES) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (NOT ARG_LIBRARIES) + message(FATAL_ERROR "add_halide_xcframework requires LIBRARIES") + endif () + + if (ARG_LIBRARIES STREQUAL "ALL") + get_directory_property(ARG_LIBRARIES Halide_BUILDSYSTEM_TARGETS) + if (NOT ARG_LIBRARIES) + message(FATAL_ERROR "add_halide_xcframework: LIBRARIES ALL but no Halide targets found in this directory") + endif () + endif () + + # Collect per-platform information from library target properties. + set(all_platforms "") + foreach (lib IN LISTS ARG_LIBRARIES) + get_property(targets TARGET "${lib}" PROPERTY Halide_LIBRARY_TARGETS) + get_property(base_name TARGET "${lib}" PROPERTY Halide_LIBRARY_FILE_BASE_NAME) + get_property(output_dir TARGET "${lib}" PROPERTY Halide_LIBRARY_OUTPUT_DIR) + + if (NOT targets) + message(FATAL_ERROR "Target '${lib}' is missing Halide_LIBRARY_TARGETS. " + "Was it created with add_halide_library?") + endif () + + _Halide_targets_to_apple_platform(platform ${targets}) + + if (NOT platform IN_LIST all_platforms) + list(APPEND all_platforms "${platform}") + endif () + + # Accumulate per-platform data in list variables. + list(APPEND libs_${platform} "${output_dir}/${base_name}.a") + list(APPEND libs_${platform} "${output_dir}/${base_name}.runtime.a") + list(APPEND hdrs_${platform} "${output_dir}/${base_name}.h") + endforeach () + + # Locate Halide runtime headers. + set(halide_inc "$") + + set(staging "${CMAKE_CURRENT_BINARY_DIR}/_xcfw_staging") + set(xcfw "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.xcframework") + + set(xcfw_commands + COMMAND ${CMAKE_COMMAND} -E rm -rf "${staging}" "${xcfw}") + set(xcfw_create_args "") + + foreach (platform IN LISTS all_platforms) + list(APPEND xcfw_commands + COMMAND ${CMAKE_COMMAND} -E make_directory "${staging}/${platform}/Headers") + + # Copy generated kernel headers. + foreach (hdr IN LISTS hdrs_${platform}) + cmake_path(GET hdr FILENAME hdr_name) + list(APPEND xcfw_commands + COMMAND ${CMAKE_COMMAND} -E copy + "${hdr}" "${staging}/${platform}/Headers/${hdr_name}") + endforeach () + + # Copy Halide runtime headers. + foreach (hdr_name IN ITEMS + HalideBuffer.h + HalideRuntime.h + HalideRuntimeCuda.h + HalideRuntimeD3D12Compute.h + HalideRuntimeHexagonDma.h + HalideRuntimeHexagonHost.h + HalideRuntimeMetal.h + HalideRuntimeOpenCL.h + HalideRuntimeQurt.h + HalideRuntimeVulkan.h + HalideRuntimeWebGPU.h) + list(APPEND xcfw_commands + COMMAND ${CMAKE_COMMAND} -E copy "${halide_inc}/${hdr_name}" "${staging}/${platform}/Headers/${hdr_name}") + endforeach () + + # Merge all static libraries for this platform into one. + list(APPEND xcfw_commands + COMMAND libtool -static -o "${staging}/${platform}/lib${TARGET}.a" ${libs_${platform}}) + + list(APPEND xcfw_create_args + -library "${staging}/${platform}/lib${TARGET}.a" + -headers "${staging}/${platform}/Headers") + endforeach () + + add_custom_target( + ${TARGET} ALL + DEPENDS ${ARG_LIBRARIES} + ${xcfw_commands} + COMMAND xcodebuild -create-xcframework ${xcfw_create_args} -output "${xcfw}" + COMMENT "Packaging ${TARGET}.xcframework" + ) + set_property(TARGET ${TARGET} PROPERTY FOLDER "Halide Internal") +endfunction() From bcdd4839e005d438d079d114d5cdf59dbfc65ce8 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Sat, 7 Mar 2026 20:04:15 -0500 Subject: [PATCH 21/37] Use new add_halide_xcframework helper --- apps/HelloiOS/Generators/CMakeLists.txt | 73 +++---------------- .../HelloiOS.xcodeproj/project.pbxproj | 2 +- 2 files changed, 11 insertions(+), 64 deletions(-) diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index 5ba270ca332e..d867b22a7c94 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -12,79 +12,26 @@ add_halide_generator( SOURCES reaction_diffusion_2_generator.cpp ) -set(_all_kernels "") -set(platforms iphoneos iphonesimulator) -set(targets arm-64-ios arm-64-ios-simulator) -foreach (platform target IN ZIP_LISTS platforms targets) +foreach (simulator IN ITEMS "" "-simulator") foreach (stage IN ITEMS init update render) - add_halide_library(reaction_diffusion_2_${stage}_${platform} + add_halide_library(reaction_diffusion_2_${stage}${simulator} FROM reaction_diffusion_2_generator GENERATOR reaction_diffusion_2_${stage} FUNCTION_NAME reaction_diffusion_2_${stage} - TARGETS ${target} + FILE_BASE_NAME reaction_diffusion_2_${stage} + OUTPUT_DIR "arm-64-ios${simulator}" + TARGETS "arm-64-ios${simulator}" FEATURES user_context) - add_halide_library(reaction_diffusion_2_metal_${stage}_${platform} + add_halide_library(reaction_diffusion_2_metal_${stage}${simulator} FROM reaction_diffusion_2_generator GENERATOR reaction_diffusion_2_${stage} FUNCTION_NAME reaction_diffusion_2_metal_${stage} - TARGETS ${target} + FILE_BASE_NAME reaction_diffusion_2_metal_${stage} + OUTPUT_DIR "arm-64-ios${simulator}" + TARGETS "arm-64-ios${simulator}" FEATURES metal user_context) - - list(APPEND _all_kernels - reaction_diffusion_2_${stage}_${platform} - reaction_diffusion_2_metal_${stage}_${platform}) endforeach () endforeach () -# Package all generated kernels into an xcframework for the native Xcode project. -set(_staging "${CMAKE_CURRENT_BINARY_DIR}/_xcfw_staging") -set(_xcfw "${CMAKE_CURRENT_BINARY_DIR}/HalideKernels.xcframework") - -set(_xcfw_commands - COMMAND ${CMAKE_COMMAND} -E rm -rf "${_staging}" "${_xcfw}") -set(_xcfw_create_args "") - -set(_halide_inc "$") - -foreach (platform IN LISTS platforms) - list(APPEND _xcfw_commands - COMMAND ${CMAKE_COMMAND} -E make_directory "${_staging}/${platform}/Headers") - - set(_platform_libs "") - foreach (stage IN ITEMS init update render) - foreach (variant IN ITEMS "" "metal_") - set(_base "reaction_diffusion_2_${variant}${stage}") - list(APPEND _platform_libs - "${CMAKE_CURRENT_BINARY_DIR}/${_base}_${platform}.a" - "${CMAKE_CURRENT_BINARY_DIR}/${_base}_${platform}.runtime.a") - list(APPEND _xcfw_commands - COMMAND ${CMAKE_COMMAND} -E copy - "${CMAKE_CURRENT_BINARY_DIR}/${_base}_${platform}.h" - "${_staging}/${platform}/Headers/${_base}.h") - endforeach () - endforeach () - - # Copy Halide runtime headers into this platform slice. - foreach (_hdr IN ITEMS HalideBuffer.h HalideRuntime.h HalideRuntimeMetal.h) - list(APPEND _xcfw_commands - COMMAND ${CMAKE_COMMAND} -E copy - "${_halide_inc}/${_hdr}" - "${_staging}/${platform}/Headers/${_hdr}") - endforeach () - - list(APPEND _xcfw_commands - COMMAND libtool -static -o "${_staging}/${platform}/libHalideKernels.a" ${_platform_libs}) - list(APPEND _xcfw_create_args - -library "${_staging}/${platform}/libHalideKernels.a" - -headers "${_staging}/${platform}/Headers") -endforeach () - -list(APPEND _xcfw_commands - COMMAND xcodebuild -create-xcframework ${_xcfw_create_args} -output "${_xcfw}") - -add_custom_target(halide_kernels ALL - DEPENDS ${_all_kernels} - ${_xcfw_commands} - COMMENT "Packaging HalideKernels.xcframework") -set_property(TARGET halide_kernels PROPERTY FOLDER "Halide Internal") +add_halide_xcframework(HalideKernels LIBRARIES ALL) diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index fb29ff6d1a9d..8e28960985eb 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -178,7 +178,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "xcodebuild -project \"${PROJECT_DIR}/../Generators/build/HelloiOS-Generators.xcodeproj\" -target halide_kernels -configuration Release\n"; + shellScript = "xcodebuild -project \"${PROJECT_DIR}/../Generators/build/HelloiOS-Generators.xcodeproj\" -target HalideKernels -configuration Release\n"; }; /* End PBXShellScriptBuildPhase section */ From b7aff8ffa636a8a7864a0bbcbb69b3683cec4fdf Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 9 Mar 2026 17:59:52 -0400 Subject: [PATCH 22/37] Get code-signing working --- apps/HelloiOS/Generators/CMakeLists.txt | 4 + apps/HelloiOS/HelloiOS/HelloiOS-Info.plist | 8 +- .../HelloiOS.xcodeproj/project.pbxproj | 20 +++-- .../AppIcon.appiconset/Contents.json | 79 ++++++++++--------- apps/HelloiOS/setup.sh | 3 + cmake/HalideGeneratorHelpers.cmake | 11 +++ 6 files changed, 77 insertions(+), 48 deletions(-) diff --git a/apps/HelloiOS/Generators/CMakeLists.txt b/apps/HelloiOS/Generators/CMakeLists.txt index d867b22a7c94..0f3b1e36798b 100644 --- a/apps/HelloiOS/Generators/CMakeLists.txt +++ b/apps/HelloiOS/Generators/CMakeLists.txt @@ -1,6 +1,10 @@ cmake_minimum_required(VERSION 3.28) project(HelloiOS-Generators LANGUAGES C CXX) +# CMake hasn't yet finished implementing support for Xcode's new build system, +# so disable the warning about it for now. +set(CMAKE_XCODE_ATTRIBUTE_DISABLE_MANUAL_TARGET_ORDER_BUILD_WARNING YES) + set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) diff --git a/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist b/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist index 5d568f0c393c..2fd88cd2fd3a 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist +++ b/apps/HelloiOS/HelloiOS/HelloiOS-Info.plist @@ -24,10 +24,6 @@ 1.0 LSRequiresIPhoneOS - UIRequiredDeviceCapabilities - - arm64 - UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -52,6 +48,10 @@ UIImageName + UIRequiredDeviceCapabilities + + arm64 + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index 8e28960985eb..ce393d64802e 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -42,7 +42,7 @@ 4A1000000000000000000012 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 4A1000000000000000000013 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 4A1000000000000000000014 /* HelloiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloiOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A1000000000000000000015 /* HalideKernels.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = HalideKernels.xcframework; path = "../Generators/build/HalideKernels.xcframework"; sourceTree = SOURCE_ROOT; }; + 4A1000000000000000000015 /* HalideKernels.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = HalideKernels.xcframework; path = ../Generators/build/HalideKernels.xcframework; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,7 +62,7 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 4A3000000000000000000001 /* HelloiOS */ = { + 4A3000000000000000000001 = { isa = PBXGroup; children = ( 4A1000000000000000000001 /* AppDelegate.h */, @@ -132,7 +132,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastUpgradeCheck = 1600; + LastUpgradeCheck = 2630; }; buildConfigurationList = 4A7000000000000000000001 /* Build configuration list for PBXProject "HelloiOS" */; compatibilityVersion = "Xcode 14.0"; @@ -142,7 +142,7 @@ en, Base, ); - mainGroup = 4A3000000000000000000001 /* HelloiOS */; + mainGroup = 4A3000000000000000000001; productRefGroup = 4A3000000000000000000002 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -225,6 +225,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -244,6 +245,7 @@ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; }; name = Debug; }; @@ -274,6 +276,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -286,6 +289,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; VALIDATE_PRODUCT = YES; }; name = Release; @@ -293,18 +297,19 @@ 4A8000000000000000000003 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_IDENTITY = "-"; ENABLE_BITCODE = NO; + EXCLUDED_ARCHS = x86_64; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HelloiOS-Prefix.pch"; INFOPLIST_FILE = "HelloiOS-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; PRODUCT_NAME = HelloiOS; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -314,18 +319,19 @@ 4A8000000000000000000004 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_IDENTITY = "-"; ENABLE_BITCODE = NO; + EXCLUDED_ARCHS = x86_64; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HelloiOS-Prefix.pch"; INFOPLIST_FILE = "HelloiOS-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; PRODUCT_BUNDLE_IDENTIFIER = org.halide.HelloiOS; PRODUCT_NAME = HelloiOS; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -356,4 +362,4 @@ /* End XCConfigurationList section */ }; rootObject = 4A6000000000000000000001 /* Project object */; -} \ No newline at end of file +} diff --git a/apps/HelloiOS/HelloiOS/Images.xcassets/AppIcon.appiconset/Contents.json b/apps/HelloiOS/HelloiOS/Images.xcassets/AppIcon.appiconset/Contents.json index 1d060ed28827..9221b9bb1a35 100644 --- a/apps/HelloiOS/HelloiOS/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/apps/HelloiOS/HelloiOS/Images.xcassets/AppIcon.appiconset/Contents.json @@ -2,92 +2,97 @@ "images" : [ { "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" + "scale" : "3x", + "size" : "20x20" }, { "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" + "scale" : "3x", + "size" : "29x29" }, { "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" + "scale" : "3x", + "size" : "40x40" }, { "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" + "scale" : "2x", + "size" : "60x60" }, { "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" + "scale" : "3x", + "size" : "60x60" }, { "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" + "scale" : "1x", + "size" : "20x20" }, { "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" + "scale" : "1x", + "size" : "29x29" }, { "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" + "scale" : "1x", + "size" : "40x40" }, { "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" + "scale" : "1x", + "size" : "76x76" }, { "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" + "scale" : "2x", + "size" : "76x76" }, { "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/apps/HelloiOS/setup.sh b/apps/HelloiOS/setup.sh index ccc39fa2ac5d..c4b30e01b13d 100755 --- a/apps/HelloiOS/setup.sh +++ b/apps/HelloiOS/setup.sh @@ -17,3 +17,6 @@ echo "Setup complete. Open HelloiOS.xcworkspace in Xcode to build and run." echo "" echo " open $(pwd)/HelloiOS.xcworkspace" echo "" +echo "To run on a real device, you will need to set the development team " +echo "in the Xcode project settings. Check 'Automatically manage signing'" +echo "under the Signing & Capabilities tab of the HelloiOS project settings." diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index 1a7b2049b270..df577dc63cbf 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -110,6 +110,17 @@ function(add_halide_generator TARGET) $<$:-Wdeprecated-declarations> $<$:/w14996> # 4996: compiler encountered deprecated declaration ) + + if (CMAKE_GENERATOR STREQUAL "Xcode") + set_target_properties( + ${TARGET} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO + ) + add_custom_command( + TARGET ${TARGET} POST_BUILD + COMMAND codesign --sign - $ + COMMENT "Ad-hoc signing ${TARGET}" + ) + endif () endif () add_dependencies("${ARG_PACKAGE_NAME}" ${TARGET}) From 8ffb6ad236185c17254d6bf869f0ddd92be9289d Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Wed, 11 Mar 2026 15:46:02 -0700 Subject: [PATCH 23/37] Don't inherit environment from device build --- apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index ce393d64802e..98e1f7de0d0e 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -178,7 +178,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "xcodebuild -project \"${PROJECT_DIR}/../Generators/build/HelloiOS-Generators.xcodeproj\" -target HalideKernels -configuration Release\n"; + shellScript = "env -i PATH=\"$PATH\" HOME=\"$HOME\" USER=\"$USER\" \\\n xcodebuild -project \"${PROJECT_DIR}/../Generators/build/HelloiOS-Generators.xcodeproj\" \\\n -target HalideKernels \\\n -configuration Release\n"; }; /* End PBXShellScriptBuildPhase section */ From 950d9bcdefc5b882582bd02b28ef9c96f74e8caf Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Thu, 12 Mar 2026 10:20:28 -0700 Subject: [PATCH 24/37] Drop env -i and patch HalideGeneratorHelpers.cmake instead --- .../HelloiOS/HelloiOS.xcodeproj/project.pbxproj | 2 +- apps/HelloiOS/README.md | 13 +++++++++++++ apps/HelloiOS/setup.sh | 5 +++++ cmake/HalideGeneratorHelpers.cmake | 5 +++-- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj index 98e1f7de0d0e..c40c33190623 100644 --- a/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj +++ b/apps/HelloiOS/HelloiOS/HelloiOS.xcodeproj/project.pbxproj @@ -178,7 +178,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "env -i PATH=\"$PATH\" HOME=\"$HOME\" USER=\"$USER\" \\\n xcodebuild -project \"${PROJECT_DIR}/../Generators/build/HelloiOS-Generators.xcodeproj\" \\\n -target HalideKernels \\\n -configuration Release\n"; + shellScript = "xcodebuild -project \"${PROJECT_DIR}/../Generators/build/HelloiOS-Generators.xcodeproj\" \\\n -target HalideKernels \\\n -configuration Release\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index ca9e41849e89..16ca98e198e5 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -75,3 +75,16 @@ HelloiOS/ *.h / *.mm App source files setup.sh One-time setup script ``` + +## Troubleshooting + +Old Xcode versions may incorrectly think the generator binaries are +being built for iOS, and may want signing of the generator binary +itself. If this happens, the nuclear option is to prefix the +xcodebuild invocation in the 'Build Halide Generators' build phase of +the HelloiOS target with: + +env -i USER="$USER" HOME="$HOME" PATH="$PATH" DEVELOPER_DIR="$DEVELOPER_DIR" + +though only do this if necessary as it drops *all* build context and +may cause different problems in future. \ No newline at end of file diff --git a/apps/HelloiOS/setup.sh b/apps/HelloiOS/setup.sh index c4b30e01b13d..56eddbdc7dca 100755 --- a/apps/HelloiOS/setup.sh +++ b/apps/HelloiOS/setup.sh @@ -20,3 +20,8 @@ echo "" echo "To run on a real device, you will need to set the development team " echo "in the Xcode project settings. Check 'Automatically manage signing'" echo "under the Signing & Capabilities tab of the HelloiOS project settings." +echo "" +echo "If you encounter build problems, check the troubleshooting section of" +echo "the README. If that section doesn't help and you solve your build" +echo "problems regardless, we would welcome a PR that updates the" +echo "troubleshooting section of the README." diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index df577dc63cbf..57779dd27f97 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -113,8 +113,9 @@ function(add_halide_generator TARGET) if (CMAKE_GENERATOR STREQUAL "Xcode") set_target_properties( - ${TARGET} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO - ) + ${TARGET} PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO + XCODE_ATTRIBUTE_PROVISIONING_PROFILE_REQUIRED NO) add_custom_command( TARGET ${TARGET} POST_BUILD COMMAND codesign --sign - $ From 50afdcbfb0689c80a95e73077141e1f7c7d9914d Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Thu, 12 Mar 2026 10:23:51 -0700 Subject: [PATCH 25/37] grammar tweak --- apps/HelloiOS/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index 16ca98e198e5..83ff8562e34b 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -86,5 +86,5 @@ the HelloiOS target with: env -i USER="$USER" HOME="$HOME" PATH="$PATH" DEVELOPER_DIR="$DEVELOPER_DIR" -though only do this if necessary as it drops *all* build context and -may cause different problems in future. \ No newline at end of file +Only do this if necessary as it drops *all* build context and may +cause different problems in future. \ No newline at end of file From e641316b16441f3a7127de1131d3b3da2ac1ee7a Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 12 Mar 2026 13:56:05 -0400 Subject: [PATCH 26/37] Reflow troubleshooting paragraph --- apps/HelloiOS/README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index 83ff8562e34b..f991b8d4f847 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -78,13 +78,14 @@ HelloiOS/ ## Troubleshooting -Old Xcode versions may incorrectly think the generator binaries are -being built for iOS, and may want signing of the generator binary -itself. If this happens, the nuclear option is to prefix the -xcodebuild invocation in the 'Build Halide Generators' build phase of -the HelloiOS target with: +Old Xcode versions may incorrectly think the generator binaries are being built +for iOS, and may want signing of the generator binary itself. If this happens, +the nuclear option is to prefix the xcodebuild invocation in the 'Build Halide +Generators' build phase of the HelloiOS target with: +``` env -i USER="$USER" HOME="$HOME" PATH="$PATH" DEVELOPER_DIR="$DEVELOPER_DIR" +``` Only do this if necessary as it drops *all* build context and may -cause different problems in future. \ No newline at end of file +cause different problems in the future. From 6b9ad8100c0f40446a9fa0d58669911e4785c1cb Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 16 Mar 2026 12:53:04 -0700 Subject: [PATCH 27/37] clang-format --- apps/HelloiOS/HelloiOS/HalideView.mm | 47 ++++++++++++---------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/apps/HelloiOS/HelloiOS/HalideView.mm b/apps/HelloiOS/HelloiOS/HalideView.mm index 62952246f6b3..42b989edb459 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.mm +++ b/apps/HelloiOS/HelloiOS/HalideView.mm @@ -28,8 +28,7 @@ static const HalideFuncs kHalideMetal = { reaction_diffusion_2_metal_init, reaction_diffusion_2_metal_update, - reaction_diffusion_2_metal_render -}; + reaction_diffusion_2_metal_render}; @implementation HalideView { @private @@ -43,9 +42,7 @@ @implementation HalideView { double frameElapsedEstimate; } - -+ (Class)layerClass -{ ++ (Class)layerClass { return [CAMetalLayer class]; } @@ -60,7 +57,7 @@ - (void)initCommon { _device = MTLCreateSystemDefaultDevice(); _commandQueue = [_device newCommandQueue]; - _metalLayer.device = _device; + _metalLayer.device = _device; _metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; _metalLayer.framebufferOnly = NO; @@ -80,7 +77,7 @@ - (void)updateFrameTime:(double)elapsed using_metal:(bool)using_metal { } if ((iteration % 30) == 0) { dispatch_async(dispatch_get_main_queue(), ^(void) { - [self updateLogWith: self->frameElapsedEstimate using_metal: using_metal]; + [self updateLogWith:self->frameElapsedEstimate using_metal:using_metal]; }); } iteration += 1; @@ -130,15 +127,13 @@ - (id)initWithFrame:(CGRect)frame { - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; - if(self) - { + if (self) { [self initCommon]; } return self; } -- (void)updateLogWith: (double) elapsedTime using_metal: (bool) using_metal -{ +- (void)updateLogWith:(double)elapsedTime using_metal:(bool)using_metal { NSString *mode = using_metal ? @"Metal (double-tap for CPU)" : @"CPU (double-tap for Metal)"; self.statsLabel.text = [NSString stringWithFormat:@"%.1f ms • %@", elapsedTime * 1000, mode]; } @@ -167,8 +162,7 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { self.touch_active = false; } -- (void)renderOneFrame: (const HalideFuncs &) halide_funcs using_metal: (bool) using_metal -{ +- (void)renderOneFrame:(const HalideFuncs &)halide_funcs using_metal:(bool)using_metal { // -1 is interpreted as no touch event int tx = -1, ty = -1; if (self.touch_active) { @@ -202,8 +196,7 @@ - (void)renderOneFrame: (const HalideFuncs &) halide_funcs using_metal: (bool) u [self updateFrameTime:(t_after - t_before) using_metal:using_metal]; } -- (void)initiateRender -{ +- (void)initiateRender { bool using_metal = self.use_metal; const HalideFuncs &halide_funcs = using_metal ? kHalideMetal : kHalideCPU; const int required_stride = using_metal ? 3 : 1; @@ -224,13 +217,13 @@ - (void)initiateRender CGSize drawableSize = self.bounds.size; _metalLayer.drawableSize = drawableSize; - [self initBufsWithWidth: drawableSize.width height: drawableSize.height using_metal: using_metal]; + [self initBufsWithWidth:drawableSize.width height:drawableSize.height using_metal:using_metal]; halide_funcs.init((__bridge void *)self, buf1); [self resetFrameTime]; } - [self renderOneFrame: halide_funcs using_metal: using_metal]; + [self renderOneFrame:halide_funcs using_metal:using_metal]; [self renderOneFrame:halide_funcs using_metal:using_metal]; @@ -250,15 +243,15 @@ - (void)initiateRender const int bytesPerRow = pixel_buf.dim(1).stride() * pixel_buf.type().bits / 8; [blitEncoder - copyFromBuffer:buffer - sourceOffset: 0 - sourceBytesPerRow: bytesPerRow - sourceBytesPerImage: pixel_buf.dim(1).stride() * pixel_buf.dim(1).extent() // Not sizeInBytes because we're also copying the padding on the last row - sourceSize: image_size - toTexture: drawable.texture - destinationSlice: 0 - destinationLevel: 0 - destinationOrigin: origin]; + copyFromBuffer:buffer + sourceOffset:0 + sourceBytesPerRow:bytesPerRow + sourceBytesPerImage:pixel_buf.dim(1).stride() * pixel_buf.dim(1).extent() // Not sizeInBytes because we're also copying the padding on the last row + sourceSize:image_size + toTexture:drawable.texture + destinationSlice:0 + destinationLevel:0 + destinationOrigin:origin]; [blitEncoder endEncoding]; [commandBuffer addCompletedHandler:^(id MTLCommandBuffer) { dispatch_async(dispatch_get_main_queue(), ^(void) { @@ -290,4 +283,4 @@ int halide_metal_release_context(void *user_context) { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif From 50d2b467588ef857c48173bfdeee8f5434aabdf0 Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 16 Mar 2026 12:59:43 -0700 Subject: [PATCH 28/37] Add note about known issue --- apps/HelloiOS/setup.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/HelloiOS/setup.sh b/apps/HelloiOS/setup.sh index 56eddbdc7dca..b5a882a7c59f 100755 --- a/apps/HelloiOS/setup.sh +++ b/apps/HelloiOS/setup.sh @@ -25,3 +25,6 @@ echo "If you encounter build problems, check the troubleshooting section of" echo "the README. If that section doesn't help and you solve your build" echo "problems regardless, we would welcome a PR that updates the" echo "troubleshooting section of the README." +echo +echo "Known issue: You must build-and-run in Xcode twice to see the effect" +echo "of changes to the generator source (issue #9049)." From aabd972d4645a5394248c569b074257e5b39e0f9 Mon Sep 17 00:00:00 2001 From: "halide-ci[bot]" <266445882+halide-ci[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 20:03:25 +0000 Subject: [PATCH 29/37] Apply pre-commit auto-fixes --- .../Generators/reaction_diffusion_2_generator.cpp | 1 - .../HelloiOS.xcworkspace/contents.xcworkspacedata | 2 +- apps/HelloiOS/HelloiOS/AppDelegate.mm | 6 +++--- apps/HelloiOS/HelloiOS/HalideView.h | 4 ++-- apps/HelloiOS/HelloiOS/HalideViewController.mm | 9 ++++++--- apps/HelloiOS/HelloiOS/SceneDelegate.h | 2 +- apps/HelloiOS/README.md | 12 ++++++------ 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/apps/HelloiOS/Generators/reaction_diffusion_2_generator.cpp b/apps/HelloiOS/Generators/reaction_diffusion_2_generator.cpp index e589065f86c6..6de5657bbdcc 100644 --- a/apps/HelloiOS/Generators/reaction_diffusion_2_generator.cpp +++ b/apps/HelloiOS/Generators/reaction_diffusion_2_generator.cpp @@ -85,7 +85,6 @@ class ReactionDiffusion2Update : public Halide::Generator - \ No newline at end of file + diff --git a/apps/HelloiOS/HelloiOS/AppDelegate.mm b/apps/HelloiOS/HelloiOS/AppDelegate.mm index 0c3172f5de7c..3da73d7fa2d8 100644 --- a/apps/HelloiOS/HelloiOS/AppDelegate.mm +++ b/apps/HelloiOS/HelloiOS/AppDelegate.mm @@ -7,10 +7,10 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( } - (UISceneConfiguration *)application:(UIApplication *)application - configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession - options:(UISceneConnectionOptions *)options { + configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession + options:(UISceneConnectionOptions *)options { UISceneConfiguration *configuration = [[UISceneConfiguration alloc] initWithName:@"Default Configuration" - sessionRole:connectingSceneSession.role]; + sessionRole:connectingSceneSession.role]; configuration.delegateClass = NSClassFromString(@"SceneDelegate"); return configuration; } diff --git a/apps/HelloiOS/HelloiOS/HalideView.h b/apps/HelloiOS/HelloiOS/HalideView.h index 4d2d28042c2e..5d9c79cb9f73 100644 --- a/apps/HelloiOS/HelloiOS/HalideView.h +++ b/apps/HelloiOS/HelloiOS/HalideView.h @@ -1,5 +1,5 @@ -#import #import +#import #import @interface HalideView : UIView @@ -16,4 +16,4 @@ - (void)initiateRender; -@end \ No newline at end of file +@end diff --git a/apps/HelloiOS/HelloiOS/HalideViewController.mm b/apps/HelloiOS/HelloiOS/HalideViewController.mm index b330ee6c7ca0..a6d41cd4b51a 100644 --- a/apps/HelloiOS/HelloiOS/HalideViewController.mm +++ b/apps/HelloiOS/HelloiOS/HalideViewController.mm @@ -25,9 +25,12 @@ - (void)loadView { // Pin label to bottom with safe area [NSLayoutConstraint activateConstraints:@[ - [_statsLabel.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:10], - [_statsLabel.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-10], - [_statsLabel.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:-10] + [_statsLabel.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor + constant:10], + [_statsLabel.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor + constant:-10], + [_statsLabel.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor + constant:-10] ]]; // Give HalideView a reference to the label for updates diff --git a/apps/HelloiOS/HelloiOS/SceneDelegate.h b/apps/HelloiOS/HelloiOS/SceneDelegate.h index bb1f9b301c6a..387791eaa4ae 100644 --- a/apps/HelloiOS/HelloiOS/SceneDelegate.h +++ b/apps/HelloiOS/HelloiOS/SceneDelegate.h @@ -2,6 +2,6 @@ @interface SceneDelegate : UIResponder -@property (strong, nonatomic) UIWindow *window; +@property(strong, nonatomic) UIWindow *window; @end diff --git a/apps/HelloiOS/README.md b/apps/HelloiOS/README.md index f991b8d4f847..2d221b7d0915 100644 --- a/apps/HelloiOS/README.md +++ b/apps/HelloiOS/README.md @@ -18,9 +18,9 @@ The project is split into two parts: 1. **Generators/** -- A CMake project that builds the Halide generator on the host and runs it to produce iOS-targeted static libraries and headers for - each reaction-diffusion kernel. Kernels are generated for both `iphoneos` - and `iphonesimulator` platforms, so you can switch destinations in Xcode - without re-running setup. + each reaction-diffusion kernel. Kernels are generated for both `iphoneos` and + `iphonesimulator` platforms, so you can switch destinations in Xcode without + re-running setup. 2. **HelloiOS/** -- A native Xcode project for the iOS app. It compiles the Objective-C++ sources and links the generated Halide libraries. The app @@ -47,7 +47,7 @@ cmake --install build --prefix install ## Environment Variables | Variable | Default | Description | -|---------------|--------------|-----------------------| +| ------------- | ------------ | --------------------- | | `Halide_ROOT` | *(required)* | Halide install prefix | ## Launching in Simulator @@ -87,5 +87,5 @@ Generators' build phase of the HelloiOS target with: env -i USER="$USER" HOME="$HOME" PATH="$PATH" DEVELOPER_DIR="$DEVELOPER_DIR" ``` -Only do this if necessary as it drops *all* build context and may -cause different problems in the future. +Only do this if necessary as it drops *all* build context and may cause +different problems in the future. From 9b011bf347cee1ccd6b4acd39e40a026cc6d38d7 Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 16 Mar 2026 13:29:59 -0700 Subject: [PATCH 30/37] Add missing keep-sorted start --- apps/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index d06bb65d1005..622e0ac04939 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -30,6 +30,7 @@ if (Halide_TARGET MATCHES "wasm") return() endif() +# keep-sorted start case=no ignore_prefixes=# # add_app(HelloAndroid) # TODO(#5374): missing CMake build # add_app(HelloAndroidCamera2) # TODO(#5374): missing CMake build # add_app(HelloPyTorch) # TODO(#5374): missing CMake build From 9e55d9175dd26545ad0c088f760f06994f5eba9f Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 16 Mar 2026 13:35:09 -0700 Subject: [PATCH 31/37] Pacify cmake linter --- cmake/HalideGeneratorHelpers.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index 25d40b6e90aa..ef7e32d87b47 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -742,7 +742,7 @@ function(add_halide_library TARGET) endif () # Save metadata on the library target for downstream helpers. - set_property(DIRECTORY APPEND PROPERTY Halide_BUILDSYSTEM_TARGETS "${TARGET}") + set_property(DIRECTORY APPEND PROPERTY Halide_BUILDSYSTEM_TARGETS "${TARGET}") # nolint set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_RUNTIME_TARGET "${ARG_USE_RUNTIME}") set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_FUNCTION_NAME "${ARG_FUNCTION_NAME}") set_property(TARGET "${TARGET}" PROPERTY Halide_LIBRARY_TARGETS "${ARG_TARGETS}") From 811ece545cd08ad924a1d4ef6b62514c0863152b Mon Sep 17 00:00:00 2001 From: "halide-ci[bot]" <266445882+halide-ci[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 20:35:21 +0000 Subject: [PATCH 32/37] Apply pre-commit auto-fixes --- apps/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 622e0ac04939..5fcfd811b2f1 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -31,10 +31,6 @@ if (Halide_TARGET MATCHES "wasm") endif() # keep-sorted start case=no ignore_prefixes=# -# add_app(HelloAndroid) # TODO(#5374): missing CMake build -# add_app(HelloAndroidCamera2) # TODO(#5374): missing CMake build -# add_app(HelloPyTorch) # TODO(#5374): missing CMake build -# add_app(HelloiOS) # don't build HelloiOS here because it isn't universal. # add_app(auto_viz) # TODO(#5374): missing CMake build add_app(bgu) add_app(bilateral_grid) @@ -51,6 +47,7 @@ add_app(harris) # add_app(HelloAndroid) # TODO(#5374): missing CMake build # add_app(HelloAndroidCamera2) # TODO(#5374): missing CMake build add_app(HelloBaremetal) +# add_app(HelloiOS) # don't build HelloiOS here because it isn't universal. # add_app(HelloiOS) # TODO(#5374): missing CMake build # add_app(HelloPyTorch) # TODO(#5374): missing CMake build add_app(hexagon_benchmarks) From 7937eb0fcf3722915632d25579385b689fefe6c4 Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 16 Mar 2026 13:40:26 -0700 Subject: [PATCH 33/37] Fix bad merge --- apps/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 5fcfd811b2f1..4702e6c5fa32 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -48,7 +48,6 @@ add_app(harris) # add_app(HelloAndroidCamera2) # TODO(#5374): missing CMake build add_app(HelloBaremetal) # add_app(HelloiOS) # don't build HelloiOS here because it isn't universal. -# add_app(HelloiOS) # TODO(#5374): missing CMake build # add_app(HelloPyTorch) # TODO(#5374): missing CMake build add_app(hexagon_benchmarks) # add_app(hexagon_dma) # TODO(#5374): missing CMake build From 0dcc147f2f1b931afc927518afd7c292c6bfc371 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 19 Mar 2026 16:21:54 -0400 Subject: [PATCH 34/37] Add a macOS workflow for HelloiOS testing --- .github/workflows/testing-macos.yml | 85 +++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/testing-macos.yml diff --git a/.github/workflows/testing-macos.yml b/.github/workflows/testing-macos.yml new file mode 100644 index 000000000000..2d354849c326 --- /dev/null +++ b/.github/workflows/testing-macos.yml @@ -0,0 +1,85 @@ +name: macOS + +on: + pull_request: + types: [ opened, synchronize, reopened ] + paths-ignore: + - "doc/**" + - "README.md" + - "CODE_OF_CONDUCT.md" + - "LICENSE.txt" + - ".gitignore" + - ".gitattributes" + - ".gitmodules" + - ".lldbinit" + - ".github/**" + - "!.github/workflows/testing-macos.yml" + - "packaging/**" + - "Makefile" + - "Makefile.inc" + - 'run-clang-tidy.sh' + - '**.clang-tidy' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + macos: + if: "!contains(github.event.pull_request.labels.*.name, 'skip_buildbots')" + name: ${{ matrix.arch }} / ${{ matrix.uv_group }} + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + # Disable extra cases until we have a fuller workflow + # For now, we're only testing HelloiOS + uv_group: [ "ci-llvm-main", ] # "ci-llvm-22", "ci-llvm-21" + runner: [ "macos-26", ] # "macos-26-intel" + include: + - runner: macos-26 + arch: arm-64 + + steps: + - uses: actions/checkout@v4 + + - uses: astral-sh/setup-uv@v5 + + - name: Sync CI environment + run: | + uv sync --group '${{ matrix.uv_group }}' --no-install-project + echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" + echo "VIRTUAL_ENV=${GITHUB_WORKSPACE}/.venv" >> "$GITHUB_ENV" + + - name: Configure LLVM paths + run: echo "Halide_LLVM_ROOT=$(halide-llvm --prefix)" >> "$GITHUB_ENV" + + - name: Configure CMake + run: >- + cmake --preset ci-macos-${{ matrix.arch }} + -DCMAKE_INSTALL_PREFIX=/opt/halide + -DWITH_TESTS=NO + -DWITH_UTILS=NO + -DWITH_TUTORIALS=NO + -DWITH_PYTHON_BINDINGS=NO + + - name: Initial build + run: cmake --build build --target install + + - name: Configure HelloiOS + run: ./setup.sh + working-directory: apps/HelloiOS + env: + Halide_ROOT: /opt/halide + + - name: Build HelloiOS + run: >- + xcodebuild -workspace HelloiOS.xcworkspace + -scheme HelloiOS + -configuration Debug + -destination 'platform=iOS Simulator,OS=latest,name=iPhone 16' + build + working-directory: apps/HelloiOS From f3f133d93c872fe48d90b3d561486668a6db5909 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 19 Mar 2026 16:28:38 -0400 Subject: [PATCH 35/37] Use Python 3.10 so we don't need to build onnx wheels --- .github/workflows/testing-macos.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/testing-macos.yml b/.github/workflows/testing-macos.yml index 2d354849c326..02a1c6a41f78 100644 --- a/.github/workflows/testing-macos.yml +++ b/.github/workflows/testing-macos.yml @@ -42,6 +42,7 @@ jobs: include: - runner: macos-26 arch: arm-64 + python: cpython-3.10.20-macos-aarch64-none steps: - uses: actions/checkout@v4 @@ -50,7 +51,7 @@ jobs: - name: Sync CI environment run: | - uv sync --group '${{ matrix.uv_group }}' --no-install-project + uv sync --python '${{ matrix.python }}' --group '${{ matrix.uv_group }}' --no-install-project echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" echo "VIRTUAL_ENV=${GITHUB_WORKSPACE}/.venv" >> "$GITHUB_ENV" From 99f15f9cfd849a58ffc41a8f617fdad72046dff9 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 19 Mar 2026 16:39:03 -0400 Subject: [PATCH 36/37] Don't install to /opt --- .github/workflows/testing-macos.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing-macos.yml b/.github/workflows/testing-macos.yml index 02a1c6a41f78..e64a622adae2 100644 --- a/.github/workflows/testing-macos.yml +++ b/.github/workflows/testing-macos.yml @@ -61,7 +61,7 @@ jobs: - name: Configure CMake run: >- cmake --preset ci-macos-${{ matrix.arch }} - -DCMAKE_INSTALL_PREFIX=/opt/halide + -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/install" -DWITH_TESTS=NO -DWITH_UTILS=NO -DWITH_TUTORIALS=NO @@ -74,7 +74,7 @@ jobs: run: ./setup.sh working-directory: apps/HelloiOS env: - Halide_ROOT: /opt/halide + Halide_ROOT: ${{ github.workspace }}/install - name: Build HelloiOS run: >- From a0b9c5afc6234ab2ee8fe0b832b7085b65984ba8 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 19 Mar 2026 17:38:06 -0400 Subject: [PATCH 37/37] Use a more generic destination for iOS --- .github/workflows/testing-macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing-macos.yml b/.github/workflows/testing-macos.yml index e64a622adae2..2578bb0e3134 100644 --- a/.github/workflows/testing-macos.yml +++ b/.github/workflows/testing-macos.yml @@ -81,6 +81,6 @@ jobs: xcodebuild -workspace HelloiOS.xcworkspace -scheme HelloiOS -configuration Debug - -destination 'platform=iOS Simulator,OS=latest,name=iPhone 16' + -destination 'generic/platform=iOS Simulator' build working-directory: apps/HelloiOS