marzer/tomlplusplus

fails to cross-compile from Linux to Windows with mingw g++ 10

claudeha opened this issue · 2 comments

Running Debian testing (to be released as Bookworm):

$ x86_64-w64-mingw32-g++ --version
x86_64-w64-mingw32-g++ (GCC) 10-posix 20220324
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

With this test program:

$ cat test.cc 
#include "tomlplusplus/toml.hpp"

int main(int argc, char **argv)
{
  (void) argc;
  (void) argv;
  return 0;
}

I get this error message:

$ x86_64-w64-mingw32-g++ -std=c++17 -Wall -Wextra -pedantic test.cc
In file included from test.cc:1:
tomlplusplus/toml.hpp: In function ‘toml::v3::ex::parse_result toml::v3::impl::do_parse_file(std::string_view)’:
tomlplusplus/toml.hpp:15775:103: error: no matching function for call to ‘std::basic_ifstream<char>::open(std::wstring, std::_Ios_Openmode)’
15775 |   file.open(impl::widen(file_path_str), std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
      |                                                                                                       ^
In file included from tomlplusplus/toml.hpp:12042,
                 from test.cc:1:
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:658:7: note: candidate: ‘void std::basic_ifstream<_CharT, _Traits>::open(const char*, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::ios_base::openmode = std::ios_base::openmode]’
  658 |       open(const char* __s, ios_base::openmode __mode = ios_base::in)
      |       ^~~~
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:658:24: note:   no known conversion for argument 1 from ‘std::wstring’ {aka ‘std::__cxx11::basic_string<wchar_t>’} to ‘const char*’
  658 |       open(const char* __s, ios_base::openmode __mode = ios_base::in)
      |            ~~~~~~~~~~~~^~~
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:678:7: note: candidate: ‘void std::basic_ifstream<_CharT, _Traits>::open(const wchar_t*, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::ios_base::openmode = std::ios_base::openmode]’
  678 |       open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in)
      |       ^~~~
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:678:27: note:   no known conversion for argument 1 from ‘std::wstring’ {aka ‘std::__cxx11::basic_string<wchar_t>’} to ‘const wchar_t*’
  678 |       open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in)
      |            ~~~~~~~~~~~~~~~^~~
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:697:7: note: candidate: ‘void std::basic_ifstream<_CharT, _Traits>::open(const string&, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::string = std::__cxx11::basic_string<char>; std::ios_base::openmode = std::ios_base::openmode]’
  697 |       open(const std::string& __s, ios_base::openmode __mode = ios_base::in)
      |       ^~~~
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:697:31: note:   no known conversion for argument 1 from ‘std::wstring’ {aka ‘std::__cxx11::basic_string<wchar_t>’} to ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’}
  697 |       open(const std::string& __s, ios_base::openmode __mode = ios_base::in)
      |            ~~~~~~~~~~~~~~~~~~~^~~
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:718:2: note: candidate: ‘template<class _Path> std::_If_fs_path<_Path, void> std::basic_ifstream<_CharT, _Traits>::open(const _Path&, std::ios_base::openmode) [with _Path = _Path; _CharT = char; _Traits = std::char_traits<char>]’
  718 |  open(const _Path& __s, ios_base::openmode __mode = ios_base::in)
      |  ^~~~
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:718:2: note:   template argument deduction/substitution failed:
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream: In substitution of ‘template<class _Path> std::_If_fs_path<_Path, void, decltype (declval<_Path&>().make_preferred().filename())> std::basic_ifstream<char>::open<_Path>(const _Path&, std::ios_base::openmode) [with _Path = std::__cxx11::basic_string<wchar_t>]’:
tomlplusplus/toml.hpp:15775:103:   required from here
/usr/lib/gcc/x86_64-w64-mingw32/10-posix/include/c++/fstream:718:2: error: ‘class std::__cxx11::basic_string<wchar_t>’ has no member named ‘make_preferred’

Error message goes away if I revert cc741c9, but the commit messages says it fixes non-ASCII paths on Windows so it's probably not a good solution.

This patch makes it compile with mingw g++ 10. Seems hacky though.

diff --git a/include/toml++/impl/parser.inl b/include/toml++/impl/parser.inl
index 7aa9afb..f780cd8 100644
--- a/include/toml++/impl/parser.inl
+++ b/include/toml++/impl/parser.inl
@@ -3763,7 +3763,7 @@ TOML_ANON_NAMESPACE_START
                TOML_OVERALIGNED char file_buffer[sizeof(void*) * 1024u];
                file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer));
 #if TOML_WINDOWS
-               file.open(impl::widen(file_path_str), std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
+               file.open(impl::widen(file_path_str).c_str(), std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
 #else
                file.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
 #endif
diff --git a/toml.hpp b/toml.hpp
index 5e4c7f8..7f48c7d 100644
--- a/toml.hpp
+++ b/toml.hpp
@@ -15772,7 +15772,7 @@ TOML_ANON_NAMESPACE_START
                TOML_OVERALIGNED char file_buffer[sizeof(void*) * 1024u];
                file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer));
 #if TOML_WINDOWS
-               file.open(impl::widen(file_path_str), std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
+               file.open(impl::widen(file_path_str).c_str(), std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
 #else
                file.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
 #endif

Hah, yeah, that's a bit clunky but perfectly safe. I'll gladly accept that in a PR if you mind putting it in one