提交 2ca9e331 编写于 作者: A Adam Barth

Teach sky_snapshot about .packages

The sky_snapshot tool now understands the --packages command-line flag.

Progress on https://github.com/flutter/flutter/issues/1351
上级 f7909035
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("parsers") {
sources = [
"packages_map.cc",
"packages_map.h",
]
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Spec: https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md
#include "sky/engine/tonic/parsers/packages_map.h"
#include <memory>
namespace tonic {
namespace {
bool isLineBreak(char c) {
return c == '\r' || c == '\n';
}
} // namespace
PackagesMap::PackagesMap() {
}
PackagesMap::~PackagesMap() {
}
bool PackagesMap::Parse(const std::string& source, std::string* error) {
map_.clear();
const auto end = source.end();
for (auto it = source.begin(); it != end; ++it) {
const char c = *it;
// Skip blank lines.
if (isLineBreak(c))
continue;
// Skip comments.
if (c == '#') {
while (it != end && !isLineBreak(*it))
++it;
continue;
}
if (c == ':') {
map_.clear();
*error = "Packages file contains a line that begins with ':'.";
return false;
}
auto package_name_begin = it;
auto package_name_end = end;
bool found_separator = false;
for ( ; it != end; ++it) {
const char c = *it;
if (c == ':' && !found_separator) {
found_separator = true;
package_name_end = it;
continue;
}
if (isLineBreak(c))
break;
}
if (!found_separator) {
map_.clear();
*error = "Packages file contains non-comment line that lacks a ':'.";
return false;
}
std::string package_name(package_name_begin, package_name_end);
std::string package_path(package_name_end + 1, it);
auto result = map_.emplace(package_name, package_path);
if (!result.second) {
map_.clear();
*error = std::string(
"Packages file contains multiple entries for package '") +
package_name + "'.";
return false;
}
}
return true;
}
std::string PackagesMap::Resolve(const std::string& package_name) {
return map_[package_name];
}
} // namespace tonic
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_ENGINE_TONIC_PARSERS_PACKAGES_MAP_H_
#define SKY_ENGINE_TONIC_PARSERS_PACKAGES_MAP_H_
#include <unordered_map>
#include <string>
namespace tonic {
class PackagesMap {
public:
PackagesMap();
~PackagesMap();
bool Parse(const std::string& source, std::string* error);
std::string Resolve(const std::string& package_name);
private:
std::unordered_map<std::string, std::string> map_;
};
} // namespace tonic
#endif // SKY_ENGINE_TONIC_PARSERS_PACKAGES_MAP_H_
......@@ -21,6 +21,7 @@ executable("sky_snapshot") {
"//dart/runtime/vm:libdart_platform",
"//dart/runtime:libdart",
"//sky/engine/bindings:snapshot_cc",
"//sky/engine/tonic/parsers",
"//third_party/zlib",
]
......
......@@ -12,6 +12,7 @@
#include "sky/tools/sky_snapshot/logging.h"
#include "sky/tools/sky_snapshot/scope.h"
#include "sky/tools/sky_snapshot/switches.h"
#include "sky/engine/tonic/parsers/packages_map.h"
namespace {
......@@ -34,7 +35,9 @@ base::FilePath SimplifyPath(const base::FilePath& path) {
class Loader {
public:
Loader(const base::FilePath& package_root);
Loader();
void LoadPackagesMap(const base::FilePath& packages);
const std::set<std::string>& dependencies() const { return dependencies_; }
......@@ -44,20 +47,60 @@ class Loader {
Dart_Handle Import(Dart_Handle url);
Dart_Handle Source(Dart_Handle library, Dart_Handle url);
void set_package_root(const base::FilePath& package_root) {
package_root_ = package_root;
}
private:
std::set<std::string> dependencies_;
base::FilePath packages_;
base::FilePath package_root_;
std::unique_ptr<tonic::PackagesMap> packages_map_;
DISALLOW_COPY_AND_ASSIGN(Loader);
};
Loader::Loader(const base::FilePath& package_root)
: package_root_(package_root) {
Loader::Loader() {
}
void Loader::LoadPackagesMap(const base::FilePath& packages) {
packages_ = base::MakeAbsoluteFilePath(packages);
dependencies_.insert(packages_.AsUTF8Unsafe());
std::string packages_source;
if (!base::ReadFileToString(packages, &packages_source)) {
fprintf(stderr, "error: Unable to load .packages file '%s'.\n",
packages.AsUTF8Unsafe().c_str());
exit(1);
}
packages_map_.reset(new tonic::PackagesMap());
std::string error;
if (!packages_map_->Parse(packages_source, &error)) {
fprintf(stderr, "error: Unable to parse .packages file '%s'.\n%s\n",
packages.AsUTF8Unsafe().c_str(), error.c_str());
exit(1);
}
}
std::string Loader::CanonicalizePackageURL(std::string url) {
DCHECK(base::StartsWithASCII(url, "package:", true));
base::ReplaceFirstSubstringAfterOffset(&url, 0, "package:", "");
if (packages_map_) {
size_t slash = url.find('/');
if (slash == std::string::npos)
return std::string();
std::string package = url.substr(0, slash);
std::string library_path = url.substr(slash + 1);
std::string package_path = packages_map_->Resolve(package);
if (package_path.empty())
return std::string();
if (base::StartsWithASCII(package_path, "file://", true)) {
base::ReplaceFirstSubstringAfterOffset(&package_path, 0, "file://", "");
return package_path + library_path;
} else {
auto path = packages_.DirName().Append(package_path).Append(library_path);
return SimplifyPath(path).AsUTF8Unsafe();
}
}
return package_root_.Append(url).AsUTF8Unsafe();
}
......@@ -103,10 +146,18 @@ Loader* g_loader = nullptr;
Loader& GetLoader() {
if (!g_loader) {
base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
CHECK(command_line.HasSwitch(switches::kPackageRoot))
<< "Need --package-root";
g_loader =
new Loader(command_line.GetSwitchValuePath(switches::kPackageRoot));
g_loader = new Loader();
if (command_line.HasSwitch(switches::kPackages)) {
g_loader->LoadPackagesMap(
command_line.GetSwitchValuePath(switches::kPackages));
} else if (command_line.HasSwitch(switches::kPackageRoot)) {
g_loader->set_package_root(
command_line.GetSwitchValuePath(switches::kPackageRoot));
} else {
fprintf(stderr, "error: Need either --packages or --package-root.\n");
exit(1);
}
}
return *g_loader;
}
......
......@@ -19,10 +19,15 @@
#include "sky/tools/sky_snapshot/vm.h"
void Usage() {
std::cerr << "Usage: sky_snapshot"
<< " --" << switches::kPackageRoot << " --" << switches::kSnapshot
<< " --" << switches::kDepfile << " --" << switches::kBuildOutput
<< " <lib/main.dart>" << std::endl;
std::cerr << R"USAGE(usage: sky_snapshot --packages=PACKAGES --snapshot=SNAPSHOT_BLOB <lib/main.dart>
[ --depfile=DEPS_FILE ] [ --build-output=BUILD_OUTPUT ] [ --help ]
* PACKAGES is the '.packages' file that defines where to find Dart packages.
* SNAPSHOT_BLOB is the file to write the snapshot into.
* DEPS_FILE is an optional '.d' file to depedendency information into.
* BUILD_OUTPUT optionally overrides the target name used in the DEPS_FILE.
(The default is SNAPSHOT_BLOB.)
)USAGE";
}
void WriteSnapshot(base::FilePath path) {
......@@ -68,6 +73,11 @@ int main(int argc, const char* argv[]) {
return 0;
}
if (!command_line.HasSwitch(switches::kSnapshot)) {
fprintf(stderr, "error: Need --snapshot.\n");
exit(1);
}
InitDartVM();
Dart_Isolate isolate = CreateDartIsolate();
CHECK(isolate);
......@@ -81,7 +91,7 @@ int main(int argc, const char* argv[]) {
CHECK(!LogIfError(Dart_FinalizeLoading(true)));
CHECK(command_line.HasSwitch(switches::kSnapshot)) << "Need --snapshot";
CHECK(command_line.HasSwitch(switches::kSnapshot));
WriteSnapshot(command_line.GetSwitchValuePath(switches::kSnapshot));
if (command_line.HasSwitch(switches::kDepfile)) {
......
......@@ -9,6 +9,7 @@ namespace switches {
const char kBuildOutput[] = "build-output";
const char kDepfile[] = "depfile";
const char kHelp[] = "help";
const char kPackages[] = "packages";
const char kPackageRoot[] = "package-root";
const char kSnapshot[] = "snapshot";
......
......@@ -10,6 +10,7 @@ namespace switches {
extern const char kBuildOutput[];
extern const char kDepfile[];
extern const char kHelp[];
extern const char kPackages[];
extern const char kPackageRoot[];
extern const char kSnapshot[];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册