2016-08-29 00:04:48 +02:00
|
|
|
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
|
|
|
// MIT-style license that can be found in the LICENSE file or at
|
|
|
|
// https://opensource.org/licenses/MIT.
|
|
|
|
|
2016-10-15 00:48:34 +02:00
|
|
|
import 'dart:async';
|
|
|
|
import 'dart:convert';
|
2016-10-05 10:04:51 +02:00
|
|
|
import 'dart:io';
|
|
|
|
import 'dart:isolate';
|
|
|
|
|
2016-10-15 00:48:34 +02:00
|
|
|
import 'package:archive/archive.dart';
|
2016-08-29 00:04:48 +02:00
|
|
|
import 'package:grinder/grinder.dart';
|
2016-10-15 00:48:34 +02:00
|
|
|
import 'package:http/http.dart' as http;
|
2016-10-05 10:04:51 +02:00
|
|
|
import 'package:node_preamble/preamble.dart' as preamble;
|
2016-10-15 00:48:34 +02:00
|
|
|
import 'package:path/path.dart' as p;
|
2016-10-08 00:46:58 +02:00
|
|
|
import 'package:yaml/yaml.dart';
|
2016-08-29 00:04:48 +02:00
|
|
|
|
2016-10-15 00:48:34 +02:00
|
|
|
/// The version of Dart Sass.
|
|
|
|
final String _version =
|
|
|
|
loadYaml(new File('pubspec.yaml').readAsStringSync())['version'];
|
|
|
|
|
|
|
|
/// The version of the current Dart executable.
|
|
|
|
final String _dartVersion = Platform.version.split(" ").first;
|
|
|
|
|
|
|
|
/// The root of the Dart SDK.
|
|
|
|
final _sdkDir = p.dirname(p.dirname(Platform.resolvedExecutable));
|
|
|
|
|
2016-08-29 00:04:48 +02:00
|
|
|
main(args) => grind(args);
|
|
|
|
|
2016-10-05 10:04:51 +02:00
|
|
|
@DefaultTask('Run the Dart formatter.')
|
2016-08-29 00:04:48 +02:00
|
|
|
format() {
|
|
|
|
Pub.run('dart_style',
|
|
|
|
script: 'format',
|
|
|
|
arguments: ['--overwrite']
|
|
|
|
..addAll(existingSourceDirs.map((dir) => dir.path)));
|
|
|
|
}
|
2016-10-05 10:04:51 +02:00
|
|
|
|
|
|
|
@Task('Build Dart snapshot.')
|
|
|
|
snapshot() {
|
|
|
|
_ensureBuild();
|
|
|
|
Dart.run('bin/sass.dart', vmArgs: ['--snapshot=build/sass.dart.snapshot']);
|
|
|
|
}
|
|
|
|
|
2016-10-15 00:48:34 +02:00
|
|
|
@Task('Build packages for all OSes.')
|
|
|
|
@Depends(snapshot)
|
|
|
|
package() async {
|
|
|
|
var client = new http.Client();
|
|
|
|
await _buildPackage(client, "linux", "x64");
|
|
|
|
await _buildPackage(client, "linux", "ia32");
|
|
|
|
await _buildPackage(client, "macos", "x64");
|
|
|
|
await _buildPackage(client, "macos", "ia32");
|
|
|
|
await _buildPackage(client, "windows", "x64");
|
|
|
|
await _buildPackage(client, "windows", "ia32");
|
|
|
|
client.close();
|
|
|
|
}
|
|
|
|
|
2016-10-05 10:04:51 +02:00
|
|
|
@Task('Compile to JS.')
|
|
|
|
js() {
|
|
|
|
_ensureBuild();
|
|
|
|
var destination = new File('build/sass.dart.js');
|
|
|
|
Dart2js.compile(new File('bin/sass.dart'),
|
2016-10-15 00:48:34 +02:00
|
|
|
outFile: destination, extraArgs: ['-Dnode=true', '-Dversion=$_version']);
|
2016-10-05 10:04:51 +02:00
|
|
|
var text = destination.readAsStringSync();
|
|
|
|
destination.writeAsStringSync("${preamble.getPreamble()}\n$text");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Ensure that the `build/` directory exists.
|
|
|
|
void _ensureBuild() {
|
|
|
|
new Directory('build').createSync(recursive: true);
|
|
|
|
}
|
2016-10-08 00:46:58 +02:00
|
|
|
|
2016-10-15 00:48:34 +02:00
|
|
|
/// Builds a standalone Sass package for the given [os] and [architecture].
|
|
|
|
///
|
|
|
|
/// The [client] is used to download the corresponding Dart SDK.
|
|
|
|
Future _buildPackage(http.Client client, String os, String architecture) async {
|
|
|
|
// TODO: Compile a single executable that embeds the Dart VM and the snapshot.
|
|
|
|
var url = "https://storage.googleapis.com/dart-archive/channels/stable/"
|
|
|
|
"release/$_dartVersion/sdk/dartsdk-$os-$architecture-release.zip";
|
|
|
|
log("Downloading $url...");
|
|
|
|
var response = await client.get(Uri.parse(url));
|
|
|
|
if (response.statusCode ~/ 100 != 2) {
|
|
|
|
throw "Failed to download package: ${response.statusCode} "
|
|
|
|
"${response.reasonPhrase}.";
|
|
|
|
}
|
|
|
|
|
|
|
|
var dartExecutable = new ZipDecoder()
|
|
|
|
.decodeBytes(response.bodyBytes)
|
|
|
|
.firstWhere((file) => os == 'windows'
|
|
|
|
? file.name.endsWith("/bin/dart.exe")
|
|
|
|
: file.name.endsWith("/bin/dart"));
|
|
|
|
var executable = dartExecutable.content;
|
|
|
|
var snapshot = new File('build/sass.dart.snapshot').readAsBytesSync();
|
|
|
|
var sassLicense = new File('LICENSE').readAsBytesSync();
|
|
|
|
var dartLicense = new File(p.join(_sdkDir, 'LICENSE')).readAsBytesSync();
|
|
|
|
var archive = new Archive()
|
|
|
|
..addFile(_file("dart-sass/dart", executable, executable: true))
|
|
|
|
..addFile(_file("dart-sass/DART_LICENSE", dartLicense))
|
|
|
|
..addFile(_file("dart-sass/sass.dart.snapshot", snapshot))
|
|
|
|
..addFile(_file("dart-sass/SASS_LICENSE", sassLicense))
|
|
|
|
..addFile(_scriptFor(os));
|
|
|
|
|
|
|
|
var prefix = 'build/dart-sass-$_version-$os-$architecture';
|
|
|
|
if (os == 'windows') {
|
|
|
|
var output = "$prefix.zip";
|
|
|
|
log("Creating $output...");
|
|
|
|
new File(output).writeAsBytesSync(new ZipEncoder().encode(archive));
|
|
|
|
} else {
|
|
|
|
var output = "$prefix.tar.gz";
|
|
|
|
log("Creating $output...");
|
|
|
|
new File(output).writeAsBytesSync(
|
|
|
|
new GZipEncoder().encode(new TarEncoder().encode(archive)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a shell script archive file for the given [os].
|
|
|
|
ArchiveFile _scriptFor(String os) {
|
|
|
|
var contents = new File("script/sass.${os == 'windows' ? 'bat' : 'sh'}")
|
|
|
|
.readAsStringSync()
|
|
|
|
.replaceAll("SASS_VERSION", _version);
|
|
|
|
var bytes = UTF8.encode(contents);
|
|
|
|
return _file("dart-sass/sass${os == 'windows' ? '.bat' : ''}", bytes,
|
|
|
|
executable: true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates an [ArchiveFile] with the given [path] and [data].
|
|
|
|
///
|
|
|
|
/// If [executable] is `true`, this marks the file as executable.
|
|
|
|
ArchiveFile _file(String path, List<int> data, {bool executable: false}) =>
|
|
|
|
new ArchiveFile(path, data.length, data)
|
|
|
|
..mode = executable ? 495 : 428
|
|
|
|
..lastModTime = new DateTime.now().millisecondsSinceEpoch ~/ 1000;
|