├── .gitignore ├── AppDelegate.h ├── AppDelegate.m ├── CMakeLists.txt ├── CppInterface.h ├── CppInterface.mm ├── LICENSE ├── LaunchScreen.storyboard ├── Main.storyboard ├── Prefix.pch ├── README.md ├── ViewController.h ├── ViewController.m ├── build-ios.sh ├── build-sim.sh ├── build-sim64.sh ├── cppframework ├── CMakeLists.txt ├── Foo.cpp ├── Foo.hh ├── framework.plist.in └── install_name.sh ├── generate-project.sh ├── ios.cmake ├── main.m ├── plist.in └── tests ├── CMakeLists.txt ├── Tests.m └── tests.plist.in /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | build.ios 4 | build.sim 5 | build.sim64 6 | Xcode 7 | -------------------------------------------------------------------------------- /AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import // UIApplicationDelegate 2 | 3 | @interface AppDelegate : UIResponder 4 | 5 | @property (strong, nonatomic) UIWindow *window; 6 | 7 | @end -------------------------------------------------------------------------------- /AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | @interface AppDelegate() 4 | 5 | @end 6 | 7 | @implementation AppDelegate 8 | 9 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 10 | // Insert code here to initialize your application 11 | NSLog(@"didFinishLaunchingWithOptions"); 12 | return YES; 13 | } 14 | 15 | - (void)applicationWillResignActive:(UIApplication *)application { 16 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 17 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 18 | } 19 | 20 | - (void)applicationDidEnterBackground:(UIApplication *)application { 21 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 22 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 23 | } 24 | 25 | - (void)applicationWillEnterForeground:(UIApplication *)application { 26 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 27 | } 28 | 29 | - (void)applicationDidBecomeActive:(UIApplication *)application { 30 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 31 | } 32 | 33 | - (void)applicationWillTerminate:(UIApplication *)application { 34 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 35 | } 36 | 37 | 38 | @end -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.7) 2 | 3 | set(DEVELOPMENT_PROJECT_NAME "project") # <== Set to your project name, e.g. project.xcodeproj 4 | set(DEVELOPMENT_TEAM_ID "AAAAAAAAAA") # <== Set to your team ID from Apple 5 | set(APP_NAME "YOURAPP") # <== Set To your app's name 6 | set(APP_BUNDLE_IDENTIFIER "com.company.app") # <== Set to your app's bundle identifier 7 | set(FRAMEWORK_NAME "FooBar") # <== Set to your framework's name 8 | set(FRAMEWORK_BUNDLE_IDENTIFIER "com.company.framework") # <== Set to your framework's bundle identifier (cannot be the same as app bundle identifier) 9 | set(TEST_NAME "Tests") # <== Set to your test's name 10 | set(TEST_BUNDLE_IDENTIFIER "com.company.tests") # <== Set to your tests's bundle ID 11 | set(CODE_SIGN_IDENTITY "iPhone Developer") # <== Set to your preferred code sign identity, to see list: 12 | # /usr/bin/env xcrun security find-identity -v -p codesigning 13 | set(DEPLOYMENT_TARGET 8.0) # <== Set your deployment target version of iOS 14 | set(DEVICE_FAMILY "1") # <== Set to "1" to target iPhone, set to "2" to target iPad, set to "1,2" to target both 15 | set(LOGIC_ONLY_TESTS 0) # <== Set to 1 if you do not want tests to be hosted by the application, speeds up pure logic tests but you can not run them on real devices 16 | 17 | project(${DEVELOPMENT_PROJECT_NAME}) 18 | include(BundleUtilities) 19 | include(FindXCTest) 20 | 21 | message(STATUS XCTestFound:${XCTest_FOUND}) 22 | 23 | set(PRODUCT_NAME ${APP_NAME}) 24 | set(EXECUTABLE_NAME ${APP_NAME}) 25 | set(MACOSX_BUNDLE_EXECUTABLE_NAME ${APP_NAME}) 26 | set(MACOSX_BUNDLE_INFO_STRING ${APP_BUNDLE_IDENTIFIER}) 27 | set(MACOSX_BUNDLE_GUI_IDENTIFIER ${APP_BUNDLE_IDENTIFIER}) 28 | set(MACOSX_BUNDLE_BUNDLE_NAME ${APP_BUNDLE_IDENTIFIER}) 29 | set(MACOSX_BUNDLE_ICON_FILE "") 30 | set(MACOSX_BUNDLE_LONG_VERSION_STRING "1.0") 31 | set(MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0") 32 | set(MACOSX_BUNDLE_BUNDLE_VERSION "1.0") 33 | set(MACOSX_BUNDLE_COPYRIGHT "Copyright YOU") 34 | set(MACOSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET}) 35 | 36 | set(APP_HEADER_FILES 37 | ./AppDelegate.h 38 | ./ViewController.h 39 | ./CppInterface.h 40 | ./Prefix.pch 41 | ) 42 | 43 | set(APP_SOURCE_FILES 44 | ./AppDelegate.m 45 | ./ViewController.m 46 | ./CppInterface.mm 47 | ./main.m 48 | ) 49 | 50 | set(RESOURCES 51 | ./Main.storyboard 52 | ./LaunchScreen.storyboard 53 | ) 54 | 55 | add_executable( 56 | ${APP_NAME} 57 | MACOSX_BUNDLE 58 | ${APP_HEADER_FILES} 59 | ${APP_SOURCE_FILES} 60 | ${RESOURCES} 61 | ) 62 | 63 | # To disable bitcode: 64 | # set_target_properties(${APP_NAME} PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") 65 | 66 | # To link a statically linked Framework from the filesystem: 67 | # Note: dynamic frameworks require copying to the app bundle. Statically linked are copied into the executable itself. 68 | # target_link_libraries(${APP_NAME} 69 | # ${PROJECT_SOURCE_DIR}/Torch.framework 70 | # ) 71 | 72 | 73 | # Include the same headers for the statically linked framework: 74 | # Include headers to they're available as #import
from a framework 75 | # target_include_directories(${APP_NAME} 76 | # PUBLIC ${PROJECT_SOURCE_DIR}/Torch.framework/Headers 77 | # ) 78 | 79 | 80 | # Static Link a library archive into the executable 81 | # target_link_libraries(${APP_NAME} 82 | # ${PROJECT_SOURCE_DIR}/framework/lib/libtorch.a 83 | # ) 84 | 85 | 86 | # Include a source directory outside a framework 87 | # target_include_directories(${APP_NAME} 88 | # PUBLIC ${PROJECT_SOURCE_DIR}/framework/include 89 | # ) 90 | 91 | # Build the C++ dynamically linked framework 92 | add_subdirectory(cppframework) 93 | add_dependencies(${APP_NAME} ${FRAMEWORK_NAME}) 94 | 95 | # Build tests 96 | add_subdirectory(tests) 97 | 98 | # Locate system libraries on iOS 99 | find_library(UIKIT UIKit) 100 | find_library(FOUNDATION Foundation) 101 | find_library(MOBILECORESERVICES MobileCoreServices) 102 | find_library(CFNETWORK CFNetwork) 103 | find_library(SYSTEMCONFIGURATION SystemConfiguration) 104 | 105 | # link the frameworks located above 106 | target_link_libraries(${APP_NAME} ${UIKIT}) 107 | target_link_libraries(${APP_NAME} ${FOUNDATION}) 108 | target_link_libraries(${APP_NAME} ${MOBILECORESERVICES}) 109 | target_link_libraries(${APP_NAME} ${CFNETWORK}) 110 | target_link_libraries(${APP_NAME} ${SYSTEMCONFIGURATION}) 111 | 112 | # Link the framework to the app 113 | set_target_properties(${APP_NAME} PROPERTIES 114 | XCODE_ATTRIBUTE_OTHER_LDFLAGS "${XCODE_ATTRIBUTE_OTHER_LDFLAGS} -framework ${FRAMEWORK_NAME}" 115 | ) 116 | 117 | # Turn on ARC 118 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc") 119 | 120 | # Create the app target 121 | set_target_properties(${APP_NAME} PROPERTIES 122 | XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym" 123 | XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Prefix.pch" 124 | RESOURCE "${RESOURCES}" 125 | XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES" 126 | XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} 127 | XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${CODE_SIGN_IDENTITY} 128 | XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM_ID} 129 | XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY ${DEVICE_FAMILY} 130 | MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/plist.in 131 | XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES 132 | XCODE_ATTRIBUTE_COMBINE_HIDPI_IMAGES NO 133 | XCODE_ATTRIBUTE_INSTALL_PATH "$(LOCAL_APPS_DIR)" 134 | XCODE_ATTRIBUTE_ENABLE_TESTABILITY YES 135 | XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN YES 136 | ) 137 | 138 | # Include framework headers, needed to make "Build" Xcode action work. 139 | # "Archive" works fine just relying on default search paths as it has different 140 | # build product output directory. 141 | target_include_directories(${APP_NAME} PUBLIC 142 | "${PROJECT_BINARY_DIR}/cppframework/\${CONFIGURATION}\${EFFECTIVE_PLATFORM_NAME}/${FRAMEWORK_NAME}.framework" 143 | ) 144 | 145 | # Set the app's linker search path to the default location on iOS 146 | set_target_properties( 147 | ${APP_NAME} 148 | PROPERTIES 149 | XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS 150 | "@executable_path/Frameworks" 151 | ) 152 | 153 | # Note that commands below are indented just for readability. They will endup as 154 | # one liners after processing and unescaped ; will disappear so \; are needed. 155 | # First condition in each command is for normal build, second for archive. 156 | # \&\>/dev/null makes sure that failure of one command and success of other 157 | # is not printed and does not make Xcode complain that /bin/sh failed and build 158 | # continued. 159 | 160 | # Create Frameworks directory in app bundle 161 | add_custom_command( 162 | TARGET 163 | ${APP_NAME} 164 | POST_BUILD COMMAND /bin/sh -c 165 | \"COMMAND_DONE=0 \; 166 | if ${CMAKE_COMMAND} -E make_directory 167 | ${PROJECT_BINARY_DIR}/\${CONFIGURATION}\${EFFECTIVE_PLATFORM_NAME}/${APP_NAME}.app/Frameworks 168 | \&\>/dev/null \; then 169 | COMMAND_DONE=1 \; 170 | fi \; 171 | if ${CMAKE_COMMAND} -E make_directory 172 | \${BUILT_PRODUCTS_DIR}/${APP_NAME}.app/Frameworks 173 | \&\>/dev/null \; then 174 | COMMAND_DONE=1 \; 175 | fi \; 176 | if [ \\$$COMMAND_DONE -eq 0 ] \; then 177 | echo Failed to create Frameworks directory in app bundle \; 178 | exit 1 \; 179 | fi\" 180 | ) 181 | 182 | # Copy the framework into the app bundle 183 | add_custom_command( 184 | TARGET 185 | ${APP_NAME} 186 | POST_BUILD COMMAND /bin/sh -c 187 | \"COMMAND_DONE=0 \; 188 | if ${CMAKE_COMMAND} -E copy_directory 189 | ${PROJECT_BINARY_DIR}/cppframework/\${CONFIGURATION}\${EFFECTIVE_PLATFORM_NAME}/ 190 | ${PROJECT_BINARY_DIR}/\${CONFIGURATION}\${EFFECTIVE_PLATFORM_NAME}/${APP_NAME}.app/Frameworks 191 | \&\>/dev/null \; then 192 | COMMAND_DONE=1 \; 193 | fi \; 194 | if ${CMAKE_COMMAND} -E copy_directory 195 | \${BUILT_PRODUCTS_DIR}/${FRAMEWORK_NAME}.framework 196 | \${BUILT_PRODUCTS_DIR}/${APP_NAME}.app/Frameworks/${FRAMEWORK_NAME}.framework 197 | \&\>/dev/null \; then 198 | COMMAND_DONE=1 \; 199 | fi \; 200 | if [ \\$$COMMAND_DONE -eq 0 ] \; then 201 | echo Failed to copy the framework into the app bundle \; 202 | exit 1 \; 203 | fi\" 204 | ) 205 | 206 | # Codesign the framework in it's new spot 207 | add_custom_command( 208 | TARGET 209 | ${APP_NAME} 210 | POST_BUILD COMMAND /bin/sh -c 211 | \"COMMAND_DONE=0 \; 212 | if codesign --force --verbose 213 | ${PROJECT_BINARY_DIR}/\${CONFIGURATION}\${EFFECTIVE_PLATFORM_NAME}/${APP_NAME}.app/Frameworks/${FRAMEWORK_NAME}.framework 214 | --sign ${CODE_SIGN_IDENTITY} 215 | \&\>/dev/null \; then 216 | COMMAND_DONE=1 \; 217 | fi \; 218 | if codesign --force --verbose 219 | \${BUILT_PRODUCTS_DIR}/${APP_NAME}.app/Frameworks/${FRAMEWORK_NAME}.framework 220 | --sign ${CODE_SIGN_IDENTITY} 221 | \&\>/dev/null \; then 222 | COMMAND_DONE=1 \; 223 | fi \; 224 | if [ \\$$COMMAND_DONE -eq 0 ] \; then 225 | echo Framework codesign failed \; 226 | exit 1 \; 227 | fi\" 228 | ) 229 | 230 | # Add a "PlugIns" folder as a kludge fix for how the XcTest package generates paths 231 | add_custom_command( 232 | TARGET 233 | ${APP_NAME} 234 | POST_BUILD COMMAND /bin/sh -c 235 | \"COMMAND_DONE=0 \; 236 | if ${CMAKE_COMMAND} -E make_directory 237 | ${PROJECT_BINARY_DIR}/\${CONFIGURATION}\${EFFECTIVE_PLATFORM_NAME}/PlugIns 238 | \&\>/dev/null \; then 239 | COMMAND_DONE=1 \; 240 | fi \; 241 | if [ \\$$COMMAND_DONE -eq 0 ] \; then 242 | echo Failed to create PlugIns directory in EFFECTIVE_PLATFORM_NAME folder. \; 243 | exit 1 \; 244 | fi\" 245 | ) 246 | -------------------------------------------------------------------------------- /CppInterface.h: -------------------------------------------------------------------------------- 1 | // Objective-C++ objective-c class to interface with C++ Library 2 | @interface CppInterface : NSObject 3 | 4 | @end 5 | -------------------------------------------------------------------------------- /CppInterface.mm: -------------------------------------------------------------------------------- 1 | #import "CppInterface.h" 2 | #include 3 | 4 | @interface CppInterface () 5 | { 6 | Foo* myFoo; 7 | } 8 | @end 9 | 10 | @implementation CppInterface 11 | 12 | -(instancetype)init 13 | { 14 | self = [super init]; 15 | if (self) { 16 | myFoo = new Foo(); 17 | myFoo->PrintFoo(); 18 | delete myFoo; 19 | myFoo = nullptr; 20 | } 21 | return self; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Sheldon Thomas 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Prefix.pch: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #ifdef __OBJC__ 4 | #import 5 | #import 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CMake Build Configuration for iOS 2 | 3 | This is a blank single-view-controller iOS app, C++ dynamically linked framework and example tests which use CMake to create an Xcode-friendly out-of-source build system. Instead of configuring the build system through an `.xcodeproj` file, you instead maintain a set of `CMakeLists.txt` files describing the build system. 4 | 5 | This CMake project can do everything Xcode can; eg build the executable app & the C++ library in `cppframework`. The build systems, generated into `build.ios` `build.sim` `build.sim64` `Xcode` are gitignored. CMakeLists.txt files are the only build configuration kept in source control. This is in contrast to committing the `.xcodeproj` directory which includes the backing XML, which is nonsensically hard to edit by hand. 6 | 7 | The app instantiates a C++ object from the dynamically linked framework and calls a function on it. It subsequently deletes the C++ object pointer. 8 | 9 | The test instantiates ObjC object of class `CppInterface` from the app and checks that it exists. 10 | 11 | ## What can this do for me? 12 | - Conveniently use external C/C++/Objective-C libraries built with CMake in your app. Just clone the library and add an `add_subdirectory` to build that dependent library according to it's own build system, but directly as a target in your app's build system. 13 | - Remove sections of code from your exectuable and instead load it just-in-time as a dynamically linked embedded framework. 14 | - You can decrease the size of your executable (and thus how much data must be loaded into memory when your app starts) by bundling subsections of the code up and packaging it as an embedded framework. This won't decrease your IPA size (since the framework must still be embedded) but it will make your executable smaller, and therefore quicker to start. If a user never runs the dynamically linked code, it stays out of memory. The sample framework code contains a C++ hello world but it could be C/C++/Objective-C. 15 | - Stop dealing with and checking into source control pesky .xcodeproj and .xcworkspace directories. The scripts are designed to regenerate your build system frequently. 16 | 17 | ### To Use: 18 | - Open `CMakeLists.txt` 19 | - Set lines 3-15 with values for your project 20 | - NOTE: the build `./build-ios.sh` will fail if you don't have provisioning profiles for the current bundle identifier. It uses the `set(CODESIGNIDENTITY "iPhone Developer")` identity to use the default certificate for the current bundle identifier. 21 | - Requires CMake version 3.7 22 | 23 | #### Create Xcode project for Devices (armv7, armv7s, arm64) and Simulators (i386, x86_64) 24 | - Run `generate-project.sh` to create Xcode project in `Xcode` 25 | - Run `open Xcode/project.xcodeproj` 26 | 27 | #### Create & build Xcode project for Devices (armv7, armv7s, arm64) 28 | - Run `build-ios.sh` to generate the build system in `build.ios/` 29 | - Run `open build.ios/project.xcodeproj` 30 | 31 | #### Create & build Xcode project for Simulator 32-bit (i386) 32 | - Run `build-sim.sh` to build the build system in `build.sim/` 33 | - Run `open build.sim/project.xcodeproj` 34 | 35 | #### Create & build Xcode project for Simulator 64-bit (x86_64) 36 | - Run `build-sim64.sh` 37 | - Run `open build.sim64/project.xcodeproj` 38 | 39 | #### iPhone/iPad 40 | - The app target builds to iPhone device family. To build an iPhone/iPad target, change the value of `DEVICE_FAMILY` on line 14 of `CMakeLists.txt` to `"1,2"` 41 | 42 | ### Framework 43 | - Builds a dynamically linked iOS framework for the architectures relevant to the platform 44 | - Sets the install name and rpath to the correct values for iOS packaging 45 | - Copies the framework into the bundle of the app build as a post packaging step 46 | - The same process can be done to any dynamically linked framework on disk 47 | -------------------------------------------------------------------------------- /ViewController.h: -------------------------------------------------------------------------------- 1 | // ViewController.h 2 | // Your main view controller 3 | 4 | #import 5 | 6 | @interface ViewController : UIViewController 7 | 8 | @end 9 | 10 | -------------------------------------------------------------------------------- /ViewController.m: -------------------------------------------------------------------------------- 1 | #import "ViewController.h" 2 | #import "CppInterface.h" 3 | 4 | @interface ViewController () 5 | { 6 | CppInterface* i; 7 | } 8 | @end 9 | 10 | @implementation ViewController 11 | 12 | - (void)viewDidLoad { 13 | [super viewDidLoad]; 14 | i = [[CppInterface alloc]init]; 15 | } 16 | 17 | - (void)didReceiveMemoryWarning { 18 | [super didReceiveMemoryWarning]; 19 | // Dispose of any resources that can be recreated. 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /build-ios.sh: -------------------------------------------------------------------------------- 1 | cmake -DCMAKE_TOOLCHAIN_FILE=./ios.cmake -DIOS_PLATFORM=OS -H. -Bbuild.ios -GXcode 2 | cmake --build build.ios/ --config Release 3 | -------------------------------------------------------------------------------- /build-sim.sh: -------------------------------------------------------------------------------- 1 | cmake -DCMAKE_TOOLCHAIN_FILE=./ios.cmake -DIOS_PLATFORM=SIMULATOR -H. -Bbuild.sim -GXcode 2 | cmake --build build.sim/ --config Release 3 | -------------------------------------------------------------------------------- /build-sim64.sh: -------------------------------------------------------------------------------- 1 | cmake -DCMAKE_TOOLCHAIN_FILE=./ios.cmake -DIOS_PLATFORM=SIMULATOR64 -H. -Bbuild.sim64 -GXcode 2 | cmake --build build.sim64/ --config Release 3 | -------------------------------------------------------------------------------- /cppframework/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.7) 2 | 3 | set(LIBRARY_SOURCE 4 | ${CMAKE_CURRENT_LIST_DIR}/Foo.hh 5 | ${CMAKE_CURRENT_LIST_DIR}/Foo.cpp 6 | ) 7 | 8 | add_library( 9 | ${FRAMEWORK_NAME} SHARED 10 | ${LIBRARY_SOURCE} 11 | ) 12 | 13 | set(CMAKE_SHARED_LINKER_FLAGS "-Wall") 14 | 15 | set_target_properties(${FRAMEWORK_NAME} PROPERTIES 16 | FRAMEWORK TRUE 17 | FRAMEWORK_VERSION A 18 | MACOSX_FRAMEWORK_IDENTIFIER ${FRAMEWORK_BUNDLE_IDENTIFIER} 19 | MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_CURRENT_LIST_DIR}/framework.plist.in 20 | # "current version" in semantic format in Mach-O binary file 21 | VERSION 1.0.0 22 | # "compatibility version" in semantic format in Mach-O binary file 23 | SOVERSION 1.0.0 24 | PUBLIC_HEADER "${CMAKE_CURRENT_LIST_DIR}/Foo.hh" 25 | XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} 26 | XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${CODE_SIGN_IDENTITY} 27 | XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM_ID} 28 | XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY ${DEVICE_FAMILY} 29 | XCODE_ATTRIBUTE_SKIP_INSTALL "YES" 30 | ) 31 | 32 | # Symbol visibility setup, COMPILE_FLAGS only affect C++ so for Objective C we 33 | # have to use XCODE_ATTRIBUTE_OTHER_CFLAGS. 34 | set_target_properties(${FRAMEWORK_NAME} PROPERTIES 35 | COMPILE_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden" 36 | XCODE_ATTRIBUTE_OTHER_CFLAGS "-fvisibility=hidden -fvisibility-inlines-hidden") 37 | 38 | # set_target_properties(${FRAMEWORK_NAME} PROPERTIES COMPILE_FLAGS "-x c++") 39 | 40 | add_custom_command( 41 | TARGET ${FRAMEWORK_NAME} 42 | POST_BUILD 43 | COMMAND /bin/bash -c "${CMAKE_CURRENT_LIST_DIR}/install_name.sh \${BUILT_PRODUCTS_DIR}/\${PRODUCT_NAME}.framework/\${PRODUCT_NAME}" 44 | ) 45 | 46 | add_custom_command( 47 | TARGET ${FRAMEWORK_NAME} 48 | POST_BUILD 49 | COMMAND install_name_tool -id \"@rpath/\${PRODUCT_NAME}.framework/\${PRODUCT_NAME}\" 50 | \${BUILT_PRODUCTS_DIR}/\${PRODUCT_NAME}.framework/\${PRODUCT_NAME} 51 | ) 52 | 53 | -------------------------------------------------------------------------------- /cppframework/Foo.cpp: -------------------------------------------------------------------------------- 1 | #include "Foo.hh" 2 | #include 3 | #include 4 | 5 | #define EXPORT __attribute__((visibility("default"))) 6 | 7 | EXPORT 8 | int Foo::PrintFoo() 9 | { 10 | #if __cplusplus 11 | std::cout << "C++ environment detected." << std::endl; 12 | #endif 13 | std::cout << "Foo::PrintFoo() called." << std::endl; 14 | return 1; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /cppframework/Foo.hh: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Foo 5 | { 6 | public: 7 | int PrintFoo(); 8 | std::string foo; 9 | Foo() {std::cout << "Foo Created." << std::endl;} 10 | ~Foo() {std::cout << "Foo Destroyed." << std::endl;} 11 | private: 12 | }; 13 | 14 | 15 | -------------------------------------------------------------------------------- /cppframework/framework.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${MACOSX_FRAMEWORK_NAME} 9 | CFBundleIconFile 10 | ${MACOSX_FRAMEWORK_ICON_FILE} 11 | CFBundleIdentifier 12 | ${MACOSX_FRAMEWORK_IDENTIFIER} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | ${MACOSX_FRAMEWORK_BUNDLE_VERSION} 21 | CFBundleShortVersionString 22 | ${MACOSX_FRAMEWORK_SHORT_VERSION_STRING} 23 | CSResourcesFileMapped 24 | 25 | 26 | -------------------------------------------------------------------------------- /cppframework/install_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo $1 3 | if ! otool -l $1 | grep LC_RPATH; 4 | then 5 | install_name_tool -add_rpath "@executable_path/Frameworks;@loader_path/Frameworks" $1; 6 | else 7 | echo 'Otool Operation Skipped'; 8 | fi; 9 | -------------------------------------------------------------------------------- /generate-project.sh: -------------------------------------------------------------------------------- 1 | cmake -DCMAKE_TOOLCHAIN_FILE=./ios.cmake -DIOS_PLATFORM=OS -H. -BXcode -GXcode 2 | -------------------------------------------------------------------------------- /ios.cmake: -------------------------------------------------------------------------------- 1 | set (CMAKE_SYSTEM_NAME Darwin) 2 | set (CMAKE_SYSTEM_VERSION 1) 3 | set (UNIX True) 4 | set (APPLE True) 5 | set (IOS True) 6 | 7 | # Required as of cmake 2.8.10 8 | set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE) 9 | 10 | # Determine the cmake host system version so we know where to find the iOS SDKs 11 | find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin) 12 | if (CMAKE_UNAME) 13 | exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) 14 | string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}") 15 | endif (CMAKE_UNAME) 16 | 17 | # Force the compilers to Clang for iOS 18 | include (CMakeForceCompiler) 19 | set(CMAKE_C_COMPILER /usr/bin/clang Clang) 20 | set(CMAKE_CXX_COMPILER /usr/bin/clang++ Clang) 21 | set(CMAKE_AR ar CACHE FILEPATH "" FORCE) 22 | 23 | # Skip the platform compiler checks for cross compiling 24 | set (CMAKE_CXX_COMPILER_WORKS TRUE) 25 | set (CMAKE_C_COMPILER_WORKS TRUE) 26 | 27 | # All iOS/Darwin specific settings - some may be redundant 28 | set (CMAKE_SHARED_LIBRARY_PREFIX "lib") 29 | set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") 30 | set (CMAKE_SHARED_MODULE_PREFIX "lib") 31 | set (CMAKE_SHARED_MODULE_SUFFIX ".so") 32 | set (CMAKE_MODULE_EXISTS 1) 33 | set (CMAKE_DL_LIBS "") 34 | 35 | set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") 36 | set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") 37 | set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") 38 | set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") 39 | 40 | set (CMAKE_C_FLAGS_INIT "") 41 | set (CMAKE_CXX_FLAGS_INIT "") 42 | 43 | set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") 44 | set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") 45 | 46 | set (CMAKE_PLATFORM_HAS_INSTALLNAME 1) 47 | set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names") 48 | set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names") 49 | set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") 50 | set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") 51 | set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a") 52 | 53 | # hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree 54 | # (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache 55 | # and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun) 56 | # hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex 57 | if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL) 58 | find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool) 59 | endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL) 60 | 61 | # Setup iOS platform unless specified manually with IOS_PLATFORM 62 | if (NOT DEFINED IOS_PLATFORM) 63 | set (IOS_PLATFORM "OS") 64 | endif (NOT DEFINED IOS_PLATFORM) 65 | set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform") 66 | 67 | # Setup building for arm64 or not 68 | if (NOT DEFINED BUILD_ARM64) 69 | set (BUILD_ARM64 true) 70 | endif (NOT DEFINED BUILD_ARM64) 71 | set (BUILD_ARM64 ${BUILD_ARM64} CACHE STRING "Build arm64 arch or not") 72 | 73 | # Check the platform selection and setup for developer root 74 | if (IOS_PLATFORM STREQUAL "OS") 75 | set (IOS_PLATFORM_LOCATION "iPhoneOS.platform") 76 | 77 | # This causes the installers to properly locate the output libraries 78 | set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") 79 | elseif (IOS_PLATFORM STREQUAL "SIMULATOR") 80 | set (SIMULATOR true) 81 | set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") 82 | 83 | # This causes the installers to properly locate the output libraries 84 | set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") 85 | elseif (IOS_PLATFORM STREQUAL "SIMULATOR64") 86 | set (SIMULATOR true) 87 | set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") 88 | 89 | # This causes the installers to properly locate the output libraries 90 | set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") 91 | else () 92 | message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR") 93 | endif () 94 | 95 | # Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT 96 | # Note Xcode 4.3 changed the installation location, choose the most recent one available 97 | set (XCODE_POST_43_ROOT "/Applications/Xcode.app/Contents/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer") 98 | set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer") 99 | if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) 100 | if (EXISTS ${XCODE_POST_43_ROOT}) 101 | set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT}) 102 | elseif(EXISTS ${XCODE_PRE_43_ROOT}) 103 | set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT}) 104 | endif (EXISTS ${XCODE_POST_43_ROOT}) 105 | endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) 106 | set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform") 107 | 108 | # Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT 109 | if (NOT DEFINED CMAKE_IOS_SDK_ROOT) 110 | file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*") 111 | if (_CMAKE_IOS_SDKS) 112 | list (SORT _CMAKE_IOS_SDKS) 113 | list (REVERSE _CMAKE_IOS_SDKS) 114 | list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT) 115 | else (_CMAKE_IOS_SDKS) 116 | message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.") 117 | endif (_CMAKE_IOS_SDKS) 118 | message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}") 119 | endif (NOT DEFINED CMAKE_IOS_SDK_ROOT) 120 | set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK") 121 | 122 | # Set the sysroot default to the most recent SDK 123 | set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support") 124 | 125 | # set the architecture for iOS 126 | if (IOS_PLATFORM STREQUAL "OS") 127 | set (IOS_ARCH armv7 armv7s arm64) 128 | elseif (IOS_PLATFORM STREQUAL "SIMULATOR") 129 | set (IOS_ARCH i386) 130 | elseif (IOS_PLATFORM STREQUAL "SIMULATOR64") 131 | set (IOS_ARCH x86_64) 132 | endif () 133 | 134 | set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS") 135 | 136 | # Set the find root to the iOS developer roots and to user defined paths 137 | set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string "iOS find search path root") 138 | 139 | # default to searching for frameworks first 140 | set (CMAKE_FIND_FRAMEWORK FIRST) 141 | 142 | # set up the default search directories for frameworks 143 | set (CMAKE_SYSTEM_FRAMEWORK_PATH 144 | ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks 145 | ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks 146 | ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks 147 | ) 148 | 149 | # only search the iOS sdks, not the remainder of the host filesystem 150 | set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) 151 | set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 152 | set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 153 | 154 | 155 | # This little macro lets you set any XCode specific property 156 | macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE) 157 | set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE}) 158 | endmacro (set_xcode_property) 159 | 160 | 161 | # This macro lets you find executable programs on the host system 162 | macro (find_host_package) 163 | set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 164 | set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) 165 | set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) 166 | set (IOS FALSE) 167 | 168 | find_package(${ARGN}) 169 | 170 | set (IOS TRUE) 171 | set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) 172 | set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 173 | set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 174 | endmacro (find_host_package) 175 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // UIApplicationMain() 2 | 3 | #import 4 | #import "AppDelegate.h" 5 | 6 | int main(int argc, char * argv[]) 7 | { 8 | @autoreleasepool { 9 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 10 | } 11 | } -------------------------------------------------------------------------------- /plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleGetInfoString 12 | ${MACOSX_BUNDLE_INFO_STRING} 13 | CFBundleIconFile 14 | ${MACOSX_BUNDLE_ICON_FILE} 15 | CFBundleIdentifier 16 | ${MACOSX_BUNDLE_GUI_IDENTIFIER} 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleLongVersionString 20 | ${MACOSX_BUNDLE_LONG_VERSION_STRING} 21 | CFBundleName 22 | ${MACOSX_BUNDLE_BUNDLE_NAME} 23 | CFBundlePackageType 24 | APPL 25 | CFBundleShortVersionString 26 | ${MACOSX_BUNDLE_SHORT_VERSION_STRING} 27 | CFBundleSignature 28 | ???? 29 | CFBundleVersion 30 | ${MACOSX_BUNDLE_BUNDLE_VERSION} 31 | CSResourcesFileMapped 32 | 33 | NSHumanReadableCopyright 34 | ${MACOSX_BUNDLE_COPYRIGHT} 35 | LSMinimumSystemVersion 36 | ${MACOSX_DEPLOYMENT_TARGET} 37 | LSRequiresIPhoneOS 38 | 39 | UILaunchStoryboardName 40 | LaunchScreen 41 | UIMainStoryboardFile 42 | Main 43 | UIBackgroundModes 44 | 45 | fetch 46 | remote-notification 47 | 48 | UIRequiredDeviceCapabilities 49 | 50 | armv7 51 | 52 | UISupportedInterfaceOrientations 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationLandscapeLeft 56 | UIInterfaceOrientationLandscapeRight 57 | 58 | NSAppTransportSecurity 59 | 60 | NSAllowsArbitraryLoads 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.7) 2 | 3 | set(TEST_SOURCE 4 | ${CMAKE_CURRENT_LIST_DIR}/Tests.m 5 | ) 6 | 7 | xctest_add_bundle(${TEST_NAME} 8 | ${APP_NAME} 9 | ${TEST_SOURCE} 10 | ) 11 | 12 | if(NOT LOGIC_ONLY_TESTS) 13 | target_include_directories(${TEST_NAME} PUBLIC 14 | "${CMAKE_SOURCE_DIR}" 15 | ) 16 | endif(NOT LOGIC_ONLY_TESTS) 17 | 18 | xctest_add_test(${TEST_BUNDLE_IDENTIFIER} 19 | ${TEST_NAME} 20 | ) 21 | 22 | set(CMAKE_SHARED_LINKER_FLAGS "-Wall") 23 | 24 | set_target_properties(${TEST_NAME} PROPERTIES 25 | MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_LIST_DIR}/tests.plist.in 26 | XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} 27 | XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ${CODE_SIGN_IDENTITY} 28 | XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM_ID} 29 | XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY ${DEVICE_FAMILY} 30 | XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "\$(inherited)" 31 | ) 32 | 33 | if(LOGIC_ONLY_TESTS) 34 | set_target_properties(${TEST_NAME} PROPERTIES 35 | XCODE_ATTRIBUTE_TEST_HOST "" 36 | ) 37 | endif(LOGIC_ONLY_TESTS) 38 | 39 | # This is needed to erase invalid framework search paths set by FindXCTest. 40 | # The drawback is that you can not use target_include_directories for setting up 41 | # search paths for this target. You have to use 42 | # XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS. As long as you stick to running 43 | # tests on code compiled into the host app this is not a hindrance. 44 | set_target_properties(${TEST_NAME} PROPERTIES 45 | XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "\$(inherited) " 46 | ) 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /tests/Tests.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "CppInterface.h" 4 | 5 | @interface Tests : XCTestCase 6 | @end 7 | 8 | @implementation Tests 9 | 10 | - (void)setUp { 11 | [super setUp]; 12 | } 13 | 14 | - (void)tearDown { 15 | [super tearDown]; 16 | } 17 | 18 | - (void)testExample { 19 | CppInterface* i = [[CppInterface alloc] init]; 20 | XCTAssert(i); 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /tests/tests.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | --------------------------------------------------------------------------------