gulrak / filesystem

An implementation of C++17 std::filesystem for C++11 /C++14/C++17/C++20 on Windows, macOS, Linux and FreeBSD.
MIT License
1.31k stars 168 forks source link

Workaround for opening file streams using wide string paths on old versions of MinGW #175

Open rikyoz opened 9 months ago

rikyoz commented 9 months ago

On old MinGW versions, opening file streams using wide string paths is not supported. This basically makes it impossible to use ghc::filesystem's streams for opening files with a Unicode character in the path since, by default, the narrow path string (UTF-8 encoded) gets interpreted by Windows using the system codepage (unless you force the program to use UTF-8 via a manifest file).

Example:

#include <iostream>

#include <Windows.h>

#include "ghc/filesystem.hpp"

namespace fs = ghc::filesystem;

constexpr auto path_str = L"αρχείο.txt";

auto main() -> int {
    std::cout << "System codepage: " << GetACP() << std::endl;

    const auto path = fs::path{ path_str };
    {
        fs::ofstream ofs{ path, std::ios::binary };
        ofs << "hello world!" << std::endl;
    }
    std::cout << "File exists: " << std::boolalpha << fs::exists( path ) << std::endl;
}

Output:

image image

However, old versions of MinGW might support the _wsopen_s function, a Microsoft extension that allows opening a file using a wide C string path. This, together with an internal function of libstdc++ (__gnu_cxx::stdio_filebuf), can be used to implement a workaround.

The workaround is used only if libstdc++ doesn't natively support opening file streams using wide string paths (https://github.com/gulrak/filesystem/pull/172), which is the preferred way on recent versions of MinGW.

Output with the workaround:

image image

I tested it with both MinGW 7 and 8, which do not support GHC_HAS_FSTREAM_OPEN_WITH_WCHAR, but support _wsopen_s.

As a side note, I had to modify the CMake files so that the -Wa,-mbig-obj parameter is passed to all the test targets; otherwise, MinGW fails while linking the executables.

I hope everything is ok!