| // Copyright 2013 The Flutter Authors | |
| // 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:platform/platform.dart'; | |
| import 'core.dart'; | |
| import 'output_utils.dart'; | |
| import 'process_runner.dart'; | |
| const String _cacheCommandKey = 'CMAKE_COMMAND:INTERNAL'; | |
| /// A utility class for interacting with CMake projects. | |
| class CMakeProject { | |
| /// Creates an instance that runs commands for [project] with the given | |
| /// [processRunner]. | |
| CMakeProject( | |
| this.flutterProject, { | |
| required this.buildMode, | |
| this.processRunner = const ProcessRunner(), | |
| required this.platform, | |
| required this.arch, | |
| }); | |
| /// The directory of a Flutter project to run Gradle commands in. | |
| final Directory flutterProject; | |
| /// The [ProcessRunner] used to run commands. Overridable for testing. | |
| final ProcessRunner processRunner; | |
| /// The platform that commands are being run on. | |
| final NativePlatform platform; | |
| /// The architecture subdirectory of the build. | |
| final String arch; | |
| /// The build mode (e.g., Debug, Release). | |
| /// | |
| /// This is a constructor parameter because on Linux many properties depend | |
| /// on the build mode since it uses a single-configuration generator. | |
| final String buildMode; | |
| late final String _cmakeCommand = _determineCmakeCommand(); | |
| /// The project's platform directory name. | |
| String get _platformDirName => platform.isWindows ? 'windows' : 'linux'; | |
| /// The project's 'example' build directory for this instance's platform. | |
| Directory get buildDirectory { | |
| Directory buildDir = flutterProject | |
| .childDirectory('build') | |
| .childDirectory(_platformDirName) | |
| .childDirectory(arch); | |
| if (platform.isLinux) { | |
| // Linux uses a single-config generator, so the base build directory | |
| // includes the configuration. | |
| buildDir = buildDir.childDirectory(buildMode.toLowerCase()); | |
| } | |
| return buildDir; | |
| } | |
| File get _cacheFile => buildDirectory.childFile('CMakeCache.txt'); | |
| /// Returns the CMake command to run build commands for this project. | |
| /// | |
| /// Assumes the project has been built at least once, such that the CMake | |
| /// generation step has run. | |
| String getCmakeCommand() { | |
| return _cmakeCommand; | |
| } | |
| /// Returns the CMake command to run build commands for this project. This is | |
| /// used to initialize _cmakeCommand, and should not be called directly. | |
| /// | |
| /// Assumes the project has been built at least once, such that the CMake | |
| /// generation step has run. | |
| String _determineCmakeCommand() { | |
| // On Linux 'cmake' is expected to be in the path, so doesn't need to | |
| // be lookup up and cached. | |
| if (platform.isLinux) { | |
| return 'cmake'; | |
| } | |
| final File cacheFile = _cacheFile; | |
| String? command; | |
| for (String line in cacheFile.readAsLinesSync()) { | |
| line = line.trim(); | |
| if (line.startsWith(_cacheCommandKey)) { | |
| command = line.substring(line.indexOf('=') + 1).trim(); | |
| break; | |
| } | |
| } | |
| if (command == null) { | |
| printError('Unable to find CMake command in ${cacheFile.path}'); | |
| throw ToolExit(100); | |
| } | |
| return command; | |
| } | |
| /// Whether or not the project is ready to have CMake commands run on it | |
| /// (i.e., whether the `flutter` tool has generated the necessary files). | |
| bool isConfigured() => _cacheFile.existsSync(); | |
| /// Runs a `cmake` command with the given parameters. | |
| Future<int> runBuild(String target, {List<String> arguments = const <String>[]}) { | |
| return processRunner.runAndStream(getCmakeCommand(), <String>[ | |
| '--build', | |
| buildDirectory.path, | |
| '--target', | |
| target, | |
| if (platform.isWindows) ...<String>['--config', buildMode], | |
| ...arguments, | |
| ]); | |
| } | |
| } |