1
0

validate-ios.sh 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. #!/usr/bin/env bash
  2. # validate-ios.sh - Validate iOS Application with embedded llama.xcframework using SwiftUI
  3. # Authentication options (optional) (can be set via environment variables)
  4. # To use: export APPLE_ID=your.email@example.com
  5. # export APPLE_PASSWORD=your-app-specific-password
  6. # ./validate-ios.sh
  7. APPLE_ID=${APPLE_ID:-""}
  8. APPLE_PASSWORD=${APPLE_PASSWORD:-""}
  9. # Ensure the script exits on error
  10. set -e
  11. # Function to print usage instructions
  12. print_usage() {
  13. echo "Usage: ./validate-ios.sh [OPTIONS]"
  14. echo ""
  15. echo "Options:"
  16. echo " --help Show this help message"
  17. echo " --apple-id EMAIL Apple ID email for validation"
  18. echo " --apple-password PWD App-specific password for Apple ID"
  19. echo ""
  20. echo "Environment variables:"
  21. echo " APPLE_ID Apple ID email for validation"
  22. echo " APPLE_PASSWORD App-specific password for Apple ID"
  23. echo ""
  24. echo "Notes:"
  25. echo " - Command line options take precedence over environment variables"
  26. echo " - Authentication is optional. If not provided, alternative validation will be performed"
  27. echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
  28. }
  29. # Parse command line arguments
  30. while [[ $# -gt 0 ]]; do
  31. case $1 in
  32. --help)
  33. print_usage
  34. exit 0
  35. ;;
  36. --apple-id)
  37. APPLE_ID="$2"
  38. shift 2
  39. ;;
  40. --apple-password)
  41. APPLE_PASSWORD="$2"
  42. shift 2
  43. ;;
  44. *)
  45. echo "Unknown option: $1"
  46. print_usage
  47. exit 1
  48. ;;
  49. esac
  50. done
  51. # Function to clean up in case of error
  52. cleanup() {
  53. # Don't clean up temp files on error to help with debugging
  54. echo "===== iOS Validation Process Failed ====="
  55. exit 1
  56. }
  57. # Set up trap to call cleanup function on error
  58. trap cleanup ERR
  59. set -e # Exit on any error
  60. ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
  61. BUILD_DIR="${ROOT_DIR}/validation-builds/ios"
  62. # Configuration
  63. APP_NAME="iOSLlamaTest"
  64. BUNDLE_ID="org.ggml.iOSLlamaTest"
  65. XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
  66. TEMP_DIR="${BUILD_DIR}/temp"
  67. ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
  68. IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa"
  69. VALIDATION_DIR="${BUILD_DIR}/validation"
  70. # Create necessary directories
  71. mkdir -p "${BUILD_DIR}"
  72. mkdir -p "${TEMP_DIR}"
  73. mkdir -p "${VALIDATION_DIR}"
  74. echo "===== iOS Validation Process Started ====="
  75. # 1. Create a simple test app project
  76. echo "Creating test iOS app project..."
  77. mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
  78. cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF
  79. <?xml version="1.0" encoding="UTF-8"?>
  80. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  81. <plist version="1.0">
  82. <dict>
  83. <key>CFBundleDevelopmentRegion</key>
  84. <string>en</string>
  85. <key>CFBundleExecutable</key>
  86. <string>${APP_NAME}</string>
  87. <key>CFBundleIdentifier</key>
  88. <string>${BUNDLE_ID}</string>
  89. <key>CFBundleInfoDictionaryVersion</key>
  90. <string>6.0</string>
  91. <key>CFBundleName</key>
  92. <string>${APP_NAME}</string>
  93. <key>CFBundlePackageType</key>
  94. <string>APPL</string>
  95. <key>CFBundleShortVersionString</key>
  96. <string>1.0</string>
  97. <key>CFBundleVersion</key>
  98. <string>1</string>
  99. <key>LSRequiresIPhoneOS</key>
  100. <true/>
  101. <key>UILaunchScreen</key>
  102. <dict/>
  103. <key>UIRequiredDeviceCapabilities</key>
  104. <array>
  105. <string>armv7</string>
  106. </array>
  107. <key>UISupportedInterfaceOrientations</key>
  108. <array>
  109. <string>UIInterfaceOrientationPortrait</string>
  110. </array>
  111. </dict>
  112. </plist>
  113. EOF
  114. # Create SwiftUI app files
  115. mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
  116. # Create App.swift
  117. cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
  118. import SwiftUI
  119. import llama
  120. @main
  121. struct LlamaTestApp: App {
  122. var body: some Scene {
  123. WindowGroup {
  124. ContentView()
  125. }
  126. }
  127. }
  128. EOF
  129. # Create ContentView.swift
  130. cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
  131. import SwiftUI
  132. import llama
  133. struct ContentView: View {
  134. // Test that we can initialize a llama context params struct
  135. let params = llama_context_default_params()
  136. var body: some View {
  137. VStack(spacing: 20) {
  138. Text("Llama Framework Test")
  139. .font(.largeTitle)
  140. .padding()
  141. Text("llama_context_default_params() created successfully")
  142. .font(.headline)
  143. .multilineTextAlignment(.center)
  144. .padding()
  145. // Display some param values to confirm the framework is working
  146. Text("n_ctx: \(params.n_ctx)")
  147. .font(.body)
  148. Text("n_batch: \(params.n_batch)")
  149. .font(.body)
  150. Spacer()
  151. }
  152. .padding()
  153. }
  154. }
  155. struct ContentView_Previews: PreviewProvider {
  156. static var previews: some View {
  157. ContentView()
  158. }
  159. }
  160. EOF
  161. # Create project.pbxproj, fixing the framework search paths issues
  162. mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
  163. cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
  164. // !$*UTF8*$!
  165. {
  166. archiveVersion = 1;
  167. classes = {
  168. };
  169. objectVersion = 54;
  170. objects = {
  171. /* Begin PBXBuildFile section */
  172. 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
  173. 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
  174. 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
  175. 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
  176. /* End PBXBuildFile section */
  177. /* Begin PBXCopyFilesBuildPhase section */
  178. 88888888888888888888888 /* Embed Frameworks */ = {
  179. isa = PBXCopyFilesBuildPhase;
  180. buildActionMask = 2147483647;
  181. dstPath = "";
  182. dstSubfolderSpec = 10;
  183. files = (
  184. 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
  185. );
  186. name = "Embed Frameworks";
  187. runOnlyForDeploymentPostprocessing = 0;
  188. };
  189. /* End PBXCopyFilesBuildPhase section */
  190. /* Begin PBXFileReference section */
  191. EOF
  192. # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
  193. cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
  194. 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
  195. 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
  196. 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
  197. AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
  198. 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
  199. /* End PBXFileReference section */
  200. EOF
  201. # Add the rest of the project file with fixed framework search paths
  202. cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
  203. /* Begin PBXFrameworksBuildPhase section */
  204. BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
  205. isa = PBXFrameworksBuildPhase;
  206. buildActionMask = 2147483647;
  207. files = (
  208. 55555555555555555555555 /* llama.xcframework in Frameworks */,
  209. );
  210. runOnlyForDeploymentPostprocessing = 0;
  211. };
  212. /* End PBXFrameworksBuildPhase section */
  213. /* Begin PBXGroup section */
  214. EOF
  215. # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
  216. cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
  217. CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
  218. isa = PBXGroup;
  219. children = (
  220. 99999999999999999999999 /* ${APP_NAME}.app */,
  221. );
  222. name = Products;
  223. sourceTree = "<group>";
  224. };
  225. EOF
  226. cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
  227. DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
  228. isa = PBXGroup;
  229. children = (
  230. 66666666666666666666666 /* llama.xcframework */,
  231. );
  232. name = Frameworks;
  233. sourceTree = "<group>";
  234. };
  235. EEEEEEEEEEEEEEEEEEEEEEEE = {
  236. isa = PBXGroup;
  237. children = (
  238. FFFFFFFFFFFFFFFFFFFFFFFF /* iOSLlamaTest */,
  239. CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
  240. DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
  241. );
  242. sourceTree = "<group>";
  243. };
  244. FFFFFFFFFFFFFFFFFFFFFFFF /* iOSLlamaTest */ = {
  245. isa = PBXGroup;
  246. children = (
  247. 1111111111111111111111AA /* Sources */,
  248. AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
  249. );
  250. path = "iOSLlamaTest";
  251. sourceTree = "<group>";
  252. };
  253. 1111111111111111111111AA /* Sources */ = {
  254. isa = PBXGroup;
  255. children = (
  256. 22222222222222222222222 /* App.swift */,
  257. 44444444444444444444444 /* ContentView.swift */,
  258. );
  259. path = Sources;
  260. sourceTree = "<group>";
  261. };
  262. /* End PBXGroup section */
  263. EOF
  264. # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
  265. cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
  266. /* Begin PBXNativeTarget section */
  267. 3333333333333333333333AA /* ${APP_NAME} */ = {
  268. isa = PBXNativeTarget;
  269. buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
  270. buildPhases = (
  271. 5555555555555555555555AA /* Sources */,
  272. BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
  273. 6666666666666666666666AA /* Resources */,
  274. 88888888888888888888888 /* Embed Frameworks */,
  275. );
  276. buildRules = (
  277. );
  278. dependencies = (
  279. );
  280. name = "${APP_NAME}";
  281. productName = "${APP_NAME}";
  282. productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
  283. productType = "com.apple.product-type.application";
  284. };
  285. /* End PBXNativeTarget section */
  286. /* Begin PBXProject section */
  287. 7777777777777777777777AA /* Project object */ = {
  288. isa = PBXProject;
  289. attributes = {
  290. LastSwiftUpdateCheck = 1240;
  291. LastUpgradeCheck = 1240;
  292. TargetAttributes = {
  293. 3333333333333333333333AA = {
  294. CreatedOnToolsVersion = 12.4;
  295. };
  296. };
  297. };
  298. buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
  299. compatibilityVersion = "Xcode 12.0";
  300. developmentRegion = en;
  301. hasScannedForEncodings = 0;
  302. knownRegions = (
  303. en,
  304. Base,
  305. );
  306. mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
  307. productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
  308. projectDirPath = "";
  309. projectRoot = "";
  310. targets = (
  311. 3333333333333333333333AA /* ${APP_NAME} */,
  312. );
  313. };
  314. /* End PBXProject section */
  315. EOF
  316. # Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS
  317. cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
  318. /* Begin PBXResourcesBuildPhase section */
  319. 6666666666666666666666AA /* Resources */ = {
  320. isa = PBXResourcesBuildPhase;
  321. buildActionMask = 2147483647;
  322. files = (
  323. );
  324. runOnlyForDeploymentPostprocessing = 0;
  325. };
  326. /* End PBXResourcesBuildPhase section */
  327. /* Begin PBXSourcesBuildPhase section */
  328. 5555555555555555555555AA /* Sources */ = {
  329. isa = PBXSourcesBuildPhase;
  330. buildActionMask = 2147483647;
  331. files = (
  332. 33333333333333333333333 /* ContentView.swift in Sources */,
  333. 11111111111111111111111 /* App.swift in Sources */,
  334. );
  335. runOnlyForDeploymentPostprocessing = 0;
  336. };
  337. /* End PBXSourcesBuildPhase section */
  338. /* Begin XCBuildConfiguration section */
  339. 9999999999999999999999AA /* Debug */ = {
  340. isa = XCBuildConfiguration;
  341. buildSettings = {
  342. ALWAYS_SEARCH_USER_PATHS = NO;
  343. CLANG_ANALYZER_NONNULL = YES;
  344. CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
  345. CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
  346. CLANG_CXX_LIBRARY = "libc++";
  347. CLANG_ENABLE_MODULES = YES;
  348. CLANG_ENABLE_OBJC_ARC = YES;
  349. CLANG_ENABLE_OBJC_WEAK = YES;
  350. CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
  351. CLANG_WARN_BOOL_CONVERSION = YES;
  352. CLANG_WARN_COMMA = YES;
  353. CLANG_WARN_CONSTANT_CONVERSION = YES;
  354. CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
  355. CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  356. CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
  357. CLANG_WARN_EMPTY_BODY = YES;
  358. CLANG_WARN_ENUM_CONVERSION = YES;
  359. CLANG_WARN_INFINITE_RECURSION = YES;
  360. CLANG_WARN_INT_CONVERSION = YES;
  361. CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
  362. CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
  363. CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
  364. CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  365. CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
  366. CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
  367. CLANG_WARN_STRICT_PROTOTYPES = YES;
  368. CLANG_WARN_SUSPICIOUS_MOVE = YES;
  369. CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
  370. CLANG_WARN_UNREACHABLE_CODE = YES;
  371. CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  372. COPY_PHASE_STRIP = NO;
  373. DEBUG_INFORMATION_FORMAT = dwarf;
  374. ENABLE_STRICT_OBJC_MSGSEND = YES;
  375. ENABLE_TESTABILITY = YES;
  376. GCC_C_LANGUAGE_STANDARD = gnu11;
  377. GCC_DYNAMIC_NO_PIC = NO;
  378. GCC_NO_COMMON_BLOCKS = YES;
  379. GCC_OPTIMIZATION_LEVEL = 0;
  380. GCC_PREPROCESSOR_DEFINITIONS = (
  381. "DEBUG=1",
  382. "$(inherited)",
  383. );
  384. GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  385. GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  386. GCC_WARN_UNDECLARED_SELECTOR = YES;
  387. GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  388. GCC_WARN_UNUSED_FUNCTION = YES;
  389. GCC_WARN_UNUSED_VARIABLE = YES;
  390. IPHONEOS_DEPLOYMENT_TARGET = 16.4;
  391. MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
  392. MTL_FAST_MATH = YES;
  393. ONLY_ACTIVE_ARCH = YES;
  394. SDKROOT = iphoneos;
  395. SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
  396. SWIFT_OPTIMIZATION_LEVEL = "-Onone";
  397. };
  398. name = Debug;
  399. };
  400. AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
  401. isa = XCBuildConfiguration;
  402. buildSettings = {
  403. ALWAYS_SEARCH_USER_PATHS = NO;
  404. CLANG_ANALYZER_NONNULL = YES;
  405. CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
  406. CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
  407. CLANG_CXX_LIBRARY = "libc++";
  408. CLANG_ENABLE_MODULES = YES;
  409. CLANG_ENABLE_OBJC_ARC = YES;
  410. CLANG_ENABLE_OBJC_WEAK = YES;
  411. CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
  412. CLANG_WARN_BOOL_CONVERSION = YES;
  413. CLANG_WARN_COMMA = YES;
  414. CLANG_WARN_CONSTANT_CONVERSION = YES;
  415. CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
  416. CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  417. CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
  418. CLANG_WARN_EMPTY_BODY = YES;
  419. CLANG_WARN_ENUM_CONVERSION = YES;
  420. CLANG_WARN_INFINITE_RECURSION = YES;
  421. CLANG_WARN_INT_CONVERSION = YES;
  422. CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
  423. CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
  424. CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
  425. CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  426. CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
  427. CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
  428. CLANG_WARN_STRICT_PROTOTYPES = YES;
  429. CLANG_WARN_SUSPICIOUS_MOVE = YES;
  430. CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
  431. CLANG_WARN_UNREACHABLE_CODE = YES;
  432. CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  433. COPY_PHASE_STRIP = NO;
  434. DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
  435. ENABLE_NS_ASSERTIONS = NO;
  436. ENABLE_STRICT_OBJC_MSGSEND = YES;
  437. GCC_C_LANGUAGE_STANDARD = gnu11;
  438. GCC_NO_COMMON_BLOCKS = YES;
  439. GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  440. GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  441. GCC_WARN_UNDECLARED_SELECTOR = YES;
  442. GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  443. GCC_WARN_UNUSED_FUNCTION = YES;
  444. GCC_WARN_UNUSED_VARIABLE = YES;
  445. IPHONEOS_DEPLOYMENT_TARGET = 16.4;
  446. MTL_ENABLE_DEBUG_INFO = NO;
  447. MTL_FAST_MATH = YES;
  448. SDKROOT = iphoneos;
  449. SWIFT_COMPILATION_MODE = wholemodule;
  450. SWIFT_OPTIMIZATION_LEVEL = "-O";
  451. VALIDATE_PRODUCT = YES;
  452. };
  453. name = Release;
  454. };
  455. BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
  456. isa = XCBuildConfiguration;
  457. buildSettings = {
  458. ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  459. ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
  460. CODE_SIGN_STYLE = Manual;
  461. DEVELOPMENT_TEAM = "";
  462. ENABLE_PREVIEWS = YES;
  463. FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
  464. INFOPLIST_FILE = "iOSLlamaTest/Info.plist";
  465. LD_RUNPATH_SEARCH_PATHS = (
  466. "$(inherited)",
  467. "@executable_path/Frameworks",
  468. );
  469. PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSLlamaTest";
  470. PRODUCT_NAME = "$(TARGET_NAME)";
  471. PROVISIONING_PROFILE_SPECIFIER = "";
  472. SWIFT_VERSION = 5.0;
  473. TARGETED_DEVICE_FAMILY = "1,2";
  474. };
  475. name = Debug;
  476. };
  477. CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
  478. isa = XCBuildConfiguration;
  479. buildSettings = {
  480. ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  481. ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
  482. CODE_SIGN_STYLE = Manual;
  483. DEVELOPMENT_TEAM = "";
  484. ENABLE_PREVIEWS = YES;
  485. FRAMEWORK_SEARCH_PATHS = (
  486. "$(inherited)",
  487. "$(PROJECT_DIR)",
  488. );
  489. INFOPLIST_FILE = "iOSLlamaTest/Info.plist";
  490. LD_RUNPATH_SEARCH_PATHS = (
  491. "$(inherited)",
  492. "@executable_path/Frameworks",
  493. );
  494. PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSLlamaTest";
  495. PRODUCT_NAME = "$(TARGET_NAME)";
  496. PROVISIONING_PROFILE_SPECIFIER = "";
  497. SWIFT_VERSION = 5.0;
  498. TARGETED_DEVICE_FAMILY = "1,2";
  499. };
  500. name = Release;
  501. };
  502. /* End XCBuildConfiguration section */
  503. EOF
  504. # Finish the project.pbxproj file
  505. cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
  506. /* Begin XCConfigurationList section */
  507. 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
  508. isa = XCConfigurationList;
  509. buildConfigurations = (
  510. 9999999999999999999999AA /* Debug */,
  511. AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
  512. );
  513. defaultConfigurationIsVisible = 0;
  514. defaultConfigurationName = Release;
  515. };
  516. 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
  517. isa = XCConfigurationList;
  518. buildConfigurations = (
  519. BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
  520. CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
  521. );
  522. defaultConfigurationIsVisible = 0;
  523. defaultConfigurationName = Release;
  524. };
  525. /* End XCConfigurationList section */
  526. };
  527. rootObject = 7777777777777777777777AA /* Project object */;
  528. }
  529. EOF
  530. # 2. Copy XCFramework to test project
  531. echo "Copying XCFramework to test project..."
  532. cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
  533. # 3. Build and archive the app
  534. echo "Building and archiving test app..."
  535. cd "${TEMP_DIR}/${APP_NAME}"
  536. # Create a simple xcscheme file to avoid xcodebuild scheme issues
  537. mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
  538. cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
  539. <?xml version="1.0" encoding="UTF-8"?>
  540. <Scheme
  541. LastUpgradeVersion = "1240"
  542. version = "1.3">
  543. <BuildAction
  544. parallelizeBuildables = "YES"
  545. buildImplicitDependencies = "YES">
  546. <BuildActionEntries>
  547. <BuildActionEntry
  548. buildForTesting = "YES"
  549. buildForRunning = "YES"
  550. buildForProfiling = "YES"
  551. buildForArchiving = "YES"
  552. buildForAnalyzing = "YES">
  553. <BuildableReference
  554. BuildableIdentifier = "primary"
  555. BlueprintIdentifier = "3333333333333333333333AA"
  556. BuildableName = "${APP_NAME}.app"
  557. BlueprintName = "${APP_NAME}"
  558. ReferencedContainer = "container:${APP_NAME}.xcodeproj">
  559. </BuildableReference>
  560. </BuildActionEntry>
  561. </BuildActionEntries>
  562. </BuildAction>
  563. <TestAction
  564. buildConfiguration = "Debug"
  565. selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  566. selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  567. shouldUseLaunchSchemeArgsEnv = "YES">
  568. <Testables>
  569. </Testables>
  570. </TestAction>
  571. <LaunchAction
  572. buildConfiguration = "Debug"
  573. selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  574. selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  575. launchStyle = "0"
  576. useCustomWorkingDirectory = "NO"
  577. ignoresPersistentStateOnLaunch = "NO"
  578. debugDocumentVersioning = "YES"
  579. debugServiceExtension = "internal"
  580. allowLocationSimulation = "YES">
  581. <BuildableProductRunnable
  582. runnableDebuggingMode = "0">
  583. <BuildableReference
  584. BuildableIdentifier = "primary"
  585. BlueprintIdentifier = "3333333333333333333333AA"
  586. BuildableName = "${APP_NAME}.app"
  587. BlueprintName = "${APP_NAME}"
  588. ReferencedContainer = "container:${APP_NAME}.xcodeproj">
  589. </BuildableReference>
  590. </BuildableProductRunnable>
  591. </LaunchAction>
  592. <ProfileAction
  593. buildConfiguration = "Release"
  594. shouldUseLaunchSchemeArgsEnv = "YES"
  595. savedToolIdentifier = ""
  596. useCustomWorkingDirectory = "NO"
  597. debugDocumentVersioning = "YES">
  598. <BuildableProductRunnable
  599. runnableDebuggingMode = "0">
  600. <BuildableReference
  601. BuildableIdentifier = "primary"
  602. BlueprintIdentifier = "3333333333333333333333AA"
  603. BuildableName = "${APP_NAME}.app"
  604. BlueprintName = "${APP_NAME}"
  605. ReferencedContainer = "container:${APP_NAME}.xcodeproj">
  606. </BuildableReference>
  607. </BuildableProductRunnable>
  608. </ProfileAction>
  609. <AnalyzeAction
  610. buildConfiguration = "Debug">
  611. </AnalyzeAction>
  612. <ArchiveAction
  613. buildConfiguration = "Release"
  614. revealArchiveInOrganizer = "YES">
  615. </ArchiveAction>
  616. </Scheme>
  617. EOF
  618. # Now use xcodebuild with an explicitly defined product name
  619. xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk iphoneos -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
  620. # 4. Create IPA from archive
  621. echo "Creating IPA from archive..."
  622. mkdir -p "${TEMP_DIR}/Payload"
  623. cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/"
  624. # Check and log app structure before zipping
  625. echo "App structure:"
  626. ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/"
  627. echo "Frameworks:"
  628. ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
  629. cd "${TEMP_DIR}"
  630. zip -r "${IPA_PATH}" Payload
  631. # Check embedded provisioning profile
  632. echo "Checking provisioning profile (if any)..."
  633. PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null)
  634. if [ -n "$PROVISIONING_PROFILE" ]; then
  635. echo "Found embedded provisioning profile:"
  636. security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
  637. else
  638. echo "No embedded provisioning profile found (expected for ad-hoc builds)"
  639. fi
  640. # 5. Validate the IPA
  641. echo "Validating IPA..."
  642. VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
  643. # Check if authentication credentials are provided
  644. AUTH_ARGS=""
  645. if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
  646. echo "Using Apple ID authentication for validation..."
  647. AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
  648. else
  649. echo "No authentication credentials provided. Will perform basic validation."
  650. echo "To use your personal developer account, you can run the script with:"
  651. echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-ios.sh"
  652. echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
  653. fi
  654. # Run validation with detailed output
  655. echo "Running validation with altool..."
  656. if [ -n "$AUTH_ARGS" ]; then
  657. # Use eval to properly handle the quoted arguments
  658. eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type ios --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}"
  659. else
  660. xcrun altool --validate-app -f "${IPA_PATH}" --type ios --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}"
  661. fi
  662. VALIDATION_RESULT=$?
  663. # Final validation result
  664. FINAL_VALIDATION_RESULT=0
  665. # Check if validation failed because the app isn't in App Store Connect
  666. if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then
  667. echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect"
  668. echo "This is expected for apps that haven't been registered in App Store Connect yet."
  669. echo "This doesn't indicate a problem with the build or framework."
  670. # Perform alternative validation
  671. echo "Performing alternative validation checks..."
  672. # Check if IPA was created successfully
  673. if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then
  674. echo "✅ IPA file created successfully"
  675. else
  676. echo "❌ IPA file not created or empty"
  677. FINAL_VALIDATION_RESULT=1
  678. fi
  679. # Check if app binary exists and is executable
  680. if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then
  681. echo "✅ App binary exists and is executable"
  682. else
  683. echo "❌ App binary missing or not executable"
  684. FINAL_VALIDATION_RESULT=1
  685. fi
  686. # Check if framework was properly embedded
  687. if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then
  688. echo "✅ llama.framework properly embedded"
  689. else
  690. echo "❌ llama.framework not properly embedded"
  691. FINAL_VALIDATION_RESULT=1
  692. fi
  693. # Check if framework binary exists
  694. if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then
  695. echo "✅ Framework binary exists"
  696. # Further validate framework by checking architecture
  697. ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|armv7\\|x86_64" | tr '\n' ' ')
  698. if [ -n "$ARCHS" ]; then
  699. echo "✅ Framework architecture(s): $ARCHS"
  700. else
  701. echo "⚠️ Could not determine framework architecture"
  702. fi
  703. else
  704. echo "❌ Framework binary missing"
  705. FINAL_VALIDATION_RESULT=1
  706. fi
  707. if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
  708. echo "✅ Alternative validation PASSED: App built successfully with embedded framework"
  709. else
  710. echo "❌ Alternative validation FAILED: Issues found with the app or framework"
  711. fi
  712. elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then
  713. echo "✅ iOS Validation PASSED: IPA successfully validated"
  714. echo "Results saved to ${VALIDATION_OUTPUT}"
  715. else
  716. echo "❌ iOS Validation FAILED: IPA validation found issues"
  717. echo "See validation output at ${VALIDATION_OUTPUT}"
  718. echo ""
  719. echo "==== VALIDATION ERRORS ===="
  720. # Try to extract specific errors from the output
  721. if grep -q "Error" "${VALIDATION_OUTPUT}"; then
  722. grep -A 5 "Error" "${VALIDATION_OUTPUT}"
  723. else
  724. # If no specific error found, show the whole log
  725. cat "${VALIDATION_OUTPUT}"
  726. fi
  727. # Additional debugging: check IPA contents
  728. echo ""
  729. echo "==== IPA CONTENTS ===="
  730. mkdir -p "${TEMP_DIR}/ipa_contents"
  731. unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents"
  732. ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/"
  733. # Check for code signing issues
  734. echo ""
  735. echo "==== CODE SIGNING INFO ===="
  736. codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed"
  737. # Check embedded frameworks
  738. echo ""
  739. echo "==== FRAMEWORK INFO ===="
  740. ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
  741. fi
  742. # Don't clean up on error to allow inspection
  743. if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
  744. echo ""
  745. echo "Temporary files kept for inspection at: ${TEMP_DIR}"
  746. echo "===== iOS Validation Process Failed ====="
  747. exit 1
  748. fi
  749. # Clean up temporary files but keep build artifacts
  750. if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
  751. echo "Cleaning up temporary files..."
  752. #rm -rf "${TEMP_DIR}"
  753. fi
  754. echo "===== iOS Validation Process Completed ====="
  755. exit $FINAL_VALIDATION_RESULT