This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 2/2] PR libstdc++/86756 Move rest of std::filesystem to libstdc++.so


On 07/01/19 09:48 +0000, Jonathan Wakely wrote:
On 07/01/19 10:24 +0100, Christophe Lyon wrote:
Hi Jonathan

On Sun, 6 Jan 2019 at 23:37, Jonathan Wakely <jwakely@redhat.com> wrote:

Move std::filesystem directory iterators and operations from
libstdc++fs.a to main libstdc++ library. These components have many
dependencies on OS support, which is not available on all targets. Some
additional autoconf checks and conditional compilation is needed to
ensure the files will build for all targets. Previously this code was
not compiled without --enable-libstdcxx-filesystem-ts but the C++17
components should be available for all hosted builds.

The tests for these components no longer need to link to libstdc++fs.a,
but are not expected to pass on all targets. To avoid numerous failures
on targets which are not expected to pass the tests (due to missing OS
functionality) leave the dg-require-filesystem-ts directives in place
for now. This will ensure the tests only run for builds where the
filesystem-ts library is built, which presumably means some level of OS
support is present.


Tested x86_64-linux (old/new string ABIs, 32/64 bit), x86_64-w64-mingw32.

Committed to trunk.


After this commit (r267616), I've noticed build failures for my
newlib-based toolchains:
aarch64-elf, arm-eabi:

In file included from
/tmp/5241593_7.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/src/c++17/fs_ops.cc:57:
/tmp/5241593_7.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/src/c++17/../filesystem/ops-common.h:142:11:
error: '::truncate' has not been declared
142 |   using ::truncate;
    |           ^~~~~~~~
/tmp/5241593_7.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/src/c++17/fs_ops.cc:
In function 'void std::filesystem::resize_file(const
std::filesystem::__cxx11::path&, uintmax_t, std::error_code&)':
/tmp/5241593_7.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/src/c++17/fs_ops.cc:1274:19:
error: 'truncate' is not a member of 'posix'
1274 |   else if (posix::truncate(p.c_str(), size))
    |                   ^~~~~~~~
make[5]: *** [fs_ops.lo] Error 1

I'm not sure if there's an obvious fix? Note that I'm using a rather
old newlib version, if that matters.

That's probably the reason, as I didn't see this in my tests with
newlib builds.

The fix is to add yet another autoconf check and guard the uses of
truncate with a _GLIBCXX_USE_TRUNCATE macro. I'll do that now ...


Should be fixed with this patch, committed to trunk as r267647.

commit 5f0f0401171507e887f9ba775bcf243d3b3aff91
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Jan 7 11:47:20 2019 +0000

    Fix build for systems without POSIX truncate
    
    Older versions of newlib do not provide truncate so add a configure
    check for it, and provide a fallback definition.
    
    There were also some missing exports in the linker script, which went
    unnoticed because there are no tests for some functions. A new link-only
    test checks that every filesystem operation function is defined by the
    library.
    
            * acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for truncate.
            * config.h.in: Regenerate.
            * config/abi/pre/gnu.ver: Order patterns for filesystem operations
            alphabetically and add missing entries for copy_symlink,
            hard_link_count, rename, and resize_file.
            * configure: Regenerate.
            * src/c++17/fs_ops.cc (resize_file): Remove #if so posix::truncate is
            used unconditionally.
            * src/filesystem/ops-common.h (__gnu_posix::truncate)
            [!_GLIBCXX_HAVE_TRUNCATE]: Provide fallback definition that only
            supports truncating to zero length.
            * testsuite/27_io/filesystem/operations/all.cc: New test.
            * testsuite/27_io/filesystem/operations/resize_file.cc: New test.

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index ce91e495fab..8950e4c8872 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4589,6 +4589,19 @@ dnl
       AC_DEFINE(HAVE_SYMLINK, 1, [Define if symlink is available in <unistd.h>.])
     fi
     AC_MSG_RESULT($glibcxx_cv_symlink)
+dnl
+    AC_MSG_CHECKING([for truncate])
+    AC_CACHE_VAL(glibcxx_cv_truncate, [dnl
+      GCC_TRY_COMPILE_OR_LINK(
+        [#include <unistd.h>],
+        [truncate("", 99);],
+        [glibcxx_cv_truncate=yes],
+        [glibcxx_cv_truncate=no])
+    ])
+    if test $glibcxx_cv_truncate = yes; then
+      AC_DEFINE(HAVE_TRUNCATE, 1, [Define if truncate is available in <unistd.h>.])
+    fi
+    AC_MSG_RESULT($glibcxx_cv_truncate)
 dnl
     CXXFLAGS="$ac_save_CXXFLAGS"
     AC_LANG_RESTORE
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 20325bf7a33..02a6ec90375 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2167,31 +2167,35 @@ GLIBCXX_3.4.26 {
     _ZNSt10filesystem7__cxx114pathpLERKS1_;
     _ZT[IV]NSt10filesystem7__cxx1116filesystem_errorE;
 
-    _ZNSt10filesystem10equivalent*;
-    _ZNSt10filesystem10remove_all*;
-    _ZNSt10filesystem11permissions*;
-    _ZNSt10filesystem12current_path*;
-    _ZNSt10filesystem12read_symlink*;
-    _ZNSt10filesystem14create_symlink*;
-    _ZNSt10filesystem14symlink_status*;
-    _ZNSt10filesystem15last_write_time*;
-    _ZNSt10filesystem16create_directory*;
-    _ZNSt10filesystem16create_hard_link*;
-    _ZNSt10filesystem16weakly_canonical*;
-    _ZNSt10filesystem18create_directories*;
-    _ZNSt10filesystem19temp_directory_path*;
-    _ZNSt10filesystem24create_directory_symlink*;
-    _ZNSt10filesystem4copy*;
-    _ZNSt10filesystem5space*;
-    _ZNSt10filesystem6remove*;
-    _ZNSt10filesystem6status*;
     _ZNSt10filesystem8absolute*;
-    _ZNSt10filesystem8is_empty*;
-    _ZNSt10filesystem8relative*;
     _ZNSt10filesystem9canonical*;
+    _ZNSt10filesystem4copy*;
     _ZNSt10filesystem9copy_file*;
+    _ZNSt10filesystem12copy_symlink*;
+    _ZNSt10filesystem18create_directories*;
+    _ZNSt10filesystem16create_directory*;
+    _ZNSt10filesystem24create_directory_symlink*;
+    _ZNSt10filesystem16create_hard_link*;
+    _ZNSt10filesystem14create_symlink*;
+    _ZNSt10filesystem12current_path*;
+    _ZNSt10filesystem10equivalent*;
     _ZNSt10filesystem9file_size*;
+    _ZNSt10filesystem15hard_link_count*;
+    _ZNSt10filesystem8is_empty*;
+    _ZNSt10filesystem15last_write_time*;
+    _ZNSt10filesystem11permissions*;
     _ZNSt10filesystem9proximate*;
+    _ZNSt10filesystem12read_symlink*;
+    _ZNSt10filesystem8relative*;
+    _ZNSt10filesystem6remove*;
+    _ZNSt10filesystem10remove_all*;
+    _ZNSt10filesystem6rename*;
+    _ZNSt10filesystem11resize_file*;
+    _ZNSt10filesystem5space*;
+    _ZNSt10filesystem6status*;
+    _ZNSt10filesystem14symlink_status*;
+    _ZNSt10filesystem19temp_directory_path*;
+    _ZNSt10filesystem16weakly_canonical*;
 
     _ZNKSt10filesystem18directory_iteratordeEv;
     _ZNKSt10filesystem28recursive_directory_iterator5depthEv;
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index fd8cf353ba2..edd9315980b 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1268,16 +1268,12 @@ fs::resize_file(const path& p, uintmax_t size)
 void
 fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept
 {
-#ifdef _GLIBCXX_HAVE_UNISTD_H
   if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max()))
     ec.assign(EINVAL, std::generic_category());
   else if (posix::truncate(p.c_str(), size))
     ec.assign(errno, std::generic_category());
   else
     ec.clear();
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
 }
 
 
diff --git a/libstdc++-v3/src/filesystem/ops-common.h b/libstdc++-v3/src/filesystem/ops-common.h
index f20867c217e..55e482ff8f2 100644
--- a/libstdc++-v3/src/filesystem/ops-common.h
+++ b/libstdc++-v3/src/filesystem/ops-common.h
@@ -29,6 +29,9 @@
 
 #ifdef _GLIBCXX_HAVE_UNISTD_H
 # include <unistd.h>
+# ifdef _GLIBCXX_HAVE_FCNTL_H
+#  include <fcntl.h>  // AT_FDCWD, O_TRUNC etc.
+# endif
 # if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H)
 #  include <sys/types.h>
 #  include <sys/stat.h>
@@ -139,7 +142,23 @@ namespace __gnu_posix
   using ::utime;
 # endif
   using ::rename;
+# ifdef _GLIBCXX_HAVE_TRUNCATE
   using ::truncate;
+# else
+  inline int truncate(const char* path, off_t length)
+  {
+    if (length == 0)
+      {
+	const int fd = ::open(path, O_WRONLY|O_TRUNC);
+	if (fd == -1)
+	  return fd;
+	::close(fd);
+	return 0;
+      }
+    errno = ENOTSUP;
+    return -1;
+  }
+# endif
   using char_type = char;
 #else // ! _GLIBCXX_FILESYSTEM_IS_WINDOWS && ! _GLIBCXX_HAVE_UNISTD_H
   inline int open(const char*, int, ...) { errno = ENOTSUP; return -1; }
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/all.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/all.cc
new file mode 100644
index 00000000000..c9f34f4a7af
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/all.cc
@@ -0,0 +1,188 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17 -fno-inline" }
+// { dg-do link { target c++17 } }
+
+// C++17 30.10.15 Filesystem operation functions [fs.op.funcs]
+
+#include <filesystem>
+
+// Link-only test to ensure all operation functions are exported from the lib.
+
+int
+main()
+{
+  const std::filesystem::path p;
+  std::filesystem::path p2;
+  const std::filesystem::copy_options copyopts{};
+  const std::filesystem::file_status st{};
+  std::filesystem::file_status st2;
+  const std::filesystem::file_time_type t;
+  std::filesystem::file_time_type t2;
+  const std::filesystem::perms perms{};
+  const std::filesystem::perm_options permopts{};
+  std::filesystem::space_info sp;
+  std::error_code ec;
+  bool b;
+  std::uintmax_t size;
+
+  std::filesystem::absolute(p);
+  std::filesystem::absolute(p, ec);
+
+  std::filesystem::canonical(p);
+  std::filesystem::canonical(p, ec);
+
+  std::filesystem::copy(p, p);
+  std::filesystem::copy(p, p, ec);
+  std::filesystem::copy(p, p, copyopts);
+  std::filesystem::copy(p, p, copyopts, ec);
+
+  std::filesystem::copy_file(p, p);
+  std::filesystem::copy_file(p, p, ec);
+  std::filesystem::copy_file(p, p, copyopts);
+  std::filesystem::copy_file(p, p, copyopts, ec);
+
+  std::filesystem::copy_symlink(p, p);
+  std::filesystem::copy_symlink(p, p, ec);
+
+  std::filesystem::create_directories(p);
+  std::filesystem::create_directories(p, ec);
+
+  std::filesystem::create_directory(p);
+  std::filesystem::create_directory(p, ec);
+
+  std::filesystem::create_directory(p, p);
+  std::filesystem::create_directory(p, p, ec);
+
+  std::filesystem::create_directory_symlink(p, p);
+  std::filesystem::create_directory_symlink(p, p, ec);
+
+  std::filesystem::create_hard_link(p, p);
+  std::filesystem::create_hard_link(p, p, ec);
+
+  std::filesystem::create_symlink(p, p);
+  std::filesystem::create_symlink(p, p, ec);
+
+  p2 = std::filesystem::current_path();
+  p2 = std::filesystem::current_path(ec);
+  std::filesystem::current_path(p);
+  std::filesystem::current_path(p, ec);
+
+  b = std::filesystem::equivalent(p, p);
+  b = std::filesystem::equivalent(p, p, ec);
+
+  b = std::filesystem::exists(st);
+  b = std::filesystem::exists(p);
+  b = std::filesystem::exists(p, ec);
+
+  size = std::filesystem::file_size(p);
+  size = std::filesystem::file_size(p, ec);
+
+  size = std::filesystem::hard_link_count(p);
+  size = std::filesystem::hard_link_count(p, ec);
+
+  b = std::filesystem::is_block_file(st);
+  b = std::filesystem::is_block_file(p);
+  b = std::filesystem::is_block_file(p, ec);
+
+  b = std::filesystem::is_character_file(st);
+  b = std::filesystem::is_character_file(p);
+  b = std::filesystem::is_character_file(p, ec);
+
+  b = std::filesystem::is_directory(st);
+  b = std::filesystem::is_directory(p);
+  b = std::filesystem::is_directory(p, ec);
+
+  b = std::filesystem::is_empty(p);
+  b = std::filesystem::is_empty(p, ec);
+
+  b = std::filesystem::is_fifo(st);
+  b = std::filesystem::is_fifo(p);
+  b = std::filesystem::is_fifo(p, ec);
+
+  b = std::filesystem::is_other(st);
+  b = std::filesystem::is_other(p);
+  b = std::filesystem::is_other(p, ec);
+
+  b = std::filesystem::is_regular_file(st);
+  b = std::filesystem::is_regular_file(p);
+  b = std::filesystem::is_regular_file(p, ec);
+
+  b = std::filesystem::is_socket(st);
+  b = std::filesystem::is_socket(p);
+  b = std::filesystem::is_socket(p, ec);
+
+  b = std::filesystem::is_symlink(st);
+  b = std::filesystem::is_symlink(p);
+  b = std::filesystem::is_symlink(p, ec);
+
+  t2 = std::filesystem::last_write_time(p);
+  t2 = std::filesystem::last_write_time(p, ec);
+  std::filesystem::last_write_time(p, t);
+  std::filesystem::last_write_time(p, t, ec);
+
+  std::filesystem::permissions(p, perms);
+  std::filesystem::permissions(p, perms, permopts);
+  std::filesystem::permissions(p, perms, ec);
+  std::filesystem::permissions(p, perms, permopts, ec);
+
+  p2 = std::filesystem::proximate(p, ec);
+  p2 = std::filesystem::proximate(p);
+  p2 = std::filesystem::proximate(p, p);
+  p2 = std::filesystem::proximate(p, p, ec);
+
+  p2 = std::filesystem::read_symlink(p);
+  p2 = std::filesystem::read_symlink(p, ec);
+
+  p2 = std::filesystem::relative(p, ec);
+  p2 = std::filesystem::relative(p);
+  p2 = std::filesystem::relative(p, p);
+  p2 = std::filesystem::relative(p, p, ec);
+
+  b = std::filesystem::remove(p);
+  b = std::filesystem::remove(p, ec);
+
+  size = std::filesystem::remove_all(p);
+  size = std::filesystem::remove_all(p, ec);
+
+  std::filesystem::rename(p, p);
+  std::filesystem::rename(p, p, ec);
+
+  std::filesystem::resize_file(p, size);
+  std::filesystem::resize_file(p, size, ec);
+
+  sp = std::filesystem::space(p);
+  sp = std::filesystem::space(p, ec);
+
+  st2 = std::filesystem::status(p);
+  st2 = std::filesystem::status(p, ec);
+
+  b = std::filesystem::status_known(st);
+
+  st2 = std::filesystem::symlink_status(p);
+  st2 = std::filesystem::symlink_status(p, ec);
+
+  p2 = std::filesystem::temp_directory_path();
+  p2 = std::filesystem::temp_directory_path(ec);
+
+  p2 = std::filesystem::weakly_canonical(p);
+  p2 = std::filesystem::weakly_canonical(p, ec);
+}
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/resize_file.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/resize_file.cc
new file mode 100644
index 00000000000..953c4e1c664
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/resize_file.cc
@@ -0,0 +1,72 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+
+// C++17 30.10.15.33 Resize file [fs.op.resize_file]
+
+#include <filesystem>
+#include <string>
+#include <fstream>
+#include <testsuite_fs.h>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  auto p = __gnu_test::nonexistent_path();
+  std::error_code ec;
+  resize_file(p, 0, ec);
+  VERIFY( ec );
+  ec = {};
+  resize_file(p, 1, ec);
+  VERIFY( ec );
+
+  __gnu_test::scoped_file f(p);
+  std::ofstream{p} << "some text";
+  std::ifstream fin;
+  std::string input;
+
+#ifdef _GLIBCXX_HAVE_TRUNCATE
+  resize_file(p, 4, ec);
+  VERIFY( !ec );
+  fin.open(p);
+  getline(fin, input);
+  VERIFY( input.length() == 4 );
+  fin.close();
+
+  resize_file(p, 2);
+  fin.open(p);
+  getline(fin, input);
+  VERIFY( input.length() == 2 );
+  fin.close();
+#endif
+
+  resize_file(p, 0, ec);
+  VERIFY( !ec );
+  fin.open(p);
+  getline(fin, input);
+  VERIFY( input.length() == 0 );
+  fin.close();
+}
+
+int
+main()
+{
+  test01();
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]