From c2cd9335e9c9ff599cd84723eada6a503d1e5c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 7 Mar 2016 14:55:44 -0800 Subject: [PATCH] [ios] Non-embedded static framework Added a new ifabric Make target for packaging up a static framework similar to the one released as 3.0.1. Place artwork and certificate assets inside Mapbox.bundle inside Mapbox.framework. Link SystemConfiguration in the umbrella header. Distinguish between the framework bundle and the resources bundle. For the dynamic frameworks and embedded static frameworks, the two are the same; for the non-embedded static framework, the latter resides inside the former. --- Makefile | 1 + platform/ios/framework/Mapbox-static.h | 2 ++ platform/ios/scripts/package.sh | 42 ++++++++++++++++-------- platform/ios/src/MGLAPIClient.m | 8 ++--- platform/ios/src/MGLAccountManager.m | 4 +-- platform/ios/src/MGLMapView.mm | 3 +- platform/ios/src/MGLMapboxEvents.m | 2 -- platform/ios/src/NSBundle+MGLAdditions.h | 9 +++++ platform/ios/src/NSBundle+MGLAdditions.m | 25 ++++++++++++-- platform/osx/src/MGLMapView.mm | 2 +- 10 files changed, 72 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index 6e8eda437..fbda9b631 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,7 @@ ipackage: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DE ipackage-strip: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=NO ./platform/ios/scripts/package.sh ipackage-sim: Xcode/ios ; @JOBS=$(JOBS) BUILDTYPE=Debug BITCODE=$(BITCODE) FORMAT=dynamic BUILD_DEVICE=false SYMBOLS=$(SYMBOLS) ./platform/ios/scripts/package.sh iframework: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=dynamic BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=$(SYMBOLS) ./platform/ios/scripts/package.sh +ifabric: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=NO BUNDLE_RESOURCES=YES ./platform/ios/scripts/package.sh itest: ipackage-sim ; ./platform/ios/scripts/test.sh idocument: ; OUTPUT=$(OUTPUT) ./platform/ios/scripts/document.sh diff --git a/platform/ios/framework/Mapbox-static.h b/platform/ios/framework/Mapbox-static.h index d3674b0b6..864a3fd5b 100644 --- a/platform/ios/framework/Mapbox-static.h +++ b/platform/ios/framework/Mapbox-static.h @@ -1,3 +1,5 @@ #import #import #import +#import +#import diff --git a/platform/ios/scripts/package.sh b/platform/ios/scripts/package.sh index cb1cafa88..5d84ba5e2 100755 --- a/platform/ios/scripts/package.sh +++ b/platform/ios/scripts/package.sh @@ -21,13 +21,19 @@ elif [[ ${FORMAT} == "dynamic" ]]; then BUILD_STATIC=false fi +BUNDLE_RESOURCES=${BUNDLE_RESOURCES:-} +BUNDLE_PATH= +if [[ ${BUNDLE_RESOURCES} ]]; then + BUNDLE_PATH="/${NAME}.bundle" +fi + SDK=iphonesimulator if [[ ${BUILD_FOR_DEVICE} == true ]]; then SDK=iphoneos fi IOS_SDK_VERSION=`xcrun --sdk ${SDK} --show-sdk-version` -echo "Configuring ${FORMAT:-dynamic and static} ${BUILDTYPE} framework for ${SDK}; symbols: ${GCC_GENERATE_DEBUGGING_SYMBOLS}; Bitcode: ${ENABLE_BITCODE}" +echo "Configuring ${FORMAT:-dynamic and static} ${BUILDTYPE} framework for ${SDK}; symbols: ${GCC_GENERATE_DEBUGGING_SYMBOLS}; Bitcode: ${ENABLE_BITCODE}; Mapbox.bundle: ${BUNDLE_RESOURCES}" function step { >&2 echo -e "\033[1m\033[36m* $@\033[0m"; } function finish { >&2 echo -en "\033[0m"; } @@ -188,25 +194,35 @@ if [[ ${BUILD_STATIC} == true ]]; then step "Copying static library headers…" mkdir -p "${OUTPUT}/static/${NAME}.framework/Headers" cp -pv platform/{darwin,ios}/include/*.h "${OUTPUT}/static/${NAME}.framework/Headers" - cat ios/framework/Mapbox-static.h > "${OUTPUT}/static/${NAME}.framework/Headers/Mapbox.h" + cat platform/ios/framework/Mapbox-static.h > "${OUTPUT}/static/${NAME}.framework/Headers/Mapbox.h" cat platform/ios/framework/Mapbox.h >> "${OUTPUT}/static/${NAME}.framework/Headers/Mapbox.h" fi step "Copying library resources…" SEM_VERSION=$( git describe --tags --match=ios-v*.*.* --abbrev=0 | sed 's/^ios-v//' ) SHORT_VERSION=${SEM_VERSION%-*} -cp -pv LICENSE.md "${OUTPUT}" -cp -rv platform/ios/app/Settings.bundle "${OUTPUT}" +if [[ ${BUNDLE_RESOURCES} ]]; then + cp -pv LICENSE.md "${OUTPUT}/static/${NAME}.framework" + cp -rv platform/ios/app/Settings.bundle "${OUTPUT}/static/${NAME}.framework" +else + cp -pv LICENSE.md "${OUTPUT}" + cp -rv platform/ios/app/Settings.bundle "${OUTPUT}" +fi if [[ ${BUILD_STATIC} == true ]]; then - cp -pv platform/ios/resources/* "${OUTPUT}/static/${NAME}.framework" - cp -pv platform/ios/framework/Info.plist "${OUTPUT}/static/${NAME}.framework/Info.plist" - plutil -replace CFBundleExecutable -string ${NAME} "${OUTPUT}/static/${NAME}.framework/Info.plist" - plutil -replace CFBundleIdentifier -string com.mapbox.sdk.ios "${OUTPUT}/static/${NAME}.framework/Info.plist" - plutil -replace CFBundleName -string ${NAME} "${OUTPUT}/static/${NAME}.framework/Info.plist" - plutil -replace CFBundleShortVersionString -string "${SHORT_VERSION}" "${OUTPUT}/static/${NAME}.framework/Info.plist" - plutil -replace CFBundleVersion -string ${PROJ_VERSION} "${OUTPUT}/static/${NAME}.framework/Info.plist" - plutil -replace MGLSemanticVersionString -string "${SEM_VERSION}" "${OUTPUT}/static/${NAME}.framework/Info.plist" - plutil -replace MGLCommitHash -string "${HASH}" "${OUTPUT}/static/${NAME}.framework/Info.plist" + mkdir -p "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" + cp -pv platform/ios/resources/* "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" + INFO_PLIST_PATH="${OUTPUT}/static/${NAME}.framework/Info.plist" + cp -pv platform/ios/framework/Info.plist "${INFO_PLIST_PATH}" + plutil -replace CFBundleExecutable -string ${NAME} "${INFO_PLIST_PATH}" + plutil -replace CFBundleIdentifier -string com.mapbox.sdk.ios "${INFO_PLIST_PATH}" + plutil -replace CFBundleName -string ${NAME} "${INFO_PLIST_PATH}" + plutil -replace CFBundleShortVersionString -string "${SHORT_VERSION}" "${INFO_PLIST_PATH}" + plutil -replace CFBundleVersion -string ${PROJ_VERSION} "${INFO_PLIST_PATH}" + plutil -replace MGLSemanticVersionString -string "${SEM_VERSION}" "${INFO_PLIST_PATH}" + plutil -replace MGLCommitHash -string "${HASH}" "${INFO_PLIST_PATH}" + if [[ ${BUNDLE_RESOURCES} ]]; then + cp -pv "${INFO_PLIST_PATH}" "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}/Info.plist" + fi mkdir "${OUTPUT}/static/${NAME}.framework/Modules" cp -pv platform/ios/framework/modulemap "${OUTPUT}/static/${NAME}.framework/Modules/module.modulemap" fi diff --git a/platform/ios/src/MGLAPIClient.m b/platform/ios/src/MGLAPIClient.m index 441c7c16f..7a72496ac 100644 --- a/platform/ios/src/MGLAPIClient.m +++ b/platform/ios/src/MGLAPIClient.m @@ -107,8 +107,8 @@ static NSString * const MGLAPIClientHTTPMethodPost = @"POST"; } - (void)loadCertificate:(NSData **)certificate withResource:(NSString *)resource { - NSBundle *resourceBundle = [NSBundle mgl_frameworkBundle]; - NSString *cerPath = [resourceBundle pathForResource:resource ofType:@"der"]; + NSBundle *frameworkBundle = [NSBundle mgl_frameworkBundle]; + NSString *cerPath = [frameworkBundle pathForResource:resource ofType:@"der" inDirectory:frameworkBundle.mgl_resourcesDirectory]; if (cerPath != nil) { *certificate = [NSData dataWithContentsOfFile:cerPath]; } @@ -118,8 +118,8 @@ static NSString * const MGLAPIClientHTTPMethodPost = @"POST"; NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; NSString *appBuildNumber = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; - NSString *semanticVersion = [NSBundle mgl_frameworkBundle].infoDictionary[@"MGLSemanticVersionString"]; - NSString *shortVersion = [NSBundle mgl_frameworkBundle].infoDictionary[@"CFBundleShortVersionString"]; + NSString *semanticVersion = [NSBundle mgl_frameworkInfoDictionary][@"MGLSemanticVersionString"]; + NSString *shortVersion = [NSBundle mgl_frameworkInfoDictionary][@"CFBundleShortVersionString"]; NSString *sdkVersion = semanticVersion ? semanticVersion : shortVersion; _userAgent = [NSString stringWithFormat:@"%@/%@/%@ %@/%@", appName, appVersion, appBuildNumber, MGLAPIClientUserAgentBase, sdkVersion]; } diff --git a/platform/ios/src/MGLAccountManager.m b/platform/ios/src/MGLAccountManager.m index 6b98d5286..d50f0f86d 100644 --- a/platform/ios/src/MGLAccountManager.m +++ b/platform/ios/src/MGLAccountManager.m @@ -73,11 +73,11 @@ #pragma mark - Fabric + (NSString *)bundleIdentifier { - return [NSBundle mgl_frameworkBundle].bundleIdentifier; + return [NSBundle mgl_frameworkBundleIdentifier]; } + (NSString *)kitDisplayVersion { - return [NSBundle mgl_frameworkBundle].infoDictionary[@"CFBundleShortVersionString"]; + return [NSBundle mgl_frameworkInfoDictionary][@"CFBundleShortVersionString"]; } + (void)initializeIfNeeded { diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 158228ca2..21d15ed1d 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -3828,7 +3828,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) NSString *extension = imageName.pathExtension.length ? imageName.pathExtension : @"png"; NSBundle *bundle = [NSBundle mgl_frameworkBundle]; NSString *path = [bundle pathForResource:imageName.stringByDeletingPathExtension - ofType:extension]; + ofType:extension + inDirectory:bundle.mgl_resourcesDirectory]; if ( ! path) { [NSException raise:@"Resource not found" format: diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m index 35f6327fc..f5628bc6f 100644 --- a/platform/ios/src/MGLMapboxEvents.m +++ b/platform/ios/src/MGLMapboxEvents.m @@ -3,7 +3,6 @@ #import #import "MGLAccountManager.h" #import "NSProcessInfo+MGLAdditions.h" -#import "NSBundle+MGLAdditions.h" #import "NSException+MGLAdditions.h" #import "MGLAPIClient.h" #import "MGLLocationManager.h" @@ -167,7 +166,6 @@ const NSTimeInterval MGLFlushInterval = 180; _locationManager.delegate = self; _paused = YES; [self resumeMetricsCollection]; - NSBundle *resourceBundle = [NSBundle mgl_frameworkBundle]; // Events Control _eventQueue = [[NSMutableArray alloc] init]; diff --git a/platform/ios/src/NSBundle+MGLAdditions.h b/platform/ios/src/NSBundle+MGLAdditions.h index 6d6ebc35a..52ef7fbfa 100644 --- a/platform/ios/src/NSBundle+MGLAdditions.h +++ b/platform/ios/src/NSBundle+MGLAdditions.h @@ -8,8 +8,17 @@ void mgl_linkBundleCategory(); @interface NSBundle (MGLAdditions) +/// Returns the bundle containing the SDK’s classes and Info.plist file. + (instancetype)mgl_frameworkBundle; ++ (nullable NSString *)mgl_frameworkBundleIdentifier; + ++ (nullable NS_DICTIONARY_OF(NSString *, id) *)mgl_frameworkInfoDictionary; + +/// The relative path to the directory containing the SDK’s resource files, or +/// `nil` if the files are located directly within the bundle’s root directory. +@property (readonly, copy, nullable) NSString *mgl_resourcesDirectory; + @end NS_ASSUME_NONNULL_END diff --git a/platform/ios/src/NSBundle+MGLAdditions.m b/platform/ios/src/NSBundle+MGLAdditions.m index 868b4ff8e..e1f3e7c72 100644 --- a/platform/ios/src/NSBundle+MGLAdditions.m +++ b/platform/ios/src/NSBundle+MGLAdditions.m @@ -6,10 +6,9 @@ void mgl_linkBundleCategory() {} @implementation NSBundle (MGLAdditions) -+ (instancetype)mgl_frameworkBundle -{ ++ (instancetype)mgl_frameworkBundle { NSBundle *bundle = [self bundleForClass:[MGLAccountManager class]]; - if (![bundle.infoDictionary[@"CFBundlePackageType"] isEqualToString:@"FMWK"]) { + if (![bundle.infoDictionary[@"CFBundlePackageType"] isEqualToString:@"FMWK"] && !bundle.mgl_resourcesDirectory) { // For static frameworks, the bundle is the containing application // bundle but the resources are still in the framework bundle. bundle = [NSBundle bundleWithPath:[bundle.privateFrameworksPath @@ -18,4 +17,24 @@ void mgl_linkBundleCategory() {} return bundle; } ++ (nullable NSString *)mgl_frameworkBundleIdentifier { + return self.mgl_frameworkInfoDictionary[@"CFBundleIdentifier"]; +} + ++ (nullable NS_DICTIONARY_OF(NSString *, id) *)mgl_frameworkInfoDictionary { + NSBundle *bundle = self.mgl_frameworkBundle; + if (bundle.mgl_resourcesDirectory) { + NSString *infoPlistPath = [bundle pathForResource:@"Info" + ofType:@"plist" + inDirectory:bundle.mgl_resourcesDirectory]; + return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath]; + } else { + return bundle.infoDictionary; + } +} + +- (NSString *)mgl_resourcesDirectory { + return [self pathForResource:@"Mapbox" ofType:@"bundle"] ? @"Mapbox.bundle" : nil; +} + @end diff --git a/platform/osx/src/MGLMapView.mm b/platform/osx/src/MGLMapView.mm index 9c903484e..67729c260 100644 --- a/platform/osx/src/MGLMapView.mm +++ b/platform/osx/src/MGLMapView.mm @@ -92,7 +92,7 @@ typedef std::map MGLAnnotationContextMap /// Returns an NSImage for the default marker image. NSImage *MGLDefaultMarkerImage() { NSString *path = [[NSBundle mgl_frameworkBundle] pathForResource:MGLDefaultStyleMarkerSymbolName - ofType:@"pdf"]; + ofType:@"pdf"]; return [[NSImage alloc] initWithContentsOfFile:path]; }