[libcxx-commits] [libcxx] [libc++] Reintroduce LIBCXX_ENABLE_FSTREAM for independent fstream support (PR #193453)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Apr 22 03:11:53 PDT 2026


https://github.com/quic-k created https://github.com/llvm/llvm-project/pull/193453

possible fix for https://github.com/llvm/llvm-project/issues/75284

>From bce691546f806a10fe80c591737340aa6204198e Mon Sep 17 00:00:00 2001
From: Kushal Pal <kushpal at qti.qualcomm.com>
Date: Wed, 22 Apr 2026 15:15:43 +0530
Subject: [PATCH] [libc++] Reintroduce LIBCXX_ENABLE_FSTREAM for independent
 fstream support

This patch restores the LIBCXX_ENABLE_FSTREAM CMake option, allowing
fstream to be enabled independently of filesystem support.

Signed-off-by: Kushal Pal <kushpal at qti.qualcomm.com>
---
 libcxx/CMakeLists.txt             | 17 ++++++++++++++--
 libcxx/include/__config_site.in   |  1 +
 libcxx/include/fstream            | 34 ++++++++++++++++---------------
 libcxx/src/ios.instantiations.cpp |  2 +-
 4 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index 845240d1b894c..dba1110bfc95b 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -59,8 +59,14 @@ option(LIBCXX_ENABLE_RTTI
   This option may only be set to OFF when LIBCXX_ENABLE_EXCEPTIONS=OFF." ON)
 option(LIBCXX_ENABLE_FILESYSTEM
   "Whether to include support for parts of the library that rely on a filesystem being
-   available on the platform. This includes things like most parts of <filesystem> and
-   others like <fstream>" ON)
+   available on the platform. This includes things like most parts of <filesystem>.
+   Enabling this option also implies LIBCXX_ENABLE_FSTREAM." ON)
+option(LIBCXX_ENABLE_FSTREAM
+  "Whether to include support for <fstream> in the library. <fstream> requires only
+   basic C stdio support (fopen/fclose/fread/fwrite/fseek) and is independent of full
+   filesystem support (sys/statvfs.h, dirent.h, etc.). Enabling LIBCXX_ENABLE_FILESYSTEM
+   implies this option. Useful for targets that have file I/O but lack the full POSIX
+   filesystem API (e.g. picolibc, wasi-libc)." ON)
 option(LIBCXX_INCLUDE_TESTS "Build the libc++ tests." ${LLVM_INCLUDE_TESTS})
 set(LIBCXX_SUPPORTED_HARDENING_MODES none fast extensive debug)
 set(LIBCXX_HARDENING_MODE "none" CACHE STRING
@@ -790,6 +796,13 @@ config_define(${LIBCXX_HAS_C11_THREAD_API} _LIBCPP_HAS_THREAD_API_C11)
 config_define(${LIBCXX_HAS_MUSL_LIBC} _LIBCPP_HAS_MUSL_LIBC)
 config_define_if(LIBCXX_NO_VCRUNTIME _LIBCPP_NO_VCRUNTIME)
 config_define(${LIBCXX_ENABLE_FILESYSTEM} _LIBCPP_HAS_FILESYSTEM)
+# LIBCXX_ENABLE_FILESYSTEM implies LIBCXX_ENABLE_FSTREAM since full filesystem
+# support is a strict superset of fstream support.
+if (LIBCXX_ENABLE_FILESYSTEM AND NOT LIBCXX_ENABLE_FSTREAM)
+  message(STATUS "LIBCXX_ENABLE_FILESYSTEM implies LIBCXX_ENABLE_FSTREAM=ON")
+  set(LIBCXX_ENABLE_FSTREAM ON CACHE BOOL "" FORCE)
+endif()
+config_define(${LIBCXX_ENABLE_FSTREAM} _LIBCPP_HAS_FSTREAM)
 config_define(${LIBCXX_ENABLE_RANDOM_DEVICE} _LIBCPP_HAS_RANDOM_DEVICE)
 config_define(${LIBCXX_ENABLE_LOCALIZATION} _LIBCPP_HAS_LOCALIZATION)
 config_define(${LIBCXX_ENABLE_UNICODE} _LIBCPP_HAS_UNICODE)
diff --git a/libcxx/include/__config_site.in b/libcxx/include/__config_site.in
index e6e33a2eeb2a9..d169a28e97382 100644
--- a/libcxx/include/__config_site.in
+++ b/libcxx/include/__config_site.in
@@ -25,6 +25,7 @@
 #cmakedefine _LIBCPP_NO_VCRUNTIME
 #cmakedefine _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION @_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION@
 #cmakedefine01 _LIBCPP_HAS_FILESYSTEM
+#cmakedefine01 _LIBCPP_HAS_FSTREAM
 #cmakedefine01 _LIBCPP_HAS_RANDOM_DEVICE
 #cmakedefine01 _LIBCPP_HAS_LOCALIZATION
 #cmakedefine01 _LIBCPP_HAS_UNICODE
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 4000be8153731..221fe508885e8 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -191,11 +191,13 @@ typedef basic_fstream<wchar_t> wfstream;
 #else
 #  include <__config>
 
-#  if _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
+#  if (_LIBCPP_HAS_FILESYSTEM || _LIBCPP_HAS_FSTREAM) && _LIBCPP_HAS_LOCALIZATION
 
 #    include <__algorithm/max.h>
 #    include <__assert>
-#    include <__filesystem/path.h>
+#    if _LIBCPP_HAS_FILESYSTEM
+#      include <__filesystem/path.h>
+#    endif
 #    include <__fwd/fstream.h>
 #    include <__locale>
 #    include <__memory/addressof.h>
@@ -261,7 +263,7 @@ public:
 #    endif
   _LIBCPP_HIDE_FROM_ABI basic_filebuf* open(const string& __s, ios_base::openmode __mode);
 
-#    if _LIBCPP_STD_VER >= 17
+#    if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
   _LIBCPP_HIDE_FROM_ABI basic_filebuf* open(const filesystem::path& __p, ios_base::openmode __mode) {
     return open(__p.c_str(), __mode);
   }
@@ -1159,11 +1161,11 @@ public:
   _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const wchar_t* __s, ios_base::openmode __mode = ios_base::in);
 #    endif
   _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in);
-#    if _LIBCPP_STD_VER >= 17
+#    if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
   template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
   _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const _Tp& __p, ios_base::openmode __mode = ios_base::in)
       : basic_ifstream(__p.c_str(), __mode) {}
-#    endif // _LIBCPP_STD_VER >= 17
+#    endif // _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
   _LIBCPP_HIDE_FROM_ABI basic_ifstream(basic_ifstream&& __rhs);
   _LIBCPP_HIDE_FROM_ABI basic_ifstream& operator=(basic_ifstream&& __rhs);
   _LIBCPP_HIDE_FROM_ABI void swap(basic_ifstream& __rhs);
@@ -1180,11 +1182,11 @@ public:
   void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in);
 #    endif
   void open(const string& __s, ios_base::openmode __mode = ios_base::in);
-#    if _LIBCPP_STD_VER >= 17
+#    if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
   _LIBCPP_HIDE_FROM_ABI void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in) {
     return open(__p.c_str(), __mode);
   }
-#    endif // _LIBCPP_STD_VER >= 17
+#    endif // _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
 
   _LIBCPP_HIDE_FROM_ABI void __open(int __fd, ios_base::openmode __mode);
   _LIBCPP_HIDE_FROM_ABI void close();
@@ -1316,11 +1318,11 @@ public:
 #    endif
   _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const string& __s, ios_base::openmode __mode = ios_base::out);
 
-#    if _LIBCPP_STD_VER >= 17
+#    if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
   template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
   _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const _Tp& __p, ios_base::openmode __mode = ios_base::out)
       : basic_ofstream(__p.c_str(), __mode) {}
-#    endif // _LIBCPP_STD_VER >= 17
+#    endif // _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
 
   _LIBCPP_HIDE_FROM_ABI basic_ofstream(basic_ofstream&& __rhs);
   _LIBCPP_HIDE_FROM_ABI basic_ofstream& operator=(basic_ofstream&& __rhs);
@@ -1339,11 +1341,11 @@ public:
 #    endif
   void open(const string& __s, ios_base::openmode __mode = ios_base::out);
 
-#    if _LIBCPP_STD_VER >= 17
+#    if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
   _LIBCPP_HIDE_FROM_ABI void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out) {
     return open(__p.c_str(), __mode);
   }
-#    endif // _LIBCPP_STD_VER >= 17
+#    endif // _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
 
   _LIBCPP_HIDE_FROM_ABI void __open(int __fd, ios_base::openmode __mode);
   _LIBCPP_HIDE_FROM_ABI void close();
@@ -1478,11 +1480,11 @@ public:
   _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const string& __s,
                                                ios_base::openmode __mode = ios_base::in | ios_base::out);
 
-#    if _LIBCPP_STD_VER >= 17
+#    if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
   template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
   _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const _Tp& __p, ios_base::openmode __mode = ios_base::in | ios_base::out)
       : basic_fstream(__p.c_str(), __mode) {}
-#    endif // _LIBCPP_STD_VER >= 17
+#    endif // _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
 
   _LIBCPP_HIDE_FROM_ABI basic_fstream(basic_fstream&& __rhs);
 
@@ -1503,12 +1505,12 @@ public:
 #    endif
   _LIBCPP_HIDE_FROM_ABI void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
 
-#    if _LIBCPP_STD_VER >= 17
+#    if _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
   _LIBCPP_HIDE_FROM_ABI void
   open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in | ios_base::out) {
     return open(__p.c_str(), __mode);
   }
-#    endif // _LIBCPP_STD_VER >= 17
+#    endif // _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_FILESYSTEM
 
   _LIBCPP_HIDE_FROM_ABI void close();
 
@@ -1620,7 +1622,7 @@ _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS
 
-#  endif // _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
+#  endif // (_LIBCPP_HAS_FILESYSTEM || _LIBCPP_HAS_FSTREAM) && _LIBCPP_HAS_LOCALIZATION
 
 #  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
 #    include <atomic>
diff --git a/libcxx/src/ios.instantiations.cpp b/libcxx/src/ios.instantiations.cpp
index a8d267f7cfd42..1731b506f3c9f 100644
--- a/libcxx/src/ios.instantiations.cpp
+++ b/libcxx/src/ios.instantiations.cpp
@@ -37,7 +37,7 @@ template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_stringstream<char>
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostringstream<char>;
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istringstream<char>;
 
-#if _LIBCPP_HAS_FILESYSTEM
+#if _LIBCPP_HAS_FILESYSTEM || _LIBCPP_HAS_FSTREAM
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ifstream<char>;
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ofstream<char>;
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_filebuf<char>;



More information about the libcxx-commits mailing list