diff --git a/.gitignore b/.gitignore index 2a75873a5c..cc3ca2d398 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,8 @@ /dev/docs/flutter.docs.zip /dev/docs/lib/ /dev/docs/pubspec.yaml +/dev/integration_tests/**/xcuserdata +/dev/integration_tests/**/Pods /packages/flutter/coverage/ version diff --git a/dev/devicelab/bin/tasks/module_test_ios.dart b/dev/devicelab/bin/tasks/module_test_ios.dart index 905e7365fc..081e98f400 100644 --- a/dev/devicelab/bin/tasks/module_test_ios.dart +++ b/dev/devicelab/bin/tasks/module_test_ios.dart @@ -156,7 +156,7 @@ Future main() async { String content = await pubspec.readAsString(); content = content.replaceFirst( '\ndependencies:\n', - '\ndependencies:\n device_info:\n package_info:\n', + '\ndependencies:\n device_info:\n google_maps_flutter:\n', // One dynamic and one static framework. ); await pubspec.writeAsString(content, flush: true); await inDirectory(projectDir, () async { @@ -192,7 +192,7 @@ Future main() async { if (!podfileLockOutput.contains(':path: Flutter/engine') || !podfileLockOutput.contains(':path: Flutter/FlutterPluginRegistrant') || !podfileLockOutput.contains(':path: Flutter/.symlinks/device_info/ios') - || !podfileLockOutput.contains(':path: Flutter/.symlinks/package_info/ios')) { + || !podfileLockOutput.contains(':path: Flutter/.symlinks/google_maps_flutter/ios')) { return TaskResult.failure('Building ephemeral host app Podfile.lock does not contain expected pods'); } @@ -232,18 +232,18 @@ Future main() async { return TaskResult.failure('Failed to build editable host .app'); } - section('Add to existing iOS app'); + section('Add to existing iOS Objective-C app'); - final Directory hostApp = Directory(path.join(tempDir.path, 'hello_host_app')); - mkdir(hostApp); + final Directory objectiveCHostApp = Directory(path.join(tempDir.path, 'hello_host_app')); + mkdir(objectiveCHostApp); recursiveCopy( Directory(path.join(flutterDirectory.path, 'dev', 'integration_tests', 'ios_host_app')), - hostApp, + objectiveCHostApp, ); - final File analyticsOutputFile = File(path.join(tempDir.path, 'analytics.log')); - - await inDirectory(hostApp, () async { + final File objectiveCAnalyticsOutputFile = File(path.join(tempDir.path, 'analytics-objc.log')); + final Directory objectiveCBuildDirectory = Directory(path.join(tempDir.path, 'build-objc')); + await inDirectory(objectiveCHostApp, () async { await exec('pod', ['install']); await exec( 'xcodebuild', @@ -258,37 +258,37 @@ Future main() async { 'CODE_SIGNING_REQUIRED=NO', 'CODE_SIGN_IDENTITY=-', 'EXPANDED_CODE_SIGN_IDENTITY=-', - 'CONFIGURATION_BUILD_DIR=${tempDir.path}', + 'CONFIGURATION_BUILD_DIR=${objectiveCBuildDirectory.path}', 'COMPILER_INDEX_STORE_ENABLE=NO', ], environment: { - 'FLUTTER_ANALYTICS_LOG_FILE': analyticsOutputFile.path, + 'FLUTTER_ANALYTICS_LOG_FILE': objectiveCAnalyticsOutputFile.path, } ); }); final bool existingAppBuilt = exists(File(path.join( - tempDir.path, + objectiveCBuildDirectory.path, 'Host.app', 'Host', ))); if (!existingAppBuilt) { - return TaskResult.failure('Failed to build existing app .app'); + return TaskResult.failure('Failed to build existing Objective-C app .app'); } - final String analyticsOutput = analyticsOutputFile.readAsStringSync(); - if (!analyticsOutput.contains('cd24: ios') - || !analyticsOutput.contains('cd25: true') - || !analyticsOutput.contains('viewName: build/bundle')) { + final String objectiveCAnalyticsOutput = objectiveCAnalyticsOutputFile.readAsStringSync(); + if (!objectiveCAnalyticsOutput.contains('cd24: ios') + || !objectiveCAnalyticsOutput.contains('cd25: true') + || !objectiveCAnalyticsOutput.contains('viewName: build/bundle')) { return TaskResult.failure( - 'Building outer app produced the following analytics: "$analyticsOutput"' + 'Building outer Objective-C app produced the following analytics: "$objectiveCAnalyticsOutput"' 'but not the expected strings: "cd24: ios", "cd25: true", "viewName: build/bundle"' ); } - section('Fail building existing iOS app if flutter script fails'); + section('Fail building existing Objective-C iOS app if flutter script fails'); int xcodebuildExitCode = 0; - await inDirectory(hostApp, () async { + await inDirectory(objectiveCHostApp, () async { xcodebuildExitCode = await exec( 'xcodebuild', [ @@ -303,7 +303,7 @@ Future main() async { 'CODE_SIGNING_REQUIRED=NO', 'CODE_SIGN_IDENTITY=-', 'EXPANDED_CODE_SIGN_IDENTITY=-', - 'CONFIGURATION_BUILD_DIR=${tempDir.path}', + 'CONFIGURATION_BUILD_DIR=${objectiveCBuildDirectory.path}', 'COMPILER_INDEX_STORE_ENABLE=NO', ], canFail: true @@ -311,7 +311,62 @@ Future main() async { }); if (xcodebuildExitCode != 65) { // 65 returned on PhaseScriptExecution failure. - return TaskResult.failure('Host app build succeeded though flutter script failed'); + return TaskResult.failure('Host Objective-C app build succeeded though flutter script failed'); + } + + section('Add to existing iOS Swift app'); + + final Directory swiftHostApp = Directory(path.join(tempDir.path, 'hello_host_app_swift')); + mkdir(swiftHostApp); + recursiveCopy( + Directory(path.join(flutterDirectory.path, 'dev', 'integration_tests', 'ios_host_app_swift')), + swiftHostApp, + ); + + final File swiftAnalyticsOutputFile = File(path.join(tempDir.path, 'analytics-swift.log')); + final Directory swiftBuildDirectory = Directory(path.join(tempDir.path, 'build-swift')); + + await inDirectory(swiftHostApp, () async { + await exec('pod', ['install']); + await exec( + 'xcodebuild', + [ + '-workspace', + 'Host.xcworkspace', + '-scheme', + 'Host', + '-configuration', + 'Debug', + 'CODE_SIGNING_ALLOWED=NO', + 'CODE_SIGNING_REQUIRED=NO', + 'CODE_SIGN_IDENTITY=-', + 'EXPANDED_CODE_SIGN_IDENTITY=-', + 'CONFIGURATION_BUILD_DIR=${swiftBuildDirectory.path}', + 'COMPILER_INDEX_STORE_ENABLE=NO', + ], + environment: { + 'FLUTTER_ANALYTICS_LOG_FILE': swiftAnalyticsOutputFile.path, + } + ); + }); + + final bool existingSwiftAppBuilt = exists(File(path.join( + swiftBuildDirectory.path, + 'Host.app', + 'Host', + ))); + if (!existingSwiftAppBuilt) { + return TaskResult.failure('Failed to build existing Swift app .app'); + } + + final String swiftAnalyticsOutput = swiftAnalyticsOutputFile.readAsStringSync(); + if (!swiftAnalyticsOutput.contains('cd24: ios') + || !swiftAnalyticsOutput.contains('cd25: true') + || !swiftAnalyticsOutput.contains('viewName: build/bundle')) { + return TaskResult.failure( + 'Building outer Swift app produced the following analytics: "$swiftAnalyticsOutput"' + 'but not the expected strings: "cd24: ios", "cd25: true", "viewName: build/bundle"' + ); } return TaskResult.success(null); diff --git a/dev/integration_tests/ios_host_app/Host/ViewController.m b/dev/integration_tests/ios_host_app/Host/ViewController.m index 3eb47c0aa2..8e7df10d95 100644 --- a/dev/integration_tests/ios_host_app/Host/ViewController.m +++ b/dev/integration_tests/ios_host_app/Host/ViewController.m @@ -4,6 +4,7 @@ @implementation ViewController +// Boiler-plate add-to-app demo. Not integration tested anywhere. - (void)viewDidLoad { [super viewDidLoad]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; diff --git a/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.pbxproj b/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..d6683d56fe --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.pbxproj @@ -0,0 +1,429 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 457A8C6F3BD01A7C28D507CD /* libPods-Host.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 56715A205CEC5CEFA6932FF2 /* libPods-Host.a */; }; + F724F2C22329B8CC0012DB29 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724F2C12329B8CC0012DB29 /* AppDelegate.swift */; }; + F724F2C42329B8CC0012DB29 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724F2C32329B8CC0012DB29 /* SceneDelegate.swift */; }; + F724F2C62329B8CC0012DB29 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724F2C52329B8CC0012DB29 /* ViewController.swift */; }; + F724F2C92329B8CC0012DB29 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F724F2C72329B8CC0012DB29 /* Main.storyboard */; }; + F724F2CB2329B8CD0012DB29 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F724F2CA2329B8CD0012DB29 /* Assets.xcassets */; }; + F724F2CE2329B8CD0012DB29 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F724F2CC2329B8CD0012DB29 /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 56715A205CEC5CEFA6932FF2 /* libPods-Host.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Host.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5EF266650049BC10ECFD8C86 /* Pods-Host.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Host.debug.xcconfig"; path = "Target Support Files/Pods-Host/Pods-Host.debug.xcconfig"; sourceTree = ""; }; + A412A4193ADC80C963762A82 /* Pods-Host.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Host.release.xcconfig"; path = "Target Support Files/Pods-Host/Pods-Host.release.xcconfig"; sourceTree = ""; }; + F724F2BE2329B8CC0012DB29 /* Host.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Host.app; sourceTree = BUILT_PRODUCTS_DIR; }; + F724F2C12329B8CC0012DB29 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + F724F2C32329B8CC0012DB29 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + F724F2C52329B8CC0012DB29 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + F724F2C82329B8CC0012DB29 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + F724F2CA2329B8CD0012DB29 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + F724F2CD2329B8CD0012DB29 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + F724F2CF2329B8CD0012DB29 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + F724F2BB2329B8CC0012DB29 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 457A8C6F3BD01A7C28D507CD /* libPods-Host.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A17ED70CE5479900A9A99BB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 56715A205CEC5CEFA6932FF2 /* libPods-Host.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 794F1975CCFC17A524ECE744 /* Pods */ = { + isa = PBXGroup; + children = ( + 5EF266650049BC10ECFD8C86 /* Pods-Host.debug.xcconfig */, + A412A4193ADC80C963762A82 /* Pods-Host.release.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + F724F2B52329B8CC0012DB29 = { + isa = PBXGroup; + children = ( + F724F2C02329B8CC0012DB29 /* Host */, + F724F2BF2329B8CC0012DB29 /* Products */, + 794F1975CCFC17A524ECE744 /* Pods */, + 4A17ED70CE5479900A9A99BB /* Frameworks */, + ); + sourceTree = ""; + }; + F724F2BF2329B8CC0012DB29 /* Products */ = { + isa = PBXGroup; + children = ( + F724F2BE2329B8CC0012DB29 /* Host.app */, + ); + name = Products; + sourceTree = ""; + }; + F724F2C02329B8CC0012DB29 /* Host */ = { + isa = PBXGroup; + children = ( + F724F2C12329B8CC0012DB29 /* AppDelegate.swift */, + F724F2C32329B8CC0012DB29 /* SceneDelegate.swift */, + F724F2C52329B8CC0012DB29 /* ViewController.swift */, + F724F2C72329B8CC0012DB29 /* Main.storyboard */, + F724F2CA2329B8CD0012DB29 /* Assets.xcassets */, + F724F2CC2329B8CD0012DB29 /* LaunchScreen.storyboard */, + F724F2CF2329B8CD0012DB29 /* Info.plist */, + ); + path = Host; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + F724F2BD2329B8CC0012DB29 /* Host */ = { + isa = PBXNativeTarget; + buildConfigurationList = F724F2D22329B8CD0012DB29 /* Build configuration list for PBXNativeTarget "Host" */; + buildPhases = ( + 057F850E20C20171224A8BD8 /* [CP] Check Pods Manifest.lock */, + EEED2F2AE8060ACBF2210C77 /* [CP-User] Run Flutter Build Script */, + F724F2BA2329B8CC0012DB29 /* Sources */, + F724F2BB2329B8CC0012DB29 /* Frameworks */, + F724F2BC2329B8CC0012DB29 /* Resources */, + D7D46336FAE5656C7ADAAD08 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Host; + productName = Host; + productReference = F724F2BE2329B8CC0012DB29 /* Host.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + F724F2B62329B8CC0012DB29 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + ORGANIZATIONNAME = flutter.io; + TargetAttributes = { + F724F2BD2329B8CC0012DB29 = { + CreatedOnToolsVersion = 11.0; + }; + }; + }; + buildConfigurationList = F724F2B92329B8CC0012DB29 /* Build configuration list for PBXProject "Host" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = F724F2B52329B8CC0012DB29; + productRefGroup = F724F2BF2329B8CC0012DB29 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + F724F2BD2329B8CC0012DB29 /* Host */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + F724F2BC2329B8CC0012DB29 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F724F2CE2329B8CD0012DB29 /* LaunchScreen.storyboard in Resources */, + F724F2CB2329B8CD0012DB29 /* Assets.xcassets in Resources */, + F724F2C92329B8CC0012DB29 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 057F850E20C20171224A8BD8 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Host-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + D7D46336FAE5656C7ADAAD08 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Host/Pods-Host-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Host/Pods-Host-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Host/Pods-Host-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + EEED2F2AE8060ACBF2210C77 /* [CP-User] Run Flutter Build Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Users/magder/Projects/hello/.metadata", + "${SRCROOT}/../../../../hello/.ios/Flutter/App.framework/App", + "${SRCROOT}/../../../../hello/.ios/Flutter/engine/Flutter.framework/Flutter", + "${SRCROOT}/../../../../hello/.ios/Flutter/flutter_export_environment.sh", + ); + name = "[CP-User] Run Flutter Build Script"; + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\nset -u\nsource \"${SRCROOT}/../../../../hello/.ios/Flutter/flutter_export_environment.sh\"\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + F724F2BA2329B8CC0012DB29 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F724F2C62329B8CC0012DB29 /* ViewController.swift in Sources */, + F724F2C22329B8CC0012DB29 /* AppDelegate.swift in Sources */, + F724F2C42329B8CC0012DB29 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + F724F2C72329B8CC0012DB29 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + F724F2C82329B8CC0012DB29 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + F724F2CC2329B8CD0012DB29 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + F724F2CD2329B8CD0012DB29 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + F724F2D02329B8CD0012DB29 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + F724F2D12329B8CD0012DB29 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + F724F2D32329B8CD0012DB29 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5EF266650049BC10ECFD8C86 /* Pods-Host.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = Host/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.add2app.Host; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + F724F2D42329B8CD0012DB29 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A412A4193ADC80C963762A82 /* Pods-Host.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = Host/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.add2app.Host; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + F724F2B92329B8CC0012DB29 /* Build configuration list for PBXProject "Host" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F724F2D02329B8CD0012DB29 /* Debug */, + F724F2D12329B8CD0012DB29 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F724F2D22329B8CD0012DB29 /* Build configuration list for PBXNativeTarget "Host" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F724F2D32329B8CD0012DB29 /* Debug */, + F724F2D42329B8CD0012DB29 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = F724F2B62329B8CC0012DB29 /* Project object */; +} diff --git a/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..8ee5ee9ff6 --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/dev/integration_tests/ios_host_app_swift/Host/AppDelegate.swift b/dev/integration_tests/ios_host_app_swift/Host/AppDelegate.swift new file mode 100644 index 0000000000..9cc8e7704a --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host/AppDelegate.swift @@ -0,0 +1,8 @@ +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } +} diff --git a/dev/integration_tests/ios_host_app_swift/Host/Assets.xcassets/AppIcon.appiconset/Contents.json b/dev/integration_tests/ios_host_app_swift/Host/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..d8db8d65fd --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/dev/integration_tests/ios_host_app_swift/Host/Assets.xcassets/Contents.json b/dev/integration_tests/ios_host_app_swift/Host/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/dev/integration_tests/ios_host_app_swift/Host/Base.lproj/LaunchScreen.storyboard b/dev/integration_tests/ios_host_app_swift/Host/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000000..865e9329f3 --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/integration_tests/ios_host_app_swift/Host/Base.lproj/Main.storyboard b/dev/integration_tests/ios_host_app_swift/Host/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..25a763858e --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/integration_tests/ios_host_app_swift/Host/Info.plist b/dev/integration_tests/ios_host_app_swift/Host/Info.plist new file mode 100644 index 0000000000..2a3483c0d2 --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/dev/integration_tests/ios_host_app_swift/Host/SceneDelegate.swift b/dev/integration_tests/ios_host_app_swift/Host/SceneDelegate.swift new file mode 100644 index 0000000000..b3ca0936a9 --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host/SceneDelegate.swift @@ -0,0 +1,4 @@ +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { +} diff --git a/dev/integration_tests/ios_host_app_swift/Host/ViewController.swift b/dev/integration_tests/ios_host_app_swift/Host/ViewController.swift new file mode 100644 index 0000000000..faabbf1bd7 --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Host/ViewController.swift @@ -0,0 +1,27 @@ +import UIKit +import Flutter +import FlutterPluginRegistrant + +class ViewController: UIViewController { + var flutterEngine : FlutterEngine?; + + // Boiler-plate add-to-app demo. Not integration tested anywhere. + override func viewDidLoad() { + super.viewDidLoad() + let button = UIButton(type:UIButton.ButtonType.custom) + button.addTarget(self, action: #selector(handleButtonAction), for: .touchUpInside) + button.setTitle("Press me", for: UIControl.State.normal) + button.frame = CGRect(x: 80.0, y: 210.0, width: 160.0, height: 40.0) + button.backgroundColor = UIColor.blue + self.view.addSubview(button) + self.flutterEngine = FlutterEngine(name: "io.flutter", project: nil); + } + + @objc func handleButtonAction() { + let flutterEngine = self.flutterEngine; + GeneratedPluginRegistrant.register(with: flutterEngine); + + let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!; + self.present(flutterViewController, animated: false, completion: nil) + } +} diff --git a/dev/integration_tests/ios_host_app_swift/Podfile b/dev/integration_tests/ios_host_app_swift/Podfile new file mode 100644 index 0000000000..a74eec912b --- /dev/null +++ b/dev/integration_tests/ios_host_app_swift/Podfile @@ -0,0 +1,8 @@ +platform :ios, '9.0' + +flutter_application_path = '../hello' +load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb') + +target 'Host' do + install_all_flutter_pods flutter_application_path +end diff --git a/packages/flutter_tools/lib/src/plugins.dart b/packages/flutter_tools/lib/src/plugins.dart index a88e288cb8..1711ee624b 100644 --- a/packages/flutter_tools/lib/src/plugins.dart +++ b/packages/flutter_tools/lib/src/plugins.dart @@ -384,6 +384,7 @@ Depends on all your plugins, and provides a function to register them. s.source = { :path => '.' } s.public_header_files = './Classes/**/*.h' s.static_framework = true + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } s.dependency '{{framework}}' {{#plugins}} s.dependency '{{name}}'