How to build and use LLVM libc++ on windows(msvc)?

I’m trying to compile libc++ with this documentation: build libc++ Visual Studio, and i get this:

my build: cmad:

cmake -G "Visual Studio 17 2022"  -S runtimes -B build -T "ClangCL" -DLLVM_ENABLE_RUNTIMES=libcxx -DLIBCXX_ENABLE_SHARED=YES -DLIBCXX_ENABLE_STATIC=NO

aftter cmake --build .build got this error:

 Building Custom Rule E:/Apps/llvm-project/libcxx/src/CMakeLists.txt
lld-link : error : undefined symbol: __declspec(dllimport) _chvalidator_l [E:\Apps\llvm-project\build\libcxx\src\cxx_shared.vcxproj]
  >>> referenced by C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\ctype.h:225
  >>>               cxx_shared.dir\Debug\locale.obj:(_chvalidchk_l)

I thought it was a windows issue at first but I completely uninstalled and reinstalled VS encountering the same error.

VS version: "Visual Studio 17.11.5 2022
llvm-project & libc++ clone form tag llvmorg-19.1.3
clang-cl 17(install by VS)
windows version: 24H2(26100.2161)

_chvalidator_l is a ucrt function used by the character classification functions when building in debug mode. There should be a definition for it in ucrtd.dll which you should be linking against through ucrtd.lib.

i add the -DCMAKE_BUILD_TYPE=Release to cmake but get the some error

I guess that things have changed. Looking at the ucrt headers …

    __inline int __CRTDECL _ischartype_l(
        _In_     int       const _C,
        _In_     int       const _Mask,
        _In_opt_ _locale_t const _Locale
        )
    {
        if (!_Locale)
        {
            return _chvalidchk_l(_C, _Mask, 0);
        }

        if (_C >= -1 && _C <= 255)
        {
            return __acrt_get_locale_data_prefix(_Locale)->_locale_pctype[_C] & _Mask;
        }

        if (__acrt_get_locale_data_prefix(_Locale)->_locale_mb_cur_max > 1)
        {
            return _isctype_l(_C, _Mask, _Locale);
        }

        return 0; // >0xFF and SBCS locale
    }

So, the regular path for _ischartype_l will reference this function. _ischartype_l is used through a macro:

    #define _isalpha_l(c, locale)  _ischartype_l(c, _ALPHA, locale)
    #define _isupper_l(c, locale)  _ischartype_l(c, _UPPER, locale)
    #define _islower_l(c, locale)  _ischartype_l(c, _LOWER, locale)
    #define _isdigit_l(c, locale)  _ischartype_l(c, _DIGIT, locale)
    #define _isxdigit_l(c, locale) _ischartype_l(c, _HEX, locale)
    #define _isspace_l(c, locale)  _ischartype_l(c, _SPACE, locale)
    #define _ispunct_l(c, locale)  _ischartype_l(c, _PUNCT, locale)
    #define _isblank_l(c, locale)  (((c) == '\t') ? _BLANK : _ischartype_l(c, _BLANK, locale))
    #define _isalnum_l(c, locale)  _ischartype_l(c, _ALPHA | _DIGIT, locale)
    #define _isprint_l(c, locale)  _ischartype_l(c, _BLANK | _PUNCT | _ALPHA | _DIGIT, locale)
    #define _isgraph_l(c, locale)  _ischartype_l(c, _PUNCT | _ALPHA | _DIGIT, locale)
    #define _iscntrl_l(c, locale)  _ischartype_l(c, _CONTROL, locale)

The definition will need to be provided in all cases, so in this case, I expect that ucrt will have a definition.

The definitions are provided in the static versions of ucrt - libucrt.lib and libucrtd.lib.