1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:pub_semver/pub_semver.dart';
6
7import 'base/logger.dart';
8import 'build_info.dart';
9import 'cmake_project.dart';
10
11/// Extracts the `BINARY_NAME` from a project's CMake file.
12///
13/// Returns `null` if it cannot be found.
14String? getCmakeExecutableName(CmakeBasedProject project) {
15 if (!project.cmakeFile.existsSync()) {
16 return null;
17 }
18 final RegExp nameSetPattern = RegExp(r'^\s*set\(BINARY_NAME\s*"(.*)"\s*\)\s*$');
19 for (final String line in project.cmakeFile.readAsLinesSync()) {
20 final RegExpMatch? match = nameSetPattern.firstMatch(line);
21 if (match != null) {
22 return match.group(1);
23 }
24 }
25 return null;
26}
27
28String _escapeBackslashes(String s) {
29 return s.replaceAll(r'\', r'\\');
30}
31
32String _determineVersionString(CmakeBasedProject project, BuildInfo buildInfo) {
33 // Prefer the build arguments for version information.
34 final String buildName = buildInfo.buildName ?? project.parent.manifest.buildName ?? '1.0.0';
35 final String? buildNumber =
36 buildInfo.buildName != null
37 ? buildInfo.buildNumber
38 : (buildInfo.buildNumber ?? project.parent.manifest.buildNumber);
39
40 return buildNumber != null ? '$buildName+$buildNumber' : buildName;
41}
42
43Version _determineVersion(CmakeBasedProject project, BuildInfo buildInfo, Logger logger) {
44 final String version = _determineVersionString(project, buildInfo);
45 try {
46 return Version.parse(version);
47 } on FormatException {
48 logger.printWarning('Warning: could not parse version $version, defaulting to 1.0.0.');
49
50 return Version(1, 0, 0);
51 }
52}
53
54/// Attempts to map a Dart version's build identifier (the part after a +) into
55/// a single integer. Returns null for complex build identifiers like `foo` or `1.2`.
56int? _tryDetermineBuildVersion(Version version) {
57 if (version.build.isEmpty) {
58 return 0;
59 }
60
61 if (version.build.length != 1) {
62 return null;
63 }
64
65 final Object buildIdentifier = version.build.first;
66 return buildIdentifier is int ? buildIdentifier : null;
67}
68
69/// Writes a generated CMake configuration file for [project], including
70/// variables expected by the build template and an environment variable list
71/// for calling back into Flutter.
72void writeGeneratedCmakeConfig(
73 String flutterRoot,
74 CmakeBasedProject project,
75 BuildInfo buildInfo,
76 Map<String, String> environment,
77 Logger logger,
78) {
79 // Only a limited set of variables are needed by the CMake files themselves,
80 // the rest are put into a list to pass to the re-entrant build step.
81 final String escapedFlutterRoot = _escapeBackslashes(flutterRoot);
82 final String escapedProjectDir = _escapeBackslashes(project.parent.directory.path);
83
84 final Version version = _determineVersion(project, buildInfo, logger);
85 final int? buildVersion = _tryDetermineBuildVersion(version);
86
87 // Since complex Dart build identifiers cannot be converted into integers,
88 // different Dart versions may be converted into the same Windows numeric version.
89 // Warn the user as some Windows installers, like MSI, don't update files if their versions are equal.
90 if (buildVersion == null && project is WindowsProject) {
91 final String buildIdentifier = version.build.join('.');
92 logger.printWarning(
93 'Warning: build identifier $buildIdentifier in version $version is not numeric '
94 'and cannot be converted into a Windows build version number. Defaulting to 0.\n'
95 'This may cause issues with Windows installers.',
96 );
97 }
98
99 final StringBuffer buffer = StringBuffer('''
100# Generated code do not commit.
101file(TO_CMAKE_PATH "$escapedFlutterRoot" FLUTTER_ROOT)
102file(TO_CMAKE_PATH "$escapedProjectDir" PROJECT_DIR)
103
104set(FLUTTER_VERSION "$version" PARENT_SCOPE)
105set(FLUTTER_VERSION_MAJOR ${version.major} PARENT_SCOPE)
106set(FLUTTER_VERSION_MINOR ${version.minor} PARENT_SCOPE)
107set(FLUTTER_VERSION_PATCH ${version.patch} PARENT_SCOPE)
108set(FLUTTER_VERSION_BUILD ${buildVersion ?? 0} PARENT_SCOPE)
109
110# Environment variables to pass to tool_backend.sh
111list(APPEND FLUTTER_TOOL_ENVIRONMENT
112 "FLUTTER_ROOT=$escapedFlutterRoot"
113 "PROJECT_DIR=$escapedProjectDir"
114''');
115 environment.forEach((String key, String value) {
116 final String configValue = _escapeBackslashes(value);
117 buffer.writeln(' "$key=$configValue"');
118 });
119 buffer.writeln(')');
120
121 project.generatedCmakeConfigFile
122 ..createSync(recursive: true)
123 ..writeAsStringSync(buffer.toString());
124}
125

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com