Unverified Commit b92bb62d authored by stuartmorgan's avatar stuartmorgan Committed by GitHub

Fix Windows and Linux plugin template filenames (#66997)

parent 03190b8e
...@@ -166,6 +166,7 @@ class Template { ...@@ -166,6 +166,7 @@ class Template {
final String projectName = context['projectName'] as String; final String projectName = context['projectName'] as String;
final String androidIdentifier = context['androidIdentifier'] as String; final String androidIdentifier = context['androidIdentifier'] as String;
final String pluginClass = context['pluginClass'] as String; final String pluginClass = context['pluginClass'] as String;
final String pluginClassSnakeCase = context['pluginClassSnakeCase'] as String;
final String destinationDirPath = destination.absolute.path; final String destinationDirPath = destination.absolute.path;
final String pathSeparator = _fileSystem.path.separator; final String pathSeparator = _fileSystem.path.separator;
String finalDestinationPath = _fileSystem.path String finalDestinationPath = _fileSystem.path
...@@ -181,6 +182,10 @@ class Template { ...@@ -181,6 +182,10 @@ class Template {
if (projectName != null) { if (projectName != null) {
finalDestinationPath = finalDestinationPath.replaceAll('projectName', projectName); finalDestinationPath = finalDestinationPath.replaceAll('projectName', projectName);
} }
// This must be before the pluginClass replacement step.
if (pluginClassSnakeCase != null) {
finalDestinationPath = finalDestinationPath.replaceAll('pluginClassSnakeCase', pluginClassSnakeCase);
}
if (pluginClass != null) { if (pluginClass != null) {
finalDestinationPath = finalDestinationPath.replaceAll('pluginClass', pluginClass); finalDestinationPath = finalDestinationPath.replaceAll('pluginClass', pluginClass);
} }
......
...@@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.10) ...@@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.10)
set(PROJECT_NAME "{{projectName}}") set(PROJECT_NAME "{{projectName}}")
project(${PROJECT_NAME} LANGUAGES CXX) project(${PROJECT_NAME} LANGUAGES CXX)
set(PLUGIN_NAME "${PROJECT_NAME}_plugin") # This value is used when generating builds using this plugin, so it must
# not be changed
set(PLUGIN_NAME "{{projectName}}_plugin")
add_library(${PLUGIN_NAME} SHARED add_library(${PLUGIN_NAME} SHARED
"${PLUGIN_NAME}.cc" "{{pluginClassSnakeCase}}.cc"
) )
apply_standard_settings(${PLUGIN_NAME}) apply_standard_settings(${PLUGIN_NAME})
set_target_properties(${PLUGIN_NAME} PROPERTIES set_target_properties(${PLUGIN_NAME} PROPERTIES
......
#include "include/{{projectName}}/{{projectName}}_plugin.h" #include "include/{{projectName}}/{{pluginClassSnakeCase}}.h"
#include <flutter_linux/flutter_linux.h> #include <flutter_linux/flutter_linux.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
......
...@@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.15) ...@@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.15)
set(PROJECT_NAME "{{projectName}}") set(PROJECT_NAME "{{projectName}}")
project(${PROJECT_NAME} LANGUAGES CXX) project(${PROJECT_NAME} LANGUAGES CXX)
set(PLUGIN_NAME "${PROJECT_NAME}_plugin") # This value is used when generating builds using this plugin, so it must
# not be changed
set(PLUGIN_NAME "{{projectName}}_plugin")
add_library(${PLUGIN_NAME} SHARED add_library(${PLUGIN_NAME} SHARED
"${PLUGIN_NAME}.cpp" "{{pluginClassSnakeCase}}.cpp"
) )
apply_standard_settings(${PLUGIN_NAME}) apply_standard_settings(${PLUGIN_NAME})
set_target_properties(${PLUGIN_NAME} PROPERTIES set_target_properties(${PLUGIN_NAME} PROPERTIES
......
#include "include/{{projectName}}/{{projectName}}_plugin.h" #include "include/{{projectName}}/{{pluginClassSnakeCase}}.h"
// This must be included before many other Windows headers. // This must be included before many other Windows headers.
#include <windows.h> #include <windows.h>
......
...@@ -263,8 +263,8 @@ ...@@ -263,8 +263,8 @@
"templates/plugin/lib/projectName.dart.tmpl", "templates/plugin/lib/projectName.dart.tmpl",
"templates/plugin/LICENSE.tmpl", "templates/plugin/LICENSE.tmpl",
"templates/plugin/linux.tmpl/CMakeLists.txt.tmpl", "templates/plugin/linux.tmpl/CMakeLists.txt.tmpl",
"templates/plugin/linux.tmpl/include/projectName.tmpl/projectName_plugin.h.tmpl", "templates/plugin/linux.tmpl/include/projectName.tmpl/pluginClassSnakeCase.h.tmpl",
"templates/plugin/linux.tmpl/projectName_plugin.cc.tmpl", "templates/plugin/linux.tmpl/pluginClassSnakeCase.cc.tmpl",
"templates/plugin/macos.tmpl/Classes/pluginClass.swift.tmpl", "templates/plugin/macos.tmpl/Classes/pluginClass.swift.tmpl",
"templates/plugin/macos.tmpl/projectName.podspec.tmpl", "templates/plugin/macos.tmpl/projectName.podspec.tmpl",
"templates/plugin/projectName.iml.tmpl", "templates/plugin/projectName.iml.tmpl",
...@@ -273,8 +273,8 @@ ...@@ -273,8 +273,8 @@
"templates/plugin/test/projectName_test.dart.tmpl", "templates/plugin/test/projectName_test.dart.tmpl",
"templates/plugin/windows.tmpl/.gitignore", "templates/plugin/windows.tmpl/.gitignore",
"templates/plugin/windows.tmpl/CMakeLists.txt.tmpl", "templates/plugin/windows.tmpl/CMakeLists.txt.tmpl",
"templates/plugin/windows.tmpl/include/projectName.tmpl/projectName_plugin.h.tmpl", "templates/plugin/windows.tmpl/include/projectName.tmpl/pluginClassSnakeCase.h.tmpl",
"templates/plugin/windows.tmpl/projectName_plugin.cpp.tmpl", "templates/plugin/windows.tmpl/pluginClassSnakeCase.cpp.tmpl",
"templates/plugin/lib/projectName_web.dart.tmpl" "templates/plugin/lib/projectName_web.dart.tmpl"
] ]
} }
...@@ -2044,6 +2044,148 @@ void main() { ...@@ -2044,6 +2044,148 @@ void main() {
expect(buildContent.contains('targetSdkVersion 29'), true); expect(buildContent.contains('targetSdkVersion 29'), true);
}); });
testUsingContext('Linux plugins handle partially camel-case project names correctly', () async {
Cache.flutterRoot = '../..';
when(mockFlutterVersion.frameworkRevision).thenReturn(frameworkRevision);
when(mockFlutterVersion.channel).thenReturn(frameworkChannel);
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
const String projectName = 'foo_BarBaz';
final Directory projectDir = tempDir.childDirectory(projectName);
await runner.run(<String>['create', '--no-pub', '--template=plugin', '--platforms=linux', projectDir.path]);
final Directory platformDir = projectDir.childDirectory('linux');
const String classFilenameBase = 'foo_bar_baz_plugin';
const String headerName = '$classFilenameBase.h';
final File headerFile = platformDir
.childDirectory('include')
.childDirectory(projectName)
.childFile(headerName);
final File implFile = platformDir.childFile('$classFilenameBase.cc');
// Ensure that the files have the right names.
expect(headerFile.existsSync(), true);
expect(implFile.existsSync(), true);
// Ensure that the include is correct.
expect(implFile.readAsStringSync(), contains(headerName));
// Ensure that the CMake file has the right target and source values.
final String cmakeContents = platformDir.childFile('CMakeLists.txt').readAsStringSync();
expect(cmakeContents, contains('"$classFilenameBase.cc"'));
expect(cmakeContents, contains('set(PLUGIN_NAME "foo_BarBaz_plugin")'));
}, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true),
});
testUsingContext('Windows plugins handle partially camel-case project names correctly', () async {
Cache.flutterRoot = '../..';
when(mockFlutterVersion.frameworkRevision).thenReturn(frameworkRevision);
when(mockFlutterVersion.channel).thenReturn(frameworkChannel);
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
const String projectName = 'foo_BarBaz';
final Directory projectDir = tempDir.childDirectory(projectName);
await runner.run(<String>['create', '--no-pub', '--template=plugin', '--platforms=windows', projectDir.path]);
final Directory platformDir = projectDir.childDirectory('windows');
const String classFilenameBase = 'foo_bar_baz_plugin';
const String headerName = '$classFilenameBase.h';
final File headerFile = platformDir
.childDirectory('include')
.childDirectory(projectName)
.childFile(headerName);
final File implFile = platformDir.childFile('$classFilenameBase.cpp');
// Ensure that the files have the right names.
expect(headerFile.existsSync(), true);
expect(implFile.existsSync(), true);
// Ensure that the include is correct.
expect(implFile.readAsStringSync(), contains(headerName));
// Ensure that the plugin target name matches the post-processed version.
// Ensure that the CMake file has the right target and source values.
final String cmakeContents = platformDir.childFile('CMakeLists.txt').readAsStringSync();
expect(cmakeContents, contains('"$classFilenameBase.cpp"'));
expect(cmakeContents, contains('set(PLUGIN_NAME "foo_BarBaz_plugin")'));
}, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
testUsingContext('Linux plugins handle project names ending in _plugin correctly', () async {
Cache.flutterRoot = '../..';
when(mockFlutterVersion.frameworkRevision).thenReturn(frameworkRevision);
when(mockFlutterVersion.channel).thenReturn(frameworkChannel);
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
const String projectName = 'foo_bar_plugin';
final Directory projectDir = tempDir.childDirectory(projectName);
await runner.run(<String>['create', '--no-pub', '--template=plugin', '--platforms=linux', projectDir.path]);
final Directory platformDir = projectDir.childDirectory('linux');
// If the project already ends in _plugin, it shouldn't be added again.
const String classFilenameBase = projectName;
const String headerName = '$classFilenameBase.h';
final File headerFile = platformDir
.childDirectory('include')
.childDirectory(projectName)
.childFile(headerName);
final File implFile = platformDir.childFile('$classFilenameBase.cc');
// Ensure that the files have the right names.
expect(headerFile.existsSync(), true);
expect(implFile.existsSync(), true);
// Ensure that the include is correct.
expect(implFile.readAsStringSync(), contains(headerName));
// Ensure that the CMake file has the right target and source values.
final String cmakeContents = platformDir.childFile('CMakeLists.txt').readAsStringSync();
expect(cmakeContents, contains('"$classFilenameBase.cc"'));
// The "_plugin_plugin" suffix is intentional; because the target names must
// be unique across the ecosystem, no canonicalization can be done,
// otherwise plugins called "foo_bar" and "foo_bar_plugin" would collide in
// builds.
expect(cmakeContents, contains('set(PLUGIN_NAME "foo_bar_plugin_plugin")'));
}, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true),
});
testUsingContext('Windows plugins handle project names ending in _plugin correctly', () async {
Cache.flutterRoot = '../..';
when(mockFlutterVersion.frameworkRevision).thenReturn(frameworkRevision);
when(mockFlutterVersion.channel).thenReturn(frameworkChannel);
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
const String projectName = 'foo_bar_plugin';
final Directory projectDir = tempDir.childDirectory(projectName);
await runner.run(<String>['create', '--no-pub', '--template=plugin', '--platforms=windows', projectDir.path]);
final Directory platformDir = projectDir.childDirectory('windows');
// If the project already ends in _plugin, it shouldn't be added again.
const String classFilenameBase = projectName;
const String headerName = '$classFilenameBase.h';
final File headerFile = platformDir
.childDirectory('include')
.childDirectory(projectName)
.childFile(headerName);
final File implFile = platformDir.childFile('$classFilenameBase.cpp');
// Ensure that the files have the right names.
expect(headerFile.existsSync(), true);
expect(implFile.existsSync(), true);
// Ensure that the include is correct.
expect(implFile.readAsStringSync(), contains(headerName));
// Ensure that the CMake file has the right target and source values.
final String cmakeContents = platformDir.childFile('CMakeLists.txt').readAsStringSync();
expect(cmakeContents, contains('"$classFilenameBase.cpp"'));
// The "_plugin_plugin" suffix is intentional; because the target names must
// be unique across the ecosystem, no canonicalization can be done,
// otherwise plugins called "foo_bar" and "foo_bar_plugin" would collide in
// builds.
expect(cmakeContents, contains('set(PLUGIN_NAME "foo_bar_plugin_plugin")'));
}, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
} }
Future<void> _createProject( Future<void> _createProject(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment