[vm/ffi] Native assets Windows fixes

Some artifacts are .exe instead of .bat.

Library uris with file schemes use the Uri.path (using forward slashes
on Windows), so the tests emitting native asset mappings should use
Uri.path as well. (Not Uri.toFilePath() which uses backwards slashes.)
The paths of the dynamic libraries in the assets should use the
toFilePath(), as these are passed to the system API which expects
correct paths.

The Platform.script Uri has a path with file:///C: and back slashes.
The uri RFC does not support back slashes, and our ResolveUri does
neither. So for Windows we replace backslashes with forward slashes.

TEST=tests/ffi/native_assets/

Bug: https://github.com/dart-lang/sdk/issues/51066
Bug: https://github.com/dart-lang/sdk/issues/51067
Change-Id: I2e168e0549fe80d9a5366d636c6f1ef971942130
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-win-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-nnbd-win-release-x64-try,vm-kernel-nnbd-win-release-ia32-try,vm-kernel-msvc-windows-try,dart-sdk-win-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279356
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
Daco Harkes 2023-01-20 18:20:17 +00:00 committed by Commit Queue
parent d5d7cc967f
commit 17f4198cfe
13 changed files with 99 additions and 36 deletions

View file

@ -245,16 +245,46 @@ static void* FfiResolveWithFfiNativeResolver(Thread* const thread,
return result;
}
static StringPtr GetPlatformScriptPath(Thread* thread) {
auto* const zone = thread->zone();
IsolateGroupSource* const source = thread->isolate_group()->source();
auto& result = String::Handle(zone, String::New(source->script_uri));
const auto& fileSchema = String::Handle(zone, String::New("file://"));
if (result.StartsWith(fileSchema)) {
// Isolate.spawnUri sets a `source` including the file schema.
result ^= String::SubString(result, fileSchema.Length());
#if defined(DART_TARGET_OS_WINDOWS)
// Replaces back slashes with forward slashes in place.
static void ReplaceBackSlashes(char* cstr) {
const intptr_t length = strlen(cstr);
for (int i = 0; i < length; i++) {
cstr[i] = cstr[i] == '\\' ? '/' : cstr[i];
}
}
#endif
// Get a file path with only forward slashes from the script path.
static StringPtr GetPlatformScriptPath(Thread* thread) {
IsolateGroupSource* const source = thread->isolate_group()->source();
#if defined(DART_TARGET_OS_WINDOWS)
// Isolate.spawnUri sets a `source` including the file schema.
// And on Windows we get an extra forward slash in that case.
const char* path = source->script_uri;
if (strlen(source->script_uri) > 8 &&
strncmp(source->script_uri, "file:///", 8) == 0) {
path = (source->script_uri + 8);
}
// Replace backward slashes with forward slashes.
const intptr_t len = strlen(path);
char* path_copy = reinterpret_cast<char*>(malloc(len + 1));
snprintf(path_copy, len + 1, "%s", path);
ReplaceBackSlashes(path_copy);
const auto& result = String::Handle(String::New(path_copy));
free(path_copy);
return result.ptr();
#else
// Isolate.spawnUri sets a `source` including the file schema.
if (strlen(source->script_uri) > 7 &&
strncmp(source->script_uri, "file://", 7) == 0) {
const char* path = (source->script_uri + 7);
return String::New(path);
}
return String::New(source->script_uri);
#endif
}
// Array::null if asset is not in mapping or no mapping.
@ -302,8 +332,13 @@ static void* FfiResolveAsset(Thread* const thread,
const auto& platform_script_path =
String::Handle(zone, GetPlatformScriptPath(thread));
const char* target_uri = nullptr;
const bool resolved = ResolveUri(
path.ToCString(), platform_script_path.ToCString(), &target_uri);
char* path_cstr = path.ToMallocCString();
#if defined(DART_TARGET_OS_WINDOWS)
ReplaceBackSlashes(path_cstr);
#endif
const bool resolved =
ResolveUri(path_cstr, platform_script_path.ToCString(), &target_uri);
free(path_cstr);
if (!resolved) {
*error = OS::SCreate(/*use malloc*/ nullptr,
"Failed to resolve '%s' relative to '%s'.",

View file

@ -594,4 +594,30 @@ TEST_CASE(ResolveUri_MoreDotSegmentTests) {
#undef LH
}
TEST_CASE(ResolveUri_WindowsPaths_Forwardslash_NoScheme) {
EXPECT_STREQ(
"c:/Users/USERNA~1/AppData/Local/Temp/a/b.dll",
TestResolve("C:/Users/USERNA~1/AppData/Local/Temp/a/out.dill", "b.dll"));
}
// > Here are some examples which may be accepted by some applications on
// > Windows systems
// https://en.wikipedia.org/wiki/File_URI_scheme
// "file:///C:/"
TEST_CASE(ResolveUri_WindowsPaths_Forwardslash_FileScheme) {
EXPECT_STREQ(
"file:///"
"C:/Users/USERNA~1/AppData/Local/Temp/a/b.dll",
TestResolve("file:///C:/Users/USERNA~1/AppData/Local/Temp/a/out.dill",
"b.dll"));
}
TEST_CASE(ResolveUri_WindowsPaths_Backslash) {
EXPECT_STREQ(
"file:///b.dll",
TestResolve(
"file:///C:\\Users\\USERNA~1\\AppData\\Local\\Temp\\a\\out.dill",
"b.dll"));
}
} // namespace dart

View file

@ -43,11 +43,12 @@ main(List<String> args, Object? message) async {
Future<void> selfInvokes() async {
final selfSourceUri = Platform.script.resolve('asset_absolute_test.dart');
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${selfSourceUri.toFilePath()}',
assetMapping: [
'absolute',
ffiTestFunctionsUriAbsolute.toFilePath(),
]);
asset: selfSourceUri.toString(),
assetMapping: [
'absolute',
ffiTestFunctionsUriAbsolute.toFilePath(),
],
);
await invokeSelf(
selfSourceUri: selfSourceUri,
runtime: Runtime.jit,

View file

@ -43,8 +43,7 @@ main(List<String> args, Object? message) async {
Future<void> selfInvokes() async {
final selfSourceUri = Platform.script.resolve('asset_executable_test.dart');
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${selfSourceUri.toFilePath()}',
assetMapping: ['executable']);
asset: selfSourceUri.toString(), assetMapping: ['executable']);
await invokeSelf(
selfSourceUri: selfSourceUri,
runtime: Runtime.jit,

View file

@ -44,7 +44,7 @@ const asset2Name = 'myAsset';
Future<void> selfInvokes() async {
final selfSourceUri = Platform.script.resolve('asset_process_test.dart');
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${selfSourceUri.toFilePath()}',
asset: selfSourceUri.toString(),
assetMapping: ['process'],
asset2: asset2Name,
asset2Mapping: ['process'],

View file

@ -97,13 +97,13 @@ Future<void> invokeSelf({
tempUri.resolve(ffiTestFunctionsCopyUriRelative.toFilePath());
await File(ffiTestFunctionsUriAbsolute.toFilePath())
.copy(ffiTestFunctionsCopyUriAbsolute.toFilePath());
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${selfSourceUri.toFilePath()}',
assetMapping: [
'relative',
ffiTestFunctionsCopyUriRelative.toFilePath(),
]);
asset: selfSourceUri.toString(),
assetMapping: [
'relative',
ffiTestFunctionsCopyUriRelative.toFilePath(),
],
);
await compileAndRun(
tempUri: tempUri,

View file

@ -52,7 +52,7 @@ Future<void> selfInvokes() async {
: 'libc.so.6', // lib.so contains plain text with GROUP( ... ).
];
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${selfSourceUri.toFilePath()}',
asset: selfSourceUri.toString(),
assetMapping: assetMapping,
asset2: asset2Name,
asset2Mapping: assetMapping,

View file

@ -42,16 +42,18 @@ final sdkUriAbsolute = buildUriAbsolute.parent.parent;
final standaloneExtension = (Platform.isWindows ? '.bat' : '');
final standaloneExtensionExe = (Platform.isWindows ? '.exe' : '');
final genKernelUri =
sdkUriAbsolute.resolve('pkg/vm/tool/gen_kernel$standaloneExtension');
final genSnapshotUri =
buildUriAbsolute.resolve('gen_snapshot$standaloneExtension');
buildUriAbsolute.resolve('gen_snapshot$standaloneExtensionExe');
final dartUri = buildUriAbsolute.resolve('dart$standaloneExtension');
final dartUri = buildUriAbsolute.resolve('dart$standaloneExtensionExe');
final dartPrecompiledRuntimeUri =
buildUriAbsolute.resolve('dart_precompiled_runtime$standaloneExtension');
buildUriAbsolute.resolve('dart_precompiled_runtime$standaloneExtensionExe');
final platformDillUri = buildUriAbsolute.resolve('vm_platform_strong.dill');

View file

@ -29,7 +29,7 @@ final testPackageConfig = '''{
"packages": [
{
"name": "meta",
"rootUri": "${packageMetaUri.toFilePath()}",
"rootUri": "$packageMetaUri",
"packageUri": "lib/",
"languageVersion": "2.12"
}
@ -91,7 +91,7 @@ Future<void> createTestFiles(Uri tempUri) async {
await File.fromUri(packageConfigUri).writeAsString(testPackageConfig);
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${helperCopiedUri.toFilePath()}',
asset: helperCopiedUri.toString(),
assetMapping: [
'absolute',
ffiTestFunctionsUriAbsolute.toFilePath(),

View file

@ -75,7 +75,7 @@ Future<void> createTestFiles(Uri tempUri, Uri tempUri2) async {
await File.fromUri(packageConfigUri).writeAsString(emptyPackageConfig);
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${helper2CopiedUri.toFilePath()}',
asset: helper2CopiedUri.toString(),
assetMapping: [
'absolute',
ffiTestFunctionsUriAbsolute.toFilePath(),

View file

@ -27,7 +27,7 @@ final emptyPackageConfig = '''{
"packages": [
{
"name": "meta",
"rootUri": "${packageMetaUri.toFilePath()}",
"rootUri": "$packageMetaUri",
"packageUri": "lib/",
"languageVersion": "2.12"
}

View file

@ -34,7 +34,7 @@ final emptyPackageConfig = '''{
"packages": [
{
"name": "meta",
"rootUri": "${packageMetaUri.toFilePath()}",
"rootUri": "$packageMetaUri",
"packageUri": "lib/",
"languageVersion": "2.12"
}
@ -84,7 +84,7 @@ Future<void> createTestFiles(Uri tempUri) async {
await File.fromUri(packageConfigUri).writeAsString(emptyPackageConfig);
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${helperCopiedUri.toFilePath()}',
asset: helperCopiedUri.toString(),
assetMapping: [
'absolute',
ffiTestFunctionsUriAbsolute.toFilePath(),

View file

@ -28,7 +28,7 @@ final testPackageConfig = '''{
"packages": [
{
"name": "meta",
"rootUri": "${packageMetaUri.toFilePath()}",
"rootUri": "$packageMetaUri",
"packageUri": "lib/",
"languageVersion": "2.12"
}
@ -79,7 +79,7 @@ Future<void> createTestFiles(Uri tempUri) async {
await File.fromUri(packageConfigUri).writeAsString(testPackageConfig);
final nativeAssetsYaml = createNativeAssetYaml(
asset: 'file://${helperCopiedUri.toFilePath()}',
asset: helperCopiedUri.toString(),
assetMapping: [
'absolute',
ffiTestFunctionsUriAbsolute.toFilePath(),