Unverified Commit 4d1b74a0 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] generate empty plugin registrants for winuwp and fix local...

[flutter_tools] generate empty plugin registrants for winuwp and fix local engine for winuwp_ (#79827)
parent d5cecb11
......@@ -61,8 +61,9 @@ or
else
'flutter'
]);
final String bundlePlatform = targetPlatform == 'windows-x64' ? 'windows' : targetPlatform;
final String target = '${buildMode}_bundle_${bundlePlatform}_assets';
final bool uwp = targetPlatform.contains('uwp');
final String bundlePlatform = targetPlatform.startsWith('windows-x64') ? 'windows' : targetPlatform;
final String target = '${buildMode}_bundle_${bundlePlatform}_assets${uwp ? '_uwp' : ''}';
final Process assembleProcess = await Process.start(
flutterExecutable,
<String>[
......
......@@ -28,7 +28,20 @@ const List<String> _kWindowsArtifacts = <String>[
'flutter_windows.h',
];
const List<String> _kWindowsUwpArtifacts = <String>[
'flutter_windows_winuwp.dll',
'flutter_windows_winuwp.dll.exp',
'flutter_windows_winuwp.dll.lib',
'flutter_windows_winuwp.dll.pdb',
'flutter_export.h',
'flutter_messenger.h',
'flutter_plugin_registrar.h',
'flutter_texture_registrar.h',
'flutter_windows.h',
];
const String _kWindowsDepfile = 'windows_engine_sources.d';
const String _kWindowsUwpDepfile = 'windows_uwp_engine_sources.d';
/// Copies the Windows desktop embedding files to the copy directory.
class UnpackWindows extends Target {
......@@ -96,6 +109,82 @@ class UnpackWindows extends Target {
}
}
/// Copies the Windows desktop embedding files to the copy directory.
class UnpackWindowsUwp extends Target {
const UnpackWindowsUwp();
@override
String get name => 'unpack_windows_uwp';
@override
List<Source> get inputs => const <Source>[
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/windows.dart'),
];
@override
List<Source> get outputs => const <Source>[];
@override
List<String> get depfiles => const <String>[_kWindowsUwpDepfile];
@override
List<Target> get dependencies => const <Target>[];
@override
Future<void> build(Environment environment) async {
// These artifact look ups need to modified to windows-x64-uwp once
// the cache updates have landed.
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
final String engineSourcePath = environment.artifacts
.getArtifactPath(
Artifact.windowsDesktopPath,
platform: TargetPlatform.windows_x64,
mode: buildMode,
);
final String clientSourcePath = environment.artifacts
.getArtifactPath(
Artifact.windowsCppClientWrapper,
platform: TargetPlatform.windows_x64,
mode: buildMode,
);
final Directory outputDirectory = environment.fileSystem.directory(
environment.fileSystem.path.join(
environment.projectDir.path,
'winuwp',
'flutter',
'ephemeral',
),
);
final Depfile depfile = unpackDesktopArtifacts(
fileSystem: environment.fileSystem,
artifacts: _kWindowsUwpArtifacts,
engineSourcePath: engineSourcePath,
outputDirectory: outputDirectory,
clientSourcePaths: <String>[clientSourcePath],
icuDataPath: environment.artifacts.getArtifactPath(
Artifact.icuData,
platform: TargetPlatform.windows_x64
)
);
// Copy flutter_windows.h into flutter directory as well.
final File flutterWindows = outputDirectory.childFile('flutter_windows.h');
final File flutterWindowsDest = flutterWindows.parent.parent.childFile('flutter_windows.h');
flutterWindows.copySync(flutterWindowsDest.path);
depfile.outputs.add(flutterWindowsDest);
//
final DepfileService depfileService = DepfileService(
fileSystem: environment.fileSystem,
logger: environment.logger,
);
depfileService.writeToFile(
depfile,
environment.buildDir.childFile(_kWindowsUwpDepfile),
);
}
}
/// Creates a bundle for the Windows desktop target.
abstract class BundleWindowsAssets extends Target {
const BundleWindowsAssets();
......@@ -151,6 +240,18 @@ abstract class BundleWindowsAssets extends Target {
}
}
/// Creates a bundle for the Windows desktop target.
abstract class BundleWindowsAssetsUwp extends BundleWindowsAssets {
const BundleWindowsAssetsUwp();
@override
List<Target> get dependencies => const <Target>[
KernelSnapshot(),
UnpackWindowsUwp(),
];
}
/// A wrapper for AOT compilation that copies app.so into the output directory.
class WindowsAotBundle extends Target {
/// Create a [WindowsAotBundle] wrapper for [aotTarget].
......@@ -236,3 +337,53 @@ class DebugBundleWindowsAssets extends BundleWindowsAssets {
const Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'),
];
}
class ReleaseBundleWindowsAssetsUwp extends BundleWindowsAssetsUwp {
const ReleaseBundleWindowsAssetsUwp();
@override
String get name => 'release_bundle_windows_assets_uwp';
@override
List<Source> get outputs => const <Source>[];
@override
List<Target> get dependencies => <Target>[
...super.dependencies,
const WindowsAotBundle(AotElfRelease(TargetPlatform.windows_x64)),
];
}
class ProfileBundleWindowsAssetsUwp extends BundleWindowsAssetsUwp {
const ProfileBundleWindowsAssetsUwp();
@override
String get name => 'profile_bundle_windows_assets_uwp';
@override
List<Source> get outputs => const <Source>[];
@override
List<Target> get dependencies => <Target>[
...super.dependencies,
const WindowsAotBundle(AotElfProfile(TargetPlatform.windows_x64)),
];
}
class DebugBundleWindowsAssetsUwp extends BundleWindowsAssetsUwp {
const DebugBundleWindowsAssetsUwp();
@override
String get name => 'debug_bundle_windows_assets_uwp';
@override
List<Source> get inputs => <Source>[
const Source.pattern('{BUILD_DIR}/app.dill'),
];
@override
List<Source> get outputs => <Source>[
const Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'),
];
}
......@@ -79,6 +79,10 @@ List<Target> _kDefaultTargets = <Target>[
const DebugBundleWindowsAssets(),
const ProfileBundleWindowsAssets(),
const ReleaseBundleWindowsAssets(),
// Windows UWP targets
const DebugBundleWindowsAssetsUwp(),
const ProfileBundleWindowsAssetsUwp(),
const ReleaseBundleWindowsAssetsUwp(),
];
// TODO(ianh): https://github.com/dart-lang/args/issues/181 will allow us to remove useLegacyNames
......
......@@ -431,7 +431,7 @@ abstract class CreateBase extends FlutterCommand {
macOSPlatform: templateContext['macos'] as bool ?? false,
windowsPlatform: templateContext['windows'] as bool ?? false,
webPlatform: templateContext['web'] as bool ?? false,
windowsUwpPlatform: templateContext['winuwp'] as bool ?? false,
winUwpPlatform: templateContext['winuwp'] as bool ?? false,
);
}
if (templateContext['android'] == true) {
......
......@@ -1003,7 +1003,7 @@ List<Plugin> _filterNativePlugins(List<Plugin> plugins, String platformKey) {
}
Future<void> _writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugins) async {
final List<Plugin>nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
final List<Plugin> nativePlugins = _filterNativePlugins(plugins, WindowsPlugin.kConfigKey);
final List<Map<String, dynamic>> windowsPlugins = _extractPlatformMaps(nativePlugins, WindowsPlugin.kConfigKey);
final Map<String, dynamic> context = <String, dynamic>{
'os': 'windows',
......@@ -1014,6 +1014,21 @@ Future<void> _writeWindowsPluginFiles(FlutterProject project, List<Plugin> plugi
await _writePluginCmakefile(project.windows.generatedPluginCmakeFile, context);
}
/// The tooling does not currently support any UWP plugins.
///
/// Always generates an empty file to satisfy the cmake template.
Future<void> _writeWindowsUwpPluginFiles(FlutterProject project, List<Plugin> plugins) async {
final List<Plugin> nativePlugins = <Plugin>[];
final List<Map<String, dynamic>> windowsPlugins = _extractPlatformMaps(nativePlugins, WindowsPlugin.kConfigKey);
final Map<String, dynamic> context = <String, dynamic>{
'os': 'windows',
'plugins': windowsPlugins,
'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(project.windowsUwp),
};
await _writeCppPluginRegistrant(project.windowsUwp.managedDirectory, context);
await _writePluginCmakefile(project.windowsUwp.generatedPluginCmakeFile, context);
}
Future<void> _writeCppPluginRegistrant(Directory destination, Map<String, dynamic> templateContext) async {
final String registryDirectory = destination.path;
_renderTemplateToFile(
......@@ -1078,6 +1093,13 @@ void createPluginSymlinks(FlutterProject project, {bool force = false}) {
force: force,
);
}
if (featureFlags.isWindowsUwpEnabled && project.windowsUwp.existsSync()) {
_createPlatformPluginSymlinks(
project.windowsUwp.pluginSymlinkDirectory,
<dynamic>[],
force: force,
);
}
}
/// Handler for symlink failures which provides specific instructions for known
......@@ -1170,6 +1192,7 @@ Future<void> injectPlugins(
bool linuxPlatform = false,
bool macOSPlatform = false,
bool windowsPlatform = false,
bool winUwpPlatform = false,
bool webPlatform = false,
}) async {
final List<Plugin> plugins = await findPlugins(project);
......@@ -1190,6 +1213,9 @@ Future<void> injectPlugins(
if (windowsPlatform) {
await _writeWindowsPluginFiles(project, plugins);
}
if (winUwpPlatform) {
await _writeWindowsUwpPluginFiles(project, plugins);
}
if (!project.isModule) {
final List<XcodeBasedProject> darwinProjects = <XcodeBasedProject>[
if (iosPlatform) project.ios,
......
......@@ -279,6 +279,7 @@ class FlutterProject {
macOSPlatform: featureFlags.isMacOSEnabled && macos.existsSync(),
windowsPlatform: featureFlags.isWindowsEnabled && windows.existsSync(),
webPlatform: featureFlags.isWebEnabled && web.existsSync(),
winUwpPlatform: featureFlags.isWindowsUwpEnabled && windowsUwp.existsSync(),
);
}
......@@ -291,7 +292,7 @@ class FlutterProject {
bool macOSPlatform = false,
bool windowsPlatform = false,
bool webPlatform = false,
bool windowsUwpPlatform = false,
bool winUwpPlatform = false,
}) async {
if (!directory.existsSync() || hasExampleApp || isPlugin) {
return;
......@@ -315,7 +316,7 @@ class FlutterProject {
if (webPlatform) {
await web.ensureReadyForPlatformSpecificTooling();
}
if (windowsUwpPlatform) {
if (winUwpPlatform) {
await windowsUwp.ensureReadyForPlatformSpecificTooling();
}
await injectPlugins(
......@@ -326,6 +327,7 @@ class FlutterProject {
macOSPlatform: macOSPlatform,
windowsPlatform: windowsPlatform,
webPlatform: webPlatform,
winUwpPlatform: winUwpPlatform,
);
}
......
......@@ -152,6 +152,10 @@ class LocalEngineLocator {
// Determine the host engine directory associated with the local engine:
// Strip '_sim_' since there are no host simulator builds.
String _getHostEngineBasename(String localEngineBasename) {
// Allow winuwp builds to be treated as host builds.
if (localEngineBasename.startsWith('winuwp')) {
return localEngineBasename;
}
String tmpBasename = localEngineBasename.replaceFirst('_sim_', '_');
tmpBasename = tmpBasename.substring(tmpBasename.indexOf('_') + 1);
// Strip suffix for various archs.
......
......@@ -150,11 +150,13 @@ Future<void> buildWindowsUwp(WindowsUwpProject windowsProject, BuildInfo buildIn
}
final Directory buildDirectory = globals.fs.directory(getWindowsBuildUwpDirectory());
final String buildModeName = getNameForBuildMode(buildInfo.mode ?? BuildMode.release);
final Status status = globals.logger.startProgress(
'Building Windows application...',
);
try {
await _runCmakeGeneration(cmakePath, buildDirectory, windowsProject.cmakeFile.parent);
await _runBuild(cmakePath, buildDirectory, buildModeName, install: false);
} finally {
status.cancel();
}
......@@ -188,7 +190,12 @@ Future<void> _runCmakeGeneration(String cmakePath, Directory buildDir, Directory
globals.flutterUsage.sendTiming('build', 'windows-cmake-generation', Duration(milliseconds: sw.elapsedMilliseconds));
}
Future<void> _runBuild(String cmakePath, Directory buildDir, String buildModeName) async {
Future<void> _runBuild(
String cmakePath,
Directory buildDir,
String buildModeName,
{ bool install = true }
) async {
final Stopwatch sw = Stopwatch()..start();
// MSBuild sends all output to stdout, including build errors. This surfaces
......@@ -204,8 +211,8 @@ Future<void> _runBuild(String cmakePath, Directory buildDir, String buildModeNam
buildDir.path,
'--config',
toTitleCase(buildModeName),
'--target',
'INSTALL',
if (install)
...<String>['--target', 'INSTALL'],
if (globals.logger.isVerbose)
'--verbose'
],
......
......@@ -107,16 +107,20 @@ void main() {
bool verbose = false,
void Function() onRun,
String stdout = '',
bool winuwp = false,
}) {
return FakeCommand(
command: <String>[
cmakePath,
'--build',
if (winuwp)
r'build\winuwp'
else
r'build\windows',
'--config',
buildMode,
'--target',
'INSTALL',
if (!winuwp)
...<String>['--target', 'INSTALL'],
if (verbose)
'--verbose'
],
......@@ -498,7 +502,10 @@ C:\foo\windows\runner\main.cpp(17,1): error C2065: 'Baz': undeclared identifier
}, overrides: <Type, Generator>{
Platform: () => windowsPlatform,
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[cmakeGenerationCommand(winuwp: true)]),
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
cmakeGenerationCommand(winuwp: true),
buildCommand('Release', stdout: 'STDOUT STUFF', winuwp: true),
]),
FeatureFlags: () => TestFeatureFlags(isWindowsUwpEnabled: true),
});
}
......
......@@ -27,7 +27,7 @@ final Platform kWindowsPlatform = FakePlatform(
);
void main() {
testWithoutContext('UnpackWindows copies files to the correct cache directory', () async {
testWithoutContext('UnpackWindows copies files to the correct windows/ cache directory', () async {
final Artifacts artifacts = Artifacts.test();
final FileSystem fileSystem = MemoryFileSystem.test(style: FileSystemStyle.windows);
final Environment environment = Environment.test(
......@@ -126,6 +126,107 @@ void main() {
]));
});
testWithoutContext('UnpackWindowsUwp copies files to the correct winuwp/ cache directory', () async {
final Artifacts artifacts = Artifacts.test();
final FileSystem fileSystem = MemoryFileSystem.test(style: FileSystemStyle.windows);
final Environment environment = Environment.test(
fileSystem.currentDirectory,
artifacts: artifacts,
processManager: FakeProcessManager.any(),
fileSystem: fileSystem,
logger: BufferLogger.test(),
defines: <String, String>{
kBuildMode: 'debug',
},
);
final DepfileService depfileService = DepfileService(
logger: BufferLogger.test(),
fileSystem: fileSystem,
);
environment.buildDir.createSync(recursive: true);
final String windowsDesktopPath = artifacts.getArtifactPath(Artifact.windowsDesktopPath, platform: TargetPlatform.windows_x64, mode: BuildMode.debug);
final String windowsCppClientWrapper = artifacts.getArtifactPath(Artifact.windowsCppClientWrapper, platform: TargetPlatform.windows_x64, mode: BuildMode.debug);
final String icuData = artifacts.getArtifactPath(Artifact.icuData, platform: TargetPlatform.windows_x64);
final List<String> requiredFiles = <String>[
'$windowsDesktopPath\\flutter_export.h',
'$windowsDesktopPath\\flutter_messenger.h',
'$windowsDesktopPath\\flutter_windows_winuwp.dll',
'$windowsDesktopPath\\flutter_windows_winuwp.dll.exp',
'$windowsDesktopPath\\flutter_windows_winuwp.dll.lib',
'$windowsDesktopPath\\flutter_windows_winuwp.dll.pdb',
'$windowsDesktopPath\\flutter_plugin_registrar.h',
'$windowsDesktopPath\\flutter_texture_registrar.h',
'$windowsDesktopPath\\flutter_windows.h',
icuData,
'$windowsCppClientWrapper\\foo',
r'C:\packages\flutter_tools\lib\src\build_system\targets\windows.dart',
];
for (final String path in requiredFiles) {
fileSystem.file(path).createSync(recursive: true);
}
fileSystem.directory('windows').createSync();
await const UnpackWindowsUwp().build(environment);
// Output files are copied correctly.
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_export.h'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_messenger.h'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_windows_winuwp.dll'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_windows_winuwp.dll.exp'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_windows_winuwp.dll.lib'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_windows_winuwp.dll.pdb'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_export.h'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_messenger.h'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_plugin_registrar.h'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_texture_registrar.h'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\ephemeral\flutter_windows.h'), exists);
expect(fileSystem.file(r'C:\winuwp\flutter\flutter_windows.h'), exists);
expect(fileSystem.file('C:\\winuwp\\flutter\\ephemeral\\$icuData'), exists);
expect(fileSystem.file('C:\\winuwp\\flutter\\ephemeral\\$windowsCppClientWrapper\\foo'), exists);
final File outputDepfile = environment.buildDir
.childFile('windows_uwp_engine_sources.d');
// Depfile is created correctly.
expect(outputDepfile, exists);
final List<String> inputPaths = depfileService.parse(outputDepfile)
.inputs.map((File file) => file.path).toList();
final List<String> outputPaths = depfileService.parse(outputDepfile)
.outputs.map((File file) => file.path).toList();
// Depfile has expected sources.
expect(inputPaths, unorderedEquals(<String>[
'$windowsDesktopPath\\flutter_export.h',
'$windowsDesktopPath\\flutter_messenger.h',
'$windowsDesktopPath\\flutter_windows_winuwp.dll',
'$windowsDesktopPath\\flutter_windows_winuwp.dll.exp',
'$windowsDesktopPath\\flutter_windows_winuwp.dll.lib',
'$windowsDesktopPath\\flutter_windows_winuwp.dll.pdb',
'$windowsDesktopPath\\flutter_plugin_registrar.h',
'$windowsDesktopPath\\flutter_texture_registrar.h',
'$windowsDesktopPath\\flutter_windows.h',
icuData,
'$windowsCppClientWrapper\\foo',
]));
expect(outputPaths, unorderedEquals(<String>[
r'C:\winuwp\flutter\ephemeral\flutter_export.h',
r'C:\winuwp\flutter\ephemeral\flutter_messenger.h',
r'C:\winuwp\flutter\ephemeral\flutter_windows_winuwp.dll',
r'C:\winuwp\flutter\ephemeral\flutter_windows_winuwp.dll.exp',
r'C:\winuwp\flutter\ephemeral\flutter_windows_winuwp.dll.lib',
r'C:\winuwp\flutter\ephemeral\flutter_windows_winuwp.dll.pdb',
r'C:\winuwp\flutter\ephemeral\flutter_plugin_registrar.h',
r'C:\winuwp\flutter\ephemeral\flutter_texture_registrar.h',
r'C:\winuwp\flutter\ephemeral\flutter_windows.h',
r'C:\winuwp\flutter\flutter_windows.h',
'C:\\winuwp\\flutter\\ephemeral\\$icuData',
'C:\\winuwp\\flutter\\ephemeral\\$windowsCppClientWrapper\\foo',
]));
});
// AssetBundleFactory still uses context injection
FileSystem fileSystem;
......
......@@ -95,6 +95,31 @@ void main() {
expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src'));
});
testWithoutContext('treats winuwp_debug_unopt as a host engine', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Directory localEngine = fileSystem
.directory('$kArbitraryEngineRoot/src/out/winuwp_debug_unopt/')
..createSync(recursive: true);
fileSystem.directory('$kArbitraryEngineRoot/src/out/winuwp_debug_unopt/').createSync(recursive: true);
final BufferLogger logger = BufferLogger.test();
final LocalEngineLocator localEngineLocator = LocalEngineLocator(
fileSystem: fileSystem,
flutterRoot: 'flutter/flutter',
logger: logger,
userMessages: UserMessages(),
platform: FakePlatform(environment: <String, String>{}),
);
expect(
await localEngineLocator.findEnginePath(null, localEngine.path, null),
matchesEngineBuildPaths(
hostEngine: '/arbitrary/engine/src/out/winuwp_debug_unopt',
targetEngine: '/arbitrary/engine/src/out/winuwp_debug_unopt',
),
);
});
testWithoutContext('works if --local-engine is specified and --local-engine-src-path '
'is determined by --local-engine', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
......
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