Skip to content

Commit

Permalink
fix: Make build_shaders script compatible with other platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
luanpotter committed Dec 14, 2024
1 parent 8352ad8 commit 9403c68
Showing 1 changed file with 96 additions and 3 deletions.
99 changes: 96 additions & 3 deletions packages/flame_3d/bin/build_shaders.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ Future<void> compute(Directory assets, Directory shaders) async {
};

stdout.writeln('Computing shader "$name"');
final result = await Process.run(impellerC, [
final impellerC = await findImpellerC();
final result = await Process.run(impellerC.toFilePath(), [
'--sl=${assets.path}/$name.shaderbundle',
'--shader-bundle=${jsonEncode(bundle)}',
]);
Expand All @@ -68,5 +69,97 @@ Future<void> compute(Directory assets, Directory shaders) async {
}
}

final impellerC =
'${Platform.environment['FLUTTER_HOME']}/bin/cache/artifacts/engine/darwin-x64/impellerc';
// Copied from https://github.com/bdero/flutter_gpu_shaders/blob/master/lib/environment.dart#L53
const _macosHostArtifacts = 'darwin-x64';
const _linuxHostArtifacts = 'linux-x64';
const _windowsHostArtifacts = 'windows-x64';

const _impellercLocations = [
'$_macosHostArtifacts/impellerc',
'$_linuxHostArtifacts/impellerc',
'$_windowsHostArtifacts/impellerc.exe',
];

/// Locate the engine artifacts cache directory in the Flutter SDK.
Uri findEngineArtifactsDir({String? dartPath}) {
// Could be:
// `/path/to/flutter/bin/cache/dart-sdk/bin/dart`
// `/path/to/flutter/bin/cache/artifacts/engine/darwin-x64/flutter_tester`
// `/path/to/.puro/shared/caches/94cf8c8fad31206e440611e309757a5a9b3be712/dart-sdk/bin/dart`
final dartExec = Uri.file(dartPath ?? Platform.resolvedExecutable);

Uri? cacheDir;
// Search backwards through the segment list until finding `bin` and `cache` in sequence.

Check notice on line 92 in packages/flame_3d/bin/build_shaders.dart

View workflow job for this annotation

GitHub Actions / analyze

The line length exceeds the 80-character limit.

Try breaking the line across multiple lines. See https://dart.dev/lints/lines_longer_than_80_chars to learn more about this problem.

Check notice on line 92 in packages/flame_3d/bin/build_shaders.dart

View workflow job for this annotation

GitHub Actions / analyze-latest

The line length exceeds the 80-character limit.

Try breaking the line across multiple lines. See https://dart.dev/lints/lines_longer_than_80_chars to learn more about this problem.
for (var i = dartExec.pathSegments.length - 1; i >= 0; i--) {
if (dartExec.pathSegments[i] == 'dart-sdk' ||
dartExec.pathSegments[i] == 'artifacts') {
// Note: The final empty string denotes that this is a directory path.
cacheDir = dartExec.replace(
pathSegments: dartExec.pathSegments.sublist(0, i) + [''],
);
break;
}
}
if (cacheDir == null) {
throw Exception(
'Unable to find Flutter SDK cache directory! '
'Dart executable: `${dartExec.toFilePath()}`',
);
}
// We should now have a path of `/path/to/flutter/bin/cache/`.

final engineArtifactsDir = cacheDir
.resolve('./artifacts/engine/'); // Note: The final slash is important.

return engineArtifactsDir;
}

/// Locate the ImpellerC offline shader compiler in the engine artifacts cache
/// directory.
Future<Uri> findImpellerC() async {
/////////////////////////////////////////////////////////////////////////////
/// 1. If the `IMPELLERC` environment variable is set, use it.
///
// ignore: do_not_use_environment
const impellercEnvVar = String.fromEnvironment('IMPELLERC');
if (impellercEnvVar != '') {
if (!doesFileExist(impellercEnvVar)) {
throw Exception(
'IMPELLERC environment variable is set, '
"but it doesn't point to a valid file!",
);
}
return Uri.file(impellercEnvVar);
}

/////////////////////////////////////////////////////////////////////////////
/// 3. Search for the `impellerc` binary within the host-specific artifacts.
///
final engineArtifactsDir = findEngineArtifactsDir();

// No need to get fancy. Just search all the possible directories rather than
// picking the correct one for the specific host type.
Uri? found;
final tried = <Uri>[];
for (final variant in _impellercLocations) {
final impellercPath = engineArtifactsDir.resolve(variant);
if (doesFileExist(impellercPath.toFilePath())) {
found = impellercPath;
break;
}
tried.add(impellercPath);
}
if (found == null) {
throw Exception(
'Unable to find impellerc! Tried the following locations: $tried',
);
}

return found;
}

bool doesFileExist(String path) {
return File(path).existsSync();
}

0 comments on commit 9403c68

Please sign in to comment.