From c5fdb82de12318049832cf8fa6184cd5e17f34d8 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Fri, 9 Apr 2021 13:59:20 -0700 Subject: [PATCH] [flutter_tools] treat win32 plugins as uwp plugins (#80131) --- packages/flutter_tools/lib/src/plugins.dart | 84 ++++++++++--------- .../general.shard/windows/plugins_test.dart | 74 ++++++++++++++++ 2 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 packages/flutter_tools/test/general.shard/windows/plugins_test.dart diff --git a/packages/flutter_tools/lib/src/plugins.dart b/packages/flutter_tools/lib/src/plugins.dart index 5326c5711d5..219d846fcbd 100644 --- a/packages/flutter_tools/lib/src/plugins.dart +++ b/packages/flutter_tools/lib/src/plugins.dart @@ -15,6 +15,7 @@ import 'base/error_handling_io.dart'; import 'base/file_system.dart'; import 'base/os.dart'; import 'base/platform.dart'; +import 'base/template.dart'; import 'base/version.dart'; import 'convert.dart'; import 'dart/package_map.dart'; @@ -23,10 +24,9 @@ import 'globals.dart' as globals; import 'platform_plugins.dart'; import 'project.dart'; -void _renderTemplateToFile(String template, dynamic context, String filePath) { - final String renderedTemplate = globals.templateRenderer +void _renderTemplateToFile(String template, dynamic context, File file, TemplateRenderer templateRenderer) { + final String renderedTemplate = templateRenderer .renderString(template, context, htmlEscapeValues: false); - final File file = globals.fs.file(filePath); file.createSync(recursive: true); file.writeAsStringSync(renderedTemplate); } @@ -690,7 +690,8 @@ Future _writeAndroidPluginRegistrant(FlutterProject project, List _renderTemplateToFile( templateContent, templateContext, - registryPath, + globals.fs.file(registryPath), + globals.templateRenderer, ); } @@ -910,22 +911,25 @@ Future _writeIOSPluginRegistrant(FlutterProject project, List plug 'plugins': iosPlugins, }; if (project.isModule) { - final String registryDirectory = project.ios.pluginRegistrantHost.path; + final Directory registryDirectory = project.ios.pluginRegistrantHost; _renderTemplateToFile( _pluginRegistrantPodspecTemplate, context, - globals.fs.path.join(registryDirectory, 'FlutterPluginRegistrant.podspec'), + registryDirectory.childFile('FlutterPluginRegistrant.podspec'), + globals.templateRenderer, ); } _renderTemplateToFile( _objcPluginRegistryHeaderTemplate, context, - project.ios.pluginRegistrantHeader.path, + project.ios.pluginRegistrantHeader, + globals.templateRenderer, ); _renderTemplateToFile( _objcPluginRegistryImplementationTemplate, context, - project.ios.pluginRegistrantImplementation.path, + project.ios.pluginRegistrantImplementation, + globals.templateRenderer, ); } @@ -936,10 +940,11 @@ Future _writeIOSPluginRegistrant(FlutterProject project, List plug /// designed to be included by the main CMakeLists.txt, so it relative to /// that file, rather than the generated file. String _cmakeRelativePluginSymlinkDirectoryPath(CmakeBasedProject project) { + final FileSystem fileSystem = project.pluginSymlinkDirectory.fileSystem; final String makefileDirPath = project.cmakeFile.parent.absolute.path; // CMake always uses posix-style path separators, regardless of the platform. final path.Context cmakePathContext = path.Context(style: path.Style.posix); - final List relativePathComponents = globals.fs.path.split(globals.fs.path.relative( + final List relativePathComponents = fileSystem.path.split(fileSystem.path.relative( project.pluginSymlinkDirectory.absolute.path, from: makefileDirPath, )); @@ -955,28 +960,30 @@ Future _writeLinuxPluginFiles(FlutterProject project, List plugins 'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.linux), }; await _writeLinuxPluginRegistrant(project.linux.managedDirectory, context); - await _writePluginCmakefile(project.linux.generatedPluginCmakeFile, context); + await _writePluginCmakefile(project.linux.generatedPluginCmakeFile, context, globals.templateRenderer); } Future _writeLinuxPluginRegistrant(Directory destination, Map templateContext) async { - final String registryDirectory = destination.path; _renderTemplateToFile( _linuxPluginRegistryHeaderTemplate, templateContext, - globals.fs.path.join(registryDirectory, 'generated_plugin_registrant.h'), + destination.childFile('generated_plugin_registrant.h'), + globals.templateRenderer, ); _renderTemplateToFile( _linuxPluginRegistryImplementationTemplate, templateContext, - globals.fs.path.join(registryDirectory, 'generated_plugin_registrant.cc'), + destination.childFile('generated_plugin_registrant.cc'), + globals.templateRenderer, ); } -Future _writePluginCmakefile(File destinationFile, Map templateContext) async { +Future _writePluginCmakefile(File destinationFile, Map templateContext, TemplateRenderer templateRenderer) async { _renderTemplateToFile( _pluginCmakefileTemplate, templateContext, - destinationFile.path, + destinationFile, + templateRenderer, ); } @@ -988,11 +995,11 @@ Future _writeMacOSPluginRegistrant(FlutterProject project, List pl 'framework': 'FlutterMacOS', 'plugins': macosPlugins, }; - final String registryDirectory = project.macos.managedDirectory.path; _renderTemplateToFile( _swiftPluginRegistryTemplate, context, - globals.fs.path.join(registryDirectory, 'GeneratedPluginRegistrant.swift'), + project.macos.managedDirectory.childFile('GeneratedPluginRegistrant.swift'), + globals.templateRenderer, ); } @@ -1012,7 +1019,8 @@ List _filterNativePlugins(List plugins, String platformKey) { }).toList(); } -Future _writeWindowsPluginFiles(FlutterProject project, List plugins) async { +@visibleForTesting +Future writeWindowsPluginFiles(FlutterProject project, List plugins, TemplateRenderer templateRenderer) async { final List nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey); final List> windowsPlugins = _extractPlatformMaps(nativePlugins, WindowsPlugin.kConfigKey); final Map context = { @@ -1020,36 +1028,37 @@ Future _writeWindowsPluginFiles(FlutterProject project, List plugi 'plugins': windowsPlugins, 'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windows), }; - await _writeCppPluginRegistrant(project.windows.managedDirectory, context); - await _writePluginCmakefile(project.windows.generatedPluginCmakeFile, context); + await _writeCppPluginRegistrant(project.windows.managedDirectory, context, templateRenderer); + await _writePluginCmakefile(project.windows.generatedPluginCmakeFile, context, templateRenderer); } -/// The tooling does not currently support any UWP plugins. -/// -/// Always generates an empty file to satisfy the cmake template. -Future _writeWindowsUwpPluginFiles(FlutterProject project, List plugins) async { - final List nativePlugins = []; +/// The tooling currently treats UWP and win32 as identical for the +/// purposes of tooling support and initial UWP bootstrap. +@visibleForTesting +Future writeWindowsUwpPluginFiles(FlutterProject project, List plugins, TemplateRenderer templateRenderer) async { + final List nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey); final List> windowsPlugins = _extractPlatformMaps(nativePlugins, WindowsPlugin.kConfigKey); final Map context = { 'os': 'windows', 'plugins': windowsPlugins, 'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windowsUwp), }; - await _writeCppPluginRegistrant(project.windowsUwp.managedDirectory, context); - await _writePluginCmakefile(project.windowsUwp.generatedPluginCmakeFile, context); + await _writeCppPluginRegistrant(project.windowsUwp.managedDirectory, context, templateRenderer); + await _writePluginCmakefile(project.windowsUwp.generatedPluginCmakeFile, context, templateRenderer); } -Future _writeCppPluginRegistrant(Directory destination, Map templateContext) async { - final String registryDirectory = destination.path; +Future _writeCppPluginRegistrant(Directory destination, Map templateContext, TemplateRenderer templateRenderer) async { _renderTemplateToFile( _cppPluginRegistryHeaderTemplate, templateContext, - globals.fs.path.join(registryDirectory, 'generated_plugin_registrant.h'), + destination.childFile('generated_plugin_registrant.h'), + templateRenderer, ); _renderTemplateToFile( _cppPluginRegistryImplementationTemplate, templateContext, - globals.fs.path.join(registryDirectory, 'generated_plugin_registrant.cc'), + destination.childFile('generated_plugin_registrant.cc'), + templateRenderer, ); } @@ -1058,16 +1067,15 @@ Future _writeWebPluginRegistrant(FlutterProject project, List plug final Map context = { 'plugins': webPlugins, }; - final String registryDirectory = project.web.libDirectory.path; - final String filePath = globals.fs.path.join(registryDirectory, 'generated_plugin_registrant.dart'); + final File pluginFile = project.web.libDirectory.childFile('generated_plugin_registrant.dart'); if (webPlugins.isEmpty) { - final File file = globals.fs.file(filePath); - return ErrorHandlingFileSystem.deleteIfExists(file); + return ErrorHandlingFileSystem.deleteIfExists(pluginFile); } else { _renderTemplateToFile( _dartPluginRegistryTemplate, context, - filePath, + pluginFile, + globals.templateRenderer, ); } } @@ -1221,10 +1229,10 @@ Future injectPlugins( await _writeMacOSPluginRegistrant(project, plugins); } if (windowsPlatform) { - await _writeWindowsPluginFiles(project, plugins); + await writeWindowsPluginFiles(project, plugins, globals.templateRenderer); } if (winUwpPlatform) { - await _writeWindowsUwpPluginFiles(project, plugins); + await writeWindowsUwpPluginFiles(project, plugins, globals.templateRenderer); } if (!project.isModule) { final List darwinProjects = [ diff --git a/packages/flutter_tools/test/general.shard/windows/plugins_test.dart b/packages/flutter_tools/test/general.shard/windows/plugins_test.dart new file mode 100644 index 00000000000..09324d1a2d4 --- /dev/null +++ b/packages/flutter_tools/test/general.shard/windows/plugins_test.dart @@ -0,0 +1,74 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// @dart = 2.8 + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:file_testing/file_testing.dart'; +import 'package:flutter_tools/src/base/template.dart'; +import 'package:flutter_tools/src/isolated/mustache_template.dart'; +import 'package:flutter_tools/src/platform_plugins.dart'; +import 'package:flutter_tools/src/plugins.dart'; +import 'package:flutter_tools/src/project.dart'; + +import '../../src/common.dart'; + +const TemplateRenderer renderer = MustacheTemplateRenderer(); + +void main() { + + testWithoutContext('injects Win32 plugins', () async { + final FileSystem fileSystem = MemoryFileSystem.test(); + setUpProject(fileSystem); + final FlutterProject flutterProject = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory); + + await writeWindowsPluginFiles(flutterProject, [ + Plugin( + name: 'test', + path: 'foo', + platforms: const {WindowsPlugin.kConfigKey: WindowsPlugin(name: 'test', pluginClass: 'Foo')}, + dependencies: [], + ), + ], renderer); + + final Directory managed = flutterProject.windows.managedDirectory; + expect(flutterProject.windows.generatedPluginCmakeFile, exists); + expect(managed.childFile('generated_plugin_registrant.h'), exists); + expect( + managed.childFile('generated_plugin_registrant.cc').readAsStringSync(), + contains('#include '), + ); + }); + + testWithoutContext('UWP injects Win32 plugins', () async { + final FileSystem fileSystem = MemoryFileSystem.test(); + setUpProject(fileSystem); + final FlutterProject flutterProject = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory); + + await writeWindowsUwpPluginFiles(flutterProject, [ + Plugin( + name: 'test', + path: 'foo', + platforms: const {WindowsPlugin.kConfigKey: WindowsPlugin(name: 'test', pluginClass: 'Foo')}, + dependencies: [], + ), + ], renderer); + + final Directory managed = flutterProject.windowsUwp.managedDirectory; + expect(flutterProject.windowsUwp.generatedPluginCmakeFile, exists); + expect(managed.childFile('generated_plugin_registrant.h'), exists); + expect( + managed.childFile('generated_plugin_registrant.cc').readAsStringSync(), + contains('#include '), + ); + }); +} + +void setUpProject(FileSystem fileSystem) { + fileSystem.file('pubspec.yaml').createSync(); + fileSystem.file('winuwp/project_version') + ..createSync(recursive: true) + ..writeAsStringSync('0'); +}