Vend Flutter module App.framework as a local CocoaPod pod to be installed by a host app (#36793)
diff --git a/dev/integration_tests/ios_add2app/Podfile b/dev/integration_tests/ios_add2app/Podfile
index 72e1973..8885e60 100644
--- a/dev/integration_tests/ios_add2app/Podfile
+++ b/dev/integration_tests/ios_add2app/Podfile
@@ -1,26 +1,15 @@
platform :ios, '12.0'
-# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
-install! 'cocoapods', :disable_input_output_paths => true
-
flutter_application_path = 'flutterapp/'
-framework_dir = File.join(flutter_application_path, '.ios', 'Flutter')
-engine_dir = File.join(framework_dir, 'engine')
-if !File.exist?(engine_dir)
- # Copy the debug engine to have something to link against if the xcode backend script has not run yet.
- debug_framework_dir = File.join(flutter_root(flutter_application_path), 'bin', 'cache', 'artifacts', 'engine', 'ios')
- FileUtils.mkdir_p(engine_dir)
- FileUtils.cp_r(File.join(debug_framework_dir, 'Flutter.framework'), engine_dir)
- FileUtils.cp(File.join(debug_framework_dir, 'Flutter.podspec'), engine_dir)
-end
+load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'ios_add2app' do
- eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
+ install_all_flutter_pods(flutter_application_path, 'ios_add2app_flutter')
end
target 'ios_add2appTests' do
- pod 'Flutter', :path => engine_dir
inherit! :search_paths
+ install_flutter_engine_pod
pod 'EarlGrey'
end
diff --git a/dev/integration_tests/ios_add2app/ios_add2app.xcodeproj/project.pbxproj b/dev/integration_tests/ios_add2app/ios_add2app.xcodeproj/project.pbxproj
index 1859736..cc75d34 100644
--- a/dev/integration_tests/ios_add2app/ios_add2app.xcodeproj/project.pbxproj
+++ b/dev/integration_tests/ios_add2app/ios_add2app.xcodeproj/project.pbxproj
@@ -19,8 +19,8 @@
24E221E021A28B23008ADF09 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 24E221D721A28B23008ADF09 /* Launch Screen.storyboard */; };
24E221E221A28B36008ADF09 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 24E221E121A28B36008ADF09 /* Assets.xcassets */; };
24E7A1FE21A2AF26003A7FAD /* FlutterViewControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 24E7A1FD21A2AF26003A7FAD /* FlutterViewControllerTests.m */; };
+ 4C21FEB4D629B570C74073D1 /* libPods-ios_add2appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F90B141A9A8A680033E97924 /* libPods-ios_add2appTests.a */; };
8BDD73EC12DFA6CD2AC4EEDA /* EarlGrey.framework in EarlGrey Copy Files */ = {isa = PBXBuildFile; fileRef = DE1EF0F5719FBB45225A9EC3 /* EarlGrey.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
- AE3B0A0EAE765C1EC16866BF /* libPods-ios_add2appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 699900B7FF01268E98EC69ED /* libPods-ios_add2appTests.a */; };
DB9A200AFEB7AAE22B4E12E4 /* libPods-ios_add2app.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A318514E0307AE0FF0EFC76 /* libPods-ios_add2app.a */; };
/* End PBXBuildFile section */
@@ -73,13 +73,15 @@
24E7A1FD21A2AF26003A7FAD /* FlutterViewControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterViewControllerTests.m; sourceTree = "<group>"; };
36DA6BEAA5127D74EC6E3E13 /* Pods-ios_add2appUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios_add2appUITests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ios_add2appUITests/Pods-ios_add2appUITests.debug.xcconfig"; sourceTree = "<group>"; };
52EA0B290EEBC1D28BF6E803 /* libPods-ios_add2appUITests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ios_add2appUITests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
- 699900B7FF01268E98EC69ED /* libPods-ios_add2appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ios_add2appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
74266A4D94FA1C3157B5B560 /* Pods-ios_add2appTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios_add2appTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ios_add2appTests/Pods-ios_add2appTests.debug.xcconfig"; sourceTree = "<group>"; };
+ 762E954C71D922C091619CD4 /* Pods-ios_add2app-ios_add2appTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios_add2app-ios_add2appTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ios_add2app-ios_add2appTests/Pods-ios_add2app-ios_add2appTests.debug.xcconfig"; sourceTree = "<group>"; };
7A318514E0307AE0FF0EFC76 /* libPods-ios_add2app.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ios_add2app.a"; sourceTree = BUILT_PRODUCTS_DIR; };
83017A33946358F55BAE24E1 /* Pods-ios_add2appTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios_add2appTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ios_add2appTests/Pods-ios_add2appTests.release.xcconfig"; sourceTree = "<group>"; };
+ 98A4882F55A3E107DFCB67D8 /* Pods-ios_add2app-ios_add2appTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios_add2app-ios_add2appTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ios_add2app-ios_add2appTests/Pods-ios_add2app-ios_add2appTests.release.xcconfig"; sourceTree = "<group>"; };
A18D4CDABD6795975FD6B49F /* Pods-ios_add2app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios_add2app.release.xcconfig"; path = "Pods/Target Support Files/Pods-ios_add2app/Pods-ios_add2app.release.xcconfig"; sourceTree = "<group>"; };
CCFA174387D083C931FB85D0 /* Pods-ios_add2app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios_add2app.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ios_add2app/Pods-ios_add2app.debug.xcconfig"; sourceTree = "<group>"; };
DE1EF0F5719FBB45225A9EC3 /* EarlGrey.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EarlGrey.framework; path = Pods/EarlGrey/EarlGrey/EarlGrey.framework; sourceTree = SOURCE_ROOT; };
+ F90B141A9A8A680033E97924 /* libPods-ios_add2appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ios_add2appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -88,7 +90,7 @@
buildActionMask = 2147483647;
files = (
09C65652A2B48A21C94FF831 /* EarlGrey.framework in Frameworks */,
- AE3B0A0EAE765C1EC16866BF /* libPods-ios_add2appTests.a in Frameworks */,
+ 4C21FEB4D629B570C74073D1 /* libPods-ios_add2appTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -162,7 +164,7 @@
7A318514E0307AE0FF0EFC76 /* libPods-ios_add2app.a */,
DE1EF0F5719FBB45225A9EC3 /* EarlGrey.framework */,
52EA0B290EEBC1D28BF6E803 /* libPods-ios_add2appUITests.a */,
- 699900B7FF01268E98EC69ED /* libPods-ios_add2appTests.a */,
+ F90B141A9A8A680033E97924 /* libPods-ios_add2appTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -176,6 +178,8 @@
16D27B9BE77DC8804292A9A9 /* Pods-ios_add2appUITests.release.xcconfig */,
74266A4D94FA1C3157B5B560 /* Pods-ios_add2appTests.debug.xcconfig */,
83017A33946358F55BAE24E1 /* Pods-ios_add2appTests.release.xcconfig */,
+ 762E954C71D922C091619CD4 /* Pods-ios_add2app-ios_add2appTests.debug.xcconfig */,
+ 98A4882F55A3E107DFCB67D8 /* Pods-ios_add2app-ios_add2appTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
@@ -209,7 +213,7 @@
buildConfigurationList = 24E221CB21A28A0C008ADF09 /* Build configuration list for PBXNativeTarget "ios_add2app" */;
buildPhases = (
4375EE880A727341E9C9A57D /* [CP] Check Pods Manifest.lock */,
- 24E221E321A28B53008ADF09 /* ShellScript */,
+ CE6831C2A33C6C5C84521FDE /* [CP-User] Run Flutter Build Script */,
24E221B121A28A0B008ADF09 /* Sources */,
24E221B221A28A0B008ADF09 /* Frameworks */,
24E221B321A28A0B008ADF09 /* Resources */,
@@ -281,23 +285,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
- 24E221E321A28B53008ADF09 /* ShellScript */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- );
- inputPaths = (
- );
- outputFileListPaths = (
- );
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed\n";
- };
4375EE880A727341E9C9A57D /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -326,19 +313,33 @@
files = (
);
inputFileListPaths = (
- );
- inputPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-ios_add2app/Pods-ios_add2app-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
- );
- outputPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-ios_add2app/Pods-ios_add2app-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ios_add2app/Pods-ios_add2app-frameworks.sh\"\n";
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ios_add2app/Pods-ios_add2app-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
+ CE6831C2A33C6C5C84521FDE /* [CP-User] Run Flutter Build Script */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${SRCROOT}/flutterapp/.metadata",
+ "${SRCROOT}/flutterapp/.ios/Flutter/App.framework/App",
+ "${SRCROOT}/flutterapp/.ios/Flutter/engine/Flutter.framework/Flutter",
+ "${SRCROOT}/flutterapp/.ios/Flutter/flutter_export_environment.sh",
+ );
+ name = "[CP-User] Run Flutter Build Script";
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "source \"${SRCROOT}/flutterapp/.ios/Flutter/flutter_export_environment.sh\"\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build";
+ };
DE5CDCD8B3565EAB9F38F455 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -367,22 +368,15 @@
files = (
);
inputFileListPaths = (
- );
- inputPaths = (
- "${SRCROOT}/Pods/Target Support Files/Pods-ios_add2appTests/Pods-ios_add2appTests-frameworks.sh",
- "${PODS_ROOT}/../flutterapp/.ios/Flutter/engine/Flutter.framework",
- "${PODS_ROOT}/EarlGrey/EarlGrey/EarlGrey.framework",
+ "${PODS_ROOT}/Target Support Files/Pods-ios_add2appTests/Pods-ios_add2appTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
- );
- outputPaths = (
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EarlGrey.framework",
+ "${PODS_ROOT}/Target Support Files/Pods-ios_add2appTests/Pods-ios_add2appTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ios_add2appTests/Pods-ios_add2appTests-frameworks.sh\"\n";
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ios_add2appTests/Pods-ios_add2appTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
diff --git a/dev/integration_tests/ios_host_app/Config/Debug.xcconfig b/dev/integration_tests/ios_host_app/Config/Debug.xcconfig
deleted file mode 100644
index 3f48cde..0000000
--- a/dev/integration_tests/ios_host_app/Config/Debug.xcconfig
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "Flutter.xcconfig"
-#include "../Pods/Target Support Files/Pods-Host/Pods-Host.debug.xcconfig"
diff --git a/dev/integration_tests/ios_host_app/Config/Flutter.xcconfig b/dev/integration_tests/ios_host_app/Config/Flutter.xcconfig
deleted file mode 100644
index ccfdd63..0000000
--- a/dev/integration_tests/ios_host_app/Config/Flutter.xcconfig
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "../../hello/.ios/Flutter/Generated.xcconfig"
-ENABLE_BITCODE=NO
diff --git a/dev/integration_tests/ios_host_app/Config/Release.xcconfig b/dev/integration_tests/ios_host_app/Config/Release.xcconfig
deleted file mode 100644
index e9764d1..0000000
--- a/dev/integration_tests/ios_host_app/Config/Release.xcconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "Flutter.xcconfig"
-#include "../Pods/Target Support Files/Pods-Host/Pods-Host.release.xcconfig"
-FLUTTER_BUILD_MODE=release
diff --git a/dev/integration_tests/ios_host_app/Flutter/.gitkeep b/dev/integration_tests/ios_host_app/Flutter/.gitkeep
deleted file mode 100644
index e69de29..0000000
--- a/dev/integration_tests/ios_host_app/Flutter/.gitkeep
+++ /dev/null
diff --git a/dev/integration_tests/ios_host_app/Host.xcodeproj/project.pbxproj b/dev/integration_tests/ios_host_app/Host.xcodeproj/project.pbxproj
index b7edca5..ce8eb70 100644
--- a/dev/integration_tests/ios_host_app/Host.xcodeproj/project.pbxproj
+++ b/dev/integration_tests/ios_host_app/Host.xcodeproj/project.pbxproj
@@ -13,26 +13,9 @@
74F9786E215AB9E9005A0F04 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 74F9786D215AB9E9005A0F04 /* Assets.xcassets */; };
74F97871215AB9E9005A0F04 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74F9786F215AB9E9005A0F04 /* LaunchScreen.storyboard */; };
74F97874215AB9E9005A0F04 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 74F97873215AB9E9005A0F04 /* main.m */; };
- 74F978AF215AD6F9005A0F04 /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 74F978AC215AD6E8005A0F04 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
- DAEA7B95412864C7F3A4AE98 /* libPods-Host.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2499C53F0BD30E24745E2F6B /* libPods-Host.a */; };
/* End PBXBuildFile section */
-/* Begin PBXCopyFilesBuildPhase section */
- 74F978A2215ACF9B005A0F04 /* Embed Frameworks */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- 74F978AF215AD6F9005A0F04 /* App.framework in Embed Frameworks */,
- );
- name = "Embed Frameworks";
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXCopyFilesBuildPhase section */
-
/* Begin PBXFileReference section */
- 2499C53F0BD30E24745E2F6B /* libPods-Host.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Host.a"; sourceTree = BUILT_PRODUCTS_DIR; };
74F97861215AB9E8005A0F04 /* Host.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Host.app; sourceTree = BUILT_PRODUCTS_DIR; };
74F97864215AB9E8005A0F04 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
74F97865215AB9E8005A0F04 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -43,10 +26,6 @@
74F97870215AB9E9005A0F04 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
74F97872215AB9E9005A0F04 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
74F97873215AB9E9005A0F04 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
- 74F9787B215ABA08005A0F04 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
- 74F9787C215ABA73005A0F04 /* Flutter.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Flutter.xcconfig; sourceTree = "<group>"; };
- 74F9787D215ABA9D005A0F04 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
- 74F978AC215AD6E8005A0F04 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = ../../hello/.ios/Flutter/App.framework; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -54,7 +33,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- DAEA7B95412864C7F3A4AE98 /* libPods-Host.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -64,8 +42,6 @@
74F97858215AB9E8005A0F04 = {
isa = PBXGroup;
children = (
- 74F978A3215AD111005A0F04 /* Flutter */,
- 74F9787A215AB9F3005A0F04 /* Config */,
74F97863215AB9E8005A0F04 /* Host */,
74F97862215AB9E8005A0F04 /* Products */,
74F9788B215AC328005A0F04 /* Frameworks */,
@@ -97,32 +73,13 @@
path = Host;
sourceTree = "<group>";
};
- 74F9787A215AB9F3005A0F04 /* Config */ = {
- isa = PBXGroup;
- children = (
- 74F9787C215ABA73005A0F04 /* Flutter.xcconfig */,
- 74F9787B215ABA08005A0F04 /* Debug.xcconfig */,
- 74F9787D215ABA9D005A0F04 /* Release.xcconfig */,
- );
- path = Config;
- sourceTree = "<group>";
- };
74F9788B215AC328005A0F04 /* Frameworks */ = {
isa = PBXGroup;
children = (
- 2499C53F0BD30E24745E2F6B /* libPods-Host.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
- 74F978A3215AD111005A0F04 /* Flutter */ = {
- isa = PBXGroup;
- children = (
- 74F978AC215AD6E8005A0F04 /* App.framework */,
- );
- path = Flutter;
- sourceTree = "<group>";
- };
A4A9971F50C4EE357B74B6E0 /* Pods */ = {
isa = PBXGroup;
children = (
@@ -137,13 +94,9 @@
isa = PBXNativeTarget;
buildConfigurationList = 74F97877215AB9E9005A0F04 /* Build configuration list for PBXNativeTarget "Host" */;
buildPhases = (
- EDACAC7378E52BD5BBDB34D5 /* [CP] Check Pods Manifest.lock */,
- 74F9787E215ABB1B005A0F04 /* Run Script */,
74F9785D215AB9E8005A0F04 /* Sources */,
74F9785E215AB9E8005A0F04 /* Frameworks */,
74F9785F215AB9E8005A0F04 /* Resources */,
- 53642CAE5328D86A50FDAD59 /* [CP] Embed Pods Frameworks */,
- 74F978A2215ACF9B005A0F04 /* Embed Frameworks */,
);
buildRules = (
);
@@ -199,56 +152,6 @@
};
/* End PBXResourcesBuildPhase section */
-/* Begin PBXShellScriptBuildPhase section */
- 53642CAE5328D86A50FDAD59 /* [CP] Embed Pods Frameworks */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "[CP] Embed Pods Frameworks";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Host/Pods-Host-frameworks.sh\"\n";
- showEnvVarsInLog = 0;
- };
- 74F9787E215ABB1B005A0F04 /* Run Script */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "Run Script";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed\n";
- };
- EDACAC7378E52BD5BBDB34D5 /* [CP] Check Pods Manifest.lock */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
- "${PODS_ROOT}/Manifest.lock",
- );
- name = "[CP] Check Pods Manifest.lock";
- 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;
- };
-/* End PBXShellScriptBuildPhase section */
-
/* Begin PBXSourcesBuildPhase section */
74F9785D215AB9E8005A0F04 /* Sources */ = {
isa = PBXSourcesBuildPhase;
@@ -317,6 +220,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -376,6 +280,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -396,7 +301,6 @@
};
74F97878215AB9E9005A0F04 /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 74F9787B215ABA08005A0F04 /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
@@ -414,7 +318,6 @@
};
74F97879215AB9E9005A0F04 /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 74F9787D215ABA9D005A0F04 /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
diff --git a/dev/integration_tests/ios_host_app/Host/ViewController.m b/dev/integration_tests/ios_host_app/Host/ViewController.m
index 6101171..3eb47c0 100644
--- a/dev/integration_tests/ios_host_app/Host/ViewController.m
+++ b/dev/integration_tests/ios_host_app/Host/ViewController.m
@@ -1,6 +1,6 @@
#import "ViewController.h"
-#import "Flutter/Flutter.h"
-#import "FlutterPluginRegistrant/GeneratedPluginRegistrant.h"
+#import <Flutter/Flutter.h>
+#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h>
@implementation ViewController
diff --git a/dev/integration_tests/ios_host_app/Podfile b/dev/integration_tests/ios_host_app/Podfile
index 2b94908..a74eec9 100644
--- a/dev/integration_tests/ios_host_app/Podfile
+++ b/dev/integration_tests/ios_host_app/Podfile
@@ -1,9 +1,8 @@
platform :ios, '9.0'
-# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
-install! 'cocoapods', :disable_input_output_paths => true
+flutter_application_path = '../hello'
+load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'Host' do
- flutter_application_path = '../hello'
- eval(File.read("#{flutter_application_path}/.ios/Flutter/podhelper.rb"))
+ install_all_flutter_pods flutter_application_path
end
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 7be0ef1..7234890 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -10,6 +10,7 @@
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
+import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
@@ -48,25 +49,96 @@
bool useMacOSConfig = false,
bool setSymroot = true,
}) async {
+ final List<String> xcodeBuildSettings = _xcodeBuildSettingsLines(
+ project: project,
+ buildInfo: buildInfo,
+ targetOverride: targetOverride,
+ useMacOSConfig: useMacOSConfig,
+ setSymroot: setSymroot
+ );
+
+ _updateGeneratedXcodePropertiesFile(
+ project: project,
+ xcodeBuildSettings: xcodeBuildSettings,
+ useMacOSConfig: useMacOSConfig,
+ );
+
+ _updateGeneratedEnvironmentVariablesScript(
+ project: project,
+ xcodeBuildSettings: xcodeBuildSettings,
+ useMacOSConfig: useMacOSConfig,
+ );
+}
+
+/// Generate a xcconfig file to inherit FLUTTER_ build settings
+/// for Xcode targets that need them.
+/// See [XcodeBasedProject.generatedXcodePropertiesFile].
+void _updateGeneratedXcodePropertiesFile({
+ @required FlutterProject project,
+ @required List<String> xcodeBuildSettings,
+ bool useMacOSConfig = false,
+}) {
final StringBuffer localsBuffer = StringBuffer();
localsBuffer.writeln('// This is a generated file; do not edit or check into version control.');
+ xcodeBuildSettings.forEach(localsBuffer.writeln);
+ final File generatedXcodePropertiesFile = useMacOSConfig
+ ? project.macos.generatedXcodePropertiesFile
+ : project.ios.generatedXcodePropertiesFile;
+
+ generatedXcodePropertiesFile.createSync(recursive: true);
+ generatedXcodePropertiesFile.writeAsStringSync(localsBuffer.toString());
+}
+
+/// Generate a script to export all the FLUTTER_ environment variables needed
+/// as flags for Flutter tools.
+/// See [XcodeBasedProject.generatedEnvironmentVariableExportScript].
+void _updateGeneratedEnvironmentVariablesScript({
+ @required FlutterProject project,
+ @required List<String> xcodeBuildSettings,
+ bool useMacOSConfig = false,
+}) {
+ final StringBuffer localsBuffer = StringBuffer();
+
+ localsBuffer.writeln('#!/bin/sh');
+ localsBuffer.writeln('# This is a generated file; do not edit or check into version control.');
+ for (String line in xcodeBuildSettings) {
+ localsBuffer.writeln('export "$line"');
+ }
+
+ final File generatedModuleBuildPhaseScript = useMacOSConfig
+ ? project.macos.generatedEnvironmentVariableExportScript
+ : project.ios.generatedEnvironmentVariableExportScript;
+ generatedModuleBuildPhaseScript.createSync(recursive: true);
+ generatedModuleBuildPhaseScript.writeAsStringSync(localsBuffer.toString());
+ os.chmod(generatedModuleBuildPhaseScript, '755');
+}
+
+/// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build'
+List<String> _xcodeBuildSettingsLines({
+ @required FlutterProject project,
+ @required BuildInfo buildInfo,
+ String targetOverride,
+ bool useMacOSConfig = false,
+ bool setSymroot = true,
+}) {
+ final List<String> xcodeBuildSettings = <String>[];
final String flutterRoot = fs.path.normalize(Cache.flutterRoot);
- localsBuffer.writeln('FLUTTER_ROOT=$flutterRoot');
+ xcodeBuildSettings.add('FLUTTER_ROOT=$flutterRoot');
// This holds because requiresProjectRoot is true for this command
- localsBuffer.writeln('FLUTTER_APPLICATION_PATH=${fs.path.normalize(project.directory.path)}');
+ xcodeBuildSettings.add('FLUTTER_APPLICATION_PATH=${fs.path.normalize(project.directory.path)}');
// Relative to FLUTTER_APPLICATION_PATH, which is [Directory.current].
if (targetOverride != null)
- localsBuffer.writeln('FLUTTER_TARGET=$targetOverride');
+ xcodeBuildSettings.add('FLUTTER_TARGET=$targetOverride');
// The build outputs directory, relative to FLUTTER_APPLICATION_PATH.
- localsBuffer.writeln('FLUTTER_BUILD_DIR=${getBuildDirectory()}');
+ xcodeBuildSettings.add('FLUTTER_BUILD_DIR=${getBuildDirectory()}');
if (setSymroot) {
- localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}');
+ xcodeBuildSettings.add('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}');
}
if (!project.isModule) {
@@ -75,26 +147,26 @@
// logic to derive it from FLUTTER_ROOT and FLUTTER_BUILD_MODE.
// However, this is necessary for regular projects using Cocoapods.
final String frameworkDir = useMacOSConfig
- ? flutterMacOSFrameworkDir(buildInfo.mode)
- : flutterFrameworkDir(buildInfo.mode);
- localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=$frameworkDir');
+ ? flutterMacOSFrameworkDir(buildInfo.mode)
+ : flutterFrameworkDir(buildInfo.mode);
+ xcodeBuildSettings.add('FLUTTER_FRAMEWORK_DIR=$frameworkDir');
}
final String buildName = validatedBuildNameForPlatform(TargetPlatform.ios, buildInfo?.buildName ?? project.manifest.buildName);
if (buildName != null) {
- localsBuffer.writeln('FLUTTER_BUILD_NAME=$buildName');
+ xcodeBuildSettings.add('FLUTTER_BUILD_NAME=$buildName');
}
final String buildNumber = validatedBuildNumberForPlatform(TargetPlatform.ios, buildInfo?.buildNumber ?? project.manifest.buildNumber);
if (buildNumber != null) {
- localsBuffer.writeln('FLUTTER_BUILD_NUMBER=$buildNumber');
+ xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber');
}
if (artifacts is LocalEngineArtifacts) {
final LocalEngineArtifacts localEngineArtifacts = artifacts;
final String engineOutPath = localEngineArtifacts.engineOutPath;
- localsBuffer.writeln('FLUTTER_ENGINE=${fs.path.dirname(fs.path.dirname(engineOutPath))}');
- localsBuffer.writeln('LOCAL_ENGINE=${fs.path.basename(engineOutPath)}');
+ xcodeBuildSettings.add('FLUTTER_ENGINE=${fs.path.dirname(fs.path.dirname(engineOutPath))}');
+ xcodeBuildSettings.add('LOCAL_ENGINE=${fs.path.basename(engineOutPath)}');
// Tell Xcode not to build universal binaries for local engines, which are
// single-architecture.
@@ -106,19 +178,15 @@
// Skip this step for macOS builds.
if (!useMacOSConfig) {
final String arch = engineOutPath.endsWith('_arm') ? 'armv7' : 'arm64';
- localsBuffer.writeln('ARCHS=$arch');
+ xcodeBuildSettings.add('ARCHS=$arch');
}
}
if (buildInfo.trackWidgetCreation) {
- localsBuffer.writeln('TRACK_WIDGET_CREATION=true');
+ xcodeBuildSettings.add('TRACK_WIDGET_CREATION=true');
}
- final File generatedXcodePropertiesFile = useMacOSConfig
- ? project.macos.generatedXcodePropertiesFile
- : project.ios.generatedXcodePropertiesFile;
- generatedXcodePropertiesFile.createSync(recursive: true);
- generatedXcodePropertiesFile.writeAsStringSync(localsBuffer.toString());
+ return xcodeBuildSettings;
}
XcodeProjectInterpreter get xcodeProjectInterpreter => context.get<XcodeProjectInterpreter>();
diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart
index ece0846..d9d7a3e 100644
--- a/packages/flutter_tools/lib/src/project.dart
+++ b/packages/flutter_tools/lib/src/project.dart
@@ -260,6 +260,12 @@
/// The Flutter-managed Xcode config file for [mode].
File xcodeConfigFor(String mode);
+ /// The script that exports environment variables needed for Flutter tools.
+ /// Can be run first in a Xcode Script build phase to make FLUTTER_ROOT,
+ /// LOCAL_ENGINE, and other Flutter variables available to any flutter
+ /// tooling (`flutter build`, etc) to convert into flags.
+ File get generatedEnvironmentVariableExportScript;
+
/// The CocoaPods 'Podfile'.
File get podfile;
@@ -318,6 +324,9 @@
File xcodeConfigFor(String mode) => _flutterLibRoot.childDirectory('Flutter').childFile('$mode.xcconfig');
@override
+ File get generatedEnvironmentVariableExportScript => _flutterLibRoot.childDirectory('Flutter').childFile('flutter_export_environment.sh');
+
+ @override
File get podfile => hostAppRoot.childFile('Podfile');
@override
@@ -662,6 +671,9 @@
File xcodeConfigFor(String mode) => managedDirectory.childFile('Flutter-$mode.xcconfig');
@override
+ File get generatedEnvironmentVariableExportScript => managedDirectory.childFile('flutter_export_environment.sh');
+
+ @override
File get podfile => _macOSDirectory.childFile('Podfile');
@override
diff --git a/packages/flutter_tools/templates/module/ios/host_app_ephemeral_cocoapods/Podfile.copy.tmpl b/packages/flutter_tools/templates/module/ios/host_app_ephemeral_cocoapods/Podfile.copy.tmpl
index b2b9a40..1e70150 100644
--- a/packages/flutter_tools/templates/module/ios/host_app_ephemeral_cocoapods/Podfile.copy.tmpl
+++ b/packages/flutter_tools/templates/module/ios/host_app_ephemeral_cocoapods/Podfile.copy.tmpl
@@ -1,8 +1,18 @@
platform :ios, '8.0'
+flutter_application_path = '../'
+load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
+
target 'Runner' do
- flutter_application_path = '../'
- eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
+ install_flutter_plugin_pods flutter_application_path
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ target.build_configurations.each do |config|
+ config.build_settings['ENABLE_BITCODE'] = 'NO'
+ end
+ end
end
# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
diff --git a/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb b/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb
index 3956697..f833b85 100644
--- a/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb
+++ b/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb
@@ -1,75 +1,137 @@
-def parse_KV_file(file, separator='=')
- file_abs_path = File.expand_path(file)
- if !File.exists? file_abs_path
- return [];
- end
- pods_array = []
- skip_line_start_symbols = ["#", "/"]
- File.foreach(file_abs_path) { |line|
- next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
- plugin = line.split(pattern=separator)
- if plugin.length == 2
- podname = plugin[0].strip()
- path = plugin[1].strip()
- podpath = File.expand_path("#{path}", file_abs_path)
- pods_array.push({:name => podname, :path => podpath});
- else
- puts "Invalid plugin specification: #{line}"
- end
- }
- return pods_array
+# Install pods needed to embed Flutter application, Flutter engine, and plugins
+# from the host application Podfile.
+#
+# @example
+# target 'MyApp' do
+# install_all_flutter_pods 'my_flutter'
+# end
+# @param [String] flutter_application_path Path of the root directory of the Flutter module.
+# Optional, defaults to two levels up from the directory of this script.
+# MyApp/my_flutter/.ios/Flutter/../..
+# @param [String] flutter_application_name Name of the Flutter module. Optional, defaults to module directory name.
+def install_all_flutter_pods(flutter_application_path = nil, flutter_application_name = nil)
+ flutter_application_name ||= File.basename(File.expand_path(flutter_application_path))
+ flutter_application_path ||= File.join('..', '..')
+ install_flutter_engine_pod
+ install_flutter_plugin_pods(flutter_application_path)
+ install_flutter_application_pod(flutter_application_path, flutter_application_name)
end
-def flutter_root(f)
- generated_xcode_build_settings = parse_KV_file(File.join(f, File.join('.ios', 'Flutter', 'Generated.xcconfig')))
- if generated_xcode_build_settings.empty?
- puts "Generated.xcconfig must exist. Make sure `flutter pub get` is executed in #{f}."
- exit
- end
- generated_xcode_build_settings.map { |p|
- if p[:name] == 'FLUTTER_ROOT'
- return p[:path]
- end
- }
-end
-
-# If this wasn't specified, assume it's two levels up from the directory of this script.
-flutter_application_path ||= File.join(__dir__, '..', '..')
-framework_dir = File.join(flutter_application_path, '.ios', 'Flutter')
-
-engine_dir = File.join(framework_dir, 'engine')
-if !File.exist?(engine_dir)
+# Install Flutter engine pod.
+#
+# @example
+# target 'MyApp' do
+# install_flutter_engine_pod
+# end
+def install_flutter_engine_pod
+ engine_dir = File.join(__dir__, 'engine')
+ if !File.exist?(engine_dir)
# Copy the debug engine to have something to link against if the xcode backend script has not run yet.
- debug_framework_dir = File.join(flutter_root(flutter_application_path), 'bin', 'cache', 'artifacts', 'engine', 'ios')
+ # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
+ debug_framework_dir = File.join(flutter_root, 'bin', 'cache', 'artifacts', 'engine', 'ios')
FileUtils.mkdir_p(engine_dir)
FileUtils.cp_r(File.join(debug_framework_dir, 'Flutter.framework'), engine_dir)
FileUtils.cp(File.join(debug_framework_dir, 'Flutter.podspec'), engine_dir)
+ end
+
+ pod 'Flutter', :path => engine_dir, :inhibit_warnings => true
end
-pod 'Flutter', :path => engine_dir
-pod 'FlutterPluginRegistrant', :path => File.join(framework_dir, 'FlutterPluginRegistrant')
+# Install Flutter plugin pods.
+#
+# @example
+# target 'MyApp' do
+# install_flutter_plugin_pods 'my_flutter'
+# end
+# @param [String] flutter_application_path Path of the root directory of the Flutter module.
+# Optional, defaults to two levels up from the directory of this script.
+# MyApp/my_flutter/.ios/Flutter/../..
+def install_flutter_plugin_pods(flutter_application_path)
+ flutter_application_path ||= File.join('..', '..')
+ pod 'FlutterPluginRegistrant', :path => File.join(__dir__, 'FlutterPluginRegistrant'), :inhibit_warnings => true
-symlinks_dir = File.join(framework_dir, '.symlinks')
-FileUtils.mkdir_p(symlinks_dir)
-plugin_pods = parse_KV_file(File.join(flutter_application_path, '.flutter-plugins'))
-plugin_pods.map { |r|
+ symlinks_dir = File.join(__dir__, '.symlinks')
+ FileUtils.mkdir_p(symlinks_dir)
+ plugin_pods = parse_KV_file(File.join(flutter_application_path, '.flutter-plugins'))
+ plugin_pods.map do |r|
symlink = File.join(symlinks_dir, r[:name])
FileUtils.rm_f(symlink)
File.symlink(r[:path], symlink)
- pod r[:name], :path => File.join(symlink, 'ios')
-}
+ pod r[:name], :path => File.join(symlink, 'ios'), :inhibit_warnings => true
+ end
+end
-# Ensure that ENABLE_BITCODE is set to NO, add a #include to Generated.xcconfig, and
-# add a run script to the Build Phases.
-post_install do |installer|
- installer.pods_project.targets.each do |target|
- target.build_configurations.each do |config|
- config.build_settings['ENABLE_BITCODE'] = 'NO'
- next if config.base_configuration_reference == nil
- xcconfig_path = config.base_configuration_reference.real_path
- File.open(xcconfig_path, 'a+') do |file|
- file.puts "#include \"#{File.realpath(File.join(framework_dir, 'Generated.xcconfig'))}\""
- end
- end
+# Install Flutter application pod.
+#
+# @example
+# target 'MyApp' do
+# install_flutter_application_pod '../flutter_settings_repository', 'settings_module'
+# end
+# @param [String] flutter_application_path Path of the root directory of the Flutter module.
+# Optional, defaults to two levels up from the directory of this script.
+# MyApp/my_flutter/.ios/Flutter/../..
+def install_flutter_application_pod(flutter_application_path, flutter_application_name)
+ app_framework_dir = File.join(__dir__, 'App.framework')
+ app_framework_dylib = File.join(app_framework_dir, 'App')
+ if !File.exist?(app_framework_dylib)
+ # Fake an App.framework to have something to link against if the xcode backend script has not run yet.
+ # CocoaPods will not embed the framework on pod install (before any build phases can run) if the dylib does not exist.
+ # Create a dummy dylib.
+ FileUtils.mkdir_p(app_framework_dir)
+ `echo "static const int Moo = 88;" | xcrun clang -x c -dynamiclib -o "#{app_framework_dylib}" -`
+ end
+
+ pod flutter_application_name, :path => __dir__, :inhibit_warnings => true
+
+ # Use relative paths for script phase paths since these strings will likely be checked into source controls.
+ # Process will be run from project directory.
+ current_directory_pathname = Pathname.new __dir__.to_s
+ project_directory_pathname = Pathname.new Dir.pwd
+ relative = current_directory_pathname.relative_path_from project_directory_pathname
+
+ flutter_export_environment_path = File.join('${SRCROOT}', relative, 'flutter_export_environment.sh');
+ script_phase :name => 'Run Flutter Build Script',
+ :script => "source \"#{flutter_export_environment_path}\"\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build",
+ :input_files => [
+ File.join('${SRCROOT}', flutter_application_path, '.metadata'),
+ File.join('${SRCROOT}', relative, 'App.framework', 'App'),
+ File.join('${SRCROOT}', relative, 'engine', 'Flutter.framework', 'Flutter'),
+ flutter_export_environment_path
+ ],
+ :execution_position => :before_compile
+end
+
+def parse_KV_file(file, separator='=')
+ file_abs_path = File.expand_path(file)
+ if !File.exists? file_abs_path
+ return [];
+ end
+ pods_array = []
+ skip_line_start_symbols = ["#", "/"]
+ File.foreach(file_abs_path) { |line|
+ next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
+ plugin = line.split(pattern=separator)
+ if plugin.length == 2
+ podname = plugin[0].strip()
+ path = plugin[1].strip()
+ podpath = File.expand_path("#{path}", file_abs_path)
+ pods_array.push({:name => podname, :path => podpath});
+ else
+ puts "Invalid plugin specification: #{line}"
end
+ }
+ return pods_array
+end
+
+def flutter_root
+ generated_xcode_build_settings = parse_KV_file(File.join(__dir__, 'Generated.xcconfig'))
+ if generated_xcode_build_settings.empty?
+ puts "Generated.xcconfig must exist. Make sure `flutter pub get` is executed in the Flutter module."
+ exit
+ end
+ generated_xcode_build_settings.map { |p|
+ if p[:name] == 'FLUTTER_ROOT'
+ return p[:path]
+ end
+ }
end
diff --git a/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/projectName.podspec.tmpl b/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/projectName.podspec.tmpl
new file mode 100644
index 0000000..2fbe501
--- /dev/null
+++ b/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/projectName.podspec.tmpl
@@ -0,0 +1,13 @@
+Pod::Spec.new do |s|
+ s.name = '{{projectName}}'
+ s.version = '0.0.1'
+ s.summary = 'Flutter module'
+ s.description = 'Flutter module - {{projectName}}'
+ s.homepage = 'https://flutter.dev'
+ s.license = { :type => 'BSD' }
+ s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
+ s.source = { :path => '.' }
+ s.ios.deployment_target = '8.0'
+ s.vendored_frameworks = 'App.framework'
+ s.dependency 'Flutter'
+end
diff --git a/packages/flutter_tools/test/general.shard/commands/create_test.dart b/packages/flutter_tools/test/general.shard/commands/create_test.dart
index 7a8c087..98babb7 100644
--- a/packages/flutter_tools/test/general.shard/commands/create_test.dart
+++ b/packages/flutter_tools/test/general.shard/commands/create_test.dart
@@ -100,6 +100,7 @@
'.android/app/',
'.gitignore',
'.ios/Flutter',
+ '.ios/Flutter/flutter_project.podspec',
'.metadata',
'lib/main.dart',
'pubspec.yaml',
@@ -545,6 +546,23 @@
expect(xcodeConfig, contains('FLUTTER_ROOT='));
expect(xcodeConfig, contains('FLUTTER_APPLICATION_PATH='));
expect(xcodeConfig, contains('FLUTTER_TARGET='));
+
+ // Generated export environment variables script
+ final String buildPhaseScriptPath = fs.path.join('.ios', 'Flutter', 'flutter_export_environment.sh');
+ expectExists(buildPhaseScriptPath);
+ final File buildPhaseScriptFile = fs.file(fs.path.join(projectDir.path, buildPhaseScriptPath));
+ final String buildPhaseScript = buildPhaseScriptFile.readAsStringSync();
+ expect(buildPhaseScript, contains('FLUTTER_ROOT='));
+ expect(buildPhaseScript, contains('FLUTTER_APPLICATION_PATH='));
+ expect(buildPhaseScript, contains('FLUTTER_TARGET='));
+
+ // Generated podspec
+ final String podspecPath = fs.path.join('.ios', 'Flutter', 'flutter_project.podspec');
+ expectExists(podspecPath);
+ final File podspecFile = fs.file(fs.path.join(projectDir.path, podspecPath));
+ final String podspec = podspecFile.readAsStringSync();
+ expect(podspec, contains('Flutter module - flutter_project'));
+
// App identification
final String xcodeProjectPath = fs.path.join('.ios', 'Runner.xcodeproj', 'project.pbxproj');
expectExists(xcodeProjectPath);
diff --git a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
index b560538..ec81949 100644
--- a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
@@ -304,6 +304,12 @@
final String contents = config.readAsStringSync();
expect(contents.contains('ARCHS=armv7'), isTrue);
+
+ final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh');
+ expect(buildPhaseScript.existsSync(), isTrue);
+
+ final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync();
+ expect(buildPhaseScriptContents.contains('ARCHS=armv7'), isTrue);
});
testUsingOsxContext('sets TRACK_WIDGET_CREATION=true when trackWidgetCreation is true', () async {
@@ -322,6 +328,12 @@
final String contents = config.readAsStringSync();
expect(contents.contains('TRACK_WIDGET_CREATION=true'), isTrue);
+
+ final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh');
+ expect(buildPhaseScript.existsSync(), isTrue);
+
+ final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync();
+ expect(buildPhaseScriptContents.contains('TRACK_WIDGET_CREATION=true'), isTrue);
});
testUsingOsxContext('does not set TRACK_WIDGET_CREATION when trackWidgetCreation is false', () async {
@@ -340,6 +352,12 @@
final String contents = config.readAsStringSync();
expect(contents.contains('TRACK_WIDGET_CREATION=true'), isFalse);
+
+ final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh');
+ expect(buildPhaseScript.existsSync(), isTrue);
+
+ final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync();
+ expect(buildPhaseScriptContents.contains('TRACK_WIDGET_CREATION=true'), isFalse);
});
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
diff --git a/packages/flutter_tools/test/general.shard/project_test.dart b/packages/flutter_tools/test/general.shard/project_test.dart
index dd800b4..f5b26d1 100644
--- a/packages/flutter_tools/test/general.shard/project_test.dart
+++ b/packages/flutter_tools/test/general.shard/project_test.dart
@@ -200,6 +200,8 @@
await project.ensureReadyForPlatformSpecificTooling();
final Directory flutter = project.ios.hostAppRoot.childDirectory('Flutter');
expectExists(flutter.childFile('podhelper.rb'));
+ expectExists(flutter.childFile('flutter_export_environment.sh'));
+ expectExists(flutter.childFile('${project.manifest.appName}.podspec'));
expectExists(flutter.childFile('Generated.xcconfig'));
final Directory pluginRegistrantClasses = flutter
.childDirectory('FlutterPluginRegistrant')