[ CLI ] Fix snapshot detection logic for google3
google3 makes heavy use of symlinks, with no guarantee that the relative location of files with respect to each other will be maintained after the symlinks are resolved. This causes issues when trying to locate the DartDev snapshot using the VM executables resolved path as a base. This change updates the DartDev snapshot detection logic to first try to find the snapshot using the resolved executable path before falling back to using the unresolved path used to launch the VM (e.g., the path specified by argv[0]). TEST=pkg/dartdev/test/ Change-Id: I19a41c440ac82cbc671dafb3bda23a31fb4cdc0c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/370000 Reviewed-by: Derek Xu <derekx@google.com> Commit-Queue: Ben Konyi <bkonyi@google.com>
This commit is contained in:
@@ -30,7 +30,7 @@ class Sdk {
|
||||
// Assume that we want to use the same Dart executable that we used to spawn
|
||||
// DartDev. We should be able to run programs with out/ReleaseX64/dart even
|
||||
// if the SDK isn't completely built.
|
||||
String get dart => Platform.resolvedExecutable;
|
||||
String get dart => Platform.executable;
|
||||
|
||||
String get dartAotRuntime => _runFromBuildRoot
|
||||
? path.absolute(
|
||||
@@ -149,22 +149,37 @@ class Sdk {
|
||||
|
||||
static Sdk _createSingleton() {
|
||||
// Find SDK path.
|
||||
(String, bool)? trySDKPath(String executablePath) {
|
||||
// The common case, and how cli_util.dart computes the Dart SDK directory,
|
||||
// [path.dirname] called twice on Platform.executable. We confirm by
|
||||
// asserting that the directory `./bin/snapshots/` exists in this directory:
|
||||
var sdkPath = path.absolute(path.dirname(path.dirname(executablePath)));
|
||||
var snapshotsDir = path.join(sdkPath, 'bin', 'snapshots');
|
||||
var runFromBuildRoot = false;
|
||||
if (!Directory(snapshotsDir).existsSync()) {
|
||||
// This is the less common case where the user is in
|
||||
// the checked out Dart SDK, and is executing `dart` via:
|
||||
// ./out/ReleaseX64/dart ... or in google3.
|
||||
sdkPath = path.absolute(path.dirname(executablePath));
|
||||
snapshotsDir = sdkPath;
|
||||
runFromBuildRoot = true;
|
||||
}
|
||||
|
||||
// The common case, and how cli_util.dart computes the Dart SDK directory,
|
||||
// [path.dirname] called twice on Platform.resolvedExecutable. We confirm by
|
||||
// asserting that the directory `./bin/snapshots/` exists in this directory:
|
||||
var sdkPath =
|
||||
path.absolute(path.dirname(path.dirname(Platform.resolvedExecutable)));
|
||||
var snapshotsDir = path.join(sdkPath, 'bin', 'snapshots');
|
||||
var runFromBuildRoot = false;
|
||||
if (!Directory(snapshotsDir).existsSync()) {
|
||||
// This is the less common case where the user is in
|
||||
// the checked out Dart SDK, and is executing `dart` via:
|
||||
// ./out/ReleaseX64/dart ... or in google3.
|
||||
sdkPath = path.absolute(path.dirname(Platform.resolvedExecutable));
|
||||
runFromBuildRoot = true;
|
||||
// Try to locate the DartDev snapshot to determine if we're able to find
|
||||
// the SDK snapshots with this SDK path. This is meant to handle
|
||||
// non-standard SDK layouts that can involve symlinks (e.g., Brew
|
||||
// installations, google3 tests, etc).
|
||||
if (!File(path.join(snapshotsDir, 'dartdev.dart.snapshot'))
|
||||
.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return (sdkPath, runFromBuildRoot);
|
||||
}
|
||||
|
||||
final (sdkPath, runFromBuildRoot) =
|
||||
trySDKPath(Platform.resolvedExecutable) ??
|
||||
trySDKPath(Platform.executable)!;
|
||||
|
||||
// Defer to [Runtime] for the version.
|
||||
var version = Runtime.runtime.version;
|
||||
|
||||
|
||||
@@ -80,25 +80,37 @@ bool DartDevIsolate::ShouldParseCommand(const char* script_uri) {
|
||||
}
|
||||
|
||||
CStringUniquePtr DartDevIsolate::TryResolveArtifactPath(const char* filename) {
|
||||
// |dir_prefix| includes the last path separator.
|
||||
auto dir_prefix = EXEUtils::GetDirectoryPrefixFromExeName();
|
||||
auto try_resolve_path = [&](CStringUniquePtr dir_prefix) {
|
||||
// First assume we're in dart-sdk/bin.
|
||||
char* snapshot_path =
|
||||
Utils::SCreate("%ssnapshots/%s", dir_prefix.get(), filename);
|
||||
if (File::Exists(nullptr, snapshot_path)) {
|
||||
return CStringUniquePtr(snapshot_path);
|
||||
}
|
||||
free(snapshot_path);
|
||||
|
||||
// First assume we're in dart-sdk/bin.
|
||||
char* snapshot_path =
|
||||
Utils::SCreate("%ssnapshots/%s", dir_prefix.get(), filename);
|
||||
if (File::Exists(nullptr, snapshot_path)) {
|
||||
return CStringUniquePtr(snapshot_path);
|
||||
}
|
||||
free(snapshot_path);
|
||||
// If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
|
||||
// directories. Try to use a snapshot from a previously built SDK.
|
||||
snapshot_path = Utils::SCreate("%s%s", dir_prefix.get(), filename);
|
||||
if (File::Exists(nullptr, snapshot_path)) {
|
||||
return CStringUniquePtr(snapshot_path);
|
||||
}
|
||||
free(snapshot_path);
|
||||
return CStringUniquePtr(nullptr);
|
||||
};
|
||||
|
||||
// If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
|
||||
// directories. Try to use a snapshot from a previously built SDK.
|
||||
snapshot_path = Utils::SCreate("%s%s", dir_prefix.get(), filename);
|
||||
if (File::Exists(nullptr, snapshot_path)) {
|
||||
return CStringUniquePtr(snapshot_path);
|
||||
// Try to find the artifact using the resolved EXE path first. This can fail
|
||||
// if the Dart SDK file structure is faked using symlinks and the actual
|
||||
// artifacts are spread across directories on the file system (e.g., some
|
||||
// google3 execution environments).
|
||||
auto result =
|
||||
try_resolve_path(EXEUtils::GetDirectoryPrefixFromResolvedExeName());
|
||||
if (result == nullptr) {
|
||||
result =
|
||||
try_resolve_path(EXEUtils::GetDirectoryPrefixFromUnresolvedExeName());
|
||||
}
|
||||
free(snapshot_path);
|
||||
return CStringUniquePtr(nullptr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ void DFE::InitKernelServiceAndPlatformDills() {
|
||||
}
|
||||
|
||||
// |dir_prefix| includes the last path separator.
|
||||
auto dir_prefix = EXEUtils::GetDirectoryPrefixFromExeName();
|
||||
auto dir_prefix = EXEUtils::GetDirectoryPrefixFromResolvedExeName();
|
||||
|
||||
// Look for the frontend snapshot next to the executable.
|
||||
frontend_filename_ =
|
||||
|
||||
@@ -65,7 +65,7 @@ static const char* GetFileNameFromPath(const char* path) {
|
||||
return path;
|
||||
}
|
||||
|
||||
CStringUniquePtr EXEUtils::GetDirectoryPrefixFromExeName() {
|
||||
CStringUniquePtr EXEUtils::GetDirectoryPrefixFromResolvedExeName() {
|
||||
const char* name = nullptr;
|
||||
const int kTargetSize = PATH_MAX;
|
||||
char target[kTargetSize];
|
||||
@@ -119,6 +119,12 @@ CStringUniquePtr EXEUtils::GetDirectoryPrefixFromExeName() {
|
||||
return CStringUniquePtr(result == nullptr ? Utils::StrDup("") : result);
|
||||
}
|
||||
|
||||
CStringUniquePtr EXEUtils::GetDirectoryPrefixFromUnresolvedExeName() {
|
||||
const char* exe = Platform::GetExecutableName();
|
||||
return CStringUniquePtr(exe == nullptr ? nullptr
|
||||
: GetDirectoryFromPath(exe, nullptr));
|
||||
}
|
||||
|
||||
#if !defined(DART_HOST_OS_WINDOWS)
|
||||
void EXEUtils::LoadDartProfilerSymbols(const char* argv0) {
|
||||
char* path = reinterpret_cast<char*>(malloc(PATH_MAX + 5));
|
||||
|
||||
@@ -17,8 +17,15 @@ namespace bin {
|
||||
|
||||
class EXEUtils {
|
||||
public:
|
||||
// Returns the path to the directory the current executable resides in.
|
||||
static CStringUniquePtr GetDirectoryPrefixFromExeName();
|
||||
// Returns the resolved path to the directory the current executable resides
|
||||
// in.
|
||||
static CStringUniquePtr GetDirectoryPrefixFromResolvedExeName();
|
||||
|
||||
// Returns the path to the directory the current executable resides
|
||||
// in without following symlinks.
|
||||
//
|
||||
// Returns null if Platform::GetExecutableName() returns null.
|
||||
static CStringUniquePtr GetDirectoryPrefixFromUnresolvedExeName();
|
||||
|
||||
#if !defined(DART_HOST_OS_WINDOWS)
|
||||
// Loads a compact symbolization table from "$exepath.sym" that is used by the
|
||||
|
||||
Reference in New Issue
Block a user