diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 00000000..72f9bd20 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,76 @@ +on: + merge_group: + pull_request: + workflow_dispatch: + +name: benchmark + +permissions: + contents: write + deployments: write + +env: + PROJECT_PATH: commet + +jobs: + benchmark: + name: benchmark + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: 'true' + + - name: Setup Flutter + uses: subosito/flutter-action@v2.8.0 + with: + flutter-version: '3.19.5' + channel: 'stable' + + - name: Setup Dependencies + run: | + sudo apt-get update -y + sudo apt-get install -y ninja-build libgtk-3-dev libolm3 libmpv-dev mpv ffmpeg libmimalloc-dev + + + - name: Configure Flutter + run: flutter config --enable-linux-desktop + + - name: Code Generation + run: | + cd $PROJECT_PATH + dart run scripts/codegen.dart + + - name: Benchmark + run: | + cd $PROJECT_PATH + export DISPLAY=:99 + sudo Xvfb -ac :99 -screen 0 1920x1080x24 > /dev/null 2>&1 & + ffmpeg -f x11grab -video_size 1920x1080 -framerate 15 -i :99 -vcodec libx264 -preset ultrafast -qp 0 -nostdin -loglevel quiet -pix_fmt yuv444p video.mkv & + flutter drive -d linux --driver=test_driver/benchmark_driver.dart --target=integration_test/benchmark/benchmark.dart --profile + INTEGRATION_TEST_EXIT_CODE=$? + sleep 1 + kill $(pgrep ffmpeg) + exit $INTEGRATION_TEST_EXIT_CODE + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: result.mkv + path: commet/video.mkv + + - name: Store benchmark result - separate results repo + uses: benchmark-action/github-action-benchmark@v1 + with: + name: Benchmark + tool: 'customSmallerIsBetter' + output-file-path: commet/build/customSmallerIsBetter.json + github-token: ${{ secrets.BENCHMARK_ACTION_BOT_TOKEN }} + auto-push: true + # Show alert with commit comment on detecting possible performance regression + alert-threshold: '350%' + comment-on-alert: true + fail-on-alert: false + summary-always: true + gh-repository: 'github.com/commetchat/commet_benchmark_results' \ No newline at end of file diff --git a/commet/integration_test/benchmark/benchmark.dart b/commet/integration_test/benchmark/benchmark.dart new file mode 100644 index 00000000..6bcabddf --- /dev/null +++ b/commet/integration_test/benchmark/benchmark.dart @@ -0,0 +1,8 @@ +import 'package:integration_test/integration_test.dart'; +import 'benchmarks/timeline_viewer_benchmark.dart' as timeline; + +main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + timeline.main(); +} diff --git a/commet/integration_test/benchmark/benchmarks/timeline_viewer_benchmark.dart b/commet/integration_test/benchmark/benchmarks/timeline_viewer_benchmark.dart new file mode 100644 index 00000000..ea3f83b5 --- /dev/null +++ b/commet/integration_test/benchmark/benchmarks/timeline_viewer_benchmark.dart @@ -0,0 +1,64 @@ +import 'package:commet/diagnostic/benchmark_values.dart'; +import 'package:commet/ui/pages/developer/benchmarks/benchmark_utils.dart'; +import 'package:commet/ui/pages/developer/benchmarks/timeline_viewer_benchmark.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:tiamat/config/style/theme_dark.dart'; + +void main() { + final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('Timeline Viewer Test', (tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MaterialApp( + theme: ThemeDark.theme, + home: const Scaffold( + body: BenchmarkTimelineViewer(), + ), + )); + + await tester.pump(const Duration(seconds: 1)); + + final listFinder = find.byType(Scrollable); + final itemFinder = find.text(finalEventMessage); + + var reportKey = 'TimelineViewer Scrolling'; + + await binding.traceAction( + () async { + // Scroll until the item to be found appears. + await tester.scrollUntilVisible( + itemFinder, + 50.0, + maxScrolls: 10000, + scrollable: listFinder, + ); + }, + reportKey: reportKey, + ); + + binding.reportData?[reportKey]["extra_values"] = [ + { + "name": "$reportKey - Timeline Event Build Count", + "value": BenchmarkValues.numTimelineEventsBuilt, + "unit": "Builds", + }, + { + "name": "$reportKey - Timeline Event Message Body Build Count", + "value": BenchmarkValues.numTimelineMessageBodyBuilt, + "unit": "Builds", + }, + { + "name": "$reportKey - Timeline Event Message Reply Body Build Count", + "value": BenchmarkValues.numTimelineReplyBodyBuilt, + "unit": "Builds", + }, + { + "name": "$reportKey - Timeline Event Message Url Preview Build Count", + "value": BenchmarkValues.numTimelineUrlPreviewBuilt, + "unit": "Builds", + } + ]; + }); +} diff --git a/commet/lib/client/matrix/matrix_client.dart b/commet/lib/client/matrix/matrix_client.dart index 2e4b6592..dbdef4f3 100644 --- a/commet/lib/client/matrix/matrix_client.dart +++ b/commet/lib/client/matrix/matrix_client.dart @@ -37,7 +37,7 @@ import 'package:olm/olm.dart' as olm; class MatrixClient extends Client { late matrix.Client _matrixClient; - late final List> _components; + late final List> componentsInternal; Future? firstSync; @@ -72,7 +72,7 @@ class MatrixClient extends Client { _id = identifier; _matrixClient = _createMatrixClient(identifier); _matrixClient.onSync.stream.listen(onMatrixClientSync); - _components = ComponentRegistry.getMatrixComponents(this); + componentsInternal = ComponentRegistry.getMatrixComponents(this); } static String hash(String name) { @@ -471,7 +471,7 @@ class MatrixClient extends Client { @override T? getComponent() { - for (var component in _components) { + for (var component in componentsInternal) { if (component is T) return component as T; } @@ -481,7 +481,7 @@ class MatrixClient extends Client { @override List? getAllComponents>() { List components = List.empty(growable: true); - for (var component in _components) { + for (var component in componentsInternal) { if (component is T) { components.add(component as T); } diff --git a/commet/lib/client/matrix/matrix_timeline.dart b/commet/lib/client/matrix/matrix_timeline.dart index 0997c074..1d1bcea7 100644 --- a/commet/lib/client/matrix/matrix_timeline.dart +++ b/commet/lib/client/matrix/matrix_timeline.dart @@ -16,12 +16,18 @@ class MatrixTimeline extends Timeline { MatrixTimeline( Client client, Room room, - matrix.Room matrixRoom, - ) { + matrix.Room matrixRoom, { + matrix.Timeline? initialTimeline, + }) { events = List.empty(growable: true); _matrixRoom = matrixRoom; this.client = client; this.room = room; + _matrixTimeline = initialTimeline; + + if (_matrixTimeline != null) { + convertAllTimelineEvents(); + } } Future initTimeline() async { @@ -35,6 +41,10 @@ class MatrixTimeline extends Timeline { // This could maybe make load times realllly slow if we have a ton of stuff in the cache? // Might be better to only convert as many as we would need to display immediately and then convert the rest on demand + convertAllTimelineEvents(); + } + + void convertAllTimelineEvents() { for (int i = 0; i < _matrixTimeline!.events.length; i++) { var converted = MatrixTimelineEvent( _matrixTimeline!.events[i], _matrixTimeline!.room.client, diff --git a/commet/lib/diagnostic/benchmark_values.dart b/commet/lib/diagnostic/benchmark_values.dart new file mode 100644 index 00000000..be934cf9 --- /dev/null +++ b/commet/lib/diagnostic/benchmark_values.dart @@ -0,0 +1,6 @@ +class BenchmarkValues { + static int numTimelineEventsBuilt = 0; + static int numTimelineMessageBodyBuilt = 0; + static int numTimelineReplyBodyBuilt = 0; + static int numTimelineUrlPreviewBuilt = 0; +} diff --git a/commet/lib/diagnostic/mocks/matrix_client_component_mocks.dart b/commet/lib/diagnostic/mocks/matrix_client_component_mocks.dart new file mode 100644 index 00000000..6ab3db7c --- /dev/null +++ b/commet/lib/diagnostic/mocks/matrix_client_component_mocks.dart @@ -0,0 +1,51 @@ +import 'package:commet/client/components/url_preview/url_preview_component.dart'; +import 'package:commet/client/matrix/matrix_client.dart'; +import 'package:commet/client/room.dart'; +import 'package:commet/client/timeline.dart'; +import 'package:flutter/material.dart'; + +extension MatrixClientComponentReplacement on MatrixClient { + void mockComponents() { + componentsInternal.removeWhere((element) => element is UrlPreviewComponent); + componentsInternal.add(MockMatrixUrlPreviewComponent(this)); + } +} + +class MockMatrixUrlPreviewComponent + implements UrlPreviewComponent { + @override + MatrixClient client; + + MockMatrixUrlPreviewComponent(this.client); + + var imageIndex = 0; + + @override + Future getPreview(Room room, TimelineEvent event) async { + await Future.delayed(const Duration(seconds: 1)); + + var image = [ + "assets/images/app_icon/app_icon_filled.png", + "assets/images/app_icon/app_icon_rounded.png", + "assets/images/app_icon/app_icon_transparent_cropped.png", + "assets/images/app_icon/app_icon_transparent.png" + ][imageIndex % 4]; + + imageIndex += 1; + + return UrlPreviewData(Uri.parse("https://example.com"), + siteName: "Example", + description: "Example description", + image: AssetImage(image)); + } + + @override + bool shouldGetPreviewData(Room room, TimelineEvent event) { + return true; + } + + @override + UrlPreviewData? getCachedPreview(Room room, TimelineEvent event) { + return null; + } +} diff --git a/commet/lib/ui/molecules/message.dart b/commet/lib/ui/molecules/message.dart index 042ea7f7..59020c9a 100644 --- a/commet/lib/ui/molecules/message.dart +++ b/commet/lib/ui/molecules/message.dart @@ -1,6 +1,7 @@ import 'package:commet/client/components/emoticon/emoticon.dart'; import 'package:commet/client/components/url_preview/url_preview_component.dart'; import 'package:commet/config/build_config.dart'; +import 'package:commet/diagnostic/benchmark_values.dart'; import 'package:commet/ui/atoms/emoji_reaction.dart'; import 'package:commet/ui/molecules/url_preview_widget.dart'; import 'package:commet/utils/link_utils.dart'; @@ -144,6 +145,7 @@ class _MessageState extends State { } Widget urlPreviews() { + BenchmarkValues.numTimelineUrlPreviewBuilt += 1; return Padding( padding: const EdgeInsets.fromLTRB(0, 0, 40, 0), child: UrlPreviewWidget( @@ -183,6 +185,7 @@ class _MessageState extends State { } Widget replyText() { + BenchmarkValues.numTimelineReplyBodyBuilt += 1; return SizedBox( child: Row( crossAxisAlignment: CrossAxisAlignment.baseline, diff --git a/commet/lib/ui/molecules/timeline_event.dart b/commet/lib/ui/molecules/timeline_event.dart index 1237c5ca..931c8e43 100644 --- a/commet/lib/ui/molecules/timeline_event.dart +++ b/commet/lib/ui/molecules/timeline_event.dart @@ -1,5 +1,6 @@ import 'package:commet/client/components/url_preview/url_preview_component.dart'; import 'package:commet/config/build_config.dart'; +import 'package:commet/diagnostic/benchmark_values.dart'; import 'package:commet/main.dart'; import 'package:commet/ui/atoms/generic_room_event.dart'; import 'package:commet/ui/molecules/message.dart'; @@ -46,6 +47,8 @@ class TimelineEventView extends StatefulWidget { final bool canDeleteEvent; final Function(Emoticon emote)? onReactionTapped; + static int timelineEventBuildsCount = 0; + @override State createState() => _TimelineEventState(); } @@ -212,6 +215,8 @@ class _TimelineEventState extends State { @override Widget build(BuildContext context) { + BenchmarkValues.numTimelineEventsBuilt += 1; + return eventToWidget(widget.event) ?? Container(); } @@ -328,6 +333,7 @@ class _TimelineEventState extends State { } Widget buildBody() { + BenchmarkValues.numTimelineMessageBodyBuilt += 1; switch (widget.event.type) { case EventType.message: return buildMessageBody(); diff --git a/commet/lib/ui/pages/developer/benchmarks/benchmark_utils.dart b/commet/lib/ui/pages/developer/benchmarks/benchmark_utils.dart new file mode 100644 index 00000000..ee07ac63 --- /dev/null +++ b/commet/lib/ui/pages/developer/benchmarks/benchmark_utils.dart @@ -0,0 +1,129 @@ +import 'dart:math'; + +import 'package:commet/client/matrix/matrix_client.dart'; +import 'package:commet/client/matrix/matrix_room.dart'; +import 'package:commet/client/matrix/matrix_timeline.dart'; +import 'package:commet/utils/rng.dart'; +import 'package:matrix/matrix.dart' as matrix; + +// ignore: implementation_imports +import 'package:matrix/src/models/timeline_chunk.dart' as c; + +const _userId = "@benchy:example.com"; +const _roomId = "!benchmark:example.com"; +const finalEventMessage = "End Test Here"; + +extension BenchmarkUtils on MatrixClient { + MatrixRoom createRoomWithData() { + var mxRoom = matrix.Room.fromJson({ + 'id': _roomId, + 'notification_count': 0, + 'highlight_count': 0, + 'prev_batch': 'fake_batch_id', + 'summary': { + 'm.joined_member_count': 100, + 'm.invited_member_count': 0, + }, + }, getMatrixClient()); + + mxRoom.setState(matrix.Event.fromJson({ + 'type': 'm.room.member', + 'state_key': _userId, + 'sender': _userId, + 'content': {'display_name': 'Benchy', 'membership': 'join'} + }, mxRoom)); + + var room = MatrixRoom(this, mxRoom, getMatrixClient()); + rooms.add(room); + return room; + } +} + +extension BenchmarkTimeline on MatrixRoom { + MatrixTimeline getBenchmarkTimeline() { + int count = 500; + var chunk = c.TimelineChunk(events: [ + for (var i = 0; i < count; i++) createRandomEvent(i, count), + createTestEndEvent(count), + + // create more events so it doent try to fetch more from server + for (var i = 0; i < 50; i++) createRandomEvent(count + 1 + i, count), + ]); + + var mxTimeline = matrix.Timeline(chunk: chunk, room: matrixRoom); + + return MatrixTimeline(client, this, matrixRoom, + initialTimeline: mxTimeline); + } + + matrix.Event createTestEndEvent(int eventCount) { + var event = matrix.Event.fromJson({ + 'event_id': '\$final', + 'type': 'm.room.message', + 'content': {'body': finalEventMessage, 'msgtype': 'm.text'}, + 'sender': _userId, + 'room_id': matrixRoom.id, + 'origin_server_ts': DateTime.now() + .subtract(Duration(days: eventCount)) + .millisecondsSinceEpoch + }, matrixRoom); + + return event; + } + + matrix.Event createRandomEvent(int seed, int limit) { + final r = Random(seed); + + var relatedEventId = '\$${seed + 5}'; + bool canBeRelatedEvent = seed < limit - 10; + + var json = { + 'event_id': '\$$seed', + 'sender': _userId, + 'room_id': matrixRoom.id, + 'origin_server_ts': + DateTime.now().subtract(Duration(days: seed)).millisecondsSinceEpoch + }; + + if (r.nextDouble() < 0.33 && canBeRelatedEvent) { + json['type'] = 'm.reaction'; + json['content'] = { + 'm.relates_to': { + 'event_id': relatedEventId, + 'rel_type': 'm.annotation', + 'key': r.nextBool() ? 'String Reaction' : "❤️" + } + }; + + return matrix.Event.fromJson(json, matrixRoom); + } + + var contentLength = r.nextInt(200) + 10; + + bool isThreadReply = r.nextBool(); + + var event = matrix.Event.fromJson({ + 'event_id': '\$$seed', + 'type': 'm.room.message', + 'content': { + 'body': + '($seed) https://example.com ${RandomUtils.getRandomSentence(contentLength)}', + 'msgtype': 'm.text', + if (canBeRelatedEvent) + 'm.relates_to': { + if (isThreadReply) 'event_id': relatedEventId, + if (isThreadReply) 'rel_type': 'm.thread', + if (isThreadReply) 'is_falling_back': true, + if (isThreadReply == false) + 'm.in_reply_to': {'event_id': relatedEventId} + }, + }, + 'sender': _userId, + 'room_id': matrixRoom.id, + 'origin_server_ts': + DateTime.now().subtract(Duration(days: seed)).millisecondsSinceEpoch + }, matrixRoom); + + return event; + } +} diff --git a/commet/lib/ui/pages/developer/benchmarks/timeline_viewer_benchmark.dart b/commet/lib/ui/pages/developer/benchmarks/timeline_viewer_benchmark.dart new file mode 100644 index 00000000..7e1e9caa --- /dev/null +++ b/commet/lib/ui/pages/developer/benchmarks/timeline_viewer_benchmark.dart @@ -0,0 +1,48 @@ +import 'package:commet/client/client.dart'; +import 'package:commet/client/matrix/matrix_client.dart'; +import 'package:commet/client/matrix/matrix_profile.dart'; +import 'package:commet/diagnostic/mocks/matrix_client_component_mocks.dart'; +import 'package:commet/ui/molecules/timeline_viewer.dart'; +import 'package:commet/ui/pages/developer/benchmarks/benchmark_utils.dart'; +import 'package:flutter/material.dart'; + +import 'package:matrix/matrix.dart' as matrix; + +class BenchmarkTimelineViewer extends StatefulWidget { + const BenchmarkTimelineViewer({super.key}); + + @override + State createState() => + _BenchmarkTimelineViewerState(); +} + +class _BenchmarkTimelineViewerState extends State { + late Timeline timeline; + + @override + void initState() { + var client = MatrixClient(identifier: "benchmark"); + client.mockComponents(); + client.self = MatrixProfile(client.getMatrixClient(), + matrix.Profile(userId: '@benchy:matrix.org', displayName: 'benchy')); + + var room = client.createRoomWithData(); + timeline = room.getBenchmarkTimeline(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () => Navigator.of(context).pop(), + child: const Icon(Icons.chevron_left), + ), + body: TimelineViewer( + key: const ValueKey("timeline-viewer-benchmark"), + timeline: timeline, + doMessageOverlayMenu: false, + ), + ); + } +} diff --git a/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart b/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart index 9a4db9d8..89717080 100644 --- a/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart +++ b/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart @@ -3,6 +3,8 @@ import 'package:commet/client/components/push_notification/notification_content. import 'package:commet/client/components/push_notification/notification_manager.dart'; import 'package:commet/config/app_config.dart'; import 'package:commet/main.dart'; +import 'package:commet/ui/navigation/navigation_utils.dart'; +import 'package:commet/ui/pages/developer/benchmarks/timeline_viewer_benchmark.dart'; import 'package:commet/utils/background_tasks/background_task_manager.dart'; import 'package:commet/utils/background_tasks/mock_tasks.dart'; import 'package:file_picker/file_picker.dart'; @@ -26,6 +28,7 @@ class _DeveloperSettingsPageState extends State { return Column( children: [ performance(), + benchmarks(), windowSize(), notificationTests(), rendering(), @@ -66,7 +69,6 @@ class _DeveloperSettingsPageState extends State { Widget rendering() { return ExpansionTile( title: const tiamat.Text.labelEmphasised("Rendering"), - initiallyExpanded: false, backgroundColor: Theme.of(context).extension()!.surfaceLow2, collapsedBackgroundColor: @@ -94,6 +96,29 @@ class _DeveloperSettingsPageState extends State { ]); } + Widget benchmarks() { + return ExpansionTile( + title: const tiamat.Text.labelEmphasised("Benchmarks"), + initiallyExpanded: false, + backgroundColor: + Theme.of(context).extension()!.surfaceLow2, + collapsedBackgroundColor: + Theme.of(context).extension()!.surfaceLow2, + children: [ + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + tiamat.Button( + text: "Timeline Viewer", + onTap: () => NavigationUtils.navigateTo( + context, const BenchmarkTimelineViewer()), + ) + ], + ), + ]); + } + Widget windowSize() { return ExpansionTile( title: const tiamat.Text.labelEmphasised("Window Size"), diff --git a/commet/lib/utils/rng.dart b/commet/lib/utils/rng.dart index 2bcee0c4..f2320718 100644 --- a/commet/lib/utils/rng.dart +++ b/commet/lib/utils/rng.dart @@ -13,10 +13,11 @@ class RandomUtils { length, (_) => _chars.codeUnitAt(rnd.nextInt(_chars.length)))); } - static String getRandomSentence(int length) { + static String getRandomSentence(int length, {int? seed}) { + var r = Random(seed); String msg = ""; for (int i = 0; i < length; i++) { - msg += "${_words[Random().nextInt(_words.length)]} "; + msg += "${_words[r.nextInt(_words.length)]} "; } return msg; } diff --git a/commet/test_driver/benchmark_driver.dart b/commet/test_driver/benchmark_driver.dart new file mode 100644 index 00000000..d28b231f --- /dev/null +++ b/commet/test_driver/benchmark_driver.dart @@ -0,0 +1,86 @@ +// ignore_for_file: depend_on_referenced_packages + +import 'package:flutter_driver/flutter_driver.dart'; +import 'dart:convert' show JsonEncoder; + +import 'package:file/file.dart'; +import 'package:integration_test/integration_test_driver.dart' as test; +import 'package:path/path.dart' as path; + +Future main() { + return test.integrationDriver( + responseDataCallback: (data) async { + if (data != null) { + var result = List>.empty(growable: true); + + for (var key in data.keys) { + final File file = + fs.file(path.join(testOutputsDirectory, 'data.json')); + + const JsonEncoder prettyEncoder = JsonEncoder.withIndent(' '); + await file.writeAsString(prettyEncoder.convert(data[key])); + + final timeline = Timeline.fromJson( + data[key] as Map, + ); + + final summary = TimelineSummary.summarize(timeline); + + if (data[key]["extra_values"] != null) { + result.addAll( + List>.from(data[key]["extra_values"])); + } + + result.addAll([ + { + "name": "$key - Average Build Time", + "value": summary.computeAverageFrameBuildTimeMillis(), + "unit": "ms" + }, + { + "name": "$key - Average Raster Time", + "value": summary.computeAverageFrameRasterizerTimeMillis(), + "unit": "ms" + }, + { + "name": "$key - Worst Build Time", + "value": summary.computeWorstFrameBuildTimeMillis(), + "unit": "ms" + }, + { + "name": "$key - Worst Raster Time", + "value": summary.computeWorstFrameRasterizerTimeMillis(), + "unit": "ms" + }, + { + "name": "$key - 99th Percentile Build Time", + "value": summary.computePercentileFrameBuildTimeMillis(99), + "unit": "ms" + }, + { + "name": "$key - 90th Percentile Build Time", + "value": summary.computePercentileFrameBuildTimeMillis(99), + "unit": "ms" + }, + { + "name": "$key - 99th Percentile Raster Time", + "value": summary.computePercentileFrameRasterizerTimeMillis(99), + "unit": "ms" + }, + { + "name": "$key - 90th Percentile Raster Time", + "value": summary.computePercentileFrameRasterizerTimeMillis(90), + "unit": "ms" + }, + ]); + } + + final File file = fs.file( + path.join(testOutputsDirectory, 'customSmallerIsBetter.json')); + + const JsonEncoder prettyEncoder = JsonEncoder.withIndent(' '); + await file.writeAsString(prettyEncoder.convert(result)); + } + }, + ); +} diff --git a/commet/windows/flutter/CMakeLists.txt b/commet/windows/flutter/CMakeLists.txt index 930d2071..903f4899 100644 --- a/commet/windows/flutter/CMakeLists.txt +++ b/commet/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS