[Impeller] Don't double-convert include path encodings in ImpellerC (#37408)
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 5cb3aed..0f6405a 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1124,6 +1124,7 @@
FILE: ../../../flutter/impeller/compiler/spirv_sksl.h
FILE: ../../../flutter/impeller/compiler/switches.cc
FILE: ../../../flutter/impeller/compiler/switches.h
+FILE: ../../../flutter/impeller/compiler/switches_unittests.cc
FILE: ../../../flutter/impeller/compiler/types.cc
FILE: ../../../flutter/impeller/compiler/types.h
FILE: ../../../flutter/impeller/compiler/utilities.cc
diff --git a/impeller/compiler/BUILD.gn b/impeller/compiler/BUILD.gn
index 8512408..3098941 100644
--- a/impeller/compiler/BUILD.gn
+++ b/impeller/compiler/BUILD.gn
@@ -120,6 +120,7 @@
"compiler_test.cc",
"compiler_test.h",
"compiler_unittests.cc",
+ "switches_unittests.cc",
]
deps = [
diff --git a/impeller/compiler/switches.cc b/impeller/compiler/switches.cc
index 4ca2a27..1e73352 100644
--- a/impeller/compiler/switches.cc
+++ b/impeller/compiler/switches.cc
@@ -127,11 +127,17 @@
// fml::OpenDirectoryReadOnly for Windows doesn't handle relative paths
// beginning with `../` well, so we build an absolute path.
+
+ // Get the current working directory as a utf8 encoded string.
+ // Note that the `include_dir_path` is already utf8 encoded, and so we
+ // mustn't attempt to double-convert it to utf8 lest multi-byte characters
+ // will become mangled.
+ auto cwd = Utf8FromPath(std::filesystem::current_path());
auto include_dir_absolute = std::filesystem::absolute(
- std::filesystem::current_path() / include_dir_path);
+ std::filesystem::path(cwd) / include_dir_path);
auto dir = std::make_shared<fml::UniqueFD>(fml::OpenDirectoryReadOnly(
- *working_directory, Utf8FromPath(include_dir_absolute).c_str()));
+ *working_directory, include_dir_absolute.string().c_str()));
if (!dir || !dir->is_valid()) {
continue;
}
diff --git a/impeller/compiler/switches_unittests.cc b/impeller/compiler/switches_unittests.cc
new file mode 100644
index 0000000..54ca1e2
--- /dev/null
+++ b/impeller/compiler/switches_unittests.cc
@@ -0,0 +1,36 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/fml/command_line.h"
+#include "flutter/fml/file.h"
+#include "flutter/testing/testing.h"
+#include "impeller/compiler/switches.h"
+#include "impeller/compiler/utilities.h"
+
+namespace impeller {
+namespace compiler {
+namespace testing {
+
+TEST(SwitchesTest, DoesntMangleUnicodeIncludes) {
+ const char* directory_name = "test_shader_include_�";
+ fml::CreateDirectory(flutter::testing::OpenFixturesDirectory(),
+ {directory_name}, fml::FilePermission::kRead);
+
+ auto include_path =
+ std::string(flutter::testing::GetFixturesPath()) + "/" + directory_name;
+ auto include_option = "--include=" + include_path;
+
+ const auto cl = fml::CommandLineFromInitializerList(
+ {"impellerc", "--opengl-desktop", "--input=input.vert",
+ "--sl=output.vert", "--spirv=output.spirv", include_option.c_str()});
+ Switches switches(cl);
+ ASSERT_TRUE(switches.AreValid(std::cout));
+ ASSERT_EQ(switches.include_directories.size(), 1u);
+ ASSERT_NE(switches.include_directories[0].dir, nullptr);
+ ASSERT_EQ(switches.include_directories[0].name, include_path);
+}
+
+} // namespace testing
+} // namespace compiler
+} // namespace impeller
diff --git a/impeller/compiler/utilities.h b/impeller/compiler/utilities.h
index 7b05d30..61af436 100644
--- a/impeller/compiler/utilities.h
+++ b/impeller/compiler/utilities.h
@@ -13,6 +13,12 @@
namespace impeller {
namespace compiler {
+/// @brief Converts a native format path to a utf8 string.
+///
+/// This utility uses `path::u8string()` to convert native paths to
+/// utf8. If the given path doesn't match the underlying native path
+/// format, and the native path format isn't utf8 (i.e. Windows, which
+/// has utf16 paths), the path will get mangled.
std::string Utf8FromPath(const std::filesystem::path& path);
std::string InferShaderNameFromPath(std::string_view path);