validate-macos.sh 30 KB

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