示例#1
0
        /// <summary>
        /// Creates the Flutter module to be integrated into Xamarin (native) applications.
        /// </summary>
        private static DartProject CreateFlutterModule(NewProjectSettings settings, bool verbose = false)
        {
            try
            {
                DartProject project = FlutterTools.CreateModule(settings.FlutterSubfolderPath, settings.FlutterModuleName,
                                                                organization: settings.OrganizationId, verbose: verbose);

                FlutterTools.CreatePackage(settings.FlutterSubfolderPath, settings.FlutterPackageName,
                                           description: DartBridgeBuilder.DefaultPackageDescription, verbose: verbose);

                project.AddDevDependency(new DartProjectDependency(settings.FlutterPackageName, DartProjectDependencyType.Path, $"../{settings.FlutterPackageName}"));
                project.ApplyChanges();

                // Before building the module on a new machine, run "flutter pub get" first
                // to regenerate the .android/ and .ios/ directories.
                // (see: https://flutter.dev/docs/development/add-to-app/android/project-setup#create-a-flutter-module
                //  and: https://flutter.dev/docs/development/add-to-app/ios/project-setup#create-a-flutter-module)
                project.GetDependencies(verbose);

                return(project);
            }
            catch (Exception e)
            {
                throw new CommandLineException(CommandLineErrorCode.NewProject_CreateFlutterModuleFailed, e);
            }
        }
示例#2
0
        private static void UpdatePackageReferences(NewProjectSettings settings)
        {
            try
            {
                string productVersion = Assembly.GetEntryAssembly().GetProductVersion();
                string flutterVersion = settings.FlutterVersion;
                if (string.IsNullOrEmpty(flutterVersion))
                {
                    flutterVersion = FlutterTools.GetVersion().Version;
                }

                SdkVersion        sdk = AppSettings.Default.SdkTable.Versions.First(v => v.Version == productVersion);
                SdkFlutterVersion fv  = sdk.Compatibility.FirstOrDefault(f => VersionUtils.Compare(f.Version, flutterVersion) == 0);
                if (fv == null)
                {
                    // We're using a version of Flutter that is not officially supported by Flutnet (no binding libraries exist).
                    // Let's try and see if we can find a prior version that's fully compatible.
                    // If we can't find anything, simply return and keep the template configuration as is.
                    sdk.Compatibility.Sort(new SdkFlutterVersionComparer());
                    fv = sdk.Compatibility.LastOrDefault(f => VersionUtils.Compare(f.Version, flutterVersion) < 0);
                    if (fv == null)
                    {
                        return;
                    }
                }

                if (settings.TargetAndroid)
                {
                    string interopVersion = !string.IsNullOrEmpty(fv.AndroidInteropVersion)
                        ? fv.AndroidInteropVersion
                        : fv.Version;

                    string csprojPath = Path.Combine(settings.SolutionPath, $"{settings.ProjectName}.Android", $"{settings.ProjectName}.Android.csproj");
                    UpdatePackageReferences_AndroidProject(csprojPath, interopVersion);
                    csprojPath = Path.Combine(settings.SolutionPath, $"{settings.ProjectName}.ModuleInterop.Android", $"{settings.ProjectName}.ModuleInterop.Android.csproj");
                    UpdatePackageReferences_AndroidProject(csprojPath, interopVersion);
                }

                if (settings.TargetIos && OperatingSystem.IsMacOS())
                {
                    string interopVersion = !string.IsNullOrEmpty(fv.IosInteropVersion)
                        ? fv.IosInteropVersion
                        : fv.Version;

                    string csprojPath = Path.Combine(settings.SolutionPath, $"{settings.ProjectName}.iOS", $"{settings.ProjectName}.iOS.csproj");
                    UpdatePackageReferences_iOSProject(csprojPath, interopVersion);
                    csprojPath = Path.Combine(settings.SolutionPath, $"{settings.ProjectName}.PluginInterop.iOS", $"{settings.ProjectName}.PluginInterop.iOS.csproj");
                    UpdatePackageReferences_iOSProject(csprojPath, interopVersion);
                }
            }
            catch (Exception e)
            {
                throw new CommandLineException(CommandLineErrorCode.NewProject_SetNativeReferencesFailed, e);
            }
        }
示例#3
0
        public static void Create(NewProjectSettings settings, bool verbose = false)
        {
            try
            {
                MSBuildLocator.RegisterDefaults();
            }
            catch (Exception e)
            {
                Log.Ex(e);
                throw new CommandLineException(CommandLineErrorCode.NewProject_MSBuildDetectionFailed, e);
            }

            try
            {
                InstallFlutnetTemplate();

                if (!Directory.Exists(settings.Location))
                {
                    Directory.CreateDirectory(settings.Location);
                }

                Console.WriteLine("Creating Xamarin (.NET) projects...");
                CreateDotNetProjects(settings, verbose);
                ConfigurePostBuildEvent(settings, verbose);
                Console.WriteLine("Done.");

                if (!Directory.Exists(settings.FlutterSubfolderPath))
                {
                    Directory.CreateDirectory(settings.FlutterSubfolderPath);
                }

                Console.WriteLine("Creating Flutter module...");
                DartProject project = CreateFlutterModule(settings, verbose);
                Console.WriteLine("Done.");

                Console.WriteLine("Building Flutter module...");
                BuildFlutterModule(settings, verbose);
                Console.WriteLine("Done.");

                Console.WriteLine("Configuring native references in Xamarin projects... ");
                SetNativeReferences(settings, project);
                Console.WriteLine("Done.");

                Console.WriteLine("Configuring package references... ");
                UpdatePackageReferences(settings);
                Console.WriteLine("Done.");
            }
            finally
            {
                UninstallFlutnetTemplate();
            }
        }
示例#4
0
 /// <summary>
 /// Build the Flutter module to generate the Android Archive (AAR) and/or the iOS framework
 /// that will be embedded into Xamarin applications.
 /// </summary>
 private static void BuildFlutterModule(NewProjectSettings settings, bool verbose = false)
 {
     try
     {
         if (settings.TargetAndroid)
         {
             FlutterTools.BuildAndroidArchive(settings.FlutterModulePath, FlutterModuleBuildConfig.Debug | FlutterModuleBuildConfig.Release, verbose);
         }
         if (settings.TargetIos && OperatingSystem.IsMacOS())
         {
             FlutterTools.BuildIosFramework(settings.FlutterModulePath, FlutterModuleBuildConfig.Debug | FlutterModuleBuildConfig.Release, verbose);
         }
     }
     catch (Exception e)
     {
         throw new CommandLineException(CommandLineErrorCode.NewProject_BuildFlutterModuleFailed, e);
     }
 }
示例#5
0
        private static void SetNativeReferences(NewProjectSettings settings, DartProject project)
        {
            try
            {
                if (settings.TargetAndroid)
                {
                    string csprojPath = Path.Combine(settings.SolutionPath, $"{settings.ProjectName}.ModuleInterop.Android", $"{settings.ProjectName}.ModuleInterop.Android.csproj");
                    SetNativeReference_AndroidBindings(csprojPath, project);
                }
                if (settings.TargetIos && OperatingSystem.IsMacOS())
                {
                    string csprojPath = Path.Combine(settings.SolutionPath, $"{settings.ProjectName}.PluginInterop.iOS", $"{settings.ProjectName}.PluginInterop.iOS.csproj");
                    SetNativeReference_iOSBindings(csprojPath, project);

                    csprojPath = Path.Combine(settings.SolutionPath, $"{settings.ProjectName}.iOS", $"{settings.ProjectName}.iOS.csproj");
                    SetNativeReference_iOSApp(csprojPath, project);
                }
            }
            catch (Exception e)
            {
                Log.Ex(e);
                throw new CommandLineException(CommandLineErrorCode.NewProject_SetNativeReferencesFailed, e);
            }
        }
示例#6
0
        /// <summary>
        /// Runs a .NET Core CLI command to create a new project tree from template.
        /// </summary>
        private static void CreateDotNetProjects(NewProjectSettings settings, bool verbose = false)
        {
            List <object> arguments = new List <object> {
                "new", FlutnetTemplateName
            };

            arguments.Add("--name");
            arguments.Add(settings.ProjectName);
            arguments.Add("--output");
            arguments.Add(settings.SolutionName);
            arguments.Add("--appName");
            arguments.Add(settings.AppName);
            arguments.Add("--solutionName");
            arguments.Add(settings.SolutionName);
            if (settings.TargetAndroid)
            {
                arguments.Add("--target-android");
            }
            if (settings.TargetIos)
            {
                arguments.Add("--target-ios");
            }
            arguments.Add("--androidPackage");
            arguments.Add(settings.AndroidAppId);
            arguments.Add("--iosBundle");
            arguments.Add(settings.IosAppId);

            Command command = Command.Run("dotnet", arguments, options => { options.WorkingDirectory(settings.Location).ThrowOnError(); });

            if (verbose)
            {
                command.RedirectTo(Console.Out);
                command.RedirectStandardErrorTo(Console.Error);
            }
            command.WaitWithFancyError(CommandLineErrorCode.NewProject_CreateDotNetProjectsFailed);
        }
示例#7
0
        /// <summary>
        /// Configures the post-build event of the .NET Standard class library.
        /// </summary>
        public static void ConfigurePostBuildEvent(NewProjectSettings settings, bool verbose = false)
        {
            try
            {
                string csprojPath = Path.Combine(settings.SolutionPath, $"{settings.ProjectName}.ServiceLibrary", $"{settings.ProjectName}.ServiceLibrary.csproj");

                string executableWin;
                string executableMac;

                if (OperatingSystem.IsWindows())
                {
                    executableWin = Path.Combine(AppSettings.Default.AppPath, "flutnet.exe");
                    executableMac = $"{AppSettings.DefaultBinPath_macOS}/flutnet";
                }
                else
                {
                    executableWin = $"{AppSettings.DefaultBinPath_Windows}\\flutnet.exe";
                    executableMac = Path.Combine(AppSettings.Default.AppPath, "flutnet");
                }

                ProjectRootElement prjElement = ProjectRootElement.Open(csprojPath);

                // Configures the post-build event(s) for Visual Studio for Mac

                List <string> commandArguments = new List <string>
                {
                    executableMac.Quoted(), "pack",
                    "-a", "${TargetFile}".Quoted(),
                    "-n", settings.FlutterPackageName,
                    "-o", (settings.CreateFlutterSubfolder ? $"${{SolutionDir}}/{settings.FlutterSubfolderName}" : "${SolutionDir}").Quoted(),
                    "--force"
                };

                foreach (ProjectPropertyGroupElement groupElement in prjElement.PropertyGroups)
                {
                    if (groupElement.Condition.Contains("$(Configuration)") && groupElement.Condition.Contains("$(Platform)"))
                    {
                        ProjectPropertyElement propElement = groupElement.Properties.FirstOrDefault(p => p.Name == "CustomCommands");
                        propElement.Value = propElement.Value
                                            .Replace("<command></command>", $"<command>{string.Join(' ', commandArguments)}</command>");
                    }
                }

                // Configures the post-build event(s) for Visual Studio

                List <string> taskArguments = new List <string>
                {
                    executableWin.Quoted(), "pack",
                    "-a", "$(TargetPath)".Quoted(),
                    "-n", settings.FlutterPackageName,
                    "-o", (settings.CreateFlutterSubfolder ? $"$(SolutionDir)\\{settings.FlutterSubfolderName}" : "$(SolutionDir)").Quoted(),
                    "--force"
                };

                ProjectTargetElement targetElement = prjElement.Targets.FirstOrDefault(t => t.Name == "PostBuild");
                ProjectTaskElement   taskElement   = targetElement.AddTask("Exec");
                taskElement.SetParameter("Command", string.Join(' ', taskArguments));

                prjElement.Save();
            }
            catch (Exception e)
            {
                Log.Ex(e);
                throw new CommandLineException(CommandLineErrorCode.NewProject_CreateDotNetProjectsFailed, e);
            }
        }