1
0

validate-tvos.sh 31 KB

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