Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with mingw-w64 gcc 10.2.0 on windows 10 #76

Open
mcmarius opened this issue Nov 11, 2020 · 2 comments
Open

Issues with mingw-w64 gcc 10.2.0 on windows 10 #76

mcmarius opened this issue Nov 11, 2020 · 2 comments

Comments

@mcmarius
Copy link

Hey, first of all, awesome work! 😃

I ran into some issues when building and running the demo and I would like to share my workarounds.

First error (among many others caused by the missing header)
$ mingw32-make.exe
g++ -pthread -std=c++11 -I../include -o demo demo.cpp
In file included from ../include/indicators/details/stream_helper.hpp:6,
                 from ../include/indicators/progress_bar.hpp:4,
                 from demo.cpp:4:
../include/indicators/termcolor.hpp: In function 'std::ostream& termcolor::red(std::ostream&)':
../include/indicators/termcolor.hpp:287:17: error: 'FOREGROUND_RED' was not declared in this scope
  287 |                 FOREGROUND_RED
      |                 ^~~~~~~~~~~~~~
../include/indicators/termcolor.hpp:287:17: note: the macro 'FOREGROUND_RED' had not yet been defined
In file included from c:\winlibs-x86_64-posix-seh-gcc-10.2.0-llvm-11.0.0-mingw-w64-8.0.0-r3\mingw64\x86_64-w64-mingw32\include\windows.h:74,
                 from ../include/indicators/terminal_size.hpp:7,
                 from ../include/indicators/progress_bar.hpp:12,
                 from demo.cpp:4:
c:\winlibs-x86_64-posix-seh-gcc-10.2.0-llvm-11.0.0-mingw-w64-8.0.0-r3\mingw64\x86_64-w64-mingw32\include\wincon.h:121: note: it was later defined here
  121 | #define FOREGROUND_RED 0x4

In indicators/termcolor.hpp, some Windows-specific headers are not included. I changed lines 36-44 (moved an endif) to this:

#elif defined(TERMCOLOR_OS_WINDOWS)
#if defined(_MSC_VER)
#if !defined(NOMINMAX)
#define NOMINMAX
#endif
#endif
#   include <io.h>
#   include <windows.h>
#endif

The second issue encountered was the from_bytes conversion in function std::wstring utf8_decode(const std::string &str) from indicators/display_width.hpp. I replaced it with the function from this answer. Though I'm not sure if this second workaround is portable.

Second issue appears when using an emoji as lead in the nested progress bar example
$ ./demo.exe
[■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ] Buying more snacks
Reading package list... Done
[==================================================] Done
{ 97% } ⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠸⠧ Restoring system state
{ ERROR } 98% Failed to restore system
[■-------------------------------------------------] Reverting system restore
⡀ 101% Checking credentials
✔ Authenticated!
  Compiling mission
 - ✔ Searching for the Moon
 - ✔ Contacting Kerbal headquarters
 - ✔ Designing spaceship
 - ✔ Launching rocket
 - 🌎terminate called after throwing an instance of 'std::range_error'
  what():  wstring_convert::from_bytes
Also posting it here if the stackoverflow answer gets deleted
// credits: https://stackoverflow.com/a/7154226
static inline std::wstring utf8_decode(const std::string& utf8)
{
    std::vector unicode;
    size_t i = 0;
    while (i < utf8.size())
    {
        unsigned long uni;
        size_t todo;
        bool error = false;
        unsigned char ch = utf8[i++];
        if (ch <= 0x7F)
        {
            uni = ch;
            todo = 0;
        }
        else if (ch <= 0xBF)
        {
            throw std::logic_error("not a UTF-8 string");
        }
        else if (ch <= 0xDF)
        {
            uni = ch&0x1F;
            todo = 1;
        }
        else if (ch <= 0xEF)
        {
            uni = ch&0x0F;
            todo = 2;
        }
        else if (ch <= 0xF7)
        {
            uni = ch&0x07;
            todo = 3;
        }
        else
        {
            throw std::logic_error("not a UTF-8 string");
        }
        for (size_t j = 0; j < todo; ++j)
        {
            if (i == utf8.size())
                throw std::logic_error("not a UTF-8 string");
            unsigned char ch = utf8[i++];
            if (ch < 0x80 || ch > 0xBF)
                throw std::logic_error("not a UTF-8 string");
            uni <<= 6;
            uni += ch & 0x3F;
        }
        if (uni >= 0xD800 && uni <= 0xDFFF)
            throw std::logic_error("not a UTF-8 string");
        if (uni > 0x10FFFF)
            throw std::logic_error("not a UTF-8 string");
        unicode.push_back(uni);
    }
    std::wstring utf16;
    for (size_t i = 0; i < unicode.size(); ++i)
    {
        unsigned long uni = unicode[i];
        if (uni <= 0xFFFF)
        {
            utf16 += (wchar_t)uni;
        }
        else
        {
            uni -= 0x10000;
            utf16 += (wchar_t)((uni >> 10) + 0xD800);
            utf16 += (wchar_t)((uni & 0x3FF) + 0xDC00);
        }
    }
    return utf16;
}

An #include <vector> would also be necessary for the above workaround.

My current environment is the following:

  • Windows 10 2004
  • terminus with WSL profile
  • indicators latest commit (af7c004 as of 11 november 2020)
  • mingw-w64 gcc from winlibs.com
$ g++ -v
Using built-in specs.
COLLECT_GCC=C:\winlibs-x86_64-posix-seh-gcc-10.2.0-llvm-11.0.0-mingw-w64-8.0.0-r3\mingw64\bin\g++.exe 
COLLECT_LTO_WRAPPER=c:/winlibs-x86_64-posix-seh-gcc-10.2.0-llvm-11.0.0-mingw-w64-8.0.0-r3/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/10.2.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../configure --prefix=/R/winlibs64_stage/inst_gcc-10.2.0/share/gcc --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --with-pkgversion='MinGW-W64 x86_64-posix-seh, built by Brecht Sanders' --with-tune=generic --enable-checking=release --enable-threads=posix --disable-sjlj-exceptions --disable-libunwind-exceptions --enable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --enable-default-ssp --disable-rpath --disable-libstdcxx-pch --enable-libstdcxx-time=yes --disable-libstdcxx-debug --disable-version-specific-runtime-libs --with-stabs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++,d --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite 
--enable-mingw-wildcard --with-mpc=/d/Prog/winlibs64_stage/custombuilt --with-mpfr=/d/Prog/winlibs64_stage/custombuilt --with-gmp=/d/Prog/winlibs64_stage/custombuilt --with-isl=/d/Prog/winlibs64_stage/custombuilt --enable-install-libiberty --enable-__cxa_atexit 
--without-included-gettext --with-diagnostics-color=auto --with-libiconv --with-system-zlib --with-build-sysroot=/R/winlibs64_stage/gcc-10.2.0/build_mingw/mingw-w64
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.0 (MinGW-W64 x86_64-posix-seh, built by Brecht Sanders)
p-ranav added a commit that referenced this issue May 3, 2021
… replaced #pragma once with #ifndef-define pairs
@p-ranav
Copy link
Owner

p-ranav commented May 3, 2021

@mcmarius

The second issue encountered was the from_bytes conversion in function std::wstring utf8_decode(const std::string &str) from indicators/display_width.hpp

Can you describe the issue that was encountered?

@mcmarius
Copy link
Author

mcmarius commented May 6, 2021

It seems that std::wstring_convert::from_bytes does not like 4-byte characters on Windows with gcc and throws an exception:

terminate called after throwing an instance of 'std::range_error'
  what():  wstring_convert::from_bytes

It is called in the return statement of utf8_decode in indicators/display_width.hpp:285. It works fine on WSL now, but still throws an exception when compiling the demo with gcc MinGW. It works with 3-byte emojis such as ⌚️.
Replacing utf8_decode with the function in the linked SO answer seems to solve the issue.

With Terminus it works as expected, but there is another issue with 3-byte emojis using windows terminal which reproduces both on powershell profile and on wsl. This might be the fault of Windows Terminal though:
image

All emojis up to U+329x seem to exibit this behaviour (extra newlines), while emojis from U+1F00x seem to break on Windows without the mentioned fix (I picked some emojis randomly from this wikipedia article).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants