@@ -104,7 +104,13 @@ class CreateCommand extends FlutterCommand with CreateBase {
104104 'internally and should generally not be used manually.' ,
105105 hide: ! verboseHelp,
106106 );
107- addPlatformsOptions (customHelp: kPlatformHelp);
107+
108+ final Map <String , String > platformsAllowedHelp = {
109+ for (final String p in kAllCreatePlatforms) p: '' ,
110+ };
111+ platformsAllowedHelp['darwin' ] =
112+ 'A shared platform for iOS and macOS. (only supported for plugins)' ;
113+ addPlatformsOptions (customHelp: kPlatformHelp, allowedHelp: platformsAllowedHelp);
108114
109115 final List <ParsedFlutterTemplateType > enabledTemplates =
110116 ParsedFlutterTemplateType .enabledValues (featureFlags);
@@ -356,6 +362,7 @@ class CreateCommand extends FlutterCommand with CreateBase {
356362
357363 final String dartSdk = globals.cache.dartSdkBuild;
358364 final bool includeIos;
365+ final bool includeDarwin;
359366 final bool includeAndroid;
360367 final bool includeWeb;
361368 final bool includeLinux;
@@ -369,6 +376,7 @@ class CreateCommand extends FlutterCommand with CreateBase {
369376 includeLinux = false ;
370377 includeMacos = false ;
371378 includeWindows = false ;
379+ includeDarwin = false ;
372380 } else if (template == FlutterTemplateType .package) {
373381 // The package template does not supports any platform.
374382 includeIos = false ;
@@ -377,12 +385,32 @@ class CreateCommand extends FlutterCommand with CreateBase {
377385 includeLinux = false ;
378386 includeMacos = false ;
379387 includeWindows = false ;
388+ includeDarwin = false ;
380389 } else {
381- includeIos = featureFlags.isIOSEnabled && platforms.contains ('ios' );
390+ final bool darwinRequested = platforms.contains ('darwin' );
391+ final bool darwinSupported =
392+ (template == FlutterTemplateType .plugin) &&
393+ featureFlags.isIOSEnabled &&
394+ featureFlags.isMacOSEnabled;
395+
396+ if (darwinRequested && darwinSupported) {
397+ includeDarwin = true ;
398+ includeIos = true ;
399+ includeMacos = true ;
400+ } else {
401+ includeDarwin = false ;
402+ includeIos = featureFlags.isIOSEnabled && platforms.contains ('ios' );
403+ includeMacos = featureFlags.isMacOSEnabled && platforms.contains ('macos' );
404+ if (darwinRequested && ! darwinSupported) {
405+ globals.printWarning (
406+ 'Warning: To use the "darwin" platform, you must have both iOS and macOS enabled.\n '
407+ 'Run "flutter config --enable-ios --enable-macos-desktop" and try again.' ,
408+ );
409+ }
410+ }
382411 includeAndroid = featureFlags.isAndroidEnabled && platforms.contains ('android' );
383412 includeWeb = featureFlags.isWebEnabled && platforms.contains ('web' );
384413 includeLinux = featureFlags.isLinuxEnabled && platforms.contains ('linux' );
385- includeMacos = featureFlags.isMacOSEnabled && platforms.contains ('macos' );
386414 includeWindows = featureFlags.isWindowsEnabled && platforms.contains ('windows' );
387415 }
388416
@@ -418,6 +446,7 @@ class CreateCommand extends FlutterCommand with CreateBase {
418446 iosDevelopmentTeam: developmentTeam,
419447 ios: includeIos,
420448 android: includeAndroid,
449+ darwin: includeDarwin,
421450 web: includeWeb,
422451 linux: includeLinux,
423452 macos: includeMacos,
@@ -529,9 +558,9 @@ class CreateCommand extends FlutterCommand with CreateBase {
529558 await project.ensureReadyForPlatformSpecificTooling (
530559 releaseMode: ignoreReleaseModeSinceItsNotABuildAndHopeItWorks,
531560 androidPlatform: includeAndroid,
532- iosPlatform: includeIos,
561+ iosPlatform: includeIos || includeDarwin ,
533562 linuxPlatform: includeLinux,
534- macOSPlatform: includeMacos,
563+ macOSPlatform: includeMacos || includeDarwin ,
535564 windowsPlatform: includeWindows,
536565 webPlatform: includeWeb,
537566 );
@@ -697,10 +726,28 @@ Your $application code is in $relativeAppMain.
697726 templateContext['description' ] = description;
698727
699728 final projectName = templateContext['projectName' ] as String ? ;
729+ final bool includeDarwin = templateContext['darwin' ] as bool ? ?? false ;
730+ final bool originalIos = templateContext['ios' ] as bool ? ?? false ;
731+ final bool originalMacos = templateContext['macos' ] as bool ? ?? false ;
732+ if (includeDarwin) {
733+ // Temporarily disable ios/macos for the plugin generation
734+ // so we don't get ios/ and macos/ directories in the plugin root.
735+ templateContext['ios' ] = false ;
736+ templateContext['macos' ] = false ;
737+ }
738+
700739 final templates = < String > ['plugin' , 'plugin_shared' ];
701- if ((templateContext['ios' ] == true || templateContext['macos' ] == true ) &&
702- featureFlags.isSwiftPackageManagerEnabled) {
703- templates.add ('plugin_swift_package_manager' );
740+
741+ final bool useSwiftPackageManager =
742+ (templateContext['ios' ] == true || templateContext['macos' ] == true || includeDarwin) &&
743+ featureFlags.isSwiftPackageManagerEnabled;
744+
745+ if (useSwiftPackageManager) {
746+ if (includeDarwin) {
747+ templates.add ('plugin_darwin_spm' );
748+ } else {
749+ templates.add ('plugin_swift_package_manager' );
750+ }
704751 templateContext['swiftLibraryName' ] = projectName? .replaceAll ('_' , '-' );
705752 templateContext['swiftToolsVersion' ] = minimumSwiftToolchainVersion;
706753 templateContext['iosSupportedPlatform' ] = FlutterDarwinPlatform .ios.supportedPackagePlatform
@@ -710,16 +757,24 @@ Your $application code is in $relativeAppMain.
710757 .supportedPackagePlatform
711758 .format ();
712759 } else {
713- templates.add ('plugin_cocoapods' );
760+ if (includeDarwin) {
761+ templates.add ('plugin_darwin_cocoapods' );
762+ } else {
763+ templates.add ('plugin_cocoapods' );
764+ }
714765 }
715-
716766 generatedCount += await renderMerged (
717767 templates,
718768 directory,
719769 templateContext,
720770 overwrite: overwrite,
721771 printStatusWhenWriting: printStatusWhenWriting,
722772 );
773+ // Restore the original ios and macos values.
774+ // This is necessary in case the user requested the darwin platform,
775+ // and we need to restore them for the example app generation.
776+ templateContext['ios' ] = originalIos;
777+ templateContext['macos' ] = originalMacos;
723778
724779 final FlutterProject project = FlutterProject .fromDirectory (directory);
725780 final generateAndroid = templateContext['android' ] == true ;
@@ -984,6 +1039,10 @@ List<String> _getPlatformWarningList(List<String> requestedPlatforms) {
9841039 if (requestedPlatforms.contains ('macos' ) && ! featureFlags.isMacOSEnabled) 'macos' ,
9851040 if (requestedPlatforms.contains ('windows' ) && ! featureFlags.isWindowsEnabled) 'windows' ,
9861041 if (requestedPlatforms.contains ('linux' ) && ! featureFlags.isLinuxEnabled) 'linux' ,
1042+ if (requestedPlatforms.contains ('darwin' ) &&
1043+ ! featureFlags.isMacOSEnabled &&
1044+ ! featureFlags.isIOSEnabled)
1045+ 'darwin' ,
9871046 ];
9881047
9891048 return platformsToWarn;
@@ -992,13 +1051,16 @@ List<String> _getPlatformWarningList(List<String> requestedPlatforms) {
9921051void _printWarningDisabledPlatform (List <String > platforms) {
9931052 final desktop = < String > [];
9941053 final web = < String > [];
1054+ final darwin = < String > [];
9951055
9961056 for (final platform in platforms) {
9971057 switch (platform) {
9981058 case 'web' :
9991059 web.add (platform);
10001060 case 'macos' || 'windows' || 'linux' :
10011061 desktop.add (platform);
1062+ case 'darwin' :
1063+ darwin.add (platform);
10021064 }
10031065 }
10041066
@@ -1015,6 +1077,12 @@ For more details, see: https://flutter.dev/to/add-desktop-support
10151077 globals.printStatus ('''
10161078The web is currently not supported on your local environment.
10171079For more details, see: https://flutter.dev/to/add-web-support
1080+ ''' );
1081+ }
1082+ if (darwin.isNotEmpty) {
1083+ globals.printStatus ('''
1084+ The darwin platform is currently not supported on your local environment.
1085+ You must have a macOS host with Xcode installed to develop for iOS or macOS.
10181086''' );
10191087 }
10201088}
0 commit comments