Migrator for android 35/16kb page size cmake flags for plugin_ffi (#156221)
Migrates existing instantions of `--template plugin_ffi` to deal with Android 15 16kb memory pages. Issue: * https://github.com/flutter/flutter/issues/155933 @reidbaker I could only find migrations that run from the root application. However the file needing to be migrated is a plugin. The plugin is being referenced from the example in the example dir and that's where the migrator is run, so I wrote the code so that it walks up to find the plugin. Do you know of a way to run migrators to non-root projects? (Can we even safely do so, e.g. the non-root could be in the pub cache, could be a different project on the users' system etc. So maybe checking if we are in the examples dir is the only sane thing to do?) Tests: * Added unit tests in `test/general.shard/android/migrations/cmake_android_16k_pages_migration_test.dart`
This commit is contained in:
parent
d768a72b85
commit
e695cd6e9a
@ -35,6 +35,7 @@ import 'gradle_errors.dart';
|
|||||||
import 'gradle_utils.dart';
|
import 'gradle_utils.dart';
|
||||||
import 'java.dart';
|
import 'java.dart';
|
||||||
import 'migrations/android_studio_java_gradle_conflict_migration.dart';
|
import 'migrations/android_studio_java_gradle_conflict_migration.dart';
|
||||||
|
import 'migrations/cmake_android_16k_pages_migration.dart';
|
||||||
import 'migrations/min_sdk_version_migration.dart';
|
import 'migrations/min_sdk_version_migration.dart';
|
||||||
import 'migrations/multidex_removal_migration.dart';
|
import 'migrations/multidex_removal_migration.dart';
|
||||||
import 'migrations/top_level_gradle_build_file_migration.dart';
|
import 'migrations/top_level_gradle_build_file_migration.dart';
|
||||||
@ -311,6 +312,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
|||||||
java: globals.java),
|
java: globals.java),
|
||||||
MinSdkVersionMigration(project.android, _logger),
|
MinSdkVersionMigration(project.android, _logger),
|
||||||
MultidexRemovalMigration(project.android, _logger),
|
MultidexRemovalMigration(project.android, _logger),
|
||||||
|
CmakeAndroid16kPagesMigration(project.android, _logger),
|
||||||
];
|
];
|
||||||
|
|
||||||
final ProjectMigration migration = ProjectMigration(migrators);
|
final ProjectMigration migration = ProjectMigration(migrators);
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
import '../../base/file_system.dart';
|
||||||
|
import '../../base/project_migrator.dart';
|
||||||
|
import '../../project.dart';
|
||||||
|
|
||||||
|
/// Adds the snippet to the CMake file to compile for Android 15.
|
||||||
|
///
|
||||||
|
/// Location of CMakeLists.txt is the src/CMakeLists.txt in the plugin
|
||||||
|
/// created with --template plugin_ffi.
|
||||||
|
///
|
||||||
|
/// ```cmake
|
||||||
|
/// if (ANDROID)
|
||||||
|
/// # Support Android 15 16k page size.
|
||||||
|
/// target_link_options({{projectName}} PRIVATE "-Wl,-z,max-page-size=16384")
|
||||||
|
/// endif()
|
||||||
|
/// ```
|
||||||
|
class CmakeAndroid16kPagesMigration extends ProjectMigrator {
|
||||||
|
CmakeAndroid16kPagesMigration(AndroidProject project, super.logger)
|
||||||
|
: _project = project;
|
||||||
|
|
||||||
|
final AndroidProject _project;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> migrate() async {
|
||||||
|
// If the migrator is run in the example directory, navigate to the
|
||||||
|
// plugin directory which contains src/CMakeLists.txt.
|
||||||
|
final File cmakeLists = _project.parent.directory.parent
|
||||||
|
.childDirectory('src/')
|
||||||
|
.childFile('CMakeLists.txt');
|
||||||
|
|
||||||
|
if (!cmakeLists.existsSync()) {
|
||||||
|
logger.printTrace(
|
||||||
|
'CMake project not found, skipping support Android 15 16k page size migration.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String original = cmakeLists.readAsStringSync();
|
||||||
|
|
||||||
|
if (original.contains('-Wl,-z,max-page-size=16384')) {
|
||||||
|
// Link flags already present.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final RegExp regex =
|
||||||
|
RegExp(r'target_compile_definitions\(([^ ]*) PUBLIC DART_SHARED_LIB\)');
|
||||||
|
final String? projectName = regex.firstMatch(original)?.group(1);
|
||||||
|
const String before = '''
|
||||||
|
PUBLIC DART_SHARED_LIB)
|
||||||
|
''';
|
||||||
|
|
||||||
|
/// Relevant template: templates/plugin_ffi/src.tmpl/CMakeLists.txt.tmpl
|
||||||
|
final String linkerFlags = '''
|
||||||
|
|
||||||
|
if (ANDROID)
|
||||||
|
# Support Android 15 16k page size.
|
||||||
|
target_link_options($projectName PRIVATE "-Wl,-z,max-page-size=16384")
|
||||||
|
endif()
|
||||||
|
''';
|
||||||
|
|
||||||
|
final String updated = original.replaceFirst(
|
||||||
|
before,
|
||||||
|
'$before$linkerFlags',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (original != updated) {
|
||||||
|
logger.printStatus(
|
||||||
|
'CMake missing support Android 15 16k page size, updating.');
|
||||||
|
cmakeLists.writeAsStringSync(updated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3202,6 +3202,9 @@ void main() {
|
|||||||
expect(cmakeLists.existsSync(), true);
|
expect(cmakeLists.existsSync(), true);
|
||||||
|
|
||||||
final String cmakeListsContent = await cmakeLists.readAsString();
|
final String cmakeListsContent = await cmakeLists.readAsString();
|
||||||
|
// If we ever change the flags, this should be accounted for in the
|
||||||
|
// migration as well:
|
||||||
|
// lib/src/android/migrations/cmake_android_16k_pages_migration.dart
|
||||||
const String expected16KbFlags = 'PRIVATE "-Wl,-z,max-page-size=16384")';
|
const String expected16KbFlags = 'PRIVATE "-Wl,-z,max-page-size=16384")';
|
||||||
expect(cmakeListsContent, contains(expected16KbFlags));
|
expect(cmakeListsContent, contains(expected16KbFlags));
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,136 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
import 'package:file/file.dart';
|
||||||
|
import 'package:file/memory.dart';
|
||||||
|
import 'package:flutter_tools/src/android/migrations/cmake_android_16k_pages_migration.dart';
|
||||||
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
|
import 'package:flutter_tools/src/project.dart';
|
||||||
|
import 'package:test/fake.dart';
|
||||||
|
|
||||||
|
import '../../../src/common.dart';
|
||||||
|
|
||||||
|
const String _sampleCmakeListsTxtUnmigrated = r'''
|
||||||
|
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||||
|
# installed. You should not increase this version, as doing so will cause
|
||||||
|
# the plugin to fail to compile for some customers of the plugin.
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(my_plugin_library VERSION 0.0.1 LANGUAGES C)
|
||||||
|
|
||||||
|
add_library(my_plugin SHARED
|
||||||
|
"my_plugin.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(my_plugin PROPERTIES
|
||||||
|
PUBLIC_HEADER my_plugin.h
|
||||||
|
OUTPUT_NAME "my_plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(my_plugin PUBLIC DART_SHARED_LIB)
|
||||||
|
''';
|
||||||
|
|
||||||
|
const String _sampleCmakeListsTxtMigrated = r'''
|
||||||
|
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||||
|
# installed. You should not increase this version, as doing so will cause
|
||||||
|
# the plugin to fail to compile for some customers of the plugin.
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(my_plugin_library VERSION 0.0.1 LANGUAGES C)
|
||||||
|
|
||||||
|
add_library(my_plugin SHARED
|
||||||
|
"my_plugin.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(my_plugin PROPERTIES
|
||||||
|
PUBLIC_HEADER my_plugin.h
|
||||||
|
OUTPUT_NAME "my_plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(my_plugin PUBLIC DART_SHARED_LIB)
|
||||||
|
|
||||||
|
if (ANDROID)
|
||||||
|
# Support Android 15 16k page size.
|
||||||
|
target_link_options(my_plugin PRIVATE "-Wl,-z,max-page-size=16384")
|
||||||
|
endif()
|
||||||
|
''';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('Android migration', () {
|
||||||
|
group('CMake file', () {
|
||||||
|
late MemoryFileSystem memoryFileSystem;
|
||||||
|
late File cmakeFile;
|
||||||
|
late BufferLogger bufferLogger;
|
||||||
|
late FakeAndroidProject project;
|
||||||
|
late CmakeAndroid16kPagesMigration migration;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
memoryFileSystem = MemoryFileSystem.test();
|
||||||
|
final Directory pluginDir = memoryFileSystem.currentDirectory;
|
||||||
|
final Directory exampleDir = pluginDir.childDirectory('example');
|
||||||
|
exampleDir.createSync();
|
||||||
|
final Directory androidDir = exampleDir.childDirectory('android');
|
||||||
|
androidDir.createSync();
|
||||||
|
final Directory srcDir = pluginDir.childDirectory('src');
|
||||||
|
srcDir.createSync();
|
||||||
|
cmakeFile = srcDir.childFile('CMakeLists.txt');
|
||||||
|
cmakeFile.writeAsString(_sampleCmakeListsTxtMigrated);
|
||||||
|
|
||||||
|
bufferLogger = BufferLogger.test();
|
||||||
|
project = FakeAndroidProject(
|
||||||
|
parent: FakeFlutterProject(
|
||||||
|
directory: exampleDir,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
migration = CmakeAndroid16kPagesMigration(project, bufferLogger);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWithoutContext('do nothing when files missing', () async {
|
||||||
|
cmakeFile.deleteSync();
|
||||||
|
await migration.migrate();
|
||||||
|
expect(
|
||||||
|
bufferLogger.traceText,
|
||||||
|
contains(
|
||||||
|
'CMake project not found, skipping support Android 15 16k page size migration.',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWithoutContext('migrate', () async {
|
||||||
|
cmakeFile.writeAsStringSync(_sampleCmakeListsTxtUnmigrated);
|
||||||
|
await migration.migrate();
|
||||||
|
expect(
|
||||||
|
cmakeFile.readAsStringSync(),
|
||||||
|
_sampleCmakeListsTxtMigrated,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWithoutContext('do nothing when already migrated', () async {
|
||||||
|
expect(
|
||||||
|
cmakeFile.readAsStringSync(),
|
||||||
|
_sampleCmakeListsTxtMigrated,
|
||||||
|
);
|
||||||
|
await migration.migrate();
|
||||||
|
expect(
|
||||||
|
cmakeFile.readAsStringSync(),
|
||||||
|
_sampleCmakeListsTxtMigrated,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeAndroidProject extends Fake implements AndroidProject {
|
||||||
|
FakeAndroidProject({required this.parent});
|
||||||
|
|
||||||
|
@override
|
||||||
|
FlutterProject parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeFlutterProject extends Fake implements FlutterProject {
|
||||||
|
FakeFlutterProject({required this.directory});
|
||||||
|
|
||||||
|
@override
|
||||||
|
final Directory directory;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user