neonxc
neonxc

Reputation: 860

How do I resolve vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker mismatch in the C++WinRT project using Boost.Locale & Boost.Predef?

I'm working on a C++/WinRT project and would like to use Boost (1.73.0) Locale in it. Inspired by a Microsoft blog post I have replaced calls to unsupported WinApi functions in the library sources and compiled with windows-api=store. I managed to build all intended library variants (arm / x64, debug / release) and went on to build the UWP app. That is the point where I am stuck right now. The build fails to link with the following output:

vccorlibd.lib(init.obj) : error LNK2038: mismatch detected for 'vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker': value '1' doesn't match value '0' in MSVCRTD.lib(app_appinit.obj)

vccorlibd.lib(init.obj) : error LNK2005: __crtWinrtInitType already defined in MSVCRTD.lib(app_appinit.obj)

The line triggering the failure:

const auto text = boost::locale::conv::to_utf<char>("xxx", "yyy");

My setup is Visual Studio 17 & 19, SDK 10.0.19041.0. I have tried this solution proposed to a similar question but to no avail. The modifications I made in the boost_1_73_0/libs/locale/src/win32 directory follow:

api.h

// detecting UWP
#include <boost/predef.h>

// ...

    class winlocale{
    public:
        winlocale() :
          lcid(0)
        {
        }

        winlocale(std::string const name)
        {
#if BOOST_PLAT_WINDOWS_RUNTIME
          str.assign(cbegin(name), cend(name));
#endif
          lcid = locale_to_lcid(name);
        }

#if BOOST_PLAT_WINDOWS_RUNTIME
        std::wstring str;
#endif

        unsigned lcid;
        bool is_c() const
        {
          return lcid == 0;
        }
    };

// ...

    inline std::wstring win_map_string_l(unsigned flags,wchar_t const *begin,wchar_t const *end,winlocale const &l)
    {
        std::wstring res;

#if BOOST_PLAT_WINDOWS_RUNTIME
        int len = LCMapStringEx(l.str.c_str(), flags, begin, end - begin, 0, 0,
          /* >=win_vista must set to null*/ 0,
          /*Reserved; must be NULL.*/ 0,
          /*Reserved; must be 0.*/ 0);
        if (len == 0)
          return res;
        std::vector<wchar_t> buf(len + 1);
        int l2 = LCMapStringEx(l.str.c_str(), flags, begin, end - begin, &buf.front(), buf.size(),
          /* >=win_vista must set to null*/ 0,
          /*Reserved; must be NULL.*/ 0,
          /*Reserved; must be 0.*/ 0);
        res.assign(&buf.front(), l2);
#else
        int len = LCMapStringW(l.lcid,flags,begin,end-begin,0,0);
        if(len == 0)
            return res;
        std::vector<wchar_t> buf(len+1);
        int l2 = LCMapStringW(l.lcid,flags,begin,end-begin,&buf.front(),buf.size());
        res.assign(&buf.front(),l2);
#endif

        return res;
    }

// …

    inline std::wstring wcsfmon_l(double value,winlocale const &l)
    {
        std::wostringstream ss;
        ss.imbue(std::locale::classic());

        ss << std::setprecision(std::numeric_limits<double>::digits10+1) << value;
        std::wstring sval = ss.str();
#if BOOST_PLAT_WINDOWS_RUNTIME 
        int len = GetCurrencyFormatEx(l.str.c_str(), 0, sval.c_str(), 0, 0, 0);
        std::vector<wchar_t> buf(len + 1);
        GetCurrencyFormatEx(l.str.c_str(), 0, sval.c_str(), 0, &buf.front(), len);
#else
        int len = GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,0,0);
        std::vector<wchar_t> buf(len+1);
        GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,&buf.front(),len);
#endif
        return &buf.front();
    }

    inline std::wstring wcs_format_date_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l)
    {
#if BOOST_PLAT_WINDOWS_RUNTIME
        int len = GetDateFormatEx(l.str.c_str(), 0, tm, format, 0, 0,
          /*Reserved; must set to NULL.*/ 0);
        std::vector<wchar_t> buf(len + 1);
        GetDateFormatEx(l.str.c_str(), 0, tm, format, &buf.front(), len,
          /*Reserved; must set to NULL.*/ 0);
#else
        int len = GetDateFormatW(l.lcid,0,tm,format,0,0);
        std::vector<wchar_t> buf(len+1);
        GetDateFormatW(l.lcid,0,tm,format,&buf.front(),len);
#endif
        return &buf.front(); 
    }

    inline std::wstring wcs_format_time_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l)
    {
#if BOOST_PLAT_WINDOWS_RUNTIME
        int len = GetTimeFormatEx(l.str.c_str(), 0, tm, format, 0, 0);
        std::vector<wchar_t> buf(len + 1);
        GetTimeFormatEx(l.str.c_str(), 0, tm, format, &buf.front(), len);
#else
        int len = GetTimeFormatW(l.lcid, 0, tm, format, 0, 0);
        std::vector<wchar_t> buf(len + 1);
        GetTimeFormatW(l.lcid, 0, tm, format, &buf.front(), len);
#endif
        return &buf.front(); 
    }

lcid.cpp

BOOL CALLBACK procEx(LPWSTR s, DWORD, LPARAM)
{
  table_type& tbl = real_lcid_table();
  try {
    std::wistringstream ss;
    ss.str(s);
    ss >> std::hex;

    unsigned lcid;
    ss >> lcid; // <----- not sure about this line, but anyway...
    if (ss.fail() || !ss.eof()) {
      return FALSE;
    }

    char iso_639_lang[16];
    char iso_3166_country[16];
    if (GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, iso_639_lang, sizeof(iso_639_lang)) == 0)
      return FALSE;
    std::string lc_name = iso_639_lang;
    if (GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, iso_3166_country, sizeof(iso_3166_country)) != 0) {
      lc_name += "_";
      lc_name += iso_3166_country;
    }
    table_type::iterator p = tbl.find(lc_name);
    if (p != tbl.end()) {
      if (p->second > lcid)
        p->second = lcid;
    }
    else {
      tbl[lc_name] = lcid;
    }
  }
  catch (...) {
    tbl.clear();
    return FALSE;
  }
  return TRUE;
}

table_type  const &get_ready_lcid_table()
{
    if(table)
        return *table;
    else {
        boost::unique_lock<boost::mutex> lock(lcid_table_mutex());
        if(table)
            return *table;
#if BOOST_PLAT_WINDOWS_RUNTIME
        EnumSystemLocalesEx(procEx, LCID_INSTALLED,
          /*callback arg*/ 0, /*reserved*/ 0);
#else
        EnumSystemLocalesA(proc, LCID_INSTALLED);
#endif
        table = &real_lcid_table();
        return *table;
    }
}

UPDATE

I found out, that the problem is actually caused by inclusion of <boost/predef.h> in the api.h, which I use to define the BOOST_PLAT_WINDOWS_RUNTIME macro when appropriate. I still don't know how to handle this situation however. Can anybody point me somewhere? Thank you.

Upvotes: 0

Views: 231

Answers (0)

Related Questions