[libc++] Fix checks for terminal and flushes in std::print() (#70321)
The check whether a stream is associated with a terminal or not and the flushing of the stream in `std::print()` is needed only on Windows. Additionally, the correct flush should be used. When `std::print` is called with a C stream, `std::fflush()` should be used. When it is called with C++ `ostream`, `ostream::flush()` should be called. Because POSIX does not have a separate Unicode API for terminal output, checking for terminal (`isatty`) and flushing is not needed at all. Moreover, `isatty` has noticeable performance cost. See also https://wg21.link/LWG4044. Fixes #70142
This commit is contained in:
parent
0c4eaba2f9
commit
1616fbaccf
1
.github/workflows/libcxx-build-and-test.yaml
vendored
1
.github/workflows/libcxx-build-and-test.yaml
vendored
@ -138,7 +138,6 @@ jobs:
|
||||
'generic-no-experimental',
|
||||
'generic-no-filesystem',
|
||||
'generic-no-localization',
|
||||
'generic-no-terminal',
|
||||
'generic-no-random_device',
|
||||
'generic-no-threads',
|
||||
'generic-no-tzdb',
|
||||
|
||||
@ -106,8 +106,6 @@ option(LIBCXX_ENABLE_UNICODE
|
||||
"Whether to include support for Unicode in the library. Disabling Unicode can
|
||||
be useful when porting to platforms that don't support UTF-8 encoding (e.g.
|
||||
embedded)." ON)
|
||||
option(LIBCXX_HAS_TERMINAL_AVAILABLE
|
||||
"Build libc++ with support for checking whether a stream is a terminal." ON)
|
||||
option(LIBCXX_ENABLE_WIDE_CHARACTERS
|
||||
"Whether to include support for wide characters in the library. Disabling
|
||||
wide character support can be useful when porting to platforms that don't
|
||||
@ -750,7 +748,6 @@ config_define(${LIBCXX_ABI_FORCE_ITANIUM} _LIBCPP_ABI_FORCE_ITANIUM)
|
||||
config_define(${LIBCXX_ABI_FORCE_MICROSOFT} _LIBCPP_ABI_FORCE_MICROSOFT)
|
||||
config_define(${LIBCXX_ENABLE_THREADS} _LIBCPP_HAS_THREADS)
|
||||
config_define(${LIBCXX_ENABLE_MONOTONIC_CLOCK} _LIBCPP_HAS_MONOTONIC_CLOCK)
|
||||
config_define(${LIBCXX_HAS_TERMINAL_AVAILABLE} _LIBCPP_HAS_TERMINAL)
|
||||
if (NOT LIBCXX_TYPEINFO_COMPARISON_IMPLEMENTATION STREQUAL "default")
|
||||
config_define("${LIBCXX_TYPEINFO_COMPARISON_IMPLEMENTATION}" _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION)
|
||||
endif()
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
set(LIBCXX_HAS_TERMINAL_AVAILABLE OFF CACHE BOOL "")
|
||||
|
||||
# Speed up the CI
|
||||
set(LIBCXX_TEST_PARAMS "enable_modules=clang" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
||||
@ -15,7 +15,6 @@
|
||||
#cmakedefine01 _LIBCPP_ABI_FORCE_MICROSOFT
|
||||
#cmakedefine01 _LIBCPP_HAS_THREADS
|
||||
#cmakedefine01 _LIBCPP_HAS_MONOTONIC_CLOCK
|
||||
#cmakedefine01 _LIBCPP_HAS_TERMINAL
|
||||
#cmakedefine01 _LIBCPP_HAS_MUSL_LIBC
|
||||
#cmakedefine01 _LIBCPP_HAS_THREAD_API_PTHREAD
|
||||
#cmakedefine01 _LIBCPP_HAS_THREAD_API_EXTERNAL
|
||||
|
||||
@ -255,12 +255,6 @@
|
||||
#define _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION _LIBCPP_INTRODUCED_IN_LLVM_18
|
||||
#define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION _LIBCPP_INTRODUCED_IN_LLVM_18_ATTRIBUTE
|
||||
|
||||
// This controls the availability of C++23 <print>, which
|
||||
// has a dependency on the built library (it needs access to
|
||||
// the underlying buffer types of std::cout, std::cerr, and std::clog.
|
||||
#define _LIBCPP_AVAILABILITY_HAS_PRINT _LIBCPP_INTRODUCED_IN_LLVM_18
|
||||
#define _LIBCPP_AVAILABILITY_PRINT _LIBCPP_INTRODUCED_IN_LLVM_18_ATTRIBUTE
|
||||
|
||||
// This controls the availability of the C++17 std::pmr library,
|
||||
// which is implemented in large part in the built library.
|
||||
//
|
||||
|
||||
@ -87,7 +87,7 @@ _LIBCPP_EXPORTED_FROM_ABI FILE* __get_ostream_file(ostream& __os);
|
||||
# if _LIBCPP_HAS_UNICODE
|
||||
template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
|
||||
_LIBCPP_HIDE_FROM_ABI void __vprint_unicode(ostream& __os, string_view __fmt, format_args __args, bool __write_nl) {
|
||||
# if _LIBCPP_AVAILABILITY_HAS_PRINT == 0
|
||||
# ifndef _LIBCPP_WIN32API
|
||||
return std::__vprint_nonunicode(__os, __fmt, __args, __write_nl);
|
||||
# else
|
||||
FILE* __file = std::__get_ostream_file(__os);
|
||||
@ -110,10 +110,8 @@ _LIBCPP_HIDE_FROM_ABI void __vprint_unicode(ostream& __os, string_view __fmt, fo
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
ostream::sentry __s(__os);
|
||||
if (__s) {
|
||||
# ifndef _LIBCPP_WIN32API
|
||||
__print::__vprint_unicode_posix(__file, __fmt, __args, __write_nl, true);
|
||||
# elif _LIBCPP_HAS_WIDE_CHARACTERS
|
||||
__print::__vprint_unicode_windows(__file, __fmt, __args, __write_nl, true);
|
||||
# if _LIBCPP_HAS_WIDE_CHARACTERS
|
||||
__print::__vprint_unicode_windows(__file, __fmt, __args, __write_nl);
|
||||
# else
|
||||
# error "Windows builds with wchar_t disabled are not supported."
|
||||
# endif
|
||||
@ -124,7 +122,7 @@ _LIBCPP_HIDE_FROM_ABI void __vprint_unicode(ostream& __os, string_view __fmt, fo
|
||||
__os.__set_badbit_and_consider_rethrow();
|
||||
}
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
# endif // _LIBCPP_AVAILABILITY_HAS_PRINT
|
||||
# endif // _LIBCPP_WIN32API
|
||||
}
|
||||
|
||||
template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
|
||||
|
||||
@ -69,9 +69,7 @@ _LIBCPP_EXPORTED_FROM_ABI bool __is_windows_terminal(FILE* __stream);
|
||||
// Note the function is only implemented on the Windows platform.
|
||||
_LIBCPP_EXPORTED_FROM_ABI void __write_to_windows_console(FILE* __stream, wstring_view __view);
|
||||
# endif // _LIBCPP_HAS_WIDE_CHARACTERS
|
||||
# elif __has_include(<unistd.h>)
|
||||
_LIBCPP_EXPORTED_FROM_ABI bool __is_posix_terminal(FILE* __stream);
|
||||
# endif // _LIBCPP_WIN32API
|
||||
# endif // _LIBCPP_WIN32API
|
||||
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
|
||||
@ -197,21 +195,17 @@ inline constexpr bool __use_unicode_execution_charset = _MSVC_EXECUTION_CHARACTE
|
||||
inline constexpr bool __use_unicode_execution_charset = true;
|
||||
# endif
|
||||
|
||||
# ifdef _LIBCPP_WIN32API
|
||||
_LIBCPP_HIDE_FROM_ABI inline bool __is_terminal([[maybe_unused]] FILE* __stream) {
|
||||
// The macro _LIBCPP_TESTING_PRINT_IS_TERMINAL is used to change
|
||||
// the behavior in the test. This is not part of the public API.
|
||||
# ifdef _LIBCPP_TESTING_PRINT_IS_TERMINAL
|
||||
# ifdef _LIBCPP_TESTING_PRINT_IS_TERMINAL
|
||||
return _LIBCPP_TESTING_PRINT_IS_TERMINAL(__stream);
|
||||
# elif _LIBCPP_AVAILABILITY_HAS_PRINT == 0 || !_LIBCPP_HAS_TERMINAL
|
||||
return false;
|
||||
# elif defined(_LIBCPP_WIN32API)
|
||||
# else
|
||||
return std::__is_windows_terminal(__stream);
|
||||
# elif __has_include(<unistd.h>)
|
||||
return std::__is_posix_terminal(__stream);
|
||||
# else
|
||||
# error "Provide a way to determine whether a FILE* is a terminal"
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
# endif // _LIBCPP_WIN32API
|
||||
|
||||
template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
|
||||
_LIBCPP_HIDE_FROM_ABI inline void
|
||||
@ -236,26 +230,11 @@ __vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args, bool
|
||||
// terminal when the output is redirected. Typically during testing the
|
||||
// output is redirected to be able to capture it. This makes it hard to
|
||||
// test this code path.
|
||||
template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
|
||||
_LIBCPP_HIDE_FROM_ABI inline void
|
||||
__vprint_unicode_posix(FILE* __stream, string_view __fmt, format_args __args, bool __write_nl, bool __is_terminal) {
|
||||
// TODO PRINT Should flush errors throw too?
|
||||
if (__is_terminal)
|
||||
std::fflush(__stream);
|
||||
|
||||
__print::__vprint_nonunicode(__stream, __fmt, __args, __write_nl);
|
||||
}
|
||||
|
||||
# if _LIBCPP_HAS_WIDE_CHARACTERS
|
||||
template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
|
||||
_LIBCPP_HIDE_FROM_ABI inline void
|
||||
__vprint_unicode_windows(FILE* __stream, string_view __fmt, format_args __args, bool __write_nl, bool __is_terminal) {
|
||||
if (!__is_terminal)
|
||||
return __print::__vprint_nonunicode(__stream, __fmt, __args, __write_nl);
|
||||
|
||||
// TODO PRINT Should flush errors throw too?
|
||||
std::fflush(__stream);
|
||||
|
||||
__vprint_unicode_windows([[maybe_unused]] FILE* __stream, string_view __fmt, format_args __args, bool __write_nl) {
|
||||
string __str = std::vformat(__fmt, __args);
|
||||
// UTF-16 uses the same number or less code units than UTF-8.
|
||||
// However the size of the code unit is 16 bits instead of 8 bits.
|
||||
@ -316,9 +295,15 @@ __vprint_unicode([[maybe_unused]] FILE* __stream,
|
||||
// Windows there is a different API. This API requires transcoding.
|
||||
|
||||
# ifndef _LIBCPP_WIN32API
|
||||
__print::__vprint_unicode_posix(__stream, __fmt, __args, __write_nl, __print::__is_terminal(__stream));
|
||||
__print::__vprint_nonunicode(__stream, __fmt, __args, __write_nl);
|
||||
# elif _LIBCPP_HAS_WIDE_CHARACTERS
|
||||
__print::__vprint_unicode_windows(__stream, __fmt, __args, __write_nl, __print::__is_terminal(__stream));
|
||||
if (__print::__is_terminal(__stream)) {
|
||||
// TODO PRINT Should flush errors throw too?
|
||||
std::fflush(__stream);
|
||||
__print::__vprint_unicode_windows(__stream, __fmt, __args, __write_nl);
|
||||
} else {
|
||||
__print::__vprint_nonunicode(__stream, __fmt, __args, __write_nl);
|
||||
}
|
||||
# else
|
||||
# error "Windows builds with wchar_t disabled are not supported."
|
||||
# endif
|
||||
|
||||
@ -64,9 +64,12 @@ __write_to_windows_console([[maybe_unused]] FILE* __stream, [[maybe_unused]] wst
|
||||
}
|
||||
# endif // _LIBCPP_HAS_WIDE_CHARACTERS
|
||||
|
||||
#elif defined(HAS_FILENO_AND_ISATTY) // !_LIBCPP_WIN32API
|
||||
#elif defined(HAS_FILENO_AND_ISATTY) && _LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION < 23 // !_LIBCPP_WIN32API
|
||||
|
||||
_LIBCPP_DIAGNOSTIC_PUSH
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-prototypes")
|
||||
_LIBCPP_EXPORTED_FROM_ABI bool __is_posix_terminal(FILE* __stream) { return isatty(fileno(__stream)); }
|
||||
_LIBCPP_DIAGNOSTIC_POP
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
@ -13,13 +13,8 @@
|
||||
|
||||
// XFAIL: availability-fp_to_chars-missing
|
||||
|
||||
// When std::print is unavailable, we don't rely on an implementation of
|
||||
// std::__is_terminal and we always assume a non-unicode and non-terminal
|
||||
// output.
|
||||
// XFAIL: availability-print-missing
|
||||
|
||||
// Clang modules do not work with the definiton of _LIBCPP_TESTING_PRINT_IS_TERMINAL
|
||||
// XFAIL: clang-modules-build
|
||||
// ADDITIONAL_COMPILE_FLAGS: -fno-modules
|
||||
// <ostream>
|
||||
|
||||
// Tests the implementation of
|
||||
@ -81,14 +76,22 @@ static void test_is_terminal_file_stream() {
|
||||
assert(stream.is_open());
|
||||
assert(stream.good());
|
||||
std::print(stream, "test");
|
||||
#ifdef _WIN32
|
||||
assert(is_terminal_calls == 1);
|
||||
#else
|
||||
assert(is_terminal_calls == 0);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
std::ofstream stream(filename);
|
||||
assert(stream.is_open());
|
||||
assert(stream.good());
|
||||
std::print(stream, "test");
|
||||
#ifdef _WIN32
|
||||
assert(is_terminal_calls == 2);
|
||||
#else
|
||||
assert(is_terminal_calls == 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,7 +108,11 @@ static void test_is_terminal_rdbuf_derived_from_filebuf() {
|
||||
|
||||
std::ostream stream(&buf);
|
||||
std::print(stream, "test");
|
||||
#ifdef _WIN32
|
||||
assert(is_terminal_calls == 1);
|
||||
#else
|
||||
assert(is_terminal_calls == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// When the stream is cout, clog, or cerr, its FILE* may be a terminal. Validate
|
||||
@ -115,15 +122,27 @@ static void test_is_terminal_std_cout_cerr_clog() {
|
||||
is_terminal_result = false;
|
||||
{
|
||||
std::print(std::cout, "test");
|
||||
#ifdef _WIN32
|
||||
assert(is_terminal_calls == 1);
|
||||
#else
|
||||
assert(is_terminal_calls == 0);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
std::print(std::cerr, "test");
|
||||
#ifdef _WIN32
|
||||
assert(is_terminal_calls == 2);
|
||||
#else
|
||||
assert(is_terminal_calls == 0);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
std::print(std::clog, "test");
|
||||
#ifdef _WIN32
|
||||
assert(is_terminal_calls == 3);
|
||||
#else
|
||||
assert(is_terminal_calls == 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +175,11 @@ static void test_is_terminal_is_flushed() {
|
||||
// A terminal sync is called.
|
||||
is_terminal_result = true;
|
||||
std::print(stream, "");
|
||||
#ifdef _WIN32
|
||||
assert(buf.sync_calls == 1); // only called from the destructor of the sentry
|
||||
#else
|
||||
assert(buf.sync_calls == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: no-filesystem
|
||||
// UNSUPPORTED: libcpp-has-no-unicode
|
||||
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
|
||||
|
||||
// XFAIL: availability-fp_to_chars-missing
|
||||
|
||||
// fmemopen is available starting in Android M (API 23)
|
||||
// XFAIL: target={{.+}}-android{{(eabi)?(21|22)}}
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
|
||||
// <print>
|
||||
|
||||
// Tests the implementation of
|
||||
// void __print::__vprint_unicode_posix(FILE* __stream, string_view __fmt,
|
||||
// format_args __args, bool __write_nl,
|
||||
// bool __is_terminal);
|
||||
//
|
||||
// In the library when the stdout is redirected to a file it is no
|
||||
// longer considered a terminal and the special terminal handling is no
|
||||
// longer executed. By testing this function we can "force" emulate a
|
||||
// terminal.
|
||||
// Note __write_nl is tested by the public API.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <print>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
int main(int, char**) {
|
||||
std::array<char, 100> buffer;
|
||||
std::ranges::fill(buffer, '*');
|
||||
|
||||
FILE* file = fmemopen(buffer.data(), buffer.size(), "wb");
|
||||
assert(file);
|
||||
|
||||
// Test the file is buffered.
|
||||
std::fprintf(file, "Hello");
|
||||
assert(std::ftell(file) == 5);
|
||||
#if defined(TEST_HAS_GLIBC) && \
|
||||
!(__has_feature(address_sanitizer) || __has_feature(thread_sanitizer) || __has_feature(memory_sanitizer))
|
||||
assert(std::ranges::all_of(buffer, [](char c) { return c == '*'; }));
|
||||
#endif
|
||||
|
||||
// Test writing to a "non-terminal" stream does not flush.
|
||||
std::__print::__vprint_unicode_posix(file, " world", std::make_format_args(), false, false);
|
||||
assert(std::ftell(file) == 11);
|
||||
#if defined(TEST_HAS_GLIBC) && \
|
||||
!(__has_feature(address_sanitizer) || __has_feature(thread_sanitizer) || __has_feature(memory_sanitizer))
|
||||
assert(std::ranges::all_of(buffer, [](char c) { return c == '*'; }));
|
||||
#endif
|
||||
|
||||
// Test writing to a "terminal" stream flushes before writing.
|
||||
std::__print::__vprint_unicode_posix(file, "!", std::make_format_args(), false, true);
|
||||
assert(std::ftell(file) == 12);
|
||||
assert(std::string_view(buffer.data(), buffer.data() + 11) == "Hello world");
|
||||
#if defined(TEST_HAS_GLIBC)
|
||||
// glibc does not flush after a write.
|
||||
assert(buffer[11] != '!');
|
||||
#endif
|
||||
|
||||
// Test everything is written when closing the stream.
|
||||
std::fclose(file);
|
||||
assert(std::string_view(buffer.data(), buffer.data() + 12) == "Hello world!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -13,7 +13,7 @@
|
||||
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
|
||||
|
||||
// Clang modules do not work with the definiton of _LIBCPP_TESTING_PRINT_WRITE_TO_WINDOWS_CONSOLE_FUNCTION
|
||||
// XFAIL: clang-modules-build
|
||||
// ADDITIONAL_COMPILE_FLAGS: -fno-modules
|
||||
|
||||
// XFAIL: availability-fp_to_chars-missing
|
||||
|
||||
@ -21,8 +21,7 @@
|
||||
|
||||
// Tests the implementation of
|
||||
// void __print::__vprint_unicode_windows(FILE* __stream, string_view __fmt,
|
||||
// format_args __args, bool __write_nl,
|
||||
// bool __is_terminal);
|
||||
// format_args __args, bool __write_nl);
|
||||
//
|
||||
// In the library when the stdout is redirected to a file it is no
|
||||
// longer considered a terminal and the special terminal handling is no
|
||||
@ -62,40 +61,19 @@ static void test_basics() {
|
||||
FILE* file = std::fopen(filename.c_str(), "wb");
|
||||
assert(file);
|
||||
|
||||
// Test writing to a "non-terminal" stream does not call WriteConsoleW.
|
||||
std::__print::__vprint_unicode_windows(file, "Hello", std::make_format_args(), false, false);
|
||||
assert(std::ftell(file) == 5);
|
||||
|
||||
// It's not possible to reliably test whether writing to a "terminal" stream
|
||||
// flushes before writing. Testing flushing a closed stream worked on some
|
||||
// platforms, but was unreliable.
|
||||
calling = true;
|
||||
std::__print::__vprint_unicode_windows(file, " world", std::make_format_args(), false, true);
|
||||
std::__print::__vprint_unicode_windows(file, " world", std::make_format_args(), false);
|
||||
}
|
||||
|
||||
// When the output is a file the data is written as-is.
|
||||
// When the output is a "terminal" invalid UTF-8 input is flagged.
|
||||
// Invalid UTF-8 input is flagged.
|
||||
static void test(std::wstring_view output, std::string_view input) {
|
||||
// *** File ***
|
||||
FILE* file = std::fopen(filename.c_str(), "wb");
|
||||
assert(file);
|
||||
|
||||
std::__print::__vprint_unicode_windows(file, input, std::make_format_args(), false, false);
|
||||
assert(std::ftell(file) == static_cast<long>(input.size()));
|
||||
std::fclose(file);
|
||||
|
||||
file = std::fopen(filename.c_str(), "rb");
|
||||
assert(file);
|
||||
|
||||
std::vector<char> buffer(input.size());
|
||||
size_t read = fread(buffer.data(), 1, buffer.size(), file);
|
||||
assert(read == input.size());
|
||||
assert(input == std::string_view(buffer.begin(), buffer.end()));
|
||||
std::fclose(file);
|
||||
|
||||
// *** Terminal ***
|
||||
expected = output;
|
||||
std::__print::__vprint_unicode_windows(file, input, std::make_format_args(), false, true);
|
||||
std::__print::__vprint_unicode_windows(file, input, std::make_format_args(), false);
|
||||
assert(std::ftell(file) == 0);
|
||||
std::fclose(file);
|
||||
}
|
||||
|
||||
static void test() {
|
||||
|
||||
@ -486,11 +486,6 @@ generic-no-localization)
|
||||
generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-localization.cmake"
|
||||
check-runtimes
|
||||
;;
|
||||
generic-no-terminal)
|
||||
clean
|
||||
generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-terminal.cmake"
|
||||
check-runtimes
|
||||
;;
|
||||
generic-no-unicode)
|
||||
clean
|
||||
generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-unicode.cmake"
|
||||
|
||||
@ -67,7 +67,6 @@ inverted_macros = {
|
||||
"_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS": "libcpp-has-no-availability-markup",
|
||||
"_LIBCPP_HAS_RANDOM_DEVICE": "no-random-device",
|
||||
"_LIBCPP_HAS_UNICODE": "libcpp-has-no-unicode",
|
||||
"_LIBCPP_HAS_TERMINAL": "no-terminal",
|
||||
}
|
||||
for macro, feature in inverted_macros.items():
|
||||
features.append(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user